From 1e2476627da6e343f9c646fc5e1a6bf179a991c0 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Thu, 29 Mar 2012 12:27:43 +0000 Subject: Rework the majority of wapcaplet's interface to be macros. This removes *many* function call overheads but does require GNUish braced-group expressions. svn path=/trunk/libwapcaplet/; revision=13777 --- include/libwapcaplet/libwapcaplet.h | 95 ++++++++++++++++++++++++++++++------- src/libwapcaplet.c | 81 +------------------------------ 2 files changed, 79 insertions(+), 97 deletions(-) diff --git a/include/libwapcaplet/libwapcaplet.h b/include/libwapcaplet/libwapcaplet.h index 212b928..47d93a6 100644 --- a/include/libwapcaplet/libwapcaplet.h +++ b/include/libwapcaplet/libwapcaplet.h @@ -19,10 +19,32 @@ extern "C" #include /** - * An interned string. + * The type of a reference counter used in libwapcaplet. + */ +typedef uint32_t lwc_refcounter; + +/** + * The type of a hash value used in libwapcaplet. */ -typedef struct lwc_string_s lwc_string; +typedef uint32_t lwc_hash; +/** + * An interned string. + * + * NOTE: The contents of this struct are considered *PRIVATE* and may + * change in future revisions. Do not rely on them whatsoever. + * They're only here at all so that the ref, unref and matches etc can + * use them. + */ +typedef struct lwc_string_s { + struct lwc_string_s ** prevptr; + struct lwc_string_s * next; + size_t len; + lwc_hash hash; + lwc_refcounter refcnt; + struct lwc_string_s * insensitive; +} lwc_string; + /** * String iteration function * @@ -40,11 +62,6 @@ typedef enum lwc_error_e { lwc_error_range = 2 /**< Substring internment out of range. */ } lwc_error; -/** - * The type of a hash value used in libwapcaplet. - */ -typedef uint32_t lwc_hash; - /** * Intern a string. * @@ -104,7 +121,7 @@ extern lwc_error lwc_intern_substring(lwc_string *str, * @note Use this if copying the string and intending both sides to retain * ownership. */ -extern lwc_string *lwc_string_ref(lwc_string *str); +#define lwc_string_ref(str) ({lwc_string *__lwc_s = (str); __lwc_s->refcnt++; __lwc_s;}) /** * Release a reference on an lwc_string. @@ -112,13 +129,27 @@ extern lwc_string *lwc_string_ref(lwc_string *str); * This decreases the reference count on the given ::lwc_string. * * @param str The string to unref. - * @return The result of the operation, if not OK then the string - * was not unreffed. * * @note If the reference count reaches zero then the string will be - * freed. + * freed. (Ref count of 1 where string is its own insensitve match + * will also result in the string being freed.) */ -extern void lwc_string_unref(lwc_string *str); +#define lwc_string_unref(str) { \ + lwc_string *__lwc_s = (str); \ + __lwc_s->refcnt--; \ + if ((__lwc_s->refcnt == 0) || \ + ((__lwc_s->refcnt == 1) && (__lwc_s->insensitive == __lwc_s))) \ + lwc_string_destroy(__lwc_s); \ + } + +/** + * Destroy an unreffed lwc_string. + * + * This destroys an lwc_string whose reference count indicates that it should be. + * + * @param str The string to unref. + */ +extern void lwc_string_destroy(lwc_string *str); /** * Check if two interned strings are equal. @@ -141,9 +172,37 @@ extern void lwc_string_unref(lwc_string *str); * @return Result of operation, if not ok then value pointed to * by \a ret will not be valid. */ -extern lwc_error lwc_string_caseless_isequal(lwc_string *str1, - lwc_string *str2, - bool *ret); +#define lwc_string_caseless_isequal(_str1,_str2,_ret) ({ \ + lwc_error __lwc_err = lwc_error_ok; \ + lwc_string *__lwc_str1 = (_str1); \ + lwc_string *__lwc_str2 = (_str2); \ + bool *__lwc_ret = (_ret); \ + \ + if (__lwc_str1->insensitive == NULL) { \ + __lwc_err = lwc__intern_caseless_string(__lwc_str1); \ + } \ + if (__lwc_err == lwc_error_ok && __lwc_str2->insensitive == NULL) { \ + __lwc_err = lwc__intern_caseless_string(__lwc_str2); \ + } \ + if (__lwc_err == lwc_error_ok) \ + *__lwc_ret = (__lwc_str1->insensitive == __lwc_str2->insensitive); \ + __lwc_err; \ + }) + +/** + * Intern a caseless copy of the passed string. + * + * @param str The string to intern the caseless copy of. + * + * @return lwc_error_ok if successful, otherwise the + * error code describing the issue., + * + * @note This is for "internal" use by the caseless comparison + * macro and not for users. + */ +extern lwc_error +lwc__intern_caseless_string(lwc_string *str); + /** * Retrieve the data pointer for an interned string. * @@ -156,7 +215,7 @@ extern lwc_error lwc_string_caseless_isequal(lwc_string *str1, * in future. Any code relying on it currently should be * modified to use ::lwc_string_length if possible. */ -extern const char *lwc_string_data(const lwc_string *str); +#define lwc_string_data(str) ((const char *)((str)+1)) /** * Retrieve the data length for an interned string. @@ -164,7 +223,7 @@ extern const char *lwc_string_data(const lwc_string *str); * @param str The string to retrieve the length of. * @return The length of \a str. */ -extern size_t lwc_string_length(const lwc_string *str); +#define lwc_string_length(str) ((str)->len) /** * Retrieve (or compute if unavailable) a hash value for the content of the string. @@ -178,7 +237,7 @@ extern size_t lwc_string_length(const lwc_string *str); * to be stable between invocations of the program. Never use the hash * value as a way to directly identify the value of the string. */ -extern uint32_t lwc_string_hash_value(lwc_string *str); +#define lwc_string_hash_value(str) ((str)->hash) /** * Iterate the context and return every string in it. diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c index 5ae655a..bd20abc 100644 --- a/src/libwapcaplet.c +++ b/src/libwapcaplet.c @@ -16,8 +16,6 @@ #define UNUSED(x) ((x) = (x)) #endif -typedef uint32_t lwc_refcounter; - static inline lwc_hash lwc__calculate_hash(const char *str, size_t len) { @@ -33,15 +31,6 @@ lwc__calculate_hash(const char *str, size_t len) return z; } -struct lwc_string_s { - lwc_string ** prevptr; - lwc_string * next; - size_t len; - lwc_hash hash; - lwc_refcounter refcnt; - lwc_string * insensitive; -}; - #define STR_OF(str) ((char *)(str + 1)) #define CSTR_OF(str) ((const char *)(str + 1)) @@ -174,27 +163,11 @@ lwc_intern_substring(lwc_string *str, return lwc_intern_string(CSTR_OF(str) + ssoffset, sslen, ret); } -lwc_string * -lwc_string_ref(lwc_string *str) -{ - assert(str); - - str->refcnt++; - - return str; -} - void -lwc_string_unref(lwc_string *str) +lwc_string_destroy(lwc_string *str) { assert(str); - if (--(str->refcnt) > 1) - return; - - if ((str->refcnt == 1) && (str->insensitive != str)) - return; - *(str->prevptr) = str->next; if (str->next != NULL) @@ -254,7 +227,7 @@ lwc__lcase_memcpy(char *target, const char *source, size_t n) } } -static lwc_error +lwc_error lwc__intern_caseless_string(lwc_string *str) { assert(str); @@ -267,56 +240,6 @@ lwc__intern_caseless_string(lwc_string *str) lwc__lcase_memcpy); } -lwc_error -lwc_string_caseless_isequal(lwc_string *str1, - lwc_string *str2, - bool *ret) -{ - lwc_error err; - assert(str1); - assert(str2); - - if (str1->insensitive == NULL) { - err = lwc__intern_caseless_string(str1); - if (err != lwc_error_ok) - return err; - } - if (str2->insensitive == NULL) { - err = lwc__intern_caseless_string(str2); - if (err != lwc_error_ok) - return err; - } - - *ret = (str1->insensitive == str2->insensitive); - return lwc_error_ok; -} - -/**** Simple accessors ****/ - -const char * -lwc_string_data(const lwc_string *str) -{ - assert(str); - - return CSTR_OF(str); -} - -size_t -lwc_string_length(const lwc_string *str) -{ - assert(str); - - return str->len; -} - -uint32_t -lwc_string_hash_value(lwc_string *str) -{ - assert(str); - - return str->hash; -} - /**** Iteration ****/ void -- cgit v1.2.1