summaryrefslogtreecommitdiff
path: root/p11-kit/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'p11-kit/hash.c')
-rw-r--r--p11-kit/hash.c117
1 files changed, 67 insertions, 50 deletions
diff --git a/p11-kit/hash.c b/p11-kit/hash.c
index cfa6bf7..d116916 100644
--- a/p11-kit/hash.c
+++ b/p11-kit/hash.c
@@ -100,10 +100,6 @@ struct hash {
#define int_calloc calloc
#define int_free free
-/*
- * Hash creation functions.
- */
-
static hash_entry_t**
alloc_array(hash_t* ht, unsigned int max)
{
@@ -138,46 +134,30 @@ hash_create (hash_hash_func hash_func,
return ht;
}
-void
-hash_free (hash_t* ht)
+static hash_entry_t*
+next_entry (hash_iter_t* hi)
{
- hash_iter_t hi;
-
- if (!ht)
- return;
-
- hash_iterate (ht, &hi);
- while (hash_next (&hi, NULL, NULL)) {
- if (ht->key_destroy_func)
- ht->key_destroy_func (hi.ths->key);
- if (ht->value_destroy_func)
- ht->value_destroy_func (hi.ths->val);
- free (hi.ths);
+ hash_entry_t *he = hi->next;
+ while (!he) {
+ if (hi->index > hi->ht->max)
+ return NULL;
+ he = hi->ht->array[hi->index++];
}
-
- if (ht->array)
- int_free (ht->array);
-
- int_free (ht);
+ hi->next = he->next;
+ return he;
}
-/*
- * Hash iteration functions.
- */
+
int
hash_next (hash_iter_t* hi, void **key, void **value)
{
- hi->ths = hi->next;
- while (!hi->ths) {
- if (hi->index > hi->ht->max)
- return 0;
- hi->ths = hi->ht->array[hi->index++];
- }
- hi->next = hi->ths->next;
+ hash_entry_t *he = next_entry (hi);
+ if (he == NULL)
+ return 0;
if (key)
- *key = hi->ths->key;
+ *key = he->key;
if (value)
- *value = hi->ths->val;
+ *value = he->val;
return 1;
}
@@ -186,19 +166,15 @@ hash_iterate (hash_t* ht, hash_iter_t *hi)
{
hi->ht = ht;
hi->index = 0;
- hi->ths = NULL;
hi->next = NULL;
}
-/*
- * Expanding a hash table
- */
-
static int
expand_array (hash_t* ht)
{
hash_iter_t hi;
- hash_entry_t** new_array;
+ hash_entry_t *he;
+ hash_entry_t **new_array;
unsigned int new_max;
new_max = ht->max * 2 + 1;
@@ -208,10 +184,10 @@ expand_array (hash_t* ht)
return 0;
hash_iterate (ht, &hi);
- while (hash_next (&hi, NULL, NULL)) {
- unsigned int i = hi.ths->hash & new_max;
- hi.ths->next = new_array[i];
- new_array[i] = hi.ths;
+ while ((he = next_entry (&hi)) != NULL) {
+ unsigned int i = he->hash & new_max;
+ he->next = new_array[i];
+ new_array[i] = he;
}
if(ht->array)
@@ -301,7 +277,7 @@ hash_set (hash_t* ht, void* key, void* val)
}
int
-hash_remove (hash_t* ht, const void* key)
+hash_steal (hash_t *ht, const void *key, void **stolen_key, void **stolen_value)
{
hash_entry_t** hep = find_entry (ht, key, 0);
@@ -309,15 +285,32 @@ hash_remove (hash_t* ht, const void* key)
hash_entry_t* old = *hep;
*hep = (*hep)->next;
--ht->count;
- if (ht->key_destroy_func)
- ht->key_destroy_func (old->key);
- if (ht->value_destroy_func)
- ht->value_destroy_func (old->val);
+ if (stolen_key)
+ *stolen_key = old->key;
+ if (stolen_value)
+ *stolen_value = old->val;
free (old);
return 1;
}
return 0;
+
+}
+
+int
+hash_remove (hash_t *ht, const void *key)
+{
+ void *old_key;
+ void *old_value;
+
+ if (!hash_steal (ht, key, &old_key, &old_value))
+ return 0;
+
+ if (ht->key_destroy_func)
+ ht->key_destroy_func (old_key);
+ if (ht->value_destroy_func)
+ ht->value_destroy_func (old_value);
+ return 1;
}
void
@@ -344,6 +337,30 @@ hash_clear (hash_t* ht)
ht->count = 0;
}
+void
+hash_free (hash_t* ht)
+{
+ hash_entry_t *he;
+ hash_iter_t hi;
+
+ if (!ht)
+ return;
+
+ hash_iterate (ht, &hi);
+ while ((he = next_entry (&hi)) != NULL) {
+ if (ht->key_destroy_func)
+ ht->key_destroy_func (he->key);
+ if (ht->value_destroy_func)
+ ht->value_destroy_func (he->val);
+ free (he);
+ }
+
+ if (ht->array)
+ int_free (ht->array);
+
+ int_free (ht);
+}
+
unsigned int
hash_count (hash_t* ht)
{