From 02fdaeaf41359941559dd63e24805e78a9ee27e5 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 27 Mar 2010 14:45:09 +0000 Subject: Simplify libwapcaplet and remove context objects. Remove the lwc_context type from the API and ensure that all strings belong to the one internment context. This removes a lot of API and simplifies a lot of function calls, however it does mean that clients of the library *MUST* be better at reffing and unreffing strings or it'll explode. svn path=/trunk/libwapcaplet/; revision=10159 --- src/libwapcaplet.c | 188 ++++++++++++++++++----------------------------------- 1 file changed, 64 insertions(+), 124 deletions(-) (limited to 'src/libwapcaplet.c') diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c index 4996c6f..c452889 100644 --- a/src/libwapcaplet.c +++ b/src/libwapcaplet.c @@ -1,4 +1,4 @@ -/* libwapcaplet.h +/* libwapcaplet.c * * String internment and management tools. * @@ -15,7 +15,6 @@ #define UNUSED(x) ((x) = (x)) #endif -typedef uint32_t lwc_hash; typedef uint32_t lwc_refcounter; static inline lwc_hash @@ -45,101 +44,70 @@ struct lwc_string_s { #define STR_OF(str) ((char *)(str + 1)) #define CSTR_OF(str) ((const char *)(str + 1)) -#define NR_BUCKETS (4091) +#define NR_BUCKETS_DEFAULT (4091) -struct lwc_context_s { +typedef struct lwc_context_s { lwc_allocator_fn alloc; void * alloc_pw; - lwc_string * buckets[NR_BUCKETS]; - lwc_refcounter refcnt; - bool refweak; - size_t size; -}; + lwc_string ** buckets; + lwc_hash bucketcount; +} lwc_context; + +static lwc_context *ctx = NULL; + +#define LWC_ALLOC(s) ctx->alloc(NULL, s, ctx->alloc_pw) +#define LWC_FREE(p) ctx->alloc(p, 0, ctx->alloc_pw) + +typedef lwc_hash (*lwc_hasher)(const char *, size_t); +typedef int (*lwc_strncmp)(const char *, const char *, size_t); +typedef void (*lwc_memcpy)(char *, const char *, size_t); lwc_error -lwc_create_context(lwc_allocator_fn alloc, void *pw, - lwc_context **ret) +lwc_initialise(lwc_allocator_fn alloc, void *pw, lwc_hash buckets) { assert(alloc); - - *ret = alloc(NULL, sizeof(lwc_context), pw); - - if (*ret == NULL) - return lwc_error_oom; - - memset(*ret, 0, sizeof(lwc_context)); - (*ret)->alloc = alloc; - (*ret)->alloc_pw = pw; - (*ret)->refcnt = 1; - (*ret)->refweak = true; - (*ret)->size = sizeof(lwc_context); + if (ctx != NULL) + return lwc_error_initialised; - return lwc_error_ok; -} - -lwc_context * -lwc_context_ref(lwc_context *ctx) -{ - assert(ctx); + ctx = alloc(NULL, sizeof(lwc_context), pw); - if (ctx->refweak == true) - ctx->refweak = false; - else - ctx->refcnt++; - - return ctx; -} - -#define LWC_ALLOC(s) ctx->alloc(NULL, s, ctx->alloc_pw) -#define LWC_FREE(p) ctx->alloc(p, 0, ctx->alloc_pw) - -void -lwc_context_unref(lwc_context *ctx) -{ - int bucket_nr; - lwc_string *s, *s_next; + if (ctx == NULL) + return lwc_error_oom; - assert(ctx); + memset(ctx, 0, sizeof(lwc_context)); - if (--(ctx->refcnt)) - return; + ctx->bucketcount = (buckets > 0) ? buckets : NR_BUCKETS_DEFAULT; + ctx->alloc = alloc; + ctx->alloc_pw = pw; + ctx->buckets = alloc(NULL, sizeof(lwc_string *) * ctx->bucketcount, pw); - for (bucket_nr = 0; bucket_nr < NR_BUCKETS; ++bucket_nr) { - s = ctx->buckets[bucket_nr]; - while (s != NULL) { - s_next = s->next; - LWC_FREE(s); - s = s_next; - } + if (ctx->buckets == NULL) { + alloc(ctx, 0, pw); + return lwc_error_oom; } - LWC_FREE(ctx); + memset(ctx->buckets, 0, sizeof(lwc_string *) * ctx->bucketcount); + + return lwc_error_ok; } -typedef lwc_hash (*lwc_hasher)(const char *, size_t); -typedef int (*lwc_strncmp)(const char *, const char *, size_t); -typedef void (*lwc_memcpy)(char *, const char *, size_t); - static lwc_error -__lwc_context_intern(lwc_context *ctx, - const char *s, size_t slen, - lwc_string **ret, - lwc_hasher hasher, - lwc_strncmp compare, - lwc_memcpy copy) +__lwc_intern(const char *s, size_t slen, + lwc_string **ret, + lwc_hasher hasher, + lwc_strncmp compare, + lwc_memcpy copy) { lwc_hash h; lwc_hash bucket; lwc_string *str; - size_t required_size; - assert(ctx); assert((s != NULL) || (slen == 0)); assert(ret); h = hasher(s, slen); - bucket = h % NR_BUCKETS; + bucket = h % ctx->bucketcount; str = ctx->buckets[bucket]; while (str != NULL) { @@ -154,9 +122,7 @@ __lwc_context_intern(lwc_context *ctx, } /* Add one for the additional NUL. */ - required_size = sizeof(lwc_string) + slen + 1; - - *ret = str = LWC_ALLOC(required_size); + *ret = str = LWC_ALLOC(sizeof(lwc_string) + slen + 1); if (str == NULL) return lwc_error_oom; @@ -167,9 +133,6 @@ __lwc_context_intern(lwc_context *ctx, str->next->prevptr = &(str->next); ctx->buckets[bucket] = str; - /* Keep context size in sync */ - ctx->size += required_size; - str->len = slen; str->hash = h; str->refcnt = 1; @@ -184,22 +147,19 @@ __lwc_context_intern(lwc_context *ctx, } lwc_error -lwc_context_intern(lwc_context *ctx, - const char *s, size_t slen, - lwc_string **ret) +lwc_intern_string(const char *s, size_t slen, + lwc_string **ret) { - return __lwc_context_intern(ctx, 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_context_intern_substring(lwc_context *ctx, - lwc_string *str, - size_t ssoffset, size_t sslen, - lwc_string **ret) +lwc_intern_substring(lwc_string *str, + size_t ssoffset, size_t sslen, + lwc_string **ret) { - assert(ctx); assert(str); assert(ret); @@ -208,15 +168,12 @@ lwc_context_intern_substring(lwc_context *ctx, if ((ssoffset + sslen) > str->len) return lwc_error_range; - return lwc_context_intern(ctx, CSTR_OF(str) + ssoffset, sslen, ret); + return lwc_intern_string(CSTR_OF(str) + ssoffset, sslen, ret); } lwc_string * -lwc_context_string_ref(lwc_context *ctx, lwc_string *str) +lwc_string_ref(lwc_string *str) { - UNUSED(ctx); - - assert(ctx); assert(str); str->refcnt++; @@ -225,9 +182,8 @@ lwc_context_string_ref(lwc_context *ctx, lwc_string *str) } void -lwc_context_string_unref(lwc_context *ctx, lwc_string *str) +lwc_string_unref(lwc_string *str) { - assert(ctx); assert(str); if (--(str->refcnt) > 1) @@ -242,11 +198,8 @@ lwc_context_string_unref(lwc_context *ctx, lwc_string *str) str->next->prevptr = str->prevptr; if (str->insensitive != NULL && str->refcnt == 0) - lwc_context_string_unref(ctx, str->insensitive); + lwc_string_unref(str->insensitive); - /* Reduce context size by appropriate amount (+1 for trailing NUL) */ - ctx->size -= sizeof(lwc_string) + str->len + 1; - #ifndef NDEBUG memset(str, 0xA5, sizeof(*str) + str->len); #endif @@ -280,10 +233,11 @@ lwc_calculate_lcase_hash(const char *str, size_t len) } static int -lwc_lcase_strcmp(const char *s1, const char *s2, size_t n) +lwc_lcase_strncmp(const char *s1, const char *s2, size_t n) { while (n--) { if (*s1++ != dolower(*s2++)) + /** @todo Test this somehow? */ return 1; } return 0; @@ -298,39 +252,34 @@ lwc_lcase_memcpy(char *target, const char *source, size_t n) } static lwc_error -lwc_context_intern_caseless(lwc_context *ctx, - lwc_string *str) +lwc_intern_caseless_string(lwc_string *str) { - assert(ctx); assert(str); assert(str->insensitive == NULL); - return __lwc_context_intern(ctx, CSTR_OF(str), - str->len, &(str->insensitive), - lwc_calculate_lcase_hash, - lwc_lcase_strcmp, - lwc_lcase_memcpy); - + return __lwc_intern(CSTR_OF(str), + str->len, &(str->insensitive), + lwc_calculate_lcase_hash, + lwc_lcase_strncmp, + lwc_lcase_memcpy); } lwc_error -lwc_context_string_caseless_isequal(lwc_context *ctx, - lwc_string *str1, - lwc_string *str2, - bool *ret) +lwc_string_caseless_isequal(lwc_string *str1, + lwc_string *str2, + bool *ret) { lwc_error err; - assert(ctx); assert(str1); assert(str2); if (str1->insensitive == NULL) { - err = lwc_context_intern_caseless(ctx, str1); + err = lwc_intern_caseless_string(str1); if (err != lwc_error_ok) return err; } if (str2->insensitive == NULL) { - err = lwc_context_intern_caseless(ctx, str2); + err = lwc_intern_caseless_string(str2); if (err != lwc_error_ok) return err; } @@ -364,12 +313,3 @@ lwc_string_hash_value(lwc_string *str) return str->hash; } - -size_t -lwc_context_size(lwc_context *ctx) -{ - assert(ctx); - - return ctx->size; -} - -- cgit v1.2.3