hash-func: add destructors for key and value

If they are set, then they are called in hashmap_clear() or
hashmap_free().
This commit is contained in:
Yu Watanabe
2018-12-02 11:59:07 +01:00
parent 7a08d314f2
commit 59a5cda7b9
5 changed files with 113 additions and 90 deletions
+23 -61
View File
@@ -864,47 +864,38 @@ static void hashmap_free_no_clear(HashmapBase *h) {
free(h);
}
HashmapBase *internal_hashmap_free(HashmapBase *h) {
/* Free the hashmap, but nothing in it */
HashmapBase *internal_hashmap_free(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
if (h) {
internal_hashmap_clear(h);
internal_hashmap_clear(h, default_free_key, default_free_value);
hashmap_free_no_clear(h);
}
return NULL;
}
HashmapBase *internal_hashmap_free_free(HashmapBase *h) {
/* Free the hashmap and all data objects in it, but not the
* keys */
if (h) {
internal_hashmap_clear_free(h);
hashmap_free_no_clear(h);
}
return NULL;
}
Hashmap *hashmap_free_free_free(Hashmap *h) {
/* Free the hashmap and all data and key objects in it */
if (h) {
hashmap_clear_free_free(h);
hashmap_free_no_clear(HASHMAP_BASE(h));
}
return NULL;
}
void internal_hashmap_clear(HashmapBase *h) {
void internal_hashmap_clear(HashmapBase *h, free_func_t default_free_key, free_func_t default_free_value) {
free_func_t free_key, free_value;
if (!h)
return;
free_key = h->hash_ops->free_key ?: default_free_key;
free_value = h->hash_ops->free_value ?: default_free_value;
if (free_key || free_value) {
unsigned idx;
for (idx = skip_free_buckets(h, 0); idx != IDX_NIL;
idx = skip_free_buckets(h, idx + 1)) {
struct hashmap_base_entry *e = bucket_at(h, idx);
if (free_key)
free_key((void *) e->key);
if (free_value)
free_value(entry_value(h, e));
}
}
if (h->has_indirect) {
free(h->indirect.storage);
h->has_indirect = false;
@@ -921,35 +912,6 @@ void internal_hashmap_clear(HashmapBase *h) {
base_set_dirty(h);
}
void internal_hashmap_clear_free(HashmapBase *h) {
unsigned idx;
if (!h)
return;
for (idx = skip_free_buckets(h, 0); idx != IDX_NIL;
idx = skip_free_buckets(h, idx + 1))
free(entry_value(h, bucket_at(h, idx)));
internal_hashmap_clear(h);
}
void hashmap_clear_free_free(Hashmap *h) {
unsigned idx;
if (!h)
return;
for (idx = skip_free_buckets(HASHMAP_BASE(h), 0); idx != IDX_NIL;
idx = skip_free_buckets(HASHMAP_BASE(h), idx + 1)) {
struct plain_hashmap_entry *e = plain_bucket_at(h, idx);
free((void*)e->b.key);
free(e->value);
}
internal_hashmap_clear(HASHMAP_BASE(h));
}
static int resize_buckets(HashmapBase *h, unsigned entries_add);
/*
@@ -1740,7 +1702,7 @@ HashmapBase *internal_hashmap_copy(HashmapBase *h) {
}
if (r < 0) {
internal_hashmap_free(copy);
internal_hashmap_free(copy, false, false);
return NULL;
}