6 #include "libcitadel.h"
9 typedef struct Payload Payload;
13 DeleteHashDataFunc Destructor;
25 HashKey **LookupTable;
35 int PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Second)
42 if (Hash->MyKeys != NULL)
45 Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nMembersUsed);
47 printf("----------------------------------\n");
49 for (i=0; i < Hash->nMembersUsed; i++) {
51 if (Hash->LookupTable[i] == NULL)
59 key = Hash->LookupTable[i]->Key;
60 foo = Hash->LookupTable[i]->HashKey;
62 bar = First(Hash->Members[Hash->LookupTable[i]->Position]->Data);
64 bla = Second(Hash->Members[Hash->LookupTable[i]->Position]->Data);
67 printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' ; %s\n", i, key, foo, bar, bla);
71 printf("----------------------------------\n");
78 HashList *NewHash(void)
81 NewList = malloc (sizeof(HashList));
82 memset(NewList, 0, sizeof(HashList));
84 NewList->Members = malloc(sizeof(Payload*) * 100);
85 memset(NewList->Members, 0, sizeof(Payload*) * 100);
87 NewList->LookupTable = malloc(sizeof(HashKey*) * 100);
88 memset(NewList->LookupTable, 0, sizeof(HashKey*) * 100);
90 NewList->MemberSize = 100;
96 static void DeleteHashPayload (Payload *Data)
99 Data->Destructor(Data->Data);
103 void DeleteHash(HashList **Hash)
111 for (i=0; i < FreeMe->nMembersUsed; i++)
113 if (FreeMe->Members[i] != NULL)
115 DeleteHashPayload(FreeMe->Members[i]);
116 free(FreeMe->Members[i]);
118 if (FreeMe->LookupTable[i] != NULL)
120 free(FreeMe->LookupTable[i]->HashKey);
121 free(FreeMe->LookupTable[i]);
125 free(FreeMe->LookupTable);
126 free(FreeMe->Members);
127 if (FreeMe->MyKeys != NULL)
128 free(FreeMe->MyKeys);
134 static void InsertHashItem(HashList *Hash,
140 DeleteHashDataFunc Destructor)
142 Payload *NewPayloadItem;
145 if (Hash->nMembersUsed >= Hash->MemberSize)
147 /* Ok, Our space is used up. Double the available space. */
148 Payload **NewPayloadArea;
151 NewPayloadArea = (Payload**) malloc(sizeof(Payload*) * Hash->MemberSize * 2);
152 memset(&NewPayloadArea[Hash->MemberSize], 0, sizeof(Payload*) * Hash->MemberSize);
153 memcpy(NewPayloadArea, Hash->Members, sizeof(Payload*) * Hash->MemberSize);
155 Hash->Members = NewPayloadArea;
157 NewTable = malloc(sizeof(HashKey*) * Hash->MemberSize * 2);
158 memset(&NewTable[Hash->MemberSize], 0, sizeof(HashKey*) * Hash->MemberSize);
159 memcpy(NewTable, Hash->LookupTable, sizeof(HashKey*) * Hash->MemberSize);
160 free(Hash->LookupTable);
161 Hash->LookupTable = NewTable;
163 Hash->MemberSize *= 2;
166 NewPayloadItem = (Payload*) malloc (sizeof(Payload));
167 NewPayloadItem->Data = Data;
168 NewPayloadItem->Destructor = Destructor;
170 NewHashKey = (HashKey*) malloc (sizeof(HashKey));
171 NewHashKey->HashKey = (char *) malloc (HKLen + 1);
172 NewHashKey->HKLen = HKLen;
173 memcpy (NewHashKey->HashKey, HashKeyStr, HKLen + 1);
174 NewHashKey->Key = HashBinKey;
175 NewHashKey->Position = Hash->nMembersUsed;
177 if ((Hash->nMembersUsed != 0) &&
178 (HashPos != Hash->nMembersUsed) ) {
182 ItemsAfter = Hash->nMembersUsed - HashPos;
187 memmove(&Hash->LookupTable[InsertAt + 1],
188 &Hash->LookupTable[InsertAt],
189 ItemsAfter * sizeof(HashKey*));
193 Hash->Members[Hash->nMembersUsed] = NewPayloadItem;
194 Hash->LookupTable[HashPos] = NewHashKey;
195 Hash->nMembersUsed++;
198 static long FindInHash(HashList *Hash, long HashBinKey)
203 SearchPos = Hash->nMembersUsed / 2;
204 StepWidth = SearchPos / 2;
205 while ((SearchPos > 0) &&
206 (SearchPos < Hash->nMembersUsed))
208 /** Did we find it? */
209 if (Hash->LookupTable[SearchPos]->Key == HashBinKey){
212 /** are we Aproximating in big steps? */
214 if (Hash->LookupTable[SearchPos]->Key > HashBinKey)
215 SearchPos -= StepWidth;
217 SearchPos += StepWidth;
220 else { /** We are right next to our target, within 4 positions */
221 if (Hash->LookupTable[SearchPos]->Key > HashBinKey) {
222 if ((SearchPos > 0) &&
223 (Hash->LookupTable[SearchPos - 1]->Key < HashBinKey))
228 if ((SearchPos + 1 < Hash->nMembersUsed) &&
229 (Hash->LookupTable[SearchPos + 1]->Key > HashBinKey))
241 inline static long CalcHashKey (char *HKey, long HKLen)
243 return hashlittle(HKey, HKLen, 9283457);
247 void Put(HashList *Hash, char *HKey, long HKLen, void *Data, DeleteHashDataFunc DeleteIt)
253 HashBinKey = CalcHashKey(HKey, HKLen);
254 HashAt = FindInHash(Hash, HashBinKey);
256 if (Hash->LookupTable[HashAt] == NULL){
257 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
259 else if (Hash->LookupTable[HashAt]->Key > HashBinKey) {
260 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
262 else if (Hash->LookupTable[HashAt]->Key < HashBinKey) {
263 InsertHashItem(Hash, HashAt + 1, HashBinKey, HKey, HKLen, Data, DeleteIt);
265 else { /* Ok, we have a colision. replace it. */
268 PayloadPos = Hash->LookupTable[HashAt]->Position;
269 DeleteHashPayload(Hash->Members[PayloadPos]);
270 Hash->Members[PayloadPos]->Data = Data;
271 Hash->Members[PayloadPos]->Destructor = DeleteIt;
275 int GetHash(HashList *Hash, const char *HKey, long HKLen, void **Data)
280 HashBinKey = CalcHashKey((char*)HKey, HKLen);
281 HashAt = FindInHash(Hash, HashBinKey);
283 (HashAt >= Hash->nMembersUsed) ||
284 (Hash->LookupTable[HashAt]->Key != HashBinKey)) {
291 MemberPosition = Hash->LookupTable[HashAt]->Position;
292 *Data = Hash->Members[MemberPosition]->Data;
297 int GetKey(HashList *Hash, char *HKey, long HKLen, void **Payload)
302 int GetHashKeys(HashList *Hash, char ***List)
305 if (Hash->MyKeys != NULL)
308 Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nMembersUsed);
309 for (i=0; i < Hash->nMembersUsed; i++) {
311 Hash->MyKeys[i] = Hash->LookupTable[i]->HashKey;
313 *List = (char**)Hash->MyKeys;
314 return Hash->nMembersUsed;
317 HashPos *GetNewHashPos(void)
321 Ret = (HashPos*)malloc(sizeof(HashPos));
326 void DeleteHashPos(HashPos **DelMe)
332 int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, char **HashKey, void **Data)
336 if (Hash->nMembersUsed <= At->Position)
338 *HKLen = Hash->LookupTable[At->Position]->HKLen;
339 *HashKey = Hash->LookupTable[At->Position]->HashKey;
340 PayloadPos = Hash->LookupTable[At->Position]->Position;
341 *Data = Hash->Members[PayloadPos]->Data;