summaryrefslogtreecommitdiffstats
path: root/src/basic/hashmap.c
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2018-11-27 14:25:40 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2018-12-02 11:59:07 +0100
commit59a5cda7b904cd7ef9853bda15b498bbc0577524 (patch)
treedadee20a34a2c4211c90b44448ab98ab8fc59bbe /src/basic/hashmap.c
parenttree-wide: make hash_ops typesafe (diff)
downloadsystemd-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.c76
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;
}