diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2018-11-27 14:25:40 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2018-12-02 11:59:07 +0100 |
commit | 59a5cda7b904cd7ef9853bda15b498bbc0577524 (patch) | |
tree | dadee20a34a2c4211c90b44448ab98ab8fc59bbe /src/basic/hashmap.c | |
parent | tree-wide: make hash_ops typesafe (diff) | |
download | systemd-59a5cda7b904cd7ef9853bda15b498bbc0577524.tar.xz systemd-59a5cda7b904cd7ef9853bda15b498bbc0577524.zip |
hash-func: add destructors for key and value
If they are set, then they are called in hashmap_clear() or
hashmap_free().
Diffstat (limited to 'src/basic/hashmap.c')
-rw-r--r-- | src/basic/hashmap.c | 76 |
1 files changed, 19 insertions, 57 deletions
diff --git a/src/basic/hashmap.c b/src/basic/hashmap.c index a59640023f..5a676eeb61 100644 --- a/src/basic/hashmap.c +++ b/src/basic/hashmap.c @@ -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) { +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 the hashmap and all data objects in it, but not the - * keys */ + free_key = h->hash_ops->free_key ?: default_free_key; + free_value = h->hash_ops->free_value ?: default_free_value; - if (h) { - internal_hashmap_clear_free(h); - hashmap_free_no_clear(h); - } - - return NULL; -} + if (free_key || free_value) { + unsigned idx; -Hashmap *hashmap_free_free_free(Hashmap *h) { + 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); - /* Free the hashmap and all data and key objects in it */ + if (free_key) + free_key((void *) e->key); - if (h) { - hashmap_clear_free_free(h); - hashmap_free_no_clear(HASHMAP_BASE(h)); + if (free_value) + free_value(entry_value(h, e)); + } } - return NULL; -} - -void internal_hashmap_clear(HashmapBase *h) { - if (!h) - return; - 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; } |