added function parameters for hash table creation to free keys or values
authorHolger Schemel <info@artsoft.org>
Wed, 21 Feb 2024 23:23:55 +0000 (00:23 +0100)
committerHolger Schemel <info@artsoft.org>
Wed, 21 Feb 2024 23:23:55 +0000 (00:23 +0100)
src/libgame/hash.c
src/libgame/hash.h
src/libgame/setup.c
src/tools.c

index e021da5c5959be418610e078e212d1e150e279e7..101ec1214a30aae2faddd478c24f53321d401832 100644 (file)
 
 /*****************************************************************************/
 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 */
 
index f87f8b90e4e28ed00d0976cb418e436c69d0444f..8d0eff235c38348e4e7afbb5b9667aa33510e51d 100644 (file)
@@ -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);
 
 
 /*****************************************************************************/
index 25ad716ba0785bdca0d87afba3ef817ce610f4cb..4027a6e065a4f23823b7c1050345a08330c9b6a7 100644 (file)
@@ -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)
index 0b0b7e2ee1e2b5938dfb2e9bb4e7854087019e19..1d3607e446eb94000aace0fbc45a0439f6906f5c 100644 (file)
@@ -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)