From 579a9e8505f93a7a2308d01e6a1edd3a91c40cc5 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Fri, 27 Jun 2025 21:46:55 +0100 Subject: [PATCH] object: hashmap: implement key/value destructors --- object/hashmap.c | 41 +++++++++++++++++++++++----- object/hashmap.h | 2 ++ object/include/blue/object/hashmap.h | 10 ++++--- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/object/hashmap.c b/object/hashmap.c index 461d561..7f50283 100644 --- a/object/hashmap.c +++ b/object/hashmap.c @@ -11,8 +11,22 @@ #define HASH_OFFSET_BASIS 0xcbf29ce484222325 #define HASH_PRIME 0x100000001b3 +/* clang-format off */ +static B_BTREE_DEFINE_SIMPLE_GET( + struct b_hashmap_bucket, + uint64_t, + bk_node, + bk_hash, + get_bucket) +static B_BTREE_DEFINE_SIMPLE_INSERT( + struct b_hashmap_bucket, + bk_node, + bk_hash, + put_bucket) + static uint64_t hash_data(const void *p, size_t size) { + /* clang-format on */ const unsigned char *s = p; uint64_t hash = HASH_OFFSET_BASIS; @@ -34,7 +48,8 @@ static struct b_object_type hashmap_type = { .t_release = hashmap_release, }; -struct b_hashmap *b_hashmap_create(void) +struct b_hashmap *b_hashmap_create( + b_hashmap_key_destructor key_dtor, b_hashmap_value_destructor value_dtor) { struct b_hashmap *hashmap = (struct b_hashmap *)b_object_type_instantiate(&hashmap_type); @@ -47,7 +62,7 @@ struct b_hashmap *b_hashmap_create(void) struct b_hashmap *b_hashmap_create_with_items(const b_hashmap_item *items) { - struct b_hashmap *hashmap = b_hashmap_create(); + struct b_hashmap *hashmap = b_hashmap_create(NULL, NULL); if (!hashmap) { return NULL; } @@ -59,12 +74,9 @@ struct b_hashmap *b_hashmap_create_with_items(const b_hashmap_item *items) return hashmap; } -static B_BTREE_DEFINE_SIMPLE_GET( - struct b_hashmap_bucket, uint64_t, bk_node, bk_hash, - get_bucket) static B_BTREE_DEFINE_SIMPLE_INSERT(struct b_hashmap_bucket, bk_node, bk_hash, put_bucket) - - static struct b_hashmap_bucket *create_bucket(void) +static struct b_hashmap_bucket *create_bucket(void) { + /* clang-format on */ struct b_hashmap_bucket *bucket = malloc(sizeof *bucket); if (!bucket) { return NULL; @@ -221,6 +233,15 @@ static b_status delete_item( struct b_hashmap_bucket_item *item) { b_queue_delete(&bucket->bk_items, &item->bi_entry); + + if (hashmap->h_key_dtor) { + hashmap->h_key_dtor((void *)item->bi_key.key_data); + } + + if (hashmap->h_value_dtor) { + hashmap->h_value_dtor((void *)item->bi_value.value_data); + } + free(item); if (b_queue_empty(&bucket->bk_items)) { @@ -426,6 +447,12 @@ bool b_hashmap_iterator_is_valid(const struct b_hashmap_iterator *it) static void hashmap_release(struct b_object *obj) { struct b_hashmap *map = B_HASHMAP(obj); + + b_hashmap_iterator it; + b_hashmap_iterator_begin(map, &it); + while (b_hashmap_iterator_is_valid(&it)) { + b_hashmap_iterator_erase(&it); + } } b_object_type_id b_hashmap_type_id(void) diff --git a/object/hashmap.h b/object/hashmap.h index 8b7c960..f9ac29d 100644 --- a/object/hashmap.h +++ b/object/hashmap.h @@ -20,6 +20,8 @@ struct b_hashmap_bucket { struct b_hashmap { struct b_object h_base; struct b_btree h_buckets; + b_hashmap_key_destructor h_key_dtor; + b_hashmap_value_destructor h_value_dtor; }; #endif diff --git a/object/include/blue/object/hashmap.h b/object/include/blue/object/hashmap.h index 651af59..225b2f2 100644 --- a/object/include/blue/object/hashmap.h +++ b/object/include/blue/object/hashmap.h @@ -26,7 +26,7 @@ #define B_HASHMAP_ITEM_END \ { \ - .key = {0}, .value = {0} \ + .key = {0}, .value = { 0 } \ } #define b_hashmap_foreach(it, hashmap) \ @@ -35,16 +35,17 @@ typedef struct b_hashmap b_hashmap; +typedef void (*b_hashmap_key_destructor)(void *); +typedef void (*b_hashmap_value_destructor)(void *); + typedef struct b_hashmap_key { const void *key_data; size_t key_size; - bool key_owned; } b_hashmap_key; typedef struct b_hashmap_value { void *value_data; size_t value_size; - bool value_owned; } b_hashmap_value; typedef struct b_hashmap_item { @@ -63,7 +64,8 @@ typedef struct b_hashmap_iterator { b_queue_entry *_cqe; } b_hashmap_iterator; -BLUE_API b_hashmap *b_hashmap_create(void); +BLUE_API b_hashmap *b_hashmap_create( + b_hashmap_key_destructor key_dtor, b_hashmap_value_destructor value_dtor); BLUE_API b_hashmap *b_hashmap_create_with_items(const b_hashmap_item *items); static inline b_hashmap *b_hashmap_retain(b_hashmap *hashmap)