updates.
[silc.git] / lib / silcutil / silchashtable.c
index d5c690942d86fd389b7ae28dfbed3e1ed94b3fe5..31f333082cfbf0a4a109216a3fafc8c18fa90eac 100644 (file)
@@ -2,7 +2,7 @@
 
   silchashtable.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 2001 Pekka Riikonen
 
@@ -42,7 +42,7 @@
 #define SILC_HASH_TABLE_SIZE 3
 
 /* Produce the index by hashing the key */
-#define SILC_HASH_TABLE_HASH_F(f, c) \
+#define SILC_HASH_TABLE_HASH(f, c) \
   ((f)(key, (c)) % primesize[ht->table_size])
 
 /* Check whether need to rehash */
@@ -115,7 +115,7 @@ silc_hash_table_find_internal(SilcHashTable ht, void *key,
                              void *compare_user_context)
 {
   SilcHashTableEntry *entry, prev = NULL;
-  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+  uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
 
   SILC_HT_DEBUG(("index %d key %p", i, key));
 
@@ -149,7 +149,7 @@ silc_hash_table_find_internal_context(SilcHashTable ht, void *key,
                                      void *compare_user_context)
 {
   SilcHashTableEntry *entry, prev = NULL;
-  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+  uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
 
   SILC_HT_DEBUG(("index %d key %p context %p", i, key, context));
 
@@ -185,7 +185,7 @@ silc_hash_table_find_internal_simple(SilcHashTable ht, void *key,
                                     void *compare_user_context)
 {
   SilcHashTableEntry *entry;
-  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+  uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
 
   SILC_HT_DEBUG(("index %d key %p", i, key));
 
@@ -215,7 +215,7 @@ silc_hash_table_find_internal_all(SilcHashTable ht, void *key,
                                  void *foreach_user_context)
 {
   SilcHashTableEntry *entry;
-  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+  uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
 
   SILC_HT_DEBUG(("index %d key %p", i, key));
 
@@ -243,7 +243,7 @@ silc_hash_table_add_internal(SilcHashTable ht, void *key, void *context,
                             void *hash_user_context)
 {
   SilcHashTableEntry *entry;
-  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+  uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
 
   SILC_HT_DEBUG(("index %d key %p", i, key));
 
@@ -287,7 +287,7 @@ silc_hash_table_replace_internal(SilcHashTable ht, void *key, void *context,
                                 void *hash_user_context)
 {
   SilcHashTableEntry *entry;
-  uint32 i = SILC_HASH_TABLE_HASH_F(hash, hash_user_context);
+  uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
 
   SILC_HT_DEBUG(("index %d key %p", i, key));
 
@@ -306,6 +306,9 @@ silc_hash_table_replace_internal(SilcHashTable ht, void *key, void *context,
 
   (*entry)->key = key;
   (*entry)->context = context;
+
+  if (SILC_HASH_REHASH_INC)
+    silc_hash_table_rehash(ht, 0);
 }
 
 /* Allocates new hash table and returns it.  If the `table_size' is not
@@ -469,7 +472,9 @@ bool silc_hash_table_del_ext(SilcHashTable ht, void *key,
                             SilcHashFunction hash, 
                             void *hash_user_context,
                             SilcHashCompare compare, 
-                            void *compare_user_context)
+                            void *compare_user_context,
+                            SilcHashDestructor destructor,
+                            void *destructor_user_context)
 {
   SilcHashTableEntry *entry, prev, e;
 
@@ -495,8 +500,12 @@ bool silc_hash_table_del_ext(SilcHashTable ht, void *key,
   if (prev && e->next)
     prev->next = e->next;
 
-  if (ht->destructor)
-    ht->destructor(e->key, e->context, ht->destructor_user_context);
+  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_free(e);
 
   ht->entry_count--;
@@ -555,7 +564,9 @@ bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
                                        SilcHashFunction hash, 
                                        void *hash_user_context,
                                        SilcHashCompare compare, 
-                                       void *compare_user_context)
+                                       void *compare_user_context,
+                                       SilcHashDestructor destructor,
+                                       void *destructor_user_context)
 {
   SilcHashTableEntry *entry, prev, e;
 
@@ -583,8 +594,12 @@ bool silc_hash_table_del_by_context_ext(SilcHashTable ht, void *key,
   if (prev && e->next)
     prev->next = e->next;
 
-  if (ht->destructor)
-    ht->destructor(e->key, e->context, ht->destructor_user_context);
+  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_free(e);
 
   ht->entry_count--;
@@ -723,6 +738,8 @@ void silc_hash_table_rehash(SilcHashTable ht, uint32 new_size)
   SilcHashTableEntry *table, e, tmp;
   uint32 table_size, size_index;
 
+  SILC_HT_DEBUG(("Start"));
+
   if (new_size)
     silc_hash_table_primesize(new_size, &size_index);
   else
@@ -769,6 +786,8 @@ void silc_hash_table_rehash_ext(SilcHashTable ht, uint32 new_size,
   SilcHashTableEntry *table, e, tmp;
   uint32 table_size, size_index;
 
+  SILC_HT_DEBUG(("Start"));
+
   if (new_size)
     silc_hash_table_primesize(new_size, &size_index);
   else
@@ -815,6 +834,18 @@ 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