Added SILC Rand API, SILC Global Variables API and silcruntime.h.in
[runtime.git] / lib / silcutil / silchashtable.c
index dd59263fa85dfcfa9af8b0954ec33f5a525b003f..7c3d7cbfbad5b899de73eec3c1673a251b6c68d3 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2007 Pekka Riikonen
+  Copyright (C) 2001 - 2008 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
    However, this is reliable and no data is lost at any point. If you know
    that you never have duplicate keys then this is as fast as any simple
    hash table. */
-/* $Id$ */
 
-#include "silc.h"
-#include "silchashtable.h"
+#include "silcruntime.h"
 
 /* Define to 1 if you want hash table debug enabled */
 #define SILC_HASH_TABLE_DEBUG 0
@@ -362,8 +360,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 +491,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 +539,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 +586,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 +637,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 +703,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 +746,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 +986,144 @@ 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);
+}
+
+/* Generic destructor */
+
+void silc_hash_destructor(void *key, void *context, void *user_context)
+{
+  silc_free(key);
+  silc_free(context);
+}