From c1eabb7ee738b17cf6fd66e761a9269cb7582434 Mon Sep 17 00:00:00 2001 From: Liong Sauw Ming Date: Wed, 18 Jul 2012 07:52:33 +0000 Subject: Fixed #1556: Fix From/To tag and Via branch comparison to be case insensitive git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4208 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/include/pj/guid.h | 19 ++++++++++ pjlib/include/pj/hash.h | 38 ++++++++++++++++++-- pjlib/src/pj/guid.c | 21 +++++++++++ pjlib/src/pj/hash.c | 96 +++++++++++++++++++++++++++++++++---------------- 4 files changed, 141 insertions(+), 33 deletions(-) (limited to 'pjlib') diff --git a/pjlib/include/pj/guid.h b/pjlib/include/pj/guid.h index 96a5849e..7b24dd51 100644 --- a/pjlib/include/pj/guid.h +++ b/pjlib/include/pj/guid.h @@ -82,6 +82,17 @@ PJ_DECL(unsigned) pj_GUID_STRING_LENGTH(void); */ PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str); +/** + * Create a globally unique string in lowercase, which length is + * PJ_GUID_STRING_LENGTH characters. Caller is responsible for preallocating + * the storage used in the string. + * + * @param str The string to store the result. + * + * @return The string. + */ +PJ_DECL(pj_str_t*) pj_generate_unique_string_lower(pj_str_t *str); + /** * Generate a unique string. * @@ -90,6 +101,14 @@ PJ_DECL(pj_str_t*) pj_generate_unique_string(pj_str_t *str); */ PJ_DECL(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str); +/** + * Generate a unique string in lowercase. + * + * @param pool Pool to allocate memory from. + * @param str The string. + */ +PJ_DECL(void) pj_create_unique_string_lower(pj_pool_t *pool, pj_str_t *str); + /** * @} diff --git a/pjlib/include/pj/hash.h b/pjlib/include/pj/hash.h index 7b9f6df3..35c34137 100644 --- a/pjlib/include/pj/hash.h +++ b/pjlib/include/pj/hash.h @@ -75,8 +75,8 @@ PJ_DECL(pj_uint32_t) pj_hash_calc(pj_uint32_t hval, * string is stored in \c result. * * @param hval The initial hash value, normally zero. - * @param result Buffer to store the result, which must be enough to hold - * the string. + * @param result Optional. Buffer to store the result, which must be enough + * to hold the string. * @param key The input key to be converted and calculated. * * @return The hash value. @@ -115,6 +115,17 @@ PJ_DECL(void *) pj_hash_get( pj_hash_table_t *ht, pj_uint32_t *hval ); +/** + * Variant of #pj_hash_get() with the key being converted to lowercase when + * calculating the hash value. + * + * @see pj_hash_get() + */ +PJ_DECL(void *) pj_hash_get_lower( pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t *hval ); + + /** * Associate/disassociate a value with the specified key. If value is not * NULL and entry already exists, the entry's value will be overwritten. @@ -141,6 +152,17 @@ PJ_DECL(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, void *value ); +/** + * Variant of #pj_hash_set() with the key being converted to lowercase when + * calculating the hash value. + * + * @see pj_hash_set() + */ +PJ_DECL(void) pj_hash_set_lower( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, void *value ); + + /** * Associate/disassociate a value with the specified key. This function works * like #pj_hash_set(), except that it doesn't use pool (hence the np -- no @@ -164,6 +186,18 @@ PJ_DECL(void) pj_hash_set_np(pj_hash_table_t *ht, pj_uint32_t hval, pj_hash_entry_buf entry_buf, void *value); +/** + * Variant of #pj_hash_set_np() with the key being converted to lowercase + * when calculating the hash value. + * + * @see pj_hash_set_np() + */ +PJ_DECL(void) pj_hash_set_np_lower(pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, + pj_hash_entry_buf entry_buf, + void *value); + /** * Get the total number of entries in the hash table. * diff --git a/pjlib/src/pj/guid.c b/pjlib/src/pj/guid.c index 1ed9515c..c16a7ce0 100644 --- a/pjlib/src/pj/guid.c +++ b/pjlib/src/pj/guid.c @@ -17,11 +17,32 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include +PJ_DEF(pj_str_t*) pj_generate_unique_string_lower(pj_str_t *str) +{ + int i; + + pj_generate_unique_string(str); + for (i = 0; i < str->slen; i++) + str->ptr[i] = (char)pj_tolower(str->ptr[i]); + + return str; +} + PJ_DEF(void) pj_create_unique_string(pj_pool_t *pool, pj_str_t *str) { str->ptr = (char*)pj_pool_alloc(pool, PJ_GUID_STRING_LENGTH); pj_generate_unique_string(str); } + +PJ_DEF(void) pj_create_unique_string_lower(pj_pool_t *pool, pj_str_t *str) +{ + int i; + + pj_create_unique_string(pool, str); + for (i = 0; i < str->slen; i++) + str->ptr[i] = (char)pj_tolower(str->ptr[i]); +} diff --git a/pjlib/src/pj/hash.c b/pjlib/src/pj/hash.c index d22bf421..7ad339be 100644 --- a/pjlib/src/pj/hash.c +++ b/pjlib/src/pj/hash.c @@ -79,16 +79,21 @@ PJ_DEF(pj_uint32_t) pj_hash_calc_tolower( pj_uint32_t hval, #if defined(PJ_HASH_USE_OWN_TOLOWER) && PJ_HASH_USE_OWN_TOLOWER != 0 for (i=0; islen; ++i) { pj_uint8_t c = key->ptr[i]; + char lower; if (c & 64) - result[i] = (char)(c | 32); + lower = (char)(c | 32); else - result[i] = (char)c; - hval = hval * PJ_HASH_MULTIPLIER + result[i]; + lower = (char)c; + if (result) + result[i] = lower; + hval = hval * PJ_HASH_MULTIPLIER + lower; } #else for (i=0; islen; ++i) { - result[i] = (char)pj_tolower(key->ptr[i]); - hval = hval * PJ_HASH_MULTIPLIER + result[i]; + char lower = (char)pj_tolower(key->ptr[i]); + if (result) + result[i] = lower; + hval = hval * PJ_HASH_MULTIPLIER + lower; } #endif @@ -128,7 +133,7 @@ PJ_DEF(pj_hash_table_t*) pj_hash_create(pj_pool_t *pool, unsigned size) static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, const void *key, unsigned keylen, void *val, pj_uint32_t *hval, - void *entry_buf) + void *entry_buf, pj_bool_t lower) { pj_uint32_t hash; pj_hash_entry **p_entry, *entry; @@ -146,14 +151,20 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, if (keylen==PJ_HASH_KEY_STRING) { const pj_uint8_t *p = (const pj_uint8_t*)key; for ( ; *p; ++p ) { - hash = hash * PJ_HASH_MULTIPLIER + *p; + if (lower) + hash = hash * PJ_HASH_MULTIPLIER + pj_tolower(*p); + else + hash = hash * PJ_HASH_MULTIPLIER + *p; } keylen = p - (const unsigned char*)key; } else { const pj_uint8_t *p = (const pj_uint8_t*)key, *end = p + keylen; for ( ; p!=end; ++p) { - hash = hash * PJ_HASH_MULTIPLIER + *p; + if (lower) + hash = hash * PJ_HASH_MULTIPLIER + pj_tolower(*p); + else + hash = hash * PJ_HASH_MULTIPLIER + *p; } } @@ -167,8 +178,15 @@ static pj_hash_entry **find_entry( pj_pool_t *pool, pj_hash_table_t *ht, entry; p_entry = &entry->next, entry = *p_entry) { + pj_str_t str; + + if (lower) { + str.ptr = (char *)entry->key; + str.slen = keylen; + } if (entry->hash==hash && entry->keylen==keylen && - pj_memcmp(entry->key, key, keylen)==0) + ((lower && pj_strnicmp2(&str, (const char *)key, keylen)==0) || + (!lower && pj_memcmp(entry->key, key, keylen)==0))) { break; } @@ -214,17 +232,27 @@ PJ_DEF(void *) pj_hash_get( pj_hash_table_t *ht, pj_uint32_t *hval) { pj_hash_entry *entry; - entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL); + entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL, PJ_FALSE); return entry ? entry->value : NULL; } -PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, - const void *key, unsigned keylen, pj_uint32_t hval, - void *value ) +PJ_DEF(void *) pj_hash_get_lower( pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t *hval) +{ + pj_hash_entry *entry; + entry = *find_entry( NULL, ht, key, keylen, NULL, hval, NULL, PJ_TRUE); + return entry ? entry->value : NULL; +} + +static void hash_set( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, pj_uint32_t hval, + void *value, void *entry_buf, pj_bool_t lower ) { pj_hash_entry **p_entry; - p_entry = find_entry( pool, ht, key, keylen, value, &hval, NULL); + p_entry = find_entry( pool, ht, key, keylen, value, &hval, entry_buf, + lower); if (*p_entry) { if (value == NULL) { /* delete entry */ @@ -241,29 +269,35 @@ PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, } } +PJ_DEF(void) pj_hash_set( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, pj_uint32_t hval, + void *value ) +{ + hash_set(pool, ht, key, keylen, hval, value, NULL, PJ_FALSE); +} + +PJ_DEF(void) pj_hash_set_lower( pj_pool_t *pool, pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, void *value ) +{ + hash_set(pool, ht, key, keylen, hval, value, NULL, PJ_TRUE); +} + PJ_DEF(void) pj_hash_set_np( pj_hash_table_t *ht, const void *key, unsigned keylen, pj_uint32_t hval, pj_hash_entry_buf entry_buf, void *value) { - pj_hash_entry **p_entry; + hash_set(NULL, ht, key, keylen, hval, value, (void *)entry_buf, PJ_FALSE); +} - p_entry = find_entry( NULL, ht, key, keylen, value, &hval, - (void*)entry_buf ); - if (*p_entry) { - if (value == NULL) { - /* delete entry */ - PJ_LOG(6, ("hashtbl", "%p: p_entry %p deleted", ht, *p_entry)); - *p_entry = (*p_entry)->next; - --ht->count; - - } else { - /* overwrite */ - (*p_entry)->value = value; - PJ_LOG(6, ("hashtbl", "%p: p_entry %p value set to %p", ht, - *p_entry, value)); - } - } +PJ_DEF(void) pj_hash_set_np_lower( pj_hash_table_t *ht, + const void *key, unsigned keylen, + pj_uint32_t hval, + pj_hash_entry_buf entry_buf, + void *value) +{ + hash_set(NULL, ht, key, keylen, hval, value, (void *)entry_buf, PJ_TRUE); } PJ_DEF(unsigned) pj_hash_count( pj_hash_table_t *ht ) -- cgit v1.2.3