00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "hashtable.h"
00036 #include "hashtable_private.h"
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <math.h>
00041 #include "../MALLOC/includes/MALLOC.h"
00042
00043
00044
00045
00046
00047
00048 static const unsigned int primes[] = {
00049 53, 97, 193, 389,
00050 769, 1543, 3079, 6151,
00051 12289, 24593, 49157, 98317,
00052 196613, 393241, 786433, 1572869,
00053 3145739, 6291469, 12582917, 25165843,
00054 50331653, 100663319, 201326611, 402653189,
00055 805306457, 1610612741
00056 };
00057 const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
00058 const float max_load_factor = 0.65f;
00059
00060
00061 struct hashtable *
00062 create_hashtable(unsigned int minsize,
00063 unsigned int (*hashf) (void*),
00064 int (*eqf) (void*,void*))
00065 {
00066 struct hashtable *h;
00067 unsigned int pindex, size = primes[0];
00068
00069 if (minsize > (1u << 30)) return NULL;
00070
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;
00076 h->table = (struct entry **)MALLOC(sizeof(struct entry*) * size);
00077 if (NULL == h->table) { FREE(h); return NULL; }
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 }
00087
00088
00089 unsigned int
00090 hash(struct hashtable *h, void *k)
00091 {
00092
00093
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 }
00101
00102
00103 static int
00104 hashtable_expand(struct hashtable *h)
00105 {
00106
00107 struct entry **newtable;
00108 struct entry *e;
00109 struct entry **pE;
00110 unsigned int newsize, i, index_;
00111
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
00120
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
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 }
00159
00160
00161 unsigned int
00162 hashtable_count(struct hashtable *h)
00163 {
00164 return h->entrycount;
00165 }
00166
00167
00168 int
00169 hashtable_insert(struct hashtable *h, void *k, void *v)
00170 {
00171
00172 unsigned int index_;
00173 struct entry *e;
00174 if (++(h->entrycount) > h->loadlimit)
00175 {
00176
00177
00178
00179
00180 hashtable_expand(h);
00181 }
00182 e = (struct entry *)MALLOC(sizeof(struct entry));
00183 if (NULL == e) { --(h->entrycount); return 0; }
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 }
00192
00193
00194 void *
00195 hashtable_search(struct hashtable *h, void *k)
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
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 }
00214
00215
00216 void *
00217 hashtable_remove(struct hashtable *h, void *k)
00218 {
00219
00220
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
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 }
00248
00249
00250
00251 void hashtable_destroy(struct hashtable *h, int free_values)
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 }
00277