From 1fd06503004016a245257a08748473d749559586 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Thu, 22 Feb 2024 00:23:55 +0100 Subject: [PATCH] added function parameters for hash table creation to free keys or values --- src/libgame/hash.c | 42 ++++++++++++++++++++++++++++++------------ src/libgame/hash.h | 34 +++++++++++++++++++++++----------- src/libgame/setup.c | 4 ++-- src/tools.c | 8 ++++---- 4 files changed, 59 insertions(+), 29 deletions(-) diff --git a/src/libgame/hash.c b/src/libgame/hash.c index e021da5c..101ec121 100644 --- a/src/libgame/hash.c +++ b/src/libgame/hash.c @@ -41,9 +41,11 @@ /*****************************************************************************/ struct hashtable * -create_hashtable(unsigned int minsize, float maxloadfactor, - unsigned int (*hashf) (void*), - int (*eqf) (void*, void*)) +create_hashtable_ext(unsigned int minsize, float maxloadfactor, + unsigned int (*hashf) (void*), + int (*eqf) (void*, void*), + void (*freekfn) (void*), + void (*freevfn) (void*)) { struct hashtable *h; unsigned int i, size = 1u; @@ -78,10 +80,21 @@ create_hashtable(unsigned int minsize, float maxloadfactor, h->hashfn = hashf; h->eqfn = eqf; h->loadlimit = (unsigned int) ((float)size * maxloadfactor); + h->freekfn = freekfn; + h->freevfn = freevfn; return h; } +struct hashtable * +create_hashtable(unsigned int (*hashf) (void*), + int (*eqf) (void*, void*), + void (*freekfn) (void*), + void (*freevfn) (void*)) +{ + return create_hashtable_ext(16, 0.75, hashf, eqf, freekfn, freevfn); +} + /*****************************************************************************/ static unsigned int hash(struct hashtable *h, void *k) @@ -242,7 +255,8 @@ hashtable_change(struct hashtable *h, void *k, void *v) /* Check hash value to short circuit heavier comparison */ if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { - free(e->v); + if (h->freevfn != NULL) + h->freevfn(e->v); e->v = v; return -1; @@ -298,8 +312,13 @@ hashtable_remove(struct hashtable *h, void *k) { *pE = e->next; h->entrycount--; - v = e->v; - free(e->k); + v = NULL; + if (h->freekfn != NULL) + h->freekfn(e->k); + if (h->freevfn != NULL) + h->freevfn(e->v); + else + v = e->v; free(e); return v; @@ -315,7 +334,7 @@ hashtable_remove(struct hashtable *h, void *k) /*****************************************************************************/ /* destroy */ void -hashtable_destroy(struct hashtable *h, int free_values) +hashtable_destroy(struct hashtable *h) { unsigned int i; struct entry *e, *f; @@ -329,10 +348,10 @@ hashtable_destroy(struct hashtable *h, int free_values) { f = e; e = e->next; - free(f->k); - - if (free_values) - free(f->v); + if (h->freekfn != NULL) + h->freekfn(f->k); + if (h->freevfn != NULL) + h->freevfn(f->v); free(f); } @@ -342,7 +361,6 @@ hashtable_destroy(struct hashtable *h, int free_values) free(h); } - /*****************************************************************************/ /* hashtable_iterator - iterator constructor */ diff --git a/src/libgame/hash.h b/src/libgame/hash.h index f87f8b90..8d0eff23 100644 --- a/src/libgame/hash.h +++ b/src/libgame/hash.h @@ -45,7 +45,7 @@ * static unsigned int hash_from_key_fn( void *k ); * static int keys_equal_fn ( void *key1, void *key2 ); * - * h = create_hashtable(16, 0.75, hash_from_key_fn, keys_equal_fn); + * h = create_hashtable(16, 0.75, hash_from_key_fn, keys_equal_fn, free, free); * k = (struct some_key *) malloc(sizeof(struct some_key)); * v = (struct some_value *) malloc(sizeof(struct some_value)); * @@ -109,6 +109,8 @@ struct hashtable unsigned int loadlimit; unsigned int (*hashfn) (void *k); int (*eqfn) (void *k1, void *k2); + void (*freekfn) (void *k); + void (*freevfn) (void *v); }; /*****************************************************************************/ @@ -121,28 +123,39 @@ struct hashtable_itr /***************************************************************************** - * create_hashtable + * create_hashtable_ext * @name create_hashtable * @param minsize minimum initial size of hashtable * @param maxloadfactor maximum ratio entries / tablesize * @param hashfunction function for hashing keys * @param key_eq_fn function for determining key equality + * @param key_free_fn function for freeing keys + * @param value_free_fn function for freeing values * @return newly created hashtable or NULL on failure */ struct hashtable * -create_hashtable(unsigned int minsize, float maxloadfactor, - unsigned int (*hashfunction) (void*), - int (*key_eq_fn) (void*, void*)); +create_hashtable_ext(unsigned int minsize, float maxloadfactor, + unsigned int (*hashfunction) (void*), + int (*key_eq_fn) (void*, void*), + void (*key_free_fn) (void*), + void (*value_free_fn) (void*)); + +/* wrapper function using reasonable default values for some parameters */ +struct hashtable * +create_hashtable(unsigned int (*hashfunction) (void*), + int (*key_eq_fn) (void*, void*), + void (*key_free_fn) (void*), + void (*value_free_fn) (void*)); /***************************************************************************** * hashtable_insert * @name hashtable_insert * @param h the hashtable to insert into - * @param k the key - hashtable claims ownership and will free on removal - * @param v the value - does not claim ownership + * @param k the key - will be freed on removal if free function defined + * @param v the value - will be freed on removal if free function defined * @return non-zero for successful insertion * * This function will cause the table to expand if the insertion would take @@ -188,7 +201,7 @@ static int fnname (struct hashtable *h, keytype *k, valuetype *v) \ * @name hashtable_search * @param h the hashtable to search - * @param k the key to search for - does not claim ownership + * @param k the key to search for * @return the value associated with the key, or NULL if none found */ @@ -206,7 +219,7 @@ static valuetype * fnname (struct hashtable *h, keytype *k) \ * @name hashtable_remove * @param h the hashtable to remove the item from - * @param k the key to search for - does not claim ownership + * @param k the key to search for * @return the value associated with the key, or NULL if none found */ @@ -234,11 +247,10 @@ hashtable_count(struct hashtable *h); * hashtable_destroy * @name hashtable_destroy - * @param free_values whether to call 'free' on the remaining values */ void -hashtable_destroy(struct hashtable *h, int free_values); +hashtable_destroy(struct hashtable *h); /*****************************************************************************/ diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 25ad716b..4027a6e0 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -2331,7 +2331,7 @@ int hash_key_integers_are_equal(void *key1, void *key2) SetupFileHash *newSetupFileHash(void) { SetupFileHash *new_hash = - create_hashtable(16, 0.75, get_hash_from_string, hash_key_strings_are_equal); + create_hashtable(get_hash_from_string, hash_key_strings_are_equal, free, free); if (new_hash == NULL) Fail("create_hashtable() failed -- out of memory"); @@ -2344,7 +2344,7 @@ void freeSetupFileHash(SetupFileHash *hash) if (hash == NULL) return; - hashtable_destroy(hash, 1); // 1 == also free values stored in hash + hashtable_destroy(hash); } char *getHashEntry(SetupFileHash *hash, char *token) diff --git a/src/tools.c b/src/tools.c index 0b0b7e2e..1d3607e4 100644 --- a/src/tools.c +++ b/src/tools.c @@ -11317,9 +11317,9 @@ static unsigned int test_uuid_random_function_better(int max) static void TestGeneratingUUIDs_RunTest(int nr, int always_seed, int num_uuids) { struct hashtable *hash_seeds = - create_hashtable(16, 0.75, get_hash_from_string, hash_key_strings_are_equal); + create_hashtable(get_hash_from_string, hash_key_strings_are_equal, free, NULL); struct hashtable *hash_uuids = - create_hashtable(16, 0.75, get_hash_from_string, hash_key_strings_are_equal); + create_hashtable(get_hash_from_string, hash_key_strings_are_equal, free, NULL); static char message[100]; int i; @@ -11398,8 +11398,8 @@ static void TestGeneratingUUIDs_RunTest(int nr, int always_seed, int num_uuids) Request(message, REQ_CONFIRM); - hashtable_destroy(hash_seeds, 0); - hashtable_destroy(hash_uuids, 0); + hashtable_destroy(hash_seeds); + hashtable_destroy(hash_uuids); } void TestGeneratingUUIDs(void) -- 2.34.1