Gitweb links:
...log
http://git.netsurf-browser.org/libwapcaplet.git/shortlog/436e979d9f9ae889...
...commit
http://git.netsurf-browser.org/libwapcaplet.git/commit/436e979d9f9ae8897b...
...tree
http://git.netsurf-browser.org/libwapcaplet.git/tree/436e979d9f9ae8897bf2...
The branch, master has been updated
via 436e979d9f9ae8897bf2cc0afc985dbfa09347ba (commit)
via 08c5618a803fa32243dfa434225604566c5dac91 (commit)
via 43b2081b8d5e23c8582e2729f18ccd7555be8a40 (commit)
via 86508f207b5fbb26db06dd9411d08bb0b9bfa6c8 (commit)
from 7c802fa89776e5a39eb97286020ccc06663f6226 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commitdiff
http://git.netsurf-browser.org/libwapcaplet.git/commit/?id=436e979d9f9ae8...
commit 436e979d9f9ae8897bf2cc0afc985dbfa09347ba
Merge: 7c802fa 08c5618
Author: Michael Drake <tlsa(a)netsurf-browser.org>
Commit: Michael Drake <tlsa(a)netsurf-browser.org>
Merge branch 'tlsa/tolower'
-----------------------------------------------------------------------
Summary of changes:
include/libwapcaplet/libwapcaplet.h | 10 ++
src/libwapcaplet.c | 295 ++++++++++++++++++-----------------
test/basictests.c | 59 +++++++
3 files changed, 225 insertions(+), 139 deletions(-)
diff --git a/include/libwapcaplet/libwapcaplet.h b/include/libwapcaplet/libwapcaplet.h
index 4c0fc71..c0e8c29 100644
--- a/include/libwapcaplet/libwapcaplet.h
+++ b/include/libwapcaplet/libwapcaplet.h
@@ -106,6 +106,16 @@ extern lwc_error lwc_intern_substring(lwc_string *str,
lwc_string **ret);
/**
+ * Optain a lowercased lwc_string from given lwc_string.
+ *
+ * @param str String to create lowercase string from.
+ * @param ret Pointer to ::lwc_string pointer to fill out.
+ * @return Result of operation, if not OK then the value pointed
+ * to by \a ret will not be valid.
+ */
+extern lwc_error lwc_string_tolower(lwc_string *str, lwc_string **ret);
+
+/**
* Increment the reference count on an lwc_string.
*
* This increases the reference count on the given string. You should
diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c
index b82d62f..9521e96 100644
--- a/src/libwapcaplet.c
+++ b/src/libwapcaplet.c
@@ -20,12 +20,11 @@ static inline lwc_hash
lwc__calculate_hash(const char *str, size_t len)
{
lwc_hash z = 0x811c9dc5;
-
while (len > 0) {
z *= 0x01000193;
z ^= *str++;
- len--;
+ len--;
}
return z;
@@ -37,8 +36,8 @@ lwc__calculate_hash(const char *str, size_t len)
#define NR_BUCKETS_DEFAULT (4091)
typedef struct lwc_context_s {
- lwc_string ** buckets;
- lwc_hash bucketcount;
+ lwc_string ** buckets;
+ lwc_hash bucketcount;
} lwc_context;
static lwc_context *ctx = NULL;
@@ -53,136 +52,155 @@ typedef void (*lwc_memcpy)(char *, const char *, size_t);
static lwc_error
lwc__initialise(void)
{
- if (ctx != NULL)
- return lwc_error_ok;
-
- ctx = LWC_ALLOC(sizeof(lwc_context));
-
- if (ctx == NULL)
- return lwc_error_oom;
-
- memset(ctx, 0, sizeof(lwc_context));
-
- ctx->bucketcount = NR_BUCKETS_DEFAULT;
- ctx->buckets = LWC_ALLOC(sizeof(lwc_string *) * ctx->bucketcount);
-
- if (ctx->buckets == NULL) {
- LWC_FREE(ctx);
+ if (ctx != NULL)
+ return lwc_error_ok;
+
+ ctx = LWC_ALLOC(sizeof(lwc_context));
+
+ if (ctx == NULL)
+ return lwc_error_oom;
+
+ memset(ctx, 0, sizeof(lwc_context));
+
+ ctx->bucketcount = NR_BUCKETS_DEFAULT;
+ ctx->buckets = LWC_ALLOC(sizeof(lwc_string *) * ctx->bucketcount);
+
+ if (ctx->buckets == NULL) {
+ LWC_FREE(ctx);
ctx = NULL;
- return lwc_error_oom;
- }
-
- memset(ctx->buckets, 0, sizeof(lwc_string *) * ctx->bucketcount);
-
- return lwc_error_ok;
+ return lwc_error_oom;
+ }
+
+ memset(ctx->buckets, 0, sizeof(lwc_string *) * ctx->bucketcount);
+
+ return lwc_error_ok;
}
static lwc_error
lwc__intern(const char *s, size_t slen,
- lwc_string **ret,
- lwc_hasher hasher,
- lwc_strncmp compare,
- lwc_memcpy copy)
+ lwc_string **ret,
+ lwc_hasher hasher,
+ lwc_strncmp compare,
+ lwc_memcpy copy)
{
- lwc_hash h;
- lwc_hash bucket;
- lwc_string *str;
- lwc_error eret;
-
- assert((s != NULL) || (slen == 0));
- assert(ret);
-
- if (ctx == NULL) {
- eret = lwc__initialise();
- if (eret != lwc_error_ok)
- return eret;
- if (ctx == NULL)
- return lwc_error_oom;
- }
-
- h = hasher(s, slen);
- bucket = h % ctx->bucketcount;
- str = ctx->buckets[bucket];
-
- while (str != NULL) {
- if ((str->hash == h) && (str->len == slen)) {
- if (compare(CSTR_OF(str), s, slen) == 0) {
- str->refcnt++;
- *ret = str;
- return lwc_error_ok;
- }
- }
- str = str->next;
- }
-
- /* Add one for the additional NUL. */
- *ret = str = LWC_ALLOC(sizeof(lwc_string) + slen + 1);
-
- if (str == NULL)
- return lwc_error_oom;
-
- str->prevptr = &(ctx->buckets[bucket]);
- str->next = ctx->buckets[bucket];
- if (str->next != NULL)
- str->next->prevptr = &(str->next);
- ctx->buckets[bucket] = str;
-
- str->len = slen;
- str->hash = h;
- str->refcnt = 1;
- str->insensitive = NULL;
-
- copy(STR_OF(str), s, slen);
-
- /* Guarantee NUL termination */
- STR_OF(str)[slen] = '\0';
-
- return lwc_error_ok;
+ lwc_hash h;
+ lwc_hash bucket;
+ lwc_string *str;
+ lwc_error eret;
+
+ assert((s != NULL) || (slen == 0));
+ assert(ret);
+
+ if (ctx == NULL) {
+ eret = lwc__initialise();
+ if (eret != lwc_error_ok)
+ return eret;
+ if (ctx == NULL)
+ return lwc_error_oom;
+ }
+
+ h = hasher(s, slen);
+ bucket = h % ctx->bucketcount;
+ str = ctx->buckets[bucket];
+
+ while (str != NULL) {
+ if ((str->hash == h) && (str->len == slen)) {
+ if (compare(CSTR_OF(str), s, slen) == 0) {
+ str->refcnt++;
+ *ret = str;
+ return lwc_error_ok;
+ }
+ }
+ str = str->next;
+ }
+
+ /* Add one for the additional NUL. */
+ *ret = str = LWC_ALLOC(sizeof(lwc_string) + slen + 1);
+
+ if (str == NULL)
+ return lwc_error_oom;
+
+ str->prevptr = &(ctx->buckets[bucket]);
+ str->next = ctx->buckets[bucket];
+ if (str->next != NULL)
+ str->next->prevptr = &(str->next);
+ ctx->buckets[bucket] = str;
+
+ str->len = slen;
+ str->hash = h;
+ str->refcnt = 1;
+ str->insensitive = NULL;
+
+ copy(STR_OF(str), s, slen);
+
+ /* Guarantee NUL termination */
+ STR_OF(str)[slen] = '\0';
+
+ return lwc_error_ok;
}
lwc_error
lwc_intern_string(const char *s, size_t slen,
- lwc_string **ret)
+ lwc_string **ret)
{
- return lwc__intern(s, slen, ret,
- lwc__calculate_hash,
- strncmp, (lwc_memcpy)memcpy);
+ return lwc__intern(s, slen, ret,
+ lwc__calculate_hash,
+ strncmp, (lwc_memcpy)memcpy);
}
lwc_error
lwc_intern_substring(lwc_string *str,
- size_t ssoffset, size_t sslen,
- lwc_string **ret)
+ size_t ssoffset, size_t sslen,
+ lwc_string **ret)
+{
+ assert(str);
+ assert(ret);
+
+ if (ssoffset >= str->len)
+ return lwc_error_range;
+ if ((ssoffset + sslen) > str->len)
+ return lwc_error_range;
+
+ return lwc_intern_string(CSTR_OF(str) + ssoffset, sslen, ret);
+}
+
+lwc_error
+lwc_string_tolower(lwc_string *str, lwc_string **ret)
{
- assert(str);
- assert(ret);
-
- if (ssoffset >= str->len)
- return lwc_error_range;
- if ((ssoffset + sslen) > str->len)
- return lwc_error_range;
-
- return lwc_intern_string(CSTR_OF(str) + ssoffset, sslen, ret);
+ assert(str);
+ assert(ret);
+
+ /* Internally make use of knowledge that insensitive strings
+ * are lower case. */
+ if (str->insensitive == NULL) {
+ lwc_error error = lwc__intern_caseless_string(str);
+ if (error != lwc_error_ok) {
+ return error;
+ }
+ }
+
+ *ret = lwc_string_ref(str->insensitive);
+ return lwc_error_ok;
}
void
lwc_string_destroy(lwc_string *str)
{
- assert(str);
-
- *(str->prevptr) = str->next;
-
- if (str->next != NULL)
- str->next->prevptr = str->prevptr;
+ assert(str);
+
+ *(str->prevptr) = str->next;
+
+ if (str->next != NULL)
+ str->next->prevptr = str->prevptr;
- if (str->insensitive != NULL && str->refcnt == 0)
- lwc_string_unref(str->insensitive);
+ if (str->insensitive != NULL && str->refcnt == 0)
+ lwc_string_unref(str->insensitive);
#ifndef NDEBUG
- memset(str, 0xA5, sizeof(*str) + str->len);
+ memset(str, 0xA5, sizeof(*str) + str->len);
#endif
-
- LWC_FREE(str);
+
+ LWC_FREE(str);
}
/**** Shonky caseless bits ****/
@@ -190,21 +208,20 @@ lwc_string_destroy(lwc_string *str)
static inline char
lwc__dolower(const char c)
{
- if (c >= 'A' && c <= 'Z')
- return c + 'a' - 'A';
- return c;
+ if (c >= 'A' && c <= 'Z')
+ return c + 'a' - 'A';
+ return c;
}
static inline lwc_hash
lwc__calculate_lcase_hash(const char *str, size_t len)
{
lwc_hash z = 0x811c9dc5;
-
while (len > 0) {
z *= 0x01000193;
z ^= lwc__dolower(*str++);
- len--;
+ len--;
}
return z;
@@ -213,33 +230,33 @@ lwc__calculate_lcase_hash(const char *str, size_t len)
static int
lwc__lcase_strncmp(const char *s1, const char *s2, size_t n)
{
- while (n--) {
- if (*s1++ != lwc__dolower(*s2++))
- /** @todo Test this somehow? */
- return 1;
- }
- return 0;
+ while (n--) {
+ if (*s1++ != lwc__dolower(*s2++))
+ /** @todo Test this somehow? */
+ return 1;
+ }
+ return 0;
}
static void
lwc__lcase_memcpy(char *target, const char *source, size_t n)
{
- while (n--) {
- *target++ = lwc__dolower(*source++);
- }
+ while (n--) {
+ *target++ = lwc__dolower(*source++);
+ }
}
lwc_error
lwc__intern_caseless_string(lwc_string *str)
{
- assert(str);
- assert(str->insensitive == NULL);
-
- return lwc__intern(CSTR_OF(str),
- str->len, &(str->insensitive),
- lwc__calculate_lcase_hash,
- lwc__lcase_strncmp,
- lwc__lcase_memcpy);
+ assert(str);
+ assert(str->insensitive == NULL);
+
+ return lwc__intern(CSTR_OF(str),
+ str->len, &(str->insensitive),
+ lwc__calculate_lcase_hash,
+ lwc__lcase_strncmp,
+ lwc__lcase_memcpy);
}
/**** Iteration ****/
@@ -247,14 +264,14 @@ lwc__intern_caseless_string(lwc_string *str)
void
lwc_iterate_strings(lwc_iteration_callback_fn cb, void *pw)
{
- lwc_hash n;
- lwc_string *str;
-
+ lwc_hash n;
+ lwc_string *str;
+
if (ctx == NULL)
return;
-
- for (n = 0; n < ctx->bucketcount; ++n) {
- for (str = ctx->buckets[n]; str != NULL; str = str->next)
- cb(str, pw);
- }
+
+ for (n = 0; n < ctx->bucketcount; ++n) {
+ for (str = ctx->buckets[n]; str != NULL; str = str->next)
+ cb(str, pw);
+ }
}
diff --git a/test/basictests.c b/test/basictests.c
index ec9bf20..c23b547 100644
--- a/test/basictests.c
+++ b/test/basictests.c
@@ -50,6 +50,22 @@ START_TEST (test_lwc_intern_substring_aborts2)
}
END_TEST
+START_TEST (test_lwc_string_tolower_aborts1)
+{
+ lwc_string_tolower(null_lwc, null_lwc_p);
+}
+END_TEST
+
+START_TEST (test_lwc_string_tolower_aborts2)
+{
+ lwc_string *str;
+ fail_unless(lwc_intern_string("Badger", 6, &str) == lwc_error_ok,
+ "unable to intern 'Badger'");
+
+ lwc_string_tolower(str, null_lwc_p);
+}
+END_TEST
+
START_TEST (test_lwc_string_ref_aborts)
{
lwc_string_ref(null_lwc);
@@ -330,6 +346,41 @@ START_TEST (test_lwc_substring_is_nul_terminated)
}
END_TEST
+START_TEST (test_lwc_string_tolower_ok1)
+{
+ bool result = true;
+ lwc_string *new_ONE;
+ lwc_string *new_one;
+
+ fail_unless(lwc_intern_string("ONE", 3, &new_ONE) == lwc_error_ok,
+ "Failure interning 'ONE'");
+ fail_unless(lwc_string_tolower(new_ONE, &new_one) == lwc_error_ok);
+ fail_unless(lwc_string_isequal(intern_one, new_ONE, &result) ==
lwc_error_ok);
+ fail_unless(result == false, "'one' == 'ONE' ?!");
+ fail_unless(lwc_string_isequal(intern_one, new_one, &result) ==
lwc_error_ok);
+ fail_unless(result == true, "'one' != 'one' ?!");
+}
+END_TEST
+
+START_TEST (test_lwc_string_tolower_ok2)
+{
+ bool result = true;
+ lwc_string *new_ONE;
+ lwc_string *new_one;
+
+ fail_unless(lwc_intern_string("ONE", 3, &new_ONE) == lwc_error_ok,
+ "Failure interning 'ONE'");
+ /* Ensure new_ONE has an insensitive pointer set */
+ fail_unless(lwc_string_caseless_isequal(intern_one, new_ONE, &result) ==
lwc_error_ok);
+ fail_unless(result == true, "'one' != 'ONE' (caseless)
?!");
+ fail_unless(lwc_string_tolower(new_ONE, &new_one) == lwc_error_ok);
+ fail_unless(lwc_string_isequal(intern_one, new_ONE, &result) ==
lwc_error_ok);
+ fail_unless(result == false, "'one' == 'ONE' ?!");
+ fail_unless(lwc_string_isequal(intern_one, new_one, &result) ==
lwc_error_ok);
+ fail_unless(result == true, "'one' != 'one' ?!");
+}
+END_TEST
+
static void
counting_cb(lwc_string *str, void *pw)
{
@@ -368,6 +419,12 @@ lwc_basic_suite(SRunner *sr)
test_lwc_intern_substring_aborts2,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
+ test_lwc_string_tolower_aborts1,
+ SIGABRT);
+ tcase_add_test_raise_signal(tc_basic,
+ test_lwc_string_tolower_aborts2,
+ SIGABRT);
+ tcase_add_test_raise_signal(tc_basic,
test_lwc_string_ref_aborts,
SIGABRT);
tcase_add_test_raise_signal(tc_basic,
@@ -408,6 +465,8 @@ lwc_basic_suite(SRunner *sr)
tcase_add_test(tc_basic, test_lwc_string_caseless_isequal_ok1);
tcase_add_test(tc_basic, test_lwc_string_caseless_isequal_ok2);
tcase_add_test(tc_basic, test_lwc_string_caseless_isequal_bad);
+ tcase_add_test(tc_basic, test_lwc_string_tolower_ok1);
+ tcase_add_test(tc_basic, test_lwc_string_tolower_ok2);
tcase_add_test(tc_basic, test_lwc_extract_data_ok);
tcase_add_test(tc_basic, test_lwc_string_hash_value_ok);
tcase_add_test(tc_basic, test_lwc_string_is_nul_terminated);
--
String internment library