1 /* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
2
3 #include "hashtable.h"
4 #include "hashtable_private.h"
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <math.h>
9 #include <stdint.h>
10
11 /*
12 Credit for primes table: Aaron Krowne
13 http://br.endernet.org/~akrowne/
14 http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
15 */
16 static const unsigned int primes[] = {
17 53, 97, 193, 389,
18 769, 1543, 3079, 6151,
19 12289, 24593, 49157, 98317,
20 196613, 393241, 786433, 1572869,
21 3145739, 6291469, 12582917, 25165843,
22 50331653, 100663319, 201326611, 402653189,
23 805306457, 1610612741
24 };
25 const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
26 const unsigned int max_load_factor = 65; /* percentage */
27
28 /*****************************************************************************/
29 struct hashtable *
create_hashtable(unsigned int minsize,unsigned int (* hashf)(void *),int (* eqf)(void *,void *))30 create_hashtable(unsigned int minsize,
31 unsigned int (*hashf) (void*),
32 int (*eqf) (void*,void*))
33 {
34 struct hashtable *h;
35 unsigned int pindex, size = primes[0];
36
37 /* Check requested hashtable isn't too large */
38 if (minsize > (1u << 30)) return NULL;
39
40 /* Enforce size as prime */
41 for (pindex=0; pindex < prime_table_length; pindex++) {
42 if (primes[pindex] > minsize) { size = primes[pindex]; break; }
43 }
44
45 h = (struct hashtable *)calloc(1, sizeof(struct hashtable));
46 if (NULL == h)
47 goto err0;
48 h->table = (struct entry **)calloc(size, sizeof(struct entry *));
49 if (NULL == h->table)
50 goto err1;
51
52 h->tablelength = size;
53 h->primeindex = pindex;
54 h->entrycount = 0;
55 h->hashfn = hashf;
56 h->eqfn = eqf;
57 h->loadlimit = (unsigned int)(((uint64_t)size * max_load_factor) / 100);
58 return h;
59
60 err1:
61 free(h);
62 err0:
63 return NULL;
64 }
65
66 /*****************************************************************************/
67 unsigned int
hash(struct hashtable * h,void * k)68 hash(struct hashtable *h, void *k)
69 {
70 /* Aim to protect against poor hash functions by adding logic here
71 * - logic taken from java 1.4 hashtable source */
72 unsigned int i = h->hashfn(k);
73 i += ~(i << 9);
74 i ^= ((i >> 14) | (i << 18)); /* >>> */
75 i += (i << 4);
76 i ^= ((i >> 10) | (i << 22)); /* >>> */
77 return i;
78 }
79
80 /*****************************************************************************/
81 static int
hashtable_expand(struct hashtable * h)82 hashtable_expand(struct hashtable *h)
83 {
84 /* Double the size of the table to accomodate more entries */
85 struct entry **newtable;
86 struct entry *e;
87 struct entry **pE;
88 unsigned int newsize, i, index;
89 /* Check we're not hitting max capacity */
90 if (h->primeindex == (prime_table_length - 1)) return 0;
91 newsize = primes[++(h->primeindex)];
92
93 newtable = (struct entry **)calloc(newsize, sizeof(struct entry*));
94 if (NULL != newtable)
95 {
96 /* This algorithm is not 'stable'. ie. it reverses the list
97 * when it transfers entries between the tables */
98 for (i = 0; i < h->tablelength; i++) {
99 while (NULL != (e = h->table[i])) {
100 h->table[i] = e->next;
101 index = indexFor(newsize,e->h);
102 e->next = newtable[index];
103 newtable[index] = e;
104 }
105 }
106 free(h->table);
107 h->table = newtable;
108 }
109 /* Plan B: realloc instead */
110 else
111 {
112 newtable = (struct entry **)
113 realloc(h->table, newsize * sizeof(struct entry *));
114 if (NULL == newtable) { (h->primeindex)--; return 0; }
115 h->table = newtable;
116 memset(newtable[h->tablelength], 0, newsize - h->tablelength);
117 for (i = 0; i < h->tablelength; i++) {
118 for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
119 index = indexFor(newsize,e->h);
120 if (index == i)
121 {
122 pE = &(e->next);
123 }
124 else
125 {
126 *pE = e->next;
127 e->next = newtable[index];
128 newtable[index] = e;
129 }
130 }
131 }
132 }
133 h->tablelength = newsize;
134 h->loadlimit = (unsigned int)
135 (((uint64_t)newsize * max_load_factor) / 100);
136 return -1;
137 }
138
139 /*****************************************************************************/
140 unsigned int
hashtable_count(struct hashtable * h)141 hashtable_count(struct hashtable *h)
142 {
143 return h->entrycount;
144 }
145
146 /*****************************************************************************/
147 int
hashtable_insert(struct hashtable * h,void * k,void * v)148 hashtable_insert(struct hashtable *h, void *k, void *v)
149 {
150 /* This method allows duplicate keys - but they shouldn't be used */
151 unsigned int index;
152 struct entry *e;
153 if (++(h->entrycount) > h->loadlimit)
154 {
155 /* Ignore the return value. If expand fails, we should
156 * still try cramming just this value into the existing table
157 * -- we may not have memory for a larger table, but one more
158 * element may be ok. Next time we insert, we'll try expanding again.*/
159 hashtable_expand(h);
160 }
161 e = (struct entry *)calloc(1, sizeof(struct entry));
162 if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
163 e->h = hash(h,k);
164 index = indexFor(h->tablelength,e->h);
165 e->k = k;
166 e->v = v;
167 e->next = h->table[index];
168 h->table[index] = e;
169 return -1;
170 }
171
172 /*****************************************************************************/
173 void * /* returns value associated with key */
hashtable_search(struct hashtable * h,void * k)174 hashtable_search(struct hashtable *h, void *k)
175 {
176 struct entry *e;
177 unsigned int hashvalue, index;
178 hashvalue = hash(h,k);
179 index = indexFor(h->tablelength,hashvalue);
180 e = h->table[index];
181 while (NULL != e)
182 {
183 /* Check hash value to short circuit heavier comparison */
184 if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
185 e = e->next;
186 }
187 return NULL;
188 }
189
190 /*****************************************************************************/
191 void * /* returns value associated with key */
hashtable_remove(struct hashtable * h,void * k)192 hashtable_remove(struct hashtable *h, void *k)
193 {
194 /* TODO: consider compacting the table when the load factor drops enough,
195 * or provide a 'compact' method. */
196
197 struct entry *e;
198 struct entry **pE;
199 void *v;
200 unsigned int hashvalue, index;
201
202 hashvalue = hash(h,k);
203 index = indexFor(h->tablelength,hash(h,k));
204 pE = &(h->table[index]);
205 e = *pE;
206 while (NULL != e)
207 {
208 /* Check hash value to short circuit heavier comparison */
209 if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
210 {
211 *pE = e->next;
212 h->entrycount--;
213 v = e->v;
214 freekey(e->k);
215 free(e);
216 return v;
217 }
218 pE = &(e->next);
219 e = e->next;
220 }
221 return NULL;
222 }
223
224 /*****************************************************************************/
225 /* destroy */
226 void
hashtable_destroy(struct hashtable * h,int free_values)227 hashtable_destroy(struct hashtable *h, int free_values)
228 {
229 unsigned int i;
230 struct entry *e, *f;
231 struct entry **table = h->table;
232 if (free_values)
233 {
234 for (i = 0; i < h->tablelength; i++)
235 {
236 e = table[i];
237 while (NULL != e)
238 { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
239 }
240 }
241 else
242 {
243 for (i = 0; i < h->tablelength; i++)
244 {
245 e = table[i];
246 while (NULL != e)
247 { f = e; e = e->next; freekey(f->k); free(f); }
248 }
249 }
250 free(h->table);
251 free(h);
252 }
253
254 /*
255 * Copyright (c) 2002, Christopher Clark
256 * All rights reserved.
257 *
258 * Redistribution and use in source and binary forms, with or without
259 * modification, are permitted provided that the following conditions
260 * are met:
261 *
262 * * Redistributions of source code must retain the above copyright
263 * notice, this list of conditions and the following disclaimer.
264 *
265 * * Redistributions in binary form must reproduce the above copyright
266 * notice, this list of conditions and the following disclaimer in the
267 * documentation and/or other materials provided with the distribution.
268 *
269 * * Neither the name of the original author; nor the names of any contributors
270 * may be used to endorse or promote products derived from this software
271 * without specific prior written permission.
272 *
273 *
274 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
275 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
276 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
277 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
278 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
279 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
280 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
281 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
282 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
283 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
284 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
285 */
286