X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilchashtable.c;h=13c655e792160a6af32414ee3c2d65784fc6848e;hb=e7b6c157b80152bf9fb9266e6bdd93f9fb0db776;hp=dd59263fa85dfcfa9af8b0954ec33f5a525b003f;hpb=e8504852258db5a63e542246b64c23f8b8624006;p=silc.git diff --git a/lib/silcutil/silchashtable.c b/lib/silcutil/silchashtable.c index dd59263f..13c655e7 100644 --- a/lib/silcutil/silchashtable.c +++ b/lib/silcutil/silchashtable.c @@ -362,8 +362,10 @@ SilcHashTable silc_hash_table_alloc(SilcStack stack, SilcHashTable ht; SilcUInt32 size_index = SILC_HASH_TABLE_SIZE; - if (!hash) + if (!hash) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return NULL; + } if (stack) stack = silc_stack_alloc(0, stack); @@ -491,8 +493,10 @@ SilcBool silc_hash_table_del(SilcHashTable ht, void *key) entry = silc_hash_table_find_internal(ht, key, &prev, ht->hash, ht->hash_user_context, ht->compare, ht->compare_user_context); - if (*entry == NULL) + if (*entry == NULL) { + silc_set_errno(SILC_ERR_NOT_FOUND); return FALSE; + } e = *entry; @@ -537,8 +541,10 @@ SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key, compare_user_context ? compare_user_context : ht->compare_user_context); - if (*entry == NULL) + if (*entry == NULL) { + silc_set_errno(SILC_ERR_NOT_FOUND); return FALSE; + } e = *entry; @@ -582,8 +588,10 @@ SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key, ht->hash_user_context, ht->compare, ht->compare_user_context); - if (*entry == NULL) + if (*entry == NULL) { + silc_set_errno(SILC_ERR_NOT_FOUND); return FALSE; + } e = *entry; @@ -631,8 +639,10 @@ SilcBool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key, compare_user_context ? compare_user_context : ht->compare_user_context); - if (*entry == NULL) + if (*entry == NULL) { + silc_set_errno(SILC_ERR_NOT_FOUND); return FALSE; + } e = *entry; @@ -695,8 +705,10 @@ SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key, compare_user_context ? compare_user_context : ht->compare_user_context); - if (*entry == NULL) + if (*entry == NULL) { + silc_set_errno(SILC_ERR_NOT_FOUND); return FALSE; + } if (ret_key) *ret_key = (*entry)->key; @@ -736,8 +748,10 @@ SilcBool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key, compare_user_context ? compare_user_context : ht->compare_user_context); - if (!entry || !(*entry)) + if (!entry || !(*entry)) { + silc_set_errno(SILC_ERR_NOT_FOUND); return FALSE; + } if (ret_key) *ret_key = (*entry)->key; @@ -974,3 +988,136 @@ SilcBool silc_hash_table_get(SilcHashTableList *htl, void **key, return TRUE; } + +/**************************** Utility functions *****************************/ + +/* Case sensitive hashing */ + +SilcUInt32 silc_hash_string(void *key, void *user_context) +{ + char *s = (char *)key; + SilcUInt32 h = 0; + + while (*s != '\0') { + h += *s++; + h += (h << 10); + h ^= (h >> 6); + } + + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + + return h; +} + +/* Case-insensitive hashing */ + +SilcUInt32 silc_hash_string_case(void *key, void *user_context) +{ + char *s = (char *)key; + SilcUInt32 h = 0; + + while (*s != '\0') { + h += tolower((int)*s); + h += (h << 10); + h ^= (h >> 6); + s++; + } + + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + + return h; +} + +/* Hash UTF-8 string */ + +SilcUInt32 silc_hash_utf8_string(void *key, void *user_context) +{ + char *s = (char *)key; + SilcUInt32 h = 0; + + while (*s != '\0') { + h += *s++; + h += (h << 10); + h ^= (h >> 6); + } + + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + + return h; +} + +/* Basic hash function to hash integers. */ + +SilcUInt32 silc_hash_uint(void *key, void *user_context) +{ + return SILC_PTR_TO_32(key); +} + +/* Basic hash funtion to hash pointers. */ + +SilcUInt32 silc_hash_ptr(void *key, void *user_context) +{ + return SILC_PTR_TO_32(key); +} + +/* Hash binary data. The `user_context' is the data length. */ + +SilcUInt32 silc_hash_data(void *key, void *user_context) +{ + SilcUInt32 len = SILC_PTR_TO_32(user_context), h, i; + unsigned char *data = (char *)key; + + h = (data[0] * data[len - 1] + 1) * len; + + for (i = 0; i < len; i++) { + h += data[i]; + h += (h << 10); + h ^= (h >> 6); + } + + h += (h << 3); + h ^= (h >> 11); + h += (h << 15); + + return h; +} + +/* Compares two strings. */ + +SilcBool silc_hash_string_compare(void *key1, void *key2, void *user_context) +{ + return !strcmp((char *)key1, (char *)key2); +} + +/* Compares two strings, ignores case. */ + +SilcBool silc_hash_string_case_compare(void *key1, void *key2, + void *user_context) +{ + return !strcasecmp((char *)key1, (char *)key2); +} + +/* Compares binary data. */ + +SilcBool silc_hash_data_compare(void *key1, void *key2, void *user_context) +{ + SilcUInt32 len = SILC_PTR_TO_32(user_context); + return !memcmp(key1, key2, len); +} + +/* Compares UTF-8 string. */ + +SilcBool silc_hash_utf8_compare(void *key1, void *key2, void *user_context) +{ + int l1 = strlen((char *)key1); + int l2 = strlen((char *)key2); + if (l1 != l2) + return FALSE; + return !memcmp(key1, key2, l2); +}