/*
- silchashtable.c
+ silchashtable.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 Pekka Riikonen
+ Copyright (C) 2001 - 2002 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; either version 2 of the License, or
- (at your option) any later version.
-
+ 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
/* Hash table. */
struct SilcHashTableStruct {
SilcHashTableEntry *table;
- uint32 table_size;
- uint32 entry_count;
+ SilcUInt32 table_size;
+ SilcUInt32 entry_count;
SilcHashFunction hash;
SilcHashCompare compare;
SilcHashDestructor destructor;
/* Prime sizes for the hash table. The size of the table will always
be one of these. */
-const uint32 primesize[42] =
+const SilcUInt32 primesize[42] =
{
1, 3, 5, 11, 17, 37, 67, 109, 131, 163, 257, 367, 521, 823, 1031,
1237, 2053, 2777, 4099, 6247, 8209, 14057, 16411, 21089, 32771, 47431,
/* Find appropriate size for the hash table. The size will be a prime. */
-static uint32 silc_hash_table_primesize(uint32 size, uint32 *index)
+static SilcUInt32 silc_hash_table_primesize(SilcUInt32 size, SilcUInt32 *index)
{
int i;
void *compare_user_context)
{
SilcHashTableEntry *entry, prev = NULL;
- uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
+ SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
SILC_HT_DEBUG(("index %d key %p", i, key));
void *compare_user_context)
{
SilcHashTableEntry *entry, prev = NULL;
- uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
+ SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
SILC_HT_DEBUG(("index %d key %p context %p", i, key, context));
void *compare_user_context)
{
SilcHashTableEntry *entry;
- uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
+ SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
SILC_HT_DEBUG(("index %d key %p", i, key));
SilcHashForeach foreach,
void *foreach_user_context)
{
- SilcHashTableEntry *entry;
- uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
+ SilcHashTableEntry *entry, *tmp;
+ bool auto_rehash;
+ 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;
+
entry = &ht->table[i];
if (compare) {
while (*entry) {
- if (compare((*entry)->key, key, compare_user_context))
+ if (compare((*entry)->key, key, compare_user_context)) {
+ tmp = &(*entry)->next;
foreach((*entry)->key, (*entry)->context, foreach_user_context);
+ entry = tmp;
+ continue;
+ }
entry = &(*entry)->next;
}
} else {
while (*entry) {
- if ((*entry)->key == key)
+ if ((*entry)->key == key) {
+ tmp = &(*entry)->next;
foreach((*entry)->key, (*entry)->context, foreach_user_context);
+ entry = tmp;
+ continue;
+ }
entry = &(*entry)->next;
}
}
+
+ ht->auto_rehash = auto_rehash;
}
/* Internal routine to add new key to the hash table */
void *hash_user_context)
{
SilcHashTableEntry *entry;
- uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
+ SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
SILC_HT_DEBUG(("index %d key %p", i, key));
void *hash_user_context)
{
SilcHashTableEntry *entry;
- uint32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
+ SilcUInt32 i = SILC_HASH_TABLE_HASH(hash, hash_user_context);
SILC_HT_DEBUG(("index %d key %p", i, key));
destructor function, respectively. The `hash' is mandatory, the others
are optional. */
-SilcHashTable silc_hash_table_alloc(uint32 table_size,
+SilcHashTable silc_hash_table_alloc(SilcUInt32 table_size,
SilcHashFunction hash,
void *hash_user_context,
SilcHashCompare compare,
bool auto_rehash)
{
SilcHashTable ht;
- uint32 size_index = SILC_HASH_TABLE_SIZE;
+ SilcUInt32 size_index = SILC_HASH_TABLE_SIZE;
if (!hash)
return NULL;
/* Returns the size of the hash table */
-uint32 silc_hash_table_size(SilcHashTable ht)
+SilcUInt32 silc_hash_table_size(SilcHashTable ht)
{
return primesize[ht->table_size];
}
entries in the table thatn the size of the hash table calling the
silc_hash_table_rehash is recommended. */
-uint32 silc_hash_table_count(SilcHashTable ht)
+SilcUInt32 silc_hash_table_count(SilcHashTable ht)
{
return ht->entry_count;
}
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;
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--;
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;
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--;
{
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) {
e = tmp;
}
}
+ ht->auto_rehash = auto_rehash;
}
/* Rehashs the hash table. The size of the new hash table is provided
the new table of a suitable size. Note that this operation may be
very slow. */
-void silc_hash_table_rehash(SilcHashTable ht, uint32 new_size)
+void silc_hash_table_rehash(SilcHashTable ht, SilcUInt32 new_size)
{
int i;
SilcHashTableEntry *table, e, tmp;
- uint32 table_size, size_index;
+ SilcUInt32 table_size, size_index;
SILC_HT_DEBUG(("Start"));
/* Same as above but with specific hash function. */
-void silc_hash_table_rehash_ext(SilcHashTable ht, uint32 new_size,
+void silc_hash_table_rehash_ext(SilcHashTable ht, SilcUInt32 new_size,
SilcHashFunction hash,
void *hash_user_context)
{
int i;
SilcHashTableEntry *table, e, tmp;
- uint32 table_size, size_index;
+ SilcUInt32 table_size, size_index;
SILC_HT_DEBUG(("Start"));
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