#define NBUCKETS 127
struct hashmap_entry {
- const void *key;
+ void *key;
void *value;
struct hashmap_entry *bucket_next, *bucket_previous;
pa_hash_func_t hash_func;
pa_compare_func_t compare_func;
+ pa_free_cb_t key_free_func;
+ pa_free_cb_t value_free_func;
+
struct hashmap_entry *iterate_list_head, *iterate_list_tail;
unsigned n_entries;
};
PA_STATIC_FLIST_DECLARE(entries, 0, pa_xfree);
-pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {
+pa_hashmap *pa_hashmap_new_full(pa_hash_func_t hash_func, pa_compare_func_t compare_func, pa_free_cb_t key_free_func, pa_free_cb_t value_free_func) {
pa_hashmap *h;
h = pa_xmalloc0(PA_ALIGN(sizeof(pa_hashmap)) + NBUCKETS*sizeof(struct hashmap_entry*));
h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func;
h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func;
+ h->key_free_func = key_free_func;
+ h->value_free_func = value_free_func;
+
h->n_entries = 0;
h->iterate_list_head = h->iterate_list_tail = NULL;
return h;
}
+pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {
+ return pa_hashmap_new_full(hash_func, compare_func, NULL, NULL);
+}
+
static void remove_entry(pa_hashmap *h, struct hashmap_entry *e) {
pa_assert(h);
pa_assert(e);
BY_HASH(h)[hash] = e->bucket_next;
}
+ if (h->key_free_func)
+ h->key_free_func(e->key);
+
if (pa_flist_push(PA_STATIC_FLIST_GET(entries), e) < 0)
pa_xfree(e);
h->n_entries--;
}
-void pa_hashmap_free(pa_hashmap *h, pa_free_cb_t free_cb) {
+void pa_hashmap_free(pa_hashmap *h) {
pa_assert(h);
- pa_hashmap_remove_all(h, free_cb);
+ pa_hashmap_remove_all(h);
pa_xfree(h);
}
return NULL;
}
-int pa_hashmap_put(pa_hashmap *h, const void *key, void *value) {
+int pa_hashmap_put(pa_hashmap *h, void *key, void *value) {
struct hashmap_entry *e;
unsigned hash;
return data;
}
-void pa_hashmap_remove_all(pa_hashmap *h, pa_free_cb_t free_cb) {
+int pa_hashmap_remove_and_free(pa_hashmap *h, const void *key) {
+ void *data;
+
+ pa_assert(h);
+
+ data = pa_hashmap_remove(h, key);
+
+ if (data && h->value_free_func)
+ h->value_free_func(data);
+
+ return data ? 0 : -1;
+}
+
+void pa_hashmap_remove_all(pa_hashmap *h) {
pa_assert(h);
while (h->iterate_list_head) {
data = h->iterate_list_head->value;
remove_entry(h, h->iterate_list_head);
- if (free_cb)
- free_cb(data);
+ if (h->value_free_func)
+ h->value_free_func(data);
}
}
return h->n_entries;
}
-pa_bool_t pa_hashmap_isempty(pa_hashmap *h) {
+bool pa_hashmap_isempty(pa_hashmap *h) {
pa_assert(h);
return h->n_entries == 0;