6 #include "libcitadel.h"
9 typedef struct Payload Payload;
13 DeleteHashDataFunc Destructor;
25 HashKey **LookupTable;
35 int PrintHash(HashList *Hash)
41 if (Hash->MyKeys != NULL)
44 Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nMembersUsed);
45 printf("----------------------------------\n");
46 for (i=0; i < Hash->nMembersUsed; i++) {
48 if (Hash->LookupTable[i] == NULL)
56 key = Hash->LookupTable[i]->Key;
57 foo = Hash->LookupTable[i]->HashKey;
58 bar = (char*) Hash->Members[Hash->LookupTable[i]->Position]->Data;
60 printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' \n", i, key, foo, bar);
62 printf("----------------------------------\n");
68 HashList *NewHash(void)
71 NewList = malloc (sizeof(HashList));
72 memset(NewList, 0, sizeof(HashList));
74 NewList->Members = malloc(sizeof(Payload*) * 100);
75 memset(NewList->Members, 0, sizeof(Payload*) * 100);
77 NewList->LookupTable = malloc(sizeof(HashKey*) * 100);
78 memset(NewList->LookupTable, 0, sizeof(HashKey*) * 100);
80 NewList->MemberSize = 100;
86 static void DeleteHashPayload (Payload *Data)
89 Data->Destructor(Data->Data);
93 void DeleteHash(HashList **Hash)
101 for (i=0; i < FreeMe->nMembersUsed; i++)
103 if (FreeMe->Members[i] != NULL)
105 DeleteHashPayload(FreeMe->Members[i]);
106 free(FreeMe->Members[i]);
108 if (FreeMe->LookupTable[i] != NULL)
110 free(FreeMe->LookupTable[i]->HashKey);
111 free(FreeMe->LookupTable[i]);
115 free(FreeMe->LookupTable);
116 free(FreeMe->Members);
117 if (FreeMe->MyKeys != NULL)
118 free(FreeMe->MyKeys);
124 static void InsertHashItem(HashList *Hash,
130 DeleteHashDataFunc Destructor)
132 Payload *NewPayloadItem;
135 if (Hash->nMembersUsed >= Hash->MemberSize)
137 /* Ok, Our space is used up. Double the available space. */
138 Payload **NewPayloadArea;
141 NewPayloadArea = (Payload**) malloc(sizeof(Payload*) * Hash->MemberSize * 2);
142 memset(&NewPayloadArea[Hash->MemberSize], 0, sizeof(Payload*) * Hash->MemberSize);
143 memcpy(NewPayloadArea, Hash->Members, sizeof(Payload*) * Hash->MemberSize);
145 NewTable = malloc(sizeof(HashKey*) * Hash->MemberSize * 2);
146 memset(&NewTable[Hash->MemberSize], 0, sizeof(HashKey*) * Hash->MemberSize);
147 memcpy(NewTable, &Hash->LookupTable, sizeof(HashKey*) * Hash->MemberSize);
149 Hash->MemberSize *= 2;
152 NewPayloadItem = (Payload*) malloc (sizeof(Payload));
153 NewPayloadItem->Data = Data;
154 NewPayloadItem->Destructor = Destructor;
156 NewHashKey = (HashKey*) malloc (sizeof(HashKey));
157 NewHashKey->HashKey = (char *) malloc (HKLen + 1);
158 NewHashKey->HKLen = HKLen;
159 memcpy (NewHashKey->HashKey, HashKeyStr, HKLen + 1);
160 NewHashKey->Key = HashBinKey;
161 NewHashKey->Position = Hash->nMembersUsed;
163 if ((Hash->nMembersUsed != 0) &&
164 (HashPos != Hash->nMembersUsed) ) {
168 ItemsAfter = Hash->nMembersUsed - HashPos;
173 memmove(&Hash->LookupTable[InsertAt + 1],
174 &Hash->LookupTable[InsertAt],
175 ItemsAfter * sizeof(HashKey*));
179 Hash->Members[Hash->nMembersUsed] = NewPayloadItem;
180 Hash->LookupTable[HashPos] = NewHashKey;
181 Hash->nMembersUsed++;
184 static long FindInHash(HashList *Hash, long HashBinKey)
189 SearchPos = Hash->nMembersUsed / 2;
190 StepWidth = SearchPos / 2;
191 while ((SearchPos > 0) &&
192 (SearchPos < Hash->nMembersUsed))
194 /** Did we find it? */
195 if (Hash->LookupTable[SearchPos]->Key == HashBinKey){
198 /** are we Aproximating in big steps? */
200 if (Hash->LookupTable[SearchPos]->Key > HashBinKey)
201 SearchPos -= StepWidth;
203 SearchPos += StepWidth;
206 else { /** We are right next to our target, within 4 positions */
207 if (Hash->LookupTable[SearchPos]->Key > HashBinKey) {
208 if ((SearchPos > 0) &&
209 (Hash->LookupTable[SearchPos - 1]->Key < HashBinKey))
214 if ((SearchPos + 1 < Hash->nMembersUsed) &&
215 (Hash->LookupTable[SearchPos + 1]->Key > HashBinKey))
227 inline static long CalcHashKey (char *HKey, long HKLen)
229 return hashlittle(HKey, HKLen, 9283457);
233 void Put(HashList *Hash, char *HKey, long HKLen, void *Data, DeleteHashDataFunc DeleteIt)
239 HashBinKey = CalcHashKey(HKey, HKLen);
240 HashAt = FindInHash(Hash, HashBinKey);
242 if (Hash->LookupTable[HashAt] == NULL){
243 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
245 else if (Hash->LookupTable[HashAt]->Key > HashBinKey) {
246 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
248 else if (Hash->LookupTable[HashAt]->Key < HashBinKey) {
249 InsertHashItem(Hash, HashAt + 1, HashBinKey, HKey, HKLen, Data, DeleteIt);
251 else { /* Ok, we have a colision. replace it. */
254 PayloadPos = Hash->LookupTable[HashAt]->Position;
255 DeleteHashPayload(Hash->Members[PayloadPos]);
256 Hash->Members[PayloadPos]->Data = Data;
257 Hash->Members[PayloadPos]->Destructor = DeleteIt;
261 int GetHash(HashList *Hash, char *HKey, long HKLen, void **Data)
266 HashBinKey = CalcHashKey(HKey, HKLen);
267 HashAt = FindInHash(Hash, HashBinKey);
268 if ((HashAt < 0) || (HashAt >= Hash->nMembersUsed)) {
275 MemberPosition = Hash->LookupTable[HashAt]->Position;
276 *Data = Hash->Members[MemberPosition]->Data;
281 int GetKey(HashList *Hash, char *HKey, long HKLen, void **Payload)
286 int GetHashKeys(HashList *Hash, const char ***List)
289 if (Hash->MyKeys != NULL)
292 Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nMembersUsed);
293 for (i=0; i < Hash->nMembersUsed; i++) {
295 Hash->MyKeys[i] = Hash->LookupTable[i]->HashKey;
297 *List = Hash->MyKeys;
298 return Hash->nMembersUsed;
301 HashPos *GetNewHashPos(void)
305 Ret = (HashPos*)malloc(sizeof(HashPos));
310 void DeleteHashPos(HashPos **DelMe)
316 int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, char **HashKey, void **Data)
320 if (Hash->nMembersUsed <= At->Position)
322 *HKLen = Hash->LookupTable[At->Position]->HKLen;
323 *HashKey = Hash->LookupTable[At->Position]->HashKey;
324 PayloadPos = Hash->LookupTable[At->Position]->Position;
325 *Data = Hash->Members[PayloadPos]->Data;