4eae7571d24af74369b0f5ba55ebce40cd297a48
[model-checker.git] / hashtable.h
1 /** @file hashtable.h
2  *  @brief Hashtable.  Standard chained bucket variety.
3  */
4
5 #ifndef HASHTABLE_H
6 #define HASHTABLE_H
7
8 #include <stdlib.h>
9 #include <stdio.h>
10
11 template<typename _Key, typename _Val>
12         struct hashlistnode {
13                 _Key key;
14                 _Val val;
15                 struct hashlistnode<_Key,_Val> *next;
16         };
17
18 /** Hashtable class.  By default it is snapshotting, but you can pass
19                 in your own allocation functions. */
20
21 template<typename _Key, typename _Val, typename _KeyInt, int _Shift=0, void * (* _malloc)(size_t)=malloc, void * (* _calloc)(size_t, size_t)=calloc, void (*_free)(void *)=free>
22         class HashTable {
23  public:
24         HashTable(unsigned int initialcapacity=1024, double factor=0.5) {
25                 // Allocate space for the hash table
26                 table = (struct hashlistnode<_Key,_Val> **) _calloc(initialcapacity, sizeof(struct hashlistnode<_Key,_Val> *));
27                 loadfactor = factor;
28                 capacity = initialcapacity;
29                 threshold = (unsigned int) (initialcapacity*loadfactor);
30                 mask = (capacity << _Shift)-1;
31                 size = 0; // Initial number of elements in the hash
32         }
33
34         ~HashTable() {
35                 for(unsigned int i=0;i<capacity;i++) {
36                         struct hashlistnode<_Key,_Val> * bin = table[i];
37                         while(bin!=NULL) {
38                                 struct hashlistnode<_Key,_Val> * next=bin->next;
39                                 delete bin;
40                                 bin=next;
41                         }
42                 }
43                 _free(table);
44         }
45
46         void * operator new(size_t size) {
47                 return _malloc(size);
48         }
49
50         void operator delete(void *p, size_t size) {
51                 _free(p);
52         }
53
54         void * operator new[](size_t size) {
55                 return _malloc(size);
56         }
57
58         void operator delete[](void *p, size_t size) {\
59                 _free(p);
60         }
61
62         /** Reset the table to its initial state. */
63         void reset() {
64                 for(int i=0;i<capacity;i++) {
65                         struct hashlistnode<_Key,_Val> * bin = table[i];
66                         while(bin!=NULL) {
67                                 struct hashlistnode<_Key,_Val> * next=bin->next;
68                                 delete bin;
69                                 bin=next;
70                         }
71                 }
72                 memset(table, 0, capacity*sizeof(struct hashlistnode<_Key, _Val> *));
73                 size=0;
74         }
75
76         /** Put a key value pair into the table. */
77         void put(_Key key, _Val val) {
78                 if(size > threshold) {
79                         //Resize
80                         unsigned int newsize = capacity << 1;
81                         resize(newsize);
82                 }
83
84                 struct hashlistnode<_Key,_Val> *ptr = table[(((_KeyInt)key) & mask)>>_Shift];
85                 size++;
86                 struct hashlistnode<_Key,_Val> *search = ptr;
87
88                 while(search!=NULL) {
89                         if (search->key==key) {
90                                 search->val=val;
91                                 return;
92                         }
93                         search=search->next;
94                 }
95
96                 struct hashlistnode<_Key,_Val> *newptr=(struct hashlistnode<_Key,_Val> *)new struct hashlistnode<_Key,_Val>;
97                 newptr->key=key;
98                 newptr->val=val;
99                 newptr->next=ptr;
100                 table[(((_KeyInt)key)&mask)>>_Shift]=newptr;
101         }
102
103         /** Put a key entry into the table. */
104   _Val * ensureptr(_Key key) {
105                 if(size > threshold) {
106                         //Resize
107                   unsigned int newsize = capacity << 1;
108                   resize(newsize);
109           }
110
111           struct hashlistnode<_Key,_Val> *ptr = table[(((_KeyInt)key) & mask)>>_Shift];
112                 size++;
113                 struct hashlistnode<_Key,_Val> *search = ptr;
114
115                 while(search!=NULL) {
116                         if (search->key==key) {
117                                 return &search->val;
118                         }
119                         search=search->next;
120                 }
121
122                 struct hashlistnode<_Key,_Val> *newptr=(struct hashlistnode<_Key,_Val> *)new struct hashlistnode<_Key,_Val>;
123                 newptr->key=key;
124                 newptr->next=ptr;
125                 table[(((_KeyInt)key)&mask)>>_Shift]=newptr;
126                 return &newptr->val;
127         }
128
129         /** Lookup the corresponding value for the given key. */
130         _Val get(_Key key) {
131                 struct hashlistnode<_Key,_Val> *search = table[(((_KeyInt)key) & mask)>>_Shift];
132
133                 while(search!=NULL) {
134                         if (search->key==key) {
135                                 return search->val;
136                         }
137                         search=search->next;
138                 }
139                 return (_Val)0;
140         }
141
142         /** Lookup the corresponding value for the given key. */
143         _Val * getptr(_Key key) {
144                 struct hashlistnode<_Key,_Val> *search = table[(((_KeyInt)key) & mask)>>_Shift];
145
146                 while(search!=NULL) {
147                         if (search->key==key) {
148                                 return & search->val;
149                         }
150                         search=search->next;
151                 }
152                 return (_Val *) NULL;
153         }
154
155         /** Check whether the table contains a value for the given key. */
156         bool contains(_Key key) {
157                 struct hashlistnode<_Key,_Val> *search = table[(((_KeyInt)key) & mask)>>_Shift];
158
159                 while(search!=NULL) {
160                         if (search->key==key) {
161                                 return true;
162                         }
163                         search=search->next;
164                 }
165                 return false;
166         }
167
168         /** Resize the table. */
169         void resize(unsigned int newsize) {
170                 struct hashlistnode<_Key,_Val> ** oldtable = table;
171                 struct hashlistnode<_Key,_Val> ** newtable;
172                 unsigned int oldcapacity = capacity;
173
174                 if((newtable = (struct hashlistnode<_Key,_Val> **) _calloc(newsize, sizeof(struct hashlistnode<_Key,_Val> *))) == NULL) {
175                         printf("Calloc error %s %d\n", __FILE__, __LINE__);
176                         exit(-1);
177                 }
178
179                 table = newtable;          //Update the global hashtable upon resize()
180                 capacity = newsize;
181                 threshold = (unsigned int) (newsize * loadfactor);
182                 mask = (newsize << _Shift)-1;
183
184                 for(unsigned int i = 0; i < oldcapacity; i++) {
185                         struct hashlistnode<_Key, _Val> * bin = oldtable[i];
186
187                         while(bin!=NULL) {
188                                 _Key key=bin->key;
189                                 struct hashlistnode<_Key, _Val> * next=bin->next;
190
191                                 unsigned int index = (((_KeyInt)key) & mask) >>_Shift;
192                                 struct hashlistnode<_Key, _Val> * tmp=newtable[index];
193                                 bin->next=tmp;
194                                 newtable[index]=bin;
195                                 bin = next;
196                         }
197                 }
198
199                 _free(oldtable);            //Free the memory of the old hash table
200         }
201
202  private:
203         struct hashlistnode<_Key,_Val> **table;
204         unsigned int capacity;
205         _KeyInt mask;
206         unsigned int size;
207         unsigned int threshold;
208         double loadfactor;
209 };
210 #endif