vfs: check userland buffers before reading them.
[haiku.git] / src / bin / bfs_tools / lib / Hashtable.cpp
blobc2a8574ed9582ee427d816bce238d8410aaedc77
1 /* Hashtable - a general purpose hash table
2 **
3 ** Copyright 2001 pinc Software. All Rights Reserved.
4 ** Released under the terms of the MIT license.
5 */
8 #include <stdlib.h>
9 #include <stdarg.h>
10 #include <string.h>
12 #include "Hashtable.h"
15 /************************** standard string hash functions **************************/
18 unsigned int stringHash(const char *c)
20 int len = strlen(c);
22 return(*(int *)(c + len - 4)); // erstmal zum Testen
26 bool stringCompare(const char *a, const char *b)
28 return(!strcmp(a, b));
32 // #pragma mark - Hashtable
35 Hashtable::Hashtable(int capacity, float loadFactor)
37 fIteratorIndex(-1)
39 if (capacity < 0 || loadFactor <= 0)
40 return;
42 if (!capacity)
43 capacity = 1;
45 if (!(fTable = (struct Entry **)malloc(capacity * sizeof(void *))))
46 return;
47 memset(fTable,0,capacity * sizeof(void *));
49 fThreshold = (int)(capacity * loadFactor);
50 fModCount = 0;
51 fLoadFactor = loadFactor;
52 fCapacity = capacity;
54 fHashFunc = (uint32 (*)(const void *))stringHash;
55 fCompareFunc = (bool (*)(const void *, const void *))stringCompare;
59 Hashtable::~Hashtable()
61 struct Entry **table = fTable;
63 for(int32 index = fCapacity;--index >= 0;)
65 struct Entry *entry,*next;
67 for(entry = table[index];entry;entry = next)
69 next = entry->next;
70 delete entry;
73 free(table);
77 void Hashtable::SetHashFunction(uint32 (*func)(const void *))
79 fHashFunc = func;
83 void Hashtable::SetCompareFunction(bool (*func)(const void *, const void *))
85 fCompareFunc = func;
89 bool Hashtable::IsEmpty() const
91 return fCount == 0;
95 bool Hashtable::ContainsKey(const void *key)
97 return GetHashEntry(key) ? true : false;
101 void *Hashtable::GetValue(const void *key)
103 Entry *entry = GetHashEntry(key);
105 return entry ? entry->value : NULL;
109 bool Hashtable::Put(const void *key, void *value)
111 Entry *entry = GetHashEntry(key);
112 int hash = fHashFunc(key);
113 int index;
115 if (entry)
116 return true;
118 fModCount++;
119 if (fCount >= fThreshold)
120 Rehash();
122 index = hash % fCapacity;
124 fTable[index] = new Entry(fTable[index], key, value);
125 fCount++;
127 return true;
131 void *Hashtable::Remove(const void *key)
133 Entry **table,*entry,*prev;
134 uint32 hash,(*func)(const void *);
135 int32 index;
137 table = fTable;
138 hash = (func = fHashFunc)(key);
139 index = hash % fCapacity;
141 for(entry = table[index],prev = NULL;entry;entry = entry->next)
143 if ((func(entry->key) == hash) && fCompareFunc(entry->key,key))
145 void *value;
147 fModCount++;
148 if (prev)
149 prev->next = entry->next;
150 else
151 table[index] = entry->next;
153 fCount--;
154 value = entry->value;
155 delete entry;
157 return value;
159 prev = entry;
161 return NULL;
165 status_t Hashtable::GetNextEntry(void **value)
167 if (fIteratorIndex == -1)
169 fIteratorIndex = 0;
170 fIteratorEntry = fTable[0];
172 else if (fIteratorEntry)
173 fIteratorEntry = fIteratorEntry->next;
175 // get next filled slot
176 while (!fIteratorEntry && fIteratorIndex + 1 < fCapacity)
177 fIteratorEntry = fTable[++fIteratorIndex];
179 if (fIteratorEntry)
181 *value = fIteratorEntry->value;
182 return B_OK;
185 return B_ENTRY_NOT_FOUND;
189 void Hashtable::Rewind()
191 fIteratorIndex = -1;
195 void
196 Hashtable::MakeEmpty(int8 keyMode,int8 valueMode)
198 fModCount++;
200 for (int32 index = fCapacity; --index >= 0;) {
201 Entry *entry, *next;
203 for (entry = fTable[index]; entry; entry = next) {
204 switch (keyMode) {
205 case HASH_EMPTY_DELETE:
206 // TODO: destructors are not called!
207 delete (void*)entry->key;
208 break;
209 case HASH_EMPTY_FREE:
210 free((void*)entry->key);
211 break;
213 switch (valueMode) {
214 case HASH_EMPTY_DELETE:
215 // TODO: destructors are not called!
216 delete entry->value;
217 break;
218 case HASH_EMPTY_FREE:
219 free(entry->value);
220 break;
222 next = entry->next;
223 delete entry;
225 fTable[index] = NULL;
227 fCount = 0;
231 size_t
232 Hashtable::Size() const
234 return fCount;
238 /** The hash table will be doubled in size, and rebuild.
239 * @return true on success
242 bool Hashtable::Rehash()
244 uint32 (*hashCode)(const void *) = fHashFunc;
245 struct Entry **oldTable = fTable,**newtable;
246 int oldCapacity = fCapacity;
247 int newCapacity,i;
249 newCapacity = oldCapacity * 2 + 1;
250 if (!(newtable = (struct Entry **)malloc(newCapacity * sizeof(struct Entry *))))
251 return false;
252 memset(newtable,0,newCapacity*sizeof(struct Entry *));
254 fModCount++;
255 fThreshold = (int)(newCapacity * fLoadFactor);
256 fTable = newtable;
257 fCapacity = newCapacity;
259 for (i = oldCapacity;i-- > 0;) {
260 Entry *oldEntry,*entry = NULL;
261 int index;
263 for (oldEntry = oldTable[i];oldEntry;) {
264 entry = oldEntry; oldEntry = oldEntry->next;
266 index = hashCode(entry->key) % newCapacity;
267 entry->next = newtable[index];
268 newtable[index] = entry;
271 free(oldTable);
273 return true;
277 Hashtable::Entry *Hashtable::GetHashEntry(const void *key)
279 Entry **table,*entry;
280 uint32 hash,(*func)(const void *);
282 table = fTable;
283 hash = (func = fHashFunc)(key);
285 for(entry = table[hash % fCapacity];entry;entry = entry->next)
287 if ((func(entry->key) == hash) && fCompareFunc(entry->key,key))
288 return entry;
290 return NULL;