closes issue #11356; Many thanks to snuffy for his code review and changes to cut...
[asterisk/asterisk.git] / main / hashtab.c
index 4c36bc1..41e6b2b 100644 (file)
@@ -39,6 +39,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision")
 #include "asterisk/hashtab.h"
 
 static void ast_hashtab_resize( struct ast_hashtab *tab);
+static void *ast_hashtab_lookup_internal(struct ast_hashtab *tab, const void *obj, unsigned int h);
 
 /* some standard, default routines for general use */
 
@@ -208,12 +209,12 @@ unsigned int ast_hashtab_hash_short(const short x)
        return x;
 }
 
-struct ast_hashtab *ast_hashtab_create(int initial_buckets,
-       int (*compare)(const void *a, const void *b), /* a func to compare two elements in the hash -- cannot be null  */
-       int (*resize)(struct ast_hashtab *), /* a func to decide if the table needs to be resized, a NULL ptr here will cause a default to be used */
-       int (*newsize)(struct ast_hashtab *tab), /* a ptr to func that returns a new size of the array. A NULL will cause a default to be used */
-       unsigned int (*hash)(const void *obj), /* a func to do the hashing */
-       int do_locking ) /* use locks to guarantee safety of iterators/insertion/deletion -- real simpleminded right now */
+struct ast_hashtab *ast_hashtab_create(int initial_buckets, 
+       int (*compare)(const void *a, const void *b), 
+       int (*resize)(struct ast_hashtab *), 
+       int (*newsize)(struct ast_hashtab *tab),
+       unsigned int (*hash)(const void *obj), 
+       int do_locking)
 {
        struct ast_hashtab *ht;
        
@@ -460,12 +461,11 @@ int ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj)
        return 0;
 }
 
-void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
+void *ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
 {
        /* lookup this object in the hash table. return a ptr if found, or NULL if not */
        unsigned int h;
-       const void *ret;
-       struct ast_hashtab_bucket *b;
+       void *ret;
 
        if (!tab || !obj)
                return 0;
@@ -474,27 +474,21 @@ void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
                ast_rwlock_rdlock(&tab->lock);
 
        h = (*tab->hash)(obj) % tab->hash_tab_size;
-       for (b = tab->array[h]; b; b = b->next) {
-               if (!(*tab->compare)(obj,b->object)) {
-                       ret = b->object;
-                       if (tab->do_locking)
-                               ast_rwlock_unlock(&tab->lock);
-                       return (void*) ret; /* I can't touch obj in this func, but the outside world is welcome to */
-               }
-       }
+
+       ret = ast_hashtab_lookup_internal(tab,obj,h);
 
        if (tab->do_locking)
                ast_rwlock_unlock(&tab->lock);
 
-       return 0;
+       return ret;
 }
 
+
 void *ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, unsigned int hashval)
 {
        /* lookup this object in the hash table. return a ptr if found, or NULL if not */
        unsigned int h;
-       const void *ret;
-       struct ast_hashtab_bucket *b;
+       void *ret;
 
        if (!tab || !obj)
                return 0;
@@ -503,38 +497,43 @@ void *ast_hashtab_lookup_with_hash(struct ast_hashtab *tab, const void *obj, uns
                ast_rwlock_rdlock(&tab->lock);
                
        h = hashval % tab->hash_tab_size;
-       for (b = tab->array[h]; b; b = b->next) {
-               if (!(*tab->compare)(obj,b->object)) {
-                       ret = b->object;
-                       if (tab->do_locking)
-                               ast_rwlock_unlock(&tab->lock);
-                       return (void*) ret; /* I can't touch obj in this func, but the outside world is welcome to */
-               }
-       }
 
+       ret = ast_hashtab_lookup_internal(tab,obj,h);
+       
        if (tab->do_locking)
                ast_rwlock_unlock(&tab->lock);
 
-       return 0;
+       return ret;
 }
 
-void * ast_hashtab_lookup_bucket(struct ast_hashtab *tab, const void *obj, unsigned int *bucket)
+void *ast_hashtab_lookup_bucket(struct ast_hashtab *tab, const void *obj, unsigned int *bucket)
 {
        /* lookup this object in the hash table. return a ptr if found, or NULL if not */
        unsigned int h;
-       struct ast_hashtab_bucket *b;
+       void *ret;
 
        if (!tab || !obj)
                return 0;
        
        h = (*tab->hash)(obj) % tab->hash_tab_size;
+       
+       ret = ast_hashtab_lookup_internal(tab,obj,h);
+       
+       *bucket = h; 
+       
+       return ret;
+}
+
+static void *ast_hashtab_lookup_internal(struct ast_hashtab *tab, const void *obj, unsigned int h)
+{
+       struct ast_hashtab_bucket *b;
+
        for (b = tab->array[h]; b; b = b->next) {
-               if (!(*tab->compare)(obj,b->object))
+               if (!(*tab->compare)(obj,b->object)) {
                        return (void*) b->object; /* I can't touch obj in this func, but the outside world is welcome to */
+               }
        }
 
-       *bucket = h;
-       
        return 0;
 }