Created SILC Crypto Toolkit git repository.
[crypto.git] / lib / silcutil / silchashtable.c
diff --git a/lib/silcutil/silchashtable.c b/lib/silcutil/silchashtable.c
deleted file mode 100644 (file)
index 13c655e..0000000
+++ /dev/null
@@ -1,1123 +0,0 @@
-/*
-
-  silchashtable.c
-
-  Author: Pekka Riikonen <priikone@silcnet.org>
-
-  Copyright (C) 2001 - 2007 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
-  the Free Software Foundation; version 2 of the License.
-
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-*/
-/* Implementation of collision resistant hash table. This is a hash table
-   that provides a reliable (what you add stays there, and duplicate keys
-   are allowed) with as fast reference to the key as possible. If duplicate
-   keys are a lot in the hash table the lookup gets slower of course.
-   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"
-
-/* Define to 1 if you want hash table debug enabled */
-#define SILC_HASH_TABLE_DEBUG 0
-
-#if SILC_HASH_TABLE_DEBUG == 1
-#define SILC_HT_DEBUG(fmt) SILC_LOG_DEBUG(fmt)
-#else
-#define SILC_HT_DEBUG(fmt)
-#endif
-
-/* Default size of the hash table (index to prime table) */
-#define SILC_HASH_TABLE_SIZE 2
-
-/* Produce the index by hashing the key */
-#define SILC_HASH_TABLE_HASH(f, c) \
-  ((f)(key, (c)) % primesize[ht->table_size])
-
-/* Check whether need to rehash */
-#define SILC_HASH_REHASH_INC \
-  (ht->auto_rehash && (ht->entry_count / 2) > primesize[ht->table_size])
-#define SILC_HASH_REHASH_DEC \
-  (ht->auto_rehash && (ht->entry_count * 2) < primesize[ht->table_size] && \
-   ht->entry_count > primesize[SILC_HASH_TABLE_SIZE])
-
-/* One entry in the hash table. Includes the key and the associated
-   context. The `next' pointer is non-NULL if two (or more) different
-   keys hashed to same value.  The pointer is the pointer to the next
-   entry. */
-typedef struct SilcHashTableEntryStruct {
-  void *key;
-  void *context;
-  struct SilcHashTableEntryStruct *next;
-} *SilcHashTableEntry;
-
-/* Hash table. */
-struct SilcHashTableStruct {
-  SilcStack stack;
-  SilcHashTableEntry *table;
-  SilcUInt32 table_size;
-  SilcUInt32 entry_count;
-  SilcHashFunction hash;
-  SilcHashCompare compare;
-  SilcHashDestructor destructor;
-  void *hash_user_context;
-  void *compare_user_context;
-  void *destructor_user_context;
-  unsigned int auto_rehash : 1;
-};
-
-/* Prime sizes for the hash table. The size of the table will always
-   be one of these. */
-const SilcUInt32 primesize[] =
-{
-  3, 5, 11, 17, 37, 67, 109, 131, 163, 257, 367, 521, 823, 1031,
-  1237, 1447, 2053, 2389, 2777, 3323, 4099, 5059, 6247, 7001, 8209, 10993,
-  14057, 16411, 19181, 21089, 25033, 32771, 40009, 47431, 65537, 106721,
-  131101, 262147, 360163, 524309, 810343, 1048583, 2097169, 4194319,
-  6153409, 8388617, 13845163, 16777259, 33554467, 67108879
-};
-
-/* Find appropriate size for the hash table. The size will be a prime. */
-
-static SilcUInt32 silc_hash_table_primesize(SilcUInt32 size, SilcUInt32 *index)
-{
-  int i;
-
-  for (i = 0; i < sizeof(primesize) / sizeof(primesize[0]); i++)
-    if (primesize[i] >= size) {
-      *index = i;
-      SILC_HT_DEBUG(("sizeof of the hash table is %d", primesize[*index]));
-      return primesize[i];
-    }
-
-  *index = i - 1;
-  SILC_HT_DEBUG(("sizeof of the hash table is %d", primesize[*index]));
-  return primesize[i - 1];
-}
-
-/* Internal routine to find entry in the hash table by `key'. Returns
-   the previous entry (if exists) as well. */
-
-static inline SilcHashTableEntry *
-silc_hash_table_find_internal(SilcHashTable ht, void *key,
-                             SilcHashTableEntry *prev_entry,
-                             SilcHashFunction hash, void *hash_user_context,
-                             SilcHashCompare compare,
-                             void *compare_user_context)
-{
-  SilcHashTableEntry *entry, prev = NULL;
-  SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
-
-  SILC_HT_DEBUG(("index %d key %p", i, key));
-
-  entry = &ht->table[i];
-  if (compare) {
-    while (*entry && !compare((*entry)->key, key, compare_user_context)) {
-      prev = *entry;
-      entry = &(*entry)->next;
-    }
-  } else {
-    while (*entry && (*entry)->key != key) {
-      prev = *entry;
-      entry = &(*entry)->next;
-    }
-  }
-
-  *prev_entry = prev;
-  return entry;
-}
-
-/* Internal routine to find entry in the hash table by `key' and `context'.
-   Returns the previous entry (if exists) as well to `prev_entry'. */
-
-static inline SilcHashTableEntry *
-silc_hash_table_find_internal_context(SilcHashTable ht, void *key,
-                                     void *context,
-                                     SilcHashTableEntry *prev_entry,
-                                     SilcHashFunction hash,
-                                     void *hash_user_context,
-                                     SilcHashCompare compare,
-                                     void *compare_user_context)
-{
-  SilcHashTableEntry *entry, prev = NULL;
-  SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
-
-  SILC_HT_DEBUG(("index %d key %p context %p", i, key, context));
-
-  entry = &ht->table[i];
-  if (ht->compare) {
-    while (*entry) {
-      if (compare((*entry)->key, key, compare_user_context) &&
-         (*entry)->context == context)
-       break;
-      prev = *entry;
-      entry = &(*entry)->next;
-    }
-  } else {
-    while (*entry) {
-      if ((*entry)->key == key && (*entry)->context == context)
-       break;
-      prev = *entry;
-      entry = &(*entry)->next;
-    }
-  }
-
-  if (prev_entry)
-    *prev_entry = prev;
-  return entry;
-}
-
-/* Internal routine to find entry in the hash table by `key'. */
-
-static inline SilcHashTableEntry *
-silc_hash_table_find_internal_simple(SilcHashTable ht, void *key,
-                                    SilcHashFunction hash,
-                                    void *hash_user_context,
-                                    SilcHashCompare compare,
-                                    void *compare_user_context)
-{
-  SilcHashTableEntry *entry;
-  SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
-
-  SILC_HT_DEBUG(("index %d key %p", i, key));
-
-  entry = &ht->table[i];
-  if (compare) {
-    while (*entry && !compare((*entry)->key, key, compare_user_context))
-      entry = &(*entry)->next;
-  } else {
-    while (*entry && (*entry)->key != key)
-      entry = &(*entry)->next;
-  }
-
-  return entry;
-}
-
-/* Internal routine to find all keys by `key'. This may return multiple
-   entries if multiple entries with same key exists. With specific
-   hash and comparison functions. */
-
-static inline void
-silc_hash_table_find_internal_all(SilcHashTable ht, void *key,
-                                 SilcHashFunction hash,
-                                 void *hash_user_context,
-                                 SilcHashCompare compare,
-                                 void *compare_user_context,
-                                 SilcHashForeach foreach,
-                                 void *foreach_user_context)
-{
-  SilcHashTableEntry e, tmp;
-  SilcBool auto_rehash, found = FALSE;
-  SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
-
-  SILC_HT_DEBUG(("index %d key %p", i, key));
-
-  /* Disallow auto rehashing while going through the table since we call
-     the `foreach' function which could alter the table. */
-  auto_rehash = ht->auto_rehash;
-  ht->auto_rehash = FALSE;
-
-  e = ht->table[i];
-  if (compare) {
-    while (e) {
-      tmp = e->next;
-      if (compare(e->key, key, compare_user_context)) {
-       found = TRUE;
-       foreach(e->key, e->context, foreach_user_context);
-      }
-      e = tmp;
-    }
-  } else {
-    while (e) {
-      tmp = e->next;
-      if (e->key == key) {
-       found = TRUE;
-       foreach(e->key, e->context, foreach_user_context);
-      }
-      e = tmp;
-    }
-  }
-
-  /* If nothing was found call with NULL context the callback */
-  if (!found)
-    foreach(key, NULL, foreach_user_context);
-
-  ht->auto_rehash = auto_rehash;
-}
-
-/* Internal routine to add new key to the hash table */
-
-static inline SilcBool
-silc_hash_table_add_internal(SilcHashTable ht, void *key, void *context,
-                            SilcHashFunction hash,
-                            void *hash_user_context)
-{
-  SilcHashTableEntry *entry;
-  SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
-
-  SILC_HT_DEBUG(("index %d key %p", i, key));
-
-  entry = &ht->table[i];
-  if (*entry) {
-    /* The entry exists already. We have a collision, add it to the
-       list to avoid collision. */
-    SilcHashTableEntry e, tmp;
-
-    e = *entry;
-    tmp = e->next;
-    while (tmp) {
-      e = tmp;
-      tmp = tmp->next;
-    }
-
-    SILC_HT_DEBUG(("Collision; adding new key to list"));
-
-    e->next = silc_scalloc(ht->stack, 1, sizeof(*e->next));
-    if (!e->next)
-      return FALSE;
-    e->next->key = key;
-    e->next->context = context;
-    ht->entry_count++;
-  } else {
-    /* New key */
-    SILC_HT_DEBUG(("New key"));
-    *entry = silc_scalloc(ht->stack, 1, sizeof(**entry));
-    if (!(*entry))
-      return FALSE;
-    (*entry)->key = key;
-    (*entry)->context = context;
-    ht->entry_count++;
-  }
-
-  if (SILC_HASH_REHASH_INC)
-    silc_hash_table_rehash(ht, 0);
-
-  return TRUE;
-}
-
-/* Internal routine to replace old key with new one (if it exists) */
-
-static inline SilcBool
-silc_hash_table_replace_internal(SilcHashTable ht, void *key, void *context,
-                                SilcHashFunction hash,
-                                void *hash_user_context)
-{
-  SilcHashTableEntry *entry;
-  SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
-
-  SILC_HT_DEBUG(("index %d key %p", i, key));
-
-  entry = &ht->table[i];
-  if (*entry) {
-    /* The entry exists already. We have a collision, replace the old
-       key and context. */
-    if (ht->destructor)
-      ht->destructor((*entry)->key, (*entry)->context,
-                    ht->destructor_user_context);
-  } else {
-    /* New key */
-    *entry = silc_scalloc(ht->stack, 1, sizeof(**entry));
-    if (!(*entry))
-      return FALSE;
-    ht->entry_count++;
-  }
-
-  (*entry)->key = key;
-  (*entry)->context = context;
-
-  if (SILC_HASH_REHASH_INC)
-    silc_hash_table_rehash(ht, 0);
-
-  return TRUE;
-}
-
-/* Allocates new hash table and returns it.  If the `table_size' is not
-   zero then the hash table size is the size provided. If zero then the
-   default size will be used. Note that if the `table_size' is provided
-   it should be a prime. The `hash', `compare' and `destructor' are
-   the hash function, the key comparison function and key and context
-   destructor function, respectively. The `hash' is mandatory, the others
-   are optional. */
-
-SilcHashTable silc_hash_table_alloc(SilcStack stack,
-                                   SilcUInt32 table_size,
-                                   SilcHashFunction hash,
-                                   void *hash_user_context,
-                                   SilcHashCompare compare,
-                                   void *compare_user_context,
-                                   SilcHashDestructor destructor,
-                                   void *destructor_user_context,
-                                   SilcBool auto_rehash)
-{
-  SilcHashTable ht;
-  SilcUInt32 size_index = SILC_HASH_TABLE_SIZE;
-
-  if (!hash) {
-    silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
-    return NULL;
-  }
-
-  if (stack)
-    stack = silc_stack_alloc(0, stack);
-
-  ht = silc_scalloc(stack, 1, sizeof(*ht));
-  if (!ht) {
-    silc_stack_free(stack);
-    return NULL;
-  }
-  ht->table = silc_scalloc(stack,
-                          table_size ? silc_hash_table_primesize(table_size,
-                                                                 &size_index) :
-                          primesize[SILC_HASH_TABLE_SIZE],
-                          sizeof(*ht->table));
-  if (!ht->table) {
-    silc_stack_free(stack);
-    silc_sfree(stack, ht);
-    return NULL;
-  }
-  ht->stack = stack;
-  ht->table_size = size_index;
-  ht->hash = hash;
-  ht->compare = compare;
-  ht->destructor = destructor;
-  ht->hash_user_context = hash_user_context;
-  ht->compare_user_context = compare_user_context;
-  ht->destructor_user_context = destructor_user_context;
-  ht->auto_rehash = auto_rehash;
-
-  return ht;
-}
-
-/* Frees the hash table. The destructor function provided in the
-   silc_hash_table_alloc will be called for all keys in the hash table. */
-
-void silc_hash_table_free(SilcHashTable ht)
-{
-  SilcStack stack = ht->stack;
-  SilcHashTableEntry e, tmp;
-  int i;
-
-  for (i = 0; i < primesize[ht->table_size]; i++) {
-    e = ht->table[i];
-    while (e) {
-      if (ht->destructor)
-       ht->destructor(e->key, e->context, ht->destructor_user_context);
-      tmp = e;
-      e = e->next;
-      silc_sfree(stack, tmp);
-    }
-  }
-
-  silc_sfree(stack, ht->table);
-  silc_sfree(stack, ht);
-  silc_stack_free(stack);
-}
-
-/* Returns the size of the hash table */
-
-SilcUInt32 silc_hash_table_size(SilcHashTable ht)
-{
-  return primesize[ht->table_size];
-}
-
-/* Returns the number of the entires in the hash table. If there is more
-   entries in the table thatn the size of the hash table calling the
-   silc_hash_table_rehash is recommended. */
-
-SilcUInt32 silc_hash_table_count(SilcHashTable ht)
-{
-  return ht->entry_count;
-}
-
-/* Adds new entry to the hash table. The `key' is hashed using the
-   hash function and the both `key' and `context' will be saved to the
-   hash table. This function quarantees that the entry is always added
-   to the hash table reliably (it is collision resistant). */
-
-SilcBool silc_hash_table_add(SilcHashTable ht, void *key, void *context)
-{
-  return silc_hash_table_add_internal(ht, key, context, ht->hash,
-                                     ht->hash_user_context);
-}
-
-/* Same as above but with specific hash function and user context. */
-
-SilcBool silc_hash_table_add_ext(SilcHashTable ht, void *key, void *context,
-                                SilcHashFunction hash,
-                                void *hash_user_context)
-{
-  return silc_hash_table_add_internal(ht, key, context,
-                                     hash, hash_user_context);
-}
-
-/* Same as above but if the `key' already exists in the hash table
-   the old key and the old context will be replace with the `key' and
-   the `context. The destructor function will be called for the
-   replaced key and context. */
-
-SilcBool silc_hash_table_set(SilcHashTable ht, void *key, void *context)
-{
-  return silc_hash_table_replace_internal(ht, key, context, ht->hash,
-                                         ht->hash_user_context);
-}
-
-/* Same as above but with specific hash function. */
-
-SilcBool silc_hash_table_set_ext(SilcHashTable ht, void *key,
-                                void *context,
-                                SilcHashFunction hash,
-                                void *hash_user_context)
-{
-  return silc_hash_table_replace_internal(ht, key, context,
-                                         hash, hash_user_context);
-}
-
-/* Removes the entry from the hash table by the provided `key'. This will
-   call the destructor funtion for the found entry. Return TRUE if the
-   entry was removed successfully and FALSE otherwise. */
-
-SilcBool silc_hash_table_del(SilcHashTable ht, void *key)
-{
-  SilcHashTableEntry *entry, prev, e;
-
-  entry = silc_hash_table_find_internal(ht, key, &prev,
-                                       ht->hash, ht->hash_user_context,
-                                       ht->compare, ht->compare_user_context);
-  if (*entry == NULL) {
-    silc_set_errno(SILC_ERR_NOT_FOUND);
-    return FALSE;
-  }
-
-  e = *entry;
-
-  if (!prev && e->next)
-    *entry = e->next;
-  if (!prev && e->next == NULL)
-    *entry = NULL;
-  if (prev)
-    prev->next = NULL;
-  if (prev && e->next)
-    prev->next = e->next;
-
-  if (ht->destructor)
-    ht->destructor(e->key, e->context, ht->destructor_user_context);
-  silc_sfree(ht->stack, e);
-
-  ht->entry_count--;
-
-  if (SILC_HASH_REHASH_DEC)
-    silc_hash_table_rehash(ht, 0);
-
-  return TRUE;
-}
-
-/* Same as above but with specific hash and compare functions. */
-
-SilcBool silc_hash_table_del_ext(SilcHashTable ht, void *key,
-                                SilcHashFunction hash,
-                                void *hash_user_context,
-                                SilcHashCompare compare,
-                                void *compare_user_context,
-                                SilcHashDestructor destructor,
-                                void *destructor_user_context)
-{
-  SilcHashTableEntry *entry, prev, e;
-
-  entry = silc_hash_table_find_internal(ht, key, &prev,
-                                       hash ? hash : ht->hash,
-                                       hash_user_context ? hash_user_context :
-                                       ht->hash_user_context,
-                                       compare ? compare : ht->compare,
-                                       compare_user_context ?
-                                       compare_user_context :
-                                       ht->compare_user_context);
-  if (*entry == NULL) {
-    silc_set_errno(SILC_ERR_NOT_FOUND);
-    return FALSE;
-  }
-
-  e = *entry;
-
-  if (!prev && e->next)
-    *entry = e->next;
-  if (!prev && e->next == NULL)
-    *entry = NULL;
-  if (prev)
-    prev->next = NULL;
-  if (prev && e->next)
-    prev->next = e->next;
-
-  if (destructor) {
-    destructor(e->key, e->context, destructor_user_context);
-  } else {
-    if (ht->destructor)
-      ht->destructor(e->key, e->context, ht->destructor_user_context);
-  }
-  silc_sfree(ht->stack, e);
-
-  ht->entry_count--;
-
-  if (SILC_HASH_REHASH_DEC)
-    silc_hash_table_rehash(ht, 0);
-
-  return TRUE;
-}
-
-/* Same as above but verifies that the context associated with the `key'
-   matches the `context'. This is handy to use with hash tables that may
-   have duplicate keys. In that case the `context' may be used to check
-   whether the correct entry is being deleted. */
-
-SilcBool silc_hash_table_del_by_context(SilcHashTable ht, void *key,
-                                       void *context)
-{
-  SilcHashTableEntry *entry, prev, e;
-
-  entry = silc_hash_table_find_internal_context(ht, key, context, &prev,
-                                               ht->hash,
-                                               ht->hash_user_context,
-                                               ht->compare,
-                                               ht->compare_user_context);
-  if (*entry == NULL) {
-    silc_set_errno(SILC_ERR_NOT_FOUND);
-    return FALSE;
-  }
-
-  e = *entry;
-
-  if (!prev && e->next)
-    *entry = e->next;
-  if (!prev && e->next == NULL)
-    *entry = NULL;
-  if (prev)
-    prev->next = NULL;
-  if (prev && e->next)
-    prev->next = e->next;
-
-  if (ht->destructor)
-    ht->destructor(e->key, e->context, ht->destructor_user_context);
-  silc_sfree(ht->stack, e);
-
-  ht->entry_count--;
-
-  if (SILC_HASH_REHASH_DEC)
-    silc_hash_table_rehash(ht, 0);
-
-  return TRUE;
-}
-
-/* Same as above but with specific hash and compare functions. */
-
-SilcBool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
-                                           void *context,
-                                           SilcHashFunction hash,
-                                           void *hash_user_context,
-                                           SilcHashCompare compare,
-                                           void *compare_user_context,
-                                           SilcHashDestructor destructor,
-                                           void *destructor_user_context)
-{
-  SilcHashTableEntry *entry, prev, e;
-
-  entry = silc_hash_table_find_internal_context(ht, key, context, &prev,
-                                               hash ? hash : ht->hash,
-                                               hash_user_context ?
-                                               hash_user_context :
-                                               ht->hash_user_context,
-                                               compare ?
-                                               compare : ht->compare,
-                                               compare_user_context ?
-                                               compare_user_context :
-                                               ht->compare_user_context);
-  if (*entry == NULL) {
-    silc_set_errno(SILC_ERR_NOT_FOUND);
-    return FALSE;
-  }
-
-  e = *entry;
-
-  if (!prev && e->next)
-    *entry = e->next;
-  if (!prev && e->next == NULL)
-    *entry = NULL;
-  if (prev)
-    prev->next = NULL;
-  if (prev && e->next)
-    prev->next = e->next;
-
-  if (destructor) {
-    destructor(e->key, e->context, destructor_user_context);
-  } else {
-    if (ht->destructor)
-      ht->destructor(e->key, e->context, ht->destructor_user_context);
-  }
-  silc_sfree(ht->stack, e);
-
-  ht->entry_count--;
-
-  if (SILC_HASH_REHASH_DEC)
-    silc_hash_table_rehash(ht, 0);
-
-  return TRUE;
-}
-
-/* Finds the entry in the hash table by the provided `key' as fast as
-   possible. Return TRUE if the entry was found and FALSE otherwise.
-   The found entry is returned to the `ret_key' and `ret_context',
-   respectively. If the `ret_key and `ret_context' are NULL then this
-   maybe used only to check whether given key exists in the table. */
-
-SilcBool silc_hash_table_find(SilcHashTable ht, void *key,
-                             void **ret_key, void **ret_context)
-{
-  return silc_hash_table_find_ext(ht, key, ret_key, ret_context,
-                                 NULL, NULL, NULL, NULL);
-}
-
-/* Same as above but with specified hash and comparison functions. */
-
-SilcBool silc_hash_table_find_ext(SilcHashTable ht, void *key,
-                                 void **ret_key, void **ret_context,
-                                 SilcHashFunction hash,
-                                 void *hash_user_context,
-                                 SilcHashCompare compare,
-                                 void *compare_user_context)
-{
-  SilcHashTableEntry *entry;
-
-  entry = silc_hash_table_find_internal_simple(ht, key,
-                                              hash ? hash : ht->hash,
-                                              hash_user_context ?
-                                              hash_user_context :
-                                              ht->hash_user_context,
-                                              compare ? compare :
-                                              ht->compare,
-                                              compare_user_context ?
-                                              compare_user_context :
-                                              ht->compare_user_context);
-  if (*entry == NULL) {
-    silc_set_errno(SILC_ERR_NOT_FOUND);
-    return FALSE;
-  }
-
-  if (ret_key)
-    *ret_key = (*entry)->key;
-  if (ret_context)
-    *ret_context = (*entry)->context;
-
-  return TRUE;
-}
-
-/* Same as silc_hash_table_find but finds with specific context. */
-
-SilcBool silc_hash_table_find_by_context(SilcHashTable ht, void *key,
-                                        void *context, void **ret_key)
-{
-  return silc_hash_table_find_by_context_ext(ht, key, context, ret_key,
-                                            NULL, NULL, NULL, NULL);
-}
-
-/* Same as above but with specified hash and comparison functions. */
-
-SilcBool silc_hash_table_find_by_context_ext(SilcHashTable ht, void *key,
-                                            void *context, void **ret_key,
-                                            SilcHashFunction hash,
-                                            void *hash_user_context,
-                                            SilcHashCompare compare,
-                                            void *compare_user_context)
-{
-  SilcHashTableEntry *entry;
-
-  entry = silc_hash_table_find_internal_context(ht, key, context, NULL,
-                                               hash ? hash : ht->hash,
-                                               hash_user_context ?
-                                               hash_user_context :
-                                               ht->hash_user_context,
-                                               compare ? compare :
-                                               ht->compare,
-                                               compare_user_context ?
-                                               compare_user_context :
-                                               ht->compare_user_context);
-  if (!entry || !(*entry)) {
-    silc_set_errno(SILC_ERR_NOT_FOUND);
-    return FALSE;
-  }
-
-  if (ret_key)
-    *ret_key = (*entry)->key;
-
-  return TRUE;
-}
-
-/* As the hash table is collision resistant it is possible to save duplicate
-   keys to the hash table. This function can be used to find all keys
-   and contexts from the hash table that are found using the `key'. The
-   `foreach' is called for every found key. */
-
-void silc_hash_table_find_foreach(SilcHashTable ht, void *key,
-                                 SilcHashForeach foreach, void *user_context)
-{
-  silc_hash_table_find_internal_all(ht, key, ht->hash, ht->hash_user_context,
-                                   ht->compare, ht->compare_user_context,
-                                   foreach, user_context);
-}
-
-/* Same as above but with specific hash and comparison functions. */
-
-void silc_hash_table_find_foreach_ext(SilcHashTable ht, void *key,
-                                     SilcHashFunction hash,
-                                     void *hash_user_context,
-                                     SilcHashCompare compare,
-                                     void *compare_user_context,
-                                     SilcHashForeach foreach,
-                                     void *foreach_user_context)
-{
-  silc_hash_table_find_internal_all(ht, key,
-                                   hash ? hash : ht->hash,
-                                   hash_user_context ?
-                                   hash_user_context :
-                                   ht->hash_user_context,
-                                   compare ? compare :
-                                   ht->compare,
-                                   compare_user_context ?
-                                   compare_user_context :
-                                   ht->compare_user_context,
-                                   foreach, foreach_user_context);
-}
-
-/* Traverse all entrys in the hash table and call the `foreach' for
-   every entry with the `user_context' context. */
-
-void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
-                            void *user_context)
-{
-  SilcHashTableEntry e, tmp;
-  int i;
-  SilcBool auto_rehash;
-
-  if (!foreach)
-    return;
-
-  auto_rehash = ht->auto_rehash;
-  ht->auto_rehash = FALSE;
-  for (i = 0; i < primesize[ht->table_size]; i++) {
-    e = ht->table[i];
-    while (e) {
-      /* Entry may become invalid inside the `foreach' */
-      tmp = e->next;
-      foreach(e->key, e->context, user_context);
-      e = tmp;
-    }
-  }
-  ht->auto_rehash = auto_rehash;
-}
-
-/* Rehashs the hash table. The size of the new hash table is provided
-   as `new_size'. If the `new_size' is zero then this routine will make
-   the new table of a suitable size. Note that this operation may be
-   very slow. */
-
-void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size)
-{
-  int i;
-  SilcHashTableEntry *table, e, tmp;
-  SilcUInt32 table_size, size_index;
-  SilcBool auto_rehash;
-
-  SILC_HT_DEBUG(("Start"));
-
-  if (new_size)
-    silc_hash_table_primesize(new_size, &size_index);
-  else
-    silc_hash_table_primesize(ht->entry_count, &size_index);
-
-  if (size_index == ht->table_size)
-    return;
-
-  SILC_HT_DEBUG(("Rehashing"));
-
-  /* Take old hash table */
-  table = ht->table;
-  table_size = ht->table_size;
-  auto_rehash = ht->auto_rehash;
-  ht->auto_rehash = FALSE;
-
-  /* Allocate new table */
-  ht->table = silc_scalloc(ht->stack,
-                          primesize[size_index], sizeof(*ht->table));
-  if (!ht->table)
-    return;
-  ht->table_size = size_index;
-  ht->entry_count = 0;
-
-  /* Rehash */
-  for (i = 0; i < primesize[table_size]; i++) {
-    e = table[i];
-    while (e) {
-      silc_hash_table_add(ht, e->key, e->context);
-      tmp = e;
-      e = e->next;
-
-      /* Remove old entry */
-      silc_sfree(ht->stack, tmp);
-    }
-  }
-
-  ht->auto_rehash = auto_rehash;
-
-  /* Remove old table */
-  silc_sfree(ht->stack, table);
-}
-
-/* Same as above but with specific hash function. */
-
-void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
-                               SilcHashFunction hash,
-                               void *hash_user_context)
-{
-  int i;
-  SilcHashTableEntry *table, e, tmp;
-  SilcUInt32 table_size, size_index;
-  SilcBool auto_rehash;
-
-  SILC_HT_DEBUG(("Start"));
-
-  if (new_size)
-    silc_hash_table_primesize(new_size, &size_index);
-  else
-    silc_hash_table_primesize(ht->entry_count, &size_index);
-
-  if (size_index == ht->table_size)
-    return;
-
-  SILC_HT_DEBUG(("Rehashing"));
-
-  /* Take old hash table */
-  table = ht->table;
-  table_size = ht->table_size;
-  auto_rehash = ht->auto_rehash;
-  ht->auto_rehash = FALSE;
-
-  /* Allocate new table */
-  ht->table = silc_scalloc(ht->stack,
-                          primesize[size_index], sizeof(*ht->table));
-  if (!ht->table)
-    return;
-  ht->table_size = size_index;
-  ht->entry_count = 0;
-
-  /* Rehash */
-  for (i = 0; i < primesize[table_size]; i++) {
-    e = table[i];
-    while (e) {
-      silc_hash_table_add_ext(ht, e->key, e->context, hash,
-                             hash_user_context);
-      tmp = e;
-      e = e->next;
-
-      /* Remove old entry */
-      silc_sfree(ht->stack, tmp);
-    }
-  }
-
-  ht->auto_rehash = auto_rehash;
-
-  /* Remove old table */
-  silc_sfree(ht->stack, table);
-}
-
-/* Prepares the `htl' list structure sent as argument to be used in the
-   hash table traversing with the silc_hash_table_get. Usage:
-   SilcHashTableList htl; silc_hash_table_list(ht, &htl); */
-
-void silc_hash_table_list(SilcHashTable ht, SilcHashTableList *htl)
-{
-  htl->ht = ht;
-  htl->entry = NULL;
-  htl->index = 0;
-  htl->auto_rehash = ht->auto_rehash;
-
-  /* Disallow rehashing of the table while traversing the table */
-  ht->auto_rehash = FALSE;
-}
-
-/* Resets the `htl' SilcHashTableList. */
-
-void silc_hash_table_list_reset(SilcHashTableList *htl)
-{
-  /* Set back the original auto rehash value to the table */
-  htl->ht->auto_rehash = htl->auto_rehash;
-}
-
-/* Returns always the next entry in the hash table into the `key' and
-   `context' and TRUE.  If this returns FALSE then there are no anymore
-   any entrys. Usage: while (silc_hash_table_get(&htl, &key, &context)) */
-
-SilcBool silc_hash_table_get(SilcHashTableList *htl, void **key,
-                            void **context)
-{
-  SilcHashTableEntry entry = (SilcHashTableEntry)htl->entry;
-
-  if (!htl->ht->entry_count)
-    return FALSE;
-
-  while (!entry && htl->index < primesize[htl->ht->table_size]) {
-    entry = htl->ht->table[htl->index];
-    htl->index++;
-  }
-
-  if (!entry)
-    return FALSE;
-
-  htl->entry = entry->next;
-
-  if (key)
-    *key = entry->key;
-  if (context)
-    *context = entry->context;
-
-  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);
-}