diff options
Diffstat (limited to 'src/common/libalgo')
-rw-r--r-- | src/common/libalgo/hashtbl.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/src/common/libalgo/hashtbl.c b/src/common/libalgo/hashtbl.c index b87bcef..b4720c3 100644 --- a/src/common/libalgo/hashtbl.c +++ b/src/common/libalgo/hashtbl.c @@ -2,7 +2,7 @@ #include <malloc.h> #include <string.h> -#define DEFAULT_INIT_SIZE 16 +#define DEFAULT_HT_INIT_SIZE 16 #define SLOT_OF_HASH(k, nslots) (((size_t)(k)*21179)%(size_t)(nslots)) typedef struct hashtbl_item { @@ -16,20 +16,20 @@ typedef struct hashtbl_item { struct hashtbl { key_eq_fun_t ef; hash_fun_t hf; - free_fun_t kff; + kv_iter_fun_t releasef; size_t size, nitems; hashtbl_item_t **items; }; -hashtbl_t *create_hashtbl(key_eq_fun_t ef, hash_fun_t hf, free_fun_t kff, size_t initial_size) { +hashtbl_t *create_hashtbl(key_eq_fun_t ef, hash_fun_t hf, kv_iter_fun_t on_release) { hashtbl_t *ht = (hashtbl_t*)malloc(sizeof(hashtbl_t)); if (ht == 0) return 0; ht->ef = ef; ht->hf = hf; - ht->kff = kff; + ht->releasef = on_release; - ht->size = (initial_size == 0 ? DEFAULT_INIT_SIZE : initial_size); + ht->size = DEFAULT_HT_INIT_SIZE; ht->nitems = 0; ht->items = (hashtbl_item_t**)malloc(ht->size * sizeof(hashtbl_item_t*)); @@ -43,15 +43,16 @@ hashtbl_t *create_hashtbl(key_eq_fun_t ef, hash_fun_t hf, free_fun_t kff, size_t return ht; } -void delete_hashtbl(hashtbl_t *ht, free_fun_t data_free_fun) { +void delete_hashtbl(hashtbl_t *ht) { // Free items for (size_t i = 0; i < ht->size; i++) { while (ht->items[i] != 0) { - hashtbl_item_t *n = ht->items[i]->next; - if (data_free_fun) data_free_fun(ht->items[i]->val); - if (ht->kff) ht->kff(ht->items[i]->key); - free(ht->items[i]); - ht->items[i] = n; + hashtbl_item_t *x = ht->items[i]; + ht->items[i] = x->next; + + if (ht->releasef) ht->releasef(x->key, x->val); + + free(x); } } @@ -123,24 +124,26 @@ void hashtbl_remove(hashtbl_t* ht, const void* key) { if (ht->items[slot] == 0) return; + hashtbl_item_t *x = 0; + if (ht->ef(ht->items[slot]->key, key)) { - hashtbl_item_t *x = ht->items[slot]; + x = ht->items[slot]; ht->items[slot] = x->next; - if (ht->kff) ht->kff(x->key); - free(x); - ht->nitems--; } else { for (hashtbl_item_t *i = ht->items[slot]; i->next != 0; i = i->next) { if (ht->ef(i->next->key, key)) { - hashtbl_item_t *x = i->next; + x = i->next; i->next = x->next; - if (ht->kff) ht->kff(x->key); - free(x); - ht->nitems--; break; } } } + + if (x != 0) { + ht->nitems--; + if (ht->releasef) ht->releasef(x->key, x->val); + free(x); + } hashtbl_check_size(ht); } @@ -149,6 +152,10 @@ size_t hashtbl_count(hashtbl_t* ht) { return ht->nitems; } +// ================================== // +// UTILITY FUNCTIONS (HASH, EQ, FREE) // +// ================================== // + hash_t id_hash_fun(const void* v) { return (hash_t)v; } @@ -169,4 +176,17 @@ bool str_key_eq_fun(const void* a, const void* b) { return strcmp((const char*)a, (const char*)b) == 0; } +void free_key(void* key, void* val) { + free(key); +} + +void free_val(void* key, void* val) { + free(val); +} + +void free_key_val(void* key, void* val) { + free(key); + free(val); +} + /* vim: set ts=4 sw=4 tw=0 noet :*/ |