hashtable.c File Reference

#include "hashtable.h"
#include "hashtable_private.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "../MALLOC/includes/MALLOC.h"

Include dependency graph for hashtable.c:

Go to the source code of this file.

Functions

hashtablecreate_hashtable (unsigned int minsize, unsigned int(*hashf)(void *), int(*eqf)(void *, void *))
unsigned int hash (struct hashtable *h, void *k)
static int hashtable_expand (struct hashtable *h)
unsigned int hashtable_count (struct hashtable *h)
int hashtable_insert (struct hashtable *h, void *k, void *v)
void * hashtable_search (struct hashtable *h, void *k)
void * hashtable_remove (struct hashtable *h, void *k)
void hashtable_destroy (struct hashtable *h, int free_values)

Variables

static const unsigned int primes []
const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0])
const float max_load_factor = 0.65f


Function Documentation

struct hashtable* create_hashtable ( unsigned int  minsize,
unsigned int(*)(void *)  hashf,
int(*)(void *, void *)  eqf 
)

Definition at line 62 of file hashtable.c.

References FREE, h, MALLOC, NULL, prime_table_length, and size.

Referenced by createGetHashTable(), CreateHashtable_string(), createSetHashTable(), and myhcreate().

00065 {
00066     struct hashtable *h;
00067     unsigned int pindex, size = primes[0];
00068     /* Check requested hashtable isn't too large */
00069     if (minsize > (1u << 30)) return NULL;
00070     /* Enforce size as prime */
00071     for (pindex=0; pindex < prime_table_length; pindex++) {
00072         if (primes[pindex] > minsize) { size = primes[pindex]; break; }
00073     }
00074     h = (struct hashtable *)MALLOC(sizeof(struct hashtable));
00075     if (NULL == h) return NULL; /*oom*/
00076     h->table = (struct entry **)MALLOC(sizeof(struct entry*) * size);
00077     if (NULL == h->table) { FREE(h); return NULL; } /*oom*/
00078     memset(h->table, 0, size * sizeof(struct entry *));
00079     h->tablelength  = size;
00080     h->primeindex   = pindex;
00081     h->entrycount   = 0;
00082     h->hashfn       = hashf;
00083     h->eqfn         = eqf;
00084     h->loadlimit    = (unsigned int) ceil(size * max_load_factor);
00085     return h;
00086 }

Here is the caller graph for this function:

unsigned int hash ( struct hashtable h,
void *  k 
)

Definition at line 90 of file hashtable.c.

References h, and i.

00091 {
00092     /* Aim to protect against poor hash functions by adding logic here
00093      * - logic taken from java 1.4 hashtable source */
00094     unsigned int i = h->hashfn(k);
00095     i += ~(i << 9);
00096     i ^=  ((i >> 14) | (i << 18)); /* >>> */
00097     i +=  (i << 4);
00098     i ^=  ((i >> 10) | (i << 22)); /* >>> */
00099     return i;
00100 }

unsigned int hashtable_count ( struct hashtable h  ) 

Definition at line 162 of file hashtable.c.

References h.

00163 {
00164     return h->entrycount;
00165 }

void hashtable_destroy ( struct hashtable h,
int  free_values 
)

Definition at line 251 of file hashtable.c.

References f(), FREE, freekey, h, entry::next, NULL, and table.

Referenced by destroyGetHashTable(), DestroyHashtable_string(), destroySetHashTable(), DisposeHashTableScilabErrors(), DisposeHashTableScilabMenus(), DisposeHashTableScilabMessages(), and myhdestroy().

00252 {
00253     unsigned int i;
00254     struct entry *e, *f;
00255     struct entry **table = h->table;
00256     if (free_values)
00257     {
00258         for (i = 0; i < h->tablelength; i++)
00259         {
00260             e = table[i];
00261             while (NULL != e)
00262             { f = e; e = e->next; freekey(f->k); FREE(f->v); FREE(f); }
00263         }
00264     }
00265     else
00266     {
00267         for (i = 0; i < h->tablelength; i++)
00268         {
00269             e = table[i];
00270             while (NULL != e)
00271             { f = e; e = e->next; freekey(f->k); FREE(f); }
00272         }
00273     }
00274     FREE(h->table);
00275     FREE(h);
00276 }

Here is the call graph for this function:

Here is the caller graph for this function:

static int hashtable_expand ( struct hashtable h  )  [static]

Definition at line 104 of file hashtable.c.

References FREE, entry::h, h, i, indexFor(), MALLOC, memset(), entry::next, NULL, and prime_table_length.

Referenced by hashtable_insert().

00105 {
00106     /* Double the size of the table to accomodate more entries */
00107     struct entry **newtable;
00108     struct entry *e;
00109     struct entry **pE;
00110     unsigned int newsize, i, index_;
00111     /* Check we're not hitting max capacity */
00112     if (h->primeindex == (prime_table_length - 1)) return 0;
00113     newsize = primes[++(h->primeindex)];
00114 
00115     newtable = (struct entry **)MALLOC(sizeof(struct entry*) * newsize);
00116     if (NULL != newtable)
00117     {
00118         memset(newtable, 0, newsize * sizeof(struct entry *));
00119         /* This algorithm is not 'stable'. ie. it reverses the list
00120          * when it transfers entries between the tables */
00121         for (i = 0; i < h->tablelength; i++) {
00122             while (NULL != (e = h->table[i])) {
00123                 h->table[i] = e->next;
00124                 index_ = indexFor(newsize,e->h);
00125                 e->next = newtable[index_];
00126                 newtable[index_] = e;
00127             }
00128         }
00129         FREE(h->table);
00130         h->table = newtable;
00131     }
00132     /* Plan B: realloc instead */
00133     else 
00134     {
00135         newtable = (struct entry **) REALLOC(h->table, newsize * sizeof(struct entry *));
00136         if (NULL == newtable) { (h->primeindex)--; return 0; }
00137         h->table = newtable;
00138         memset(newtable[h->tablelength], 0, newsize - h->tablelength);
00139         for (i = 0; i < h->tablelength; i++) {
00140             for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
00141                 index_ = indexFor(newsize,e->h);
00142                 if (index_ == i)
00143                 {
00144                     pE = &(e->next);
00145                 }
00146                 else
00147                 {
00148                     *pE = e->next;
00149                     e->next = newtable[index_];
00150                     newtable[index_] = e;
00151                 }
00152             }
00153         }
00154     }
00155     h->tablelength = newsize;
00156     h->loadlimit   = (unsigned int) ceil(newsize * max_load_factor);
00157     return -1;
00158 }

Here is the call graph for this function:

Here is the caller graph for this function:

int hashtable_insert ( struct hashtable h,
void *  k,
void *  v 
)

Definition at line 169 of file hashtable.c.

References h, entry::h, hash(), hashtable_expand(), indexFor(), entry::k, MALLOC, entry::next, NULL, and entry::v.

Referenced by insertGetHashtable(), InsertHashtable_string(), and insertSetHashtable().

00170 {
00171     /* This method allows duplicate keys - but they shouldn't be used */
00172     unsigned int index_;
00173     struct entry *e;
00174     if (++(h->entrycount) > h->loadlimit)
00175     {
00176         /* Ignore the return value. If expand fails, we should
00177          * still try cramming just this value into the existing table
00178          * -- we may not have memory for a larger table, but one more
00179          * element may be ok. Next time we insert, we'll try expanding again.*/
00180         hashtable_expand(h);
00181     }
00182     e = (struct entry *)MALLOC(sizeof(struct entry));
00183     if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
00184     e->h = hash(h,k);
00185     index_ = indexFor(h->tablelength,e->h);
00186     e->k = k;
00187     e->v = v;
00188     e->next = h->table[index_];
00189     h->table[index_] = e;
00190     return -1;
00191 }

Here is the call graph for this function:

Here is the caller graph for this function:

void* hashtable_remove ( struct hashtable h,
void *  k 
)

Definition at line 217 of file hashtable.c.

References FREE, freekey, h, entry::h, hash(), indexFor(), entry::k, entry::next, NULL, v, and entry::v.

Referenced by RemoveHastable_string().

00218 {
00219     /* TODO: consider compacting the table when the load factor drops enough,
00220      *       or provide a 'compact' method. */
00221 
00222     struct entry *e;
00223     struct entry **pE;
00224     void *v;
00225     unsigned int hashvalue, index_;
00226 
00227     hashvalue = hash(h,k);
00228     index_ = indexFor(h->tablelength,hash(h,k));
00229     pE = &(h->table[index_]);
00230     e = *pE;
00231     while (NULL != e)
00232     {
00233         /* Check hash value to short circuit heavier comparison */
00234         if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
00235         {
00236             *pE = e->next;
00237             h->entrycount--;
00238             v = e->v;
00239             freekey(e->k);
00240             FREE(e);
00241             return v;
00242         }
00243         pE = &(e->next);
00244         e = e->next;
00245     }
00246     return NULL;
00247 }

Here is the call graph for this function:

Here is the caller graph for this function:

void* hashtable_search ( struct hashtable h,
void *  k 
)

Definition at line 195 of file hashtable.c.

References h, entry::h, hash(), indexFor(), entry::k, entry::next, NULL, and entry::v.

Referenced by searchGetHashtable(), SearchHashtable_string(), and searchSetHashtable().

00196 {
00197     struct entry *e;
00198     unsigned int hashvalue, index_;
00199     hashvalue = hash(h,k);
00200     index_ = indexFor(h->tablelength,hashvalue);
00201     e = h->table[index_];
00202     while (NULL != e)
00203     {
00204         /* Check hash value to short circuit heavier comparison */
00205         if ((hashvalue == e->h) && (h->eqfn(k, e->k))) 
00206                 {
00207                         return e->v;
00208                 }
00209                         
00210         e = e->next;
00211     }
00212     return NULL;
00213 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

const float max_load_factor = 0.65f

Definition at line 58 of file hashtable.c.

const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0])

Definition at line 57 of file hashtable.c.

Referenced by create_hashtable(), and hashtable_expand().

const unsigned int primes[] [static]

Initial value:

 {
53, 97, 193, 389,
769, 1543, 3079, 6151,
12289, 24593, 49157, 98317,
196613, 393241, 786433, 1572869,
3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189,
805306457, 1610612741
}

Definition at line 48 of file hashtable.c.


Generated on Sun Mar 4 15:11:32 2007 for Scilab [trunk] by  doxygen 1.5.1