1 /* Copyright (c) 2015 Regents of the University of California
3 * Author: Brian Demsky <bdemsky@uci.edu>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
11 * @brief Hashtable. Standard chained bucket variety.
14 #ifndef __HASHTABLE_H__
15 #define __HASHTABLE_H__
24 * @brief A simple, custom hash table
26 * By default it is model_malloc, but you can pass in your own allocation
27 * functions. Note that this table does not support the value 0 (NULL) used as
28 * a key and is designed primarily with pointer-based keys in mind. Other
29 * primitive key types are supported only for non-zero values.
31 * @tparam _Key Type name for the key
32 * @tparam _Val Type name for the values to be stored
33 * @tparam _KeyInt Integer type that is at least as large as _Key. Used for key
34 * manipulation and storage.
35 * @tparam _Shift Logical shift to apply to all keys. Default 0.
37 #define HashTableDef(Name, _Key, _Val, _KeyInt, _Shift, hash_function, equals)\
38 struct hashlistnode ## Name { \
43 struct HashTable ## Name { \
44 struct hashlistnode ## Name *table; \
45 struct hashlistnode ## Name *zero; \
46 unsigned int capacity; \
48 unsigned int capacitymask; \
49 unsigned int threshold; \
53 typedef struct HashTable ## Name HashTable ## Name; \
54 HashTable ## Name * allocHashTable ## Name(unsigned int initialcapacity, double factor); \
55 void freeHashTable ## Name(HashTable ## Name * tab); \
56 void reset ## Name(HashTable ## Name * tab); \
57 void resetandfree ## Name(HashTable ## Name * tab); \
58 void put ## Name(HashTable ## Name * tab, _Key key, _Val val); \
59 _Val get ## Name(HashTable ## Name * tab, _Key key) const; \
60 _Val remove ## Name(HashTable ## Name * tab, _Key key); \
61 unsigned int getSize ## Name(HashTable ## Name * tab, ) const; \
62 bool contains ## Name(HashTable ## Name * tab, _Key key) const; \
63 void resize ## Name(HashTable ## Name * tab, unsigned int newsize); \
64 double getLoadFactor ## Name(HashTable ## Name * tab); \
65 unsigned int getCapacity ## Name(HashTable ## Name * tab);
67 #define HashTableDef(Name, _Key, _Val, _KeyInt, _Shift, hash_function, equals) \
68 HashTable ## Name * allocHashTable ## Name(unsigned int initialcapacity, double factor) { \
69 HashTable ## Name * tab = (HashTable ## Name *) ourmalloc(sizeof(HashTable ## Name)); \
70 tab -> table = (struct hashlistnode ## Name *) ourcalloc(initialcapacity, sizeof(struct hashlistnode ## Name)); \
72 tab->loadfactor = factor; \
73 tab->capacity = initialcapacity; \
74 tab->capacitymask = initialcapacity - 1; \
76 tab->threshold = (unsigned int)(initialcapacity * loadfactor); \
80 void freeHashTable ## Name(HashTable ## Name * tab) { \
81 ourfree(tab->table); \
87 void reset ## Name(HashTable ## Name * tab) { \
88 memset(tab->table, 0, capacity * sizeof(struct hashlistnode ## Name)); \
96 void resetandfree ## Name(HashTable ## Name * tab) { \
97 for(unsigned int i=0;i<tab->capacity;i++) { \
98 struct hashlistnode ## Name *bin = &tab->table[i]; \
99 if (bin->key != NULL) { \
101 if (bin->val != NULL) { \
108 if (tab->zero->val != NULL) \
109 ourfree(tab->zero->val); \
110 ourfree(tab->zero); \
116 void put ## Name(HashTable ## Name * tab, _Key key, _Val val) { \
119 tab->zero=(struct hashlistnode ## Name *)ourmalloc(sizeof(struct hashlistnode ## Name)); \
122 tab->zero->key=key; \
123 tab->zero->val=val; \
127 if (tab->size > tab->threshold) \
128 resize(tab->capacity << 1); \
130 struct hashlistnode ## Name *search; \
132 unsigned int index = hash_function(key); \
134 index &= tab->capacitymask; \
135 search = &tab->table[index]; \
136 if (!search->key) { \
139 if (equals(search->key, key)) { \
151 _Val get ## Name(HashTable ## Name * tab, _Key key) const { \
152 struct hashlistnode ## Name *search; \
156 return tab->zero->val; \
161 unsigned int oindex = hash_function(key) & tab->capacitymask; \
162 unsigned int index=oindex; \
164 search = &tab->table[index]; \
165 if (!search->key) { \
169 if (equals(search->key, key)) \
170 return search->val; \
172 index &= tab->capacitymask; \
179 _Val remove ## Name(HashTable ## Name * tab, _Key key) { \
180 struct hashlistnode ## Name *search; \
186 _Val v=tab->zero->val; \
187 ourfree(tab->zero); \
194 unsigned int index = hash_function(key); \
196 index &= tab->capacitymask; \
197 search = &tab->table[index]; \
198 if (!search->key) { \
202 if (equals(search->key, key)) { \
203 _Val v=search->val; \
204 search->val=(_Val) 1; \
214 unsigned int getSize ## Name(HashTable ## Name * tab, ) const { \
219 bool contains ## Name(HashTable ## Name * tab, _Key key) const { \
220 struct hashlistnode ## Name *search; \
222 return tab->zero!=NULL; \
224 unsigned int index = hash_function(key); \
226 index &= tab->capacitymask; \
227 search = &tab->table[index]; \
228 if (!search->key) { \
232 if (equals(search->key, key)) \
239 void resize ## Name(HashTable ## Name * tab, unsigned int newsize) { \
240 struct hashlistnode ## Name *oldtable = tab->table; \
241 struct hashlistnode ## Name *newtable; \
242 unsigned int oldcapacity = tab->capacity; \
244 if ((newtable = (struct hashlistnode ## Name *)ourcalloc(newsize, sizeof(struct hashlistnode ## Name))) == NULL) { \
245 model_print("calloc error %s %d\n", __FILE__, __LINE__); \
246 exit(EXIT_FAILURE); \
249 tab->table = newtable; \
250 tab->capacity = newsize; \
251 tab->capacitymask = newsize - 1; \
253 tab->threshold = (unsigned int)(newsize * loadfactor); \
255 struct hashlistnode ## Name *bin = &oldtable[0]; \
256 struct hashlistnode ## Name *lastbin = &oldtable[oldcapacity]; \
257 for (;bin < lastbin;bin++) { \
258 _Key key = bin->key; \
260 struct hashlistnode ## Name *search; \
264 unsigned int index = hash_function(key); \
266 index &= tab->capacitymask; \
267 search = &tab->table[index]; \
269 } while (search->key); \
272 search->val = bin->val; \
277 double getLoadFactor ## Name(HashTable ## Name * tab) {return tab->loadfactor;} \
278 unsigned int getCapacity ## Name(HashTable ## Name * tab) {return tab->capacity;}
283 #endif/* __HASHTABLE_H__ */