1 /* Hashtable - a general purpose hash table
3 ** Copyright 2001 pinc Software. All Rights Reserved.
4 ** Released under the terms of the MIT license.
12 #include "Hashtable.h"
15 /************************** standard string hash functions **************************/
18 unsigned int stringHash(const char *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
)
39 if (capacity
< 0 || loadFactor
<= 0)
45 if (!(fTable
= (struct Entry
**)malloc(capacity
* sizeof(void *))))
47 memset(fTable
,0,capacity
* sizeof(void *));
49 fThreshold
= (int)(capacity
* loadFactor
);
51 fLoadFactor
= loadFactor
;
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
)
77 void Hashtable::SetHashFunction(uint32 (*func
)(const void *))
83 void Hashtable::SetCompareFunction(bool (*func
)(const void *, const void *))
89 bool Hashtable::IsEmpty() const
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
);
119 if (fCount
>= fThreshold
)
122 index
= hash
% fCapacity
;
124 fTable
[index
] = new Entry(fTable
[index
], key
, value
);
131 void *Hashtable::Remove(const void *key
)
133 Entry
**table
,*entry
,*prev
;
134 uint32 hash
,(*func
)(const void *);
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
))
149 prev
->next
= entry
->next
;
151 table
[index
] = entry
->next
;
154 value
= entry
->value
;
165 status_t
Hashtable::GetNextEntry(void **value
)
167 if (fIteratorIndex
== -1)
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
];
181 *value
= fIteratorEntry
->value
;
185 return B_ENTRY_NOT_FOUND
;
189 void Hashtable::Rewind()
196 Hashtable::MakeEmpty(int8 keyMode
,int8 valueMode
)
200 for (int32 index
= fCapacity
; --index
>= 0;) {
203 for (entry
= fTable
[index
]; entry
; entry
= next
) {
205 case HASH_EMPTY_DELETE
:
206 // TODO: destructors are not called!
207 delete (void*)entry
->key
;
209 case HASH_EMPTY_FREE
:
210 free((void*)entry
->key
);
214 case HASH_EMPTY_DELETE
:
215 // TODO: destructors are not called!
218 case HASH_EMPTY_FREE
:
225 fTable
[index
] = NULL
;
232 Hashtable::Size() const
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
;
249 newCapacity
= oldCapacity
* 2 + 1;
250 if (!(newtable
= (struct Entry
**)malloc(newCapacity
* sizeof(struct Entry
*))))
252 memset(newtable
,0,newCapacity
*sizeof(struct Entry
*));
255 fThreshold
= (int)(newCapacity
* fLoadFactor
);
257 fCapacity
= newCapacity
;
259 for (i
= oldCapacity
;i
-- > 0;) {
260 Entry
*oldEntry
,*entry
= NULL
;
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
;
277 Hashtable::Entry
*Hashtable::GetHashEntry(const void *key
)
279 Entry
**table
,*entry
;
280 uint32 hash
,(*func
)(const void *);
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
))