#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 | |
| hashtable * | create_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 |
| 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:

Definition at line 90 of file hashtable.c.
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 }
Definition at line 162 of file hashtable.c.
References h.
00163 { 00164 return h->entrycount; 00165 }
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:

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:

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:

| 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().
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.
1.5.1