added function parameters for hash table creation to free keys or values
[rocksndiamonds.git] / src / libgame / hash.c
index c7f4d73939a5668a5e6b3b3c259086401df40015..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;
@@ -70,7 +72,7 @@ create_hashtable(unsigned int minsize, float maxloadfactor,
     return NULL;
   }
 
-  for (i=0; i < size; i++)
+  for (i = 0; i < size; i++)
     h->table[i] = NULL;
 
   h->tablelength  = size;
@@ -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)
@@ -134,7 +147,7 @@ hashtable_expand(struct hashtable *h)
       while ((e = h->table[i]) != NULL)
       {
        h->table[i] = e->next;
-       index = indexFor(newsize,e->h);
+       index = indexFor(newsize, e->h);
        e->next = newtable[index];
        newtable[index] = e;
       }
@@ -160,7 +173,7 @@ hashtable_expand(struct hashtable *h)
     {
       for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE)
       {
-       index = indexFor(newsize,e->h);
+       index = indexFor(newsize, e->h);
 
        if (index == i)
        {
@@ -216,8 +229,8 @@ hashtable_insert(struct hashtable *h, void *k, void *v)
     return 0;
   }
 
-  e->h = hash(h,k);
-  index = indexFor(h->tablelength,e->h);
+  e->h = hash(h, k);
+  index = indexFor(h->tablelength, e->h);
   e->k = k;
   e->v = v;
   e->next = h->table[index];
@@ -233,8 +246,8 @@ hashtable_change(struct hashtable *h, void *k, void *v)
   struct entry *e;
   unsigned int hashvalue, index;
 
-  hashvalue = hash(h,k);
-  index = indexFor(h->tablelength,hashvalue);
+  hashvalue = hash(h, k);
+  index = indexFor(h->tablelength, hashvalue);
   e = h->table[index];
 
   while (e != NULL)
@@ -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;
@@ -261,8 +275,8 @@ hashtable_search(struct hashtable *h, void *k)
   struct entry *e;
   unsigned int hashvalue, index;
 
-  hashvalue = hash(h,k);
-  index = indexFor(h->tablelength,hashvalue);
+  hashvalue = hash(h, k);
+  index = indexFor(h->tablelength, hashvalue);
   e = h->table[index];
 
   while (e != NULL)
@@ -287,7 +301,7 @@ hashtable_remove(struct hashtable *h, void *k)
   struct entry *e;
   struct entry **pE;
   void *v;
-  unsigned int index = indexFor(h->tablelength,hash(h,k));
+  unsigned int index = indexFor(h->tablelength, hash(h, k));
 
   pE = &(h->table[index]);
   e = *pE;
@@ -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 */
 
@@ -379,7 +397,7 @@ hashtable_iterator(struct hashtable *h)
 }
 
 /*****************************************************************************/
-/* key - return the key of the (key,value) pair at the current position */
+/* key - return the key of the (key, value) pair at the current position */
 
 void *
 hashtable_iterator_key(struct hashtable_itr *i)
@@ -388,7 +406,7 @@ hashtable_iterator_key(struct hashtable_itr *i)
 }
 
 /*****************************************************************************/
-/* value - return the value of the (key,value) pair at the current position */
+/* value - return the value of the (key, value) pair at the current position */
 
 void *
 hashtable_iterator_value(struct hashtable_itr *i)
@@ -403,7 +421,7 @@ hashtable_iterator_value(struct hashtable_itr *i)
 int
 hashtable_iterator_advance(struct hashtable_itr *itr)
 {
-  unsigned int j,tablelength;
+  unsigned int j, tablelength;
   struct entry **table;
   struct entry *next;