updates
[silc.git] / lib / silcutil / silchashtable.c
index 03e2a905044364fcd3820d993e9636bae9ba0f8f..ca91ca1b66e05e4035d5a58b95cd4b759a39d759 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
 
@@ -215,10 +215,14 @@ silc_hash_table_find_internal_all(SilcHashTable ht, void *key,
                                  void *foreach_user_context)
 {
   SilcHashTableEntry *entry;
+  bool auto_rehash;
   uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
 
   SILC_HT_DEBUG(("index %d key %p", i, key));
 
+  auto_rehash = ht->auto_rehash;
+  ht->auto_rehash = FALSE;
+
   entry = &ht->table[i];
   if (compare) {
     while (*entry) {
@@ -233,6 +237,8 @@ silc_hash_table_find_internal_all(SilcHashTable ht, void *key,
       entry = &(*entry)->next;
     }
   }
+
+  ht->auto_rehash = auto_rehash;
 }
 
 /* Internal routine to add new key to the hash table */
@@ -472,7 +478,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;
 
@@ -498,8 +506,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--;
@@ -558,7 +570,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;
 
@@ -586,8 +600,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--;
@@ -700,10 +718,13 @@ void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
 {
   SilcHashTableEntry e, tmp;
   int i;
+  bool 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) {
@@ -713,6 +734,7 @@ void silc_hash_table_foreach(SilcHashTable ht, SilcHashForeach foreach,
       e = tmp;
     }
   }
+  ht->auto_rehash = auto_rehash;
 }
 
 /* Rehashs the hash table. The size of the new hash table is provided
@@ -822,6 +844,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