]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-6453 --resolve
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 10 Apr 2014 22:24:14 +0000 (03:24 +0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 10 Apr 2014 22:24:14 +0000 (03:24 +0500)
src/include/switch_hashtable.h
src/switch_core_hash.c
src/switch_hashtable.c

index dddc89f286cb1c73f2ffb7fd2687286db0327c99..1fdbeb9736baaf9f24b2a67f512227cda9a4ce41 100644 (file)
@@ -119,7 +119,8 @@ switch_create_hashtable(switch_hashtable_t **hp, unsigned int minsize,
 typedef enum {
        HASHTABLE_FLAG_NONE = 0,
        HASHTABLE_FLAG_FREE_KEY = (1 << 0),
-       HASHTABLE_FLAG_FREE_VALUE = (1 << 1)
+       HASHTABLE_FLAG_FREE_VALUE = (1 << 1),
+       HASHTABLE_DUP_CHECK = (1 << 2)
 } hashtable_flag_t;
 
 SWITCH_DECLARE(int)
index e997ac9bcc43b93b382dc5851540062a2c4394cb..ddf08c0c6c7d0c777aab11441a371a9a1258395c 100644 (file)
@@ -57,7 +57,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_hash_destroy(switch_hash_t **hash)
 
 SWITCH_DECLARE(switch_status_t) switch_core_hash_insert_destructor(switch_hash_t *hash, const char *key, const void *data, hashtable_destructor_t destructor)
 {
-       switch_hashtable_insert_destructor(hash, strdup(key), (void *)data, HASHTABLE_FLAG_FREE_KEY, destructor);
+       switch_hashtable_insert_destructor(hash, strdup(key), (void *)data, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_DUP_CHECK, destructor);
        
        return SWITCH_STATUS_SUCCESS;
 }
index 7f8ba15de031f15cc294db4127ed6c06c2735e6f..597312b8059048a228dc87d5dd6dee4ac02ebfa2 100644 (file)
@@ -153,13 +153,54 @@ switch_hashtable_count(switch_hashtable_t *h)
     return h->entrycount;
 }
 
+static void * _switch_hashtable_remove(switch_hashtable_t *h, void *k, unsigned int hashvalue, unsigned int index) {
+    /* TODO: consider compacting the table when the load factor drops enough,
+     *       or provide a 'compact' method. */
+
+    struct entry *e;
+    struct entry **pE;
+    void *v;
+
+
+    pE = &(h->table[index]);
+    e = *pE;
+    while (NULL != e) {
+               /* Check hash value to short circuit heavier comparison */
+               if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
+                       *pE = e->next;
+                       h->entrycount--;
+                       v = e->v;
+                       if (e->flags & HASHTABLE_FLAG_FREE_KEY) {
+                               freekey(e->k);
+                       }
+                       if (e->flags & HASHTABLE_FLAG_FREE_VALUE) {
+                               switch_safe_free(e->v); 
+                               v = NULL;
+                       } else if (e->destructor) {
+                               e->destructor(e->v);
+                               v = e->v = NULL;
+                       }
+                       switch_safe_free(e);
+                       return v;
+               }
+               pE = &(e->next);
+               e = e->next;
+       }
+    return NULL;
+}
+
 /*****************************************************************************/
 SWITCH_DECLARE(int)
 switch_hashtable_insert_destructor(switch_hashtable_t *h, void *k, void *v, hashtable_flag_t flags, hashtable_destructor_t destructor)
 {
-    /* This method allows duplicate keys - but they shouldn't be used */
-    unsigned int index;
     struct entry *e;
+       unsigned int hashvalue = hash(h, k);
+    unsigned index = indexFor(h->tablelength, hashvalue);
+
+       if (flags & HASHTABLE_DUP_CHECK) {
+               _switch_hashtable_remove(h, k, hashvalue, index);
+       }
+
     if (++(h->entrycount) > h->loadlimit)
                {
                        /* Ignore the return value. If expand fails, we should
@@ -167,11 +208,11 @@ switch_hashtable_insert_destructor(switch_hashtable_t *h, void *k, void *v, hash
                         * -- we may not have memory for a larger table, but one more
                         * element may be ok. Next time we insert, we'll try expanding again.*/
                        hashtable_expand(h);
+                       index = indexFor(h->tablelength, hashvalue);
                }
     e = (struct entry *)malloc(sizeof(struct entry));
     if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
-    e->h = hash(h,k);
-    index = indexFor(h->tablelength,e->h);
+    e->h = hashvalue;
     e->k = k;
     e->v = v;
        e->flags = flags;
@@ -202,40 +243,8 @@ switch_hashtable_search(switch_hashtable_t *h, void *k)
 SWITCH_DECLARE(void *) /* returns value associated with key */
 switch_hashtable_remove(switch_hashtable_t *h, void *k)
 {
-    /* TODO: consider compacting the table when the load factor drops enough,
-     *       or provide a 'compact' method. */
-
-    struct entry *e;
-    struct entry **pE;
-    void *v;
-    unsigned int hashvalue, index;
-
-    hashvalue = hash(h,k);
-    index = indexFor(h->tablelength,hashvalue);
-    pE = &(h->table[index]);
-    e = *pE;
-    while (NULL != e) {
-               /* Check hash value to short circuit heavier comparison */
-               if ((hashvalue == e->h) && (h->eqfn(k, e->k))) {
-                       *pE = e->next;
-                       h->entrycount--;
-                       v = e->v;
-                       if (e->flags & HASHTABLE_FLAG_FREE_KEY) {
-                               freekey(e->k);
-                       }
-                       if (e->flags & HASHTABLE_FLAG_FREE_VALUE) {
-                               switch_safe_free(e->v); 
-                       } else if (e->destructor) {
-                               e->destructor(e->v);
-                               e->v = NULL;
-                       }
-                       switch_safe_free(e);
-                       return v;
-               }
-               pE = &(e->next);
-               e = e->next;
-       }
-    return NULL;
+       unsigned int hashvalue = hash(h,k);
+       return _switch_hashtable_remove(h, k, hashvalue, indexFor(h->tablelength,hashvalue));
 }
 
 /*****************************************************************************/