[insert project logo here (125x200px max)]

Navigator

Mailinglists

Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums.

Copyright and Licensing Information

Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL).

All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License.

All sourcecode is made publicly available.

Acknowledgement

Splash and the Splash website are hosted by SourceForge.net

SourceForge.net Logo

osi-open source certified logo

Splash - Documentation

SNMP Plus a Lightweight API for SNAP Handling

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

snap-1.1-wjdb/lib/snap_hashtable.c

Go to the documentation of this file.
00001 /* snap-1.0. Copyright (C) 2000 by Jonathan T. Moore and Michael Hicks.
00002  *
00003  * hashtable.c : basic hash table library, used to manage the
00004  *   node-resident service namespace
00005  *
00006  * $Id: snap_hashtable.c,v 1.2 2003/03/07 11:41:53 wdebruij Exp $
00007  */
00008 
00009 #ifdef __KERNEL__
00010 #include <linux/slab.h>
00011 #include <linux/string.h>
00012 #include <snap/myassert.h>
00013 #include <snap/list.h>
00014 #include <snap/hashtable.h>
00015 #else
00016 #include <assert.h>
00017 #include "list.h"
00018 #include "memalloc.h"
00019 #include "hashtable.h"
00020 #endif /* __KERNEL__ */
00021 
00022 #include "d_printf.h"
00023 
00024 /* hash function for the table */
00025 int hash_string(char *s) {
00026   int ans   = 0;
00027   int shift = 0;
00028   int i, sz;
00029 
00030   assert(s != NULL);
00031   sz = strlen(s);
00032 
00033   for(i=0; i < sz; ++i) {
00034     ans = ans ^ (s[i] << shift);
00035     shift += 8;
00036     if(shift == 32)
00037       shift = 0;
00038   }
00039   return ans;
00040 }
00041 
00042 
00043 int ht_errno = 0;
00044 static void resize(hash_table_t* t);
00045 
00046 hash_table_t *ht_create(int sz,
00047             int (*cmp)(const void *,const void *),
00048             int (*hash)(void *)) {
00049   hash_table_t *ht = NULL;
00050   list_t **tab = NULL;
00051   int tab_sizeb = sizeof(list_t *)*sz;
00052 
00053 #ifdef __KERNEL__
00054   ht = (hash_table_t *)kmalloc(sizeof(hash_table_t),GFP_ATOMIC);
00055   if (!ht) {
00056     printk(KERN_WARNING "%s:%d: kmalloc failed\n",__FILE__,__LINE__);
00057     return NULL;
00058   }
00059   tab = (list_t **)kmalloc(tab_sizeb,GFP_ATOMIC);
00060   if (!tab) {
00061     printk(KERN_WARNING "%s:%d: kmalloc failed\n",__FILE__,__LINE__);
00062     return NULL;
00063   }
00064   memset(tab,0,tab_sizeb);
00065 #else
00066   memalloc(ht,hash_table_t *,sizeof(hash_table_t));
00067   memalloc(tab,list_t **,tab_sizeb);
00068   bzero(tab,tab_sizeb);
00069 #endif /* __KERNEL__ */
00070   ht->cmp = cmp;
00071   ht->hash = hash;
00072   ht->tab = tab;
00073   ht->max_len = 3;
00074   ht->tab_sz = sz;
00075   return ht;
00076 }
00077 
00078 void ht_insert(hash_table_t *t, void *key, void *val) {
00079   list_t **tab;
00080   int bucket;
00081   pair_t *elem;
00082 
00083   assert(t != NULL);
00084 
00085   d_printf(110,"snap_hashtable : inserting key %s\n",(char*) key);
00086   tab = t->tab;
00087   bucket = t->hash(key) % t->tab_sz;
00088 
00089 #ifdef __KERNEL__
00090   elem = (pair_t *)kmalloc(sizeof(pair_t),GFP_ATOMIC);
00091   if (!elem) {
00092     printk(KERN_WARNING "%s:%d: kmalloc failed\n",__FILE__,__LINE__);
00093     return;
00094   }
00095 #else
00096   memalloc(elem,pair_t *,sizeof(pair_t));
00097 #endif /* __KERNEL__ */
00098   elem->key = key;
00099   elem->value = val;
00100 
00101   tab[bucket] = cons(elem,tab[bucket]);
00102   if (length_list (tab[bucket]) > t->max_len) 
00103     resize(t);
00104 }
00105 
00106 static void *assoc_cmp(int (*cmp)(const void *,const void *), 
00107                list_t *list, void *key) {
00108   list_t *iter = list;
00109 
00110   ht_errno = 0;
00111   while (iter != NULL) {
00112     pair_t *elem = (pair_t *)iter->v;
00113     if (!cmp(elem->key,key))
00114       return elem->value;
00115     iter = iter->next;
00116   }
00117   ht_errno = 1; /* didn't find it */
00118   return NULL;
00119 }
00120 
00121 void *ht_lookup(hash_table_t *t, void *key) {
00122   list_t **tab, *l;
00123 
00124   d_printf(110,"snap_hashtable : searching for key %s\n",(char*) key);
00125   
00126   assert(t != NULL);
00127 
00128   tab  = t->tab;
00129   l     = tab[t->hash(key) % t->tab_sz];
00130 
00131   return assoc_cmp(t->cmp, l, key);
00132 }
00133 
00134 void ht_remove(hash_table_t * t, void *key) {
00135   int     bucket;
00136   list_t *l, *prev;
00137   pair_t *elem;
00138 
00139   assert(t != NULL);
00140 
00141   bucket   = t->hash(key) % t->tab_sz;
00142   l        = t->tab[bucket];
00143   if(l == NULL)
00144     return;
00145 
00146   elem = (pair_t *)l->v;
00147   if(t->cmp(key,elem->key)==0) {
00148     t->tab[bucket] = l->next;
00149     free(elem->key);
00150     free(elem);
00151     return;
00152   }
00153   prev = l; l = l->next;
00154   for(; l->next != NULL; prev = l, l=l->next) {
00155     elem = (pair_t *)l->v;
00156     if(t->cmp(key,elem->key)==0) {
00157       prev->next = l->next;
00158       free(elem->key);
00159       free(elem);
00160       return;
00161     }
00162   }
00163 }
00164 
00165 /* For resizing */
00166 static void insert_bucket(list_t **tab, int tab_sz,
00167               int (*hash)(void *), list_t *elems) {
00168   pair_t *elem;
00169   int nidx;
00170 
00171   assert(tab != NULL);
00172   assert(tab_sz > 0);
00173 
00174   if (elems == NULL) return;
00175   insert_bucket(tab,tab_sz,hash,elems->next); // preserve the original order
00176 #ifdef __KERNEL__
00177   elem = (pair_t *)kmalloc(sizeof(pair_t),GFP_ATOMIC);
00178   if (!elem) {
00179     printk(KERN_WARNING "%s:%d: kmalloc failed\n",__FILE__,__LINE__);
00180     return;
00181   }
00182 #else
00183   memalloc(elem,pair_t *,sizeof(pair_t));
00184 #endif /* __KERNEL__ */
00185   elem->key = ((pair_t *)(elems->v))->key;
00186   elem->value = ((pair_t *)(elems->v))->value;
00187   nidx = hash(elem->key) % tab_sz;
00188   tab[nidx] = cons(elem,tab[nidx]);
00189 }
00190 
00191 static void resize(hash_table_t *t) {
00192   list_t **odata, **ndata;
00193   int osize, nsize, ndata_sizeb;
00194   int i;
00195 
00196   assert(t != NULL);
00197 
00198   odata  = t->tab;
00199   osize       = t->tab_sz;
00200   nsize       = 2 * osize + 1;
00201   ndata_sizeb = sizeof(list_t *)*nsize;
00202 
00203 #ifdef __KERNEL__
00204   ndata = (list_t **)kmalloc(ndata_sizeb,GFP_ATOMIC);
00205   if (!ndata) {
00206     printk(KERN_WARNING "%s:%d: kmalloc failed\n",__FILE__,__LINE__);
00207     return;
00208   }
00209   memset(ndata,0,ndata_sizeb);
00210 #else
00211   memalloc(ndata,list_t **,ndata_sizeb);
00212   bzero(ndata,ndata_sizeb);
00213 #endif /* __KERNEL__ */
00214 
00215   for (i = 0; i<osize; i++)
00216     insert_bucket(ndata,t->tab_sz,t->hash,odata[i]);
00217   t->tab = ndata;
00218   t->max_len = 2 * t->max_len;
00219 }