Added SILC Thread Queue API
[silc.git] / lib / silcutil / silchashtable.c
index dd59263fa85dfcfa9af8b0954ec33f5a525b003f..13c655e792160a6af32414ee3c2d65784fc6848e 100644 (file)
@@ -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);
+}