6 #include "libcitadel.h"
9 typedef struct Payload Payload;
12 * @brief Hash Payload storage Structure; filled in linear.
15 void *Data; /**< the Data belonging to this storage */
16 DeleteHashDataFunc Destructor; /**< if we want to destroy Data, do it with this function. */
21 * @brief Hash key element; sorted by key
24 long Key; /**< Numeric Hashkey comperator for hash sorting */
25 long Position; /**< Pointer to a Payload struct in the Payload Aray */
26 char *HashKey; /**< the Plaintext Hashkey */
27 long HKLen; /**< length of the Plaintext Hashkey */
28 Payload *PL; /**< pointer to our payload for sorting */
32 * @brief Hash structure; holds arrays of Hashkey and Payload.
35 Payload **Members; /**< Our Payload members. This fills up linear */
36 HashKey **LookupTable; /**< Hash Lookup table. Elements point to members, and are sorted by their hashvalue */
37 char **MyKeys; /**< this keeps the members for a call of GetHashKeys */
38 HashFunc Algorithm; /**< should we use an alternating algorithm to calc the hash values? */
39 long nMembersUsed; /**< how many pointers inside of the array are used? */
40 long nLookupTableItems; /**< how many items of the lookup table are used? */
41 long MemberSize; /**< how big is Members and LookupTable? */
42 long tainted; /**< if 0, we're hashed, else s.b. else sorted us in his own way. */
43 long uniq; /**< are the keys going to be uniq? */
47 * @brief Anonymous Hash Iterator Object. used for traversing the whole array from outside
50 long Position; /**< Position inside of the hash */
51 int StepWidth; /**< small? big? forward? backward? */
56 * @brief Iterate over the hash and call PrintEntry.
57 * @param Hash your Hashlist structure
58 * @param Trans is called so you could for example print 'A:' if the next entries are like that.
59 * Must be aware to receive NULL in both pointers.
60 * @param PrintEntry print entry one by one
61 * \returns the number of items printed
63 int PrintHash(HashList *Hash, TransitionFunc Trans, PrintHashDataFunc PrintEntry)
73 for (i=0; i < Hash->nLookupTableItems; i++) {
78 if (Hash->LookupTable[i - 1] == NULL)
81 Previous = Hash->Members[Hash->LookupTable[i-1]->Position]->Data;
83 if (Hash->LookupTable[i] == NULL) {
88 Next = Hash->Members[Hash->LookupTable[i]->Position]->Data;
89 KeyStr = Hash->LookupTable[i]->HashKey;
92 Trans(Previous, Next, i % 2);
93 PrintEntry(KeyStr, Next, i % 2);
100 * @brief verify the contents of a hash list; here for debugging purposes.
101 * @param Hash your Hashlist structure
102 * @param First Functionpointer to allow you to print your payload
103 * @param Second Functionpointer to allow you to print your payload
106 int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Second)
110 const char *bla = "";
117 if (Hash->MyKeys != NULL)
120 Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nLookupTableItems);
122 printf("----------------------------------\n");
124 for (i=0; i < Hash->nLookupTableItems; i++) {
126 if (Hash->LookupTable[i] == NULL)
134 key = Hash->LookupTable[i]->Key;
135 foo = Hash->LookupTable[i]->HashKey;
137 bar = First(Hash->Members[Hash->LookupTable[i]->Position]->Data);
141 bla = Second(Hash->Members[Hash->LookupTable[i]->Position]->Data);
146 printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' ; %s\n", i, key, foo, bar, bla);
150 printf("----------------------------------\n");
157 * @brief instanciate a new hashlist
158 * \returns the newly allocated list.
160 HashList *NewHash(int Uniq, HashFunc F)
163 NewList = malloc (sizeof(HashList));
164 memset(NewList, 0, sizeof(HashList));
166 NewList->Members = malloc(sizeof(Payload*) * 100);
167 memset(NewList->Members, 0, sizeof(Payload*) * 100);
169 NewList->LookupTable = malloc(sizeof(HashKey*) * 100);
170 memset(NewList->LookupTable, 0, sizeof(HashKey*) * 100);
172 NewList->MemberSize = 100;
173 NewList->tainted = 0;
174 NewList->uniq = Uniq;
175 NewList->Algorithm = F;
180 int GetCount(HashList *Hash)
182 if(Hash==NULL) return 0;
183 return Hash->nLookupTableItems;
188 * @brief private destructor for one hash element.
189 * Crashing? go one frame up and do 'print *FreeMe->LookupTable[i]'
190 * @param Data an element to free using the user provided destructor, or just plain free
192 static void DeleteHashPayload (Payload *Data)
194 /** do we have a destructor for our payload? */
195 if (Data->Destructor)
196 Data->Destructor(Data->Data);
202 * @brief Destructor for nested hashes
204 void HDeleteHash(void *vHash)
206 HashList *FreeMe = (HashList*)vHash;
211 * @brief destroy a hashlist and all of its members
212 * Crashing? do 'print *FreeMe->LookupTable[i]'
213 * @param Hash Hash to destroy. Is NULL'ed so you are shure its done.
215 void DeleteHash(HashList **Hash)
223 /* even if there are sparse members already deleted... */
224 for (i=0; i < FreeMe->nMembersUsed; i++)
226 /** get rid of our payload */
227 if (FreeMe->Members[i] != NULL)
229 DeleteHashPayload(FreeMe->Members[i]);
230 free(FreeMe->Members[i]);
232 /** delete our hashing data */
233 if (FreeMe->LookupTable[i] != NULL)
235 free(FreeMe->LookupTable[i]->HashKey);
236 free(FreeMe->LookupTable[i]);
239 /** now, free our arrays... */
240 free(FreeMe->LookupTable);
241 free(FreeMe->Members);
242 /** did s.b. want an array of our keys? free them. */
243 if (FreeMe->MyKeys != NULL)
244 free(FreeMe->MyKeys);
245 /** buye bye cruel world. */
251 * @brief Private function to increase the hash size.
252 * @param Hash the Hasharray to increase
254 static void IncreaseHashSize(HashList *Hash)
256 /* Ok, Our space is used up. Double the available space. */
257 Payload **NewPayloadArea;
263 /** If we grew to much, this might be the place to rehash and shrink again.
264 if ((Hash->NMembersUsed > Hash->nLookupTableItems) &&
265 ((Hash->NMembersUsed - Hash->nLookupTableItems) >
266 (Hash->nLookupTableItems / 10)))
273 /** double our payload area */
274 NewPayloadArea = (Payload**) malloc(sizeof(Payload*) * Hash->MemberSize * 2);
275 memset(&NewPayloadArea[Hash->MemberSize], 0, sizeof(Payload*) * Hash->MemberSize);
276 memcpy(NewPayloadArea, Hash->Members, sizeof(Payload*) * Hash->MemberSize);
278 Hash->Members = NewPayloadArea;
280 /** double our hashtable area */
281 NewTable = malloc(sizeof(HashKey*) * Hash->MemberSize * 2);
282 memset(&NewTable[Hash->MemberSize], 0, sizeof(HashKey*) * Hash->MemberSize);
283 memcpy(NewTable, Hash->LookupTable, sizeof(HashKey*) * Hash->MemberSize);
284 free(Hash->LookupTable);
285 Hash->LookupTable = NewTable;
287 Hash->MemberSize *= 2;
292 * @brief private function to add a new item to / replace an existing in - the hashlist
293 * if the hash list is full, its re-alloced with double size.
294 * \parame Hash our hashlist to manipulate
295 * @param HashPos where should we insert / replace?
296 * @param HashKeyStr the Hash-String
297 * @param HKLen length of HashKeyStr
298 * @param Data your Payload to add
299 * @param Destructor Functionpointer to free Data. if NULL, default free() is used.
301 static void InsertHashItem(HashList *Hash,
304 const char *HashKeyStr,
307 DeleteHashDataFunc Destructor)
309 Payload *NewPayloadItem;
315 if (Hash->nMembersUsed >= Hash->MemberSize)
316 IncreaseHashSize (Hash);
318 /** Arrange the payload */
319 NewPayloadItem = (Payload*) malloc (sizeof(Payload));
320 NewPayloadItem->Data = Data;
321 NewPayloadItem->Destructor = Destructor;
322 /** Arrange the hashkey */
323 NewHashKey = (HashKey*) malloc (sizeof(HashKey));
324 NewHashKey->HashKey = (char *) malloc (HKLen + 1);
325 NewHashKey->HKLen = HKLen;
326 memcpy (NewHashKey->HashKey, HashKeyStr, HKLen + 1);
327 NewHashKey->Key = HashBinKey;
328 NewHashKey->PL = NewPayloadItem;
329 /** our payload is queued at the end... */
330 NewHashKey->Position = Hash->nMembersUsed;
331 /** but if we should be sorted into a specific place... */
332 if ((Hash->nLookupTableItems != 0) &&
333 (HashPos != Hash->nLookupTableItems) ) {
336 ItemsAfter = Hash->nLookupTableItems - HashPos;
337 /** make space were we can fill us in */
340 memmove(&Hash->LookupTable[HashPos + 1],
341 &Hash->LookupTable[HashPos],
342 ItemsAfter * sizeof(HashKey*));
346 Hash->Members[Hash->nMembersUsed] = NewPayloadItem;
347 Hash->LookupTable[HashPos] = NewHashKey;
348 Hash->nMembersUsed++;
349 Hash->nLookupTableItems++;
353 * @brief if the user has tainted the hash, but wants to insert / search items by their key
354 * we need to search linear through the array. You have been warned that this will take more time!
355 * @param Hash Our Hash to manipulate
356 * @param HashBinKey the Hash-Number to lookup.
357 * \returns the position (most closely) matching HashBinKey (-> Caller needs to compare! )
359 static long FindInTaintedHash(HashList *Hash, long HashBinKey)
366 for (SearchPos = 0; SearchPos < Hash->nLookupTableItems; SearchPos ++) {
367 if (Hash->LookupTable[SearchPos]->Key == HashBinKey){
375 * @brief Private function to lookup the Item / the closest position to put it in
376 * @param Hash Our Hash to manipulate
377 * @param HashBinKey the Hash-Number to lookup.
378 * \returns the position (most closely) matching HashBinKey (-> Caller needs to compare! )
380 static long FindInHash(HashList *Hash, long HashBinKey)
389 return FindInTaintedHash(Hash, HashBinKey);
391 SearchPos = Hash->nLookupTableItems / 2;
392 StepWidth = SearchPos / 2;
393 while ((SearchPos > 0) &&
394 (SearchPos < Hash->nLookupTableItems))
396 /** Did we find it? */
397 if (Hash->LookupTable[SearchPos]->Key == HashBinKey){
400 /** are we Aproximating in big steps? */
402 if (Hash->LookupTable[SearchPos]->Key > HashBinKey)
403 SearchPos -= StepWidth;
405 SearchPos += StepWidth;
408 else { /** We are right next to our target, within 4 positions */
409 if (Hash->LookupTable[SearchPos]->Key > HashBinKey) {
410 if ((SearchPos > 0) &&
411 (Hash->LookupTable[SearchPos - 1]->Key < HashBinKey))
416 if ((SearchPos + 1 < Hash->nLookupTableItems) &&
417 (Hash->LookupTable[SearchPos + 1]->Key > HashBinKey))
429 * @brief another hashing algorithm; treat it as just a pointer to long.
430 * @param str Our pointer to the long value
431 * @param len the length of the data pointed to; needs to be sizeof int, else we won't use it!
432 * \returns the calculated hash value
434 int Flathash(const char *str, long len)
436 if (len != sizeof (int))
438 else return *(int*)str;
442 * @brief private abstract wrapper around the hashing algorithm
443 * @param HKey the hash string
444 * @param HKLen length of HKey
445 * \returns the calculated hash value
447 inline static long CalcHashKey (HashList *Hash, const char *HKey, long HKLen)
452 if (Hash->Algorithm == NULL)
453 return hashlittle(HKey, HKLen, 9283457);
455 return Hash->Algorithm(HKey, HKLen);
460 * @brief Add a new / Replace an existing item in the Hash
461 * @param HashList the list to manipulate
462 * @param HKey the hash-string to store Data under
463 * @param HKeyLen Length of HKey
464 * @param Data the payload you want to associate with HKey
465 * @param DeleteIt if not free() should be used to delete Data set to NULL, else DeleteIt is used.
467 void Put(HashList *Hash, const char *HKey, long HKLen, void *Data, DeleteHashDataFunc DeleteIt)
475 /** first, find out were we could fit in... */
476 HashBinKey = CalcHashKey(Hash, HKey, HKLen);
477 HashAt = FindInHash(Hash, HashBinKey);
479 if (HashAt >= Hash->MemberSize)
480 IncreaseHashSize (Hash);
482 /** oh, we're brand new... */
483 if (Hash->LookupTable[HashAt] == NULL) {
484 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
485 }/** Insert After? */
486 else if (Hash->LookupTable[HashAt]->Key > HashBinKey) {
487 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
488 }/** Insert before? */
489 else if (Hash->LookupTable[HashAt]->Key < HashBinKey) {
490 InsertHashItem(Hash, HashAt + 1, HashBinKey, HKey, HKLen, Data, DeleteIt);
492 else { /** Ok, we have a colision. replace it. */
496 PayloadPos = Hash->LookupTable[HashAt]->Position;
497 DeleteHashPayload(Hash->Members[PayloadPos]);
498 Hash->Members[PayloadPos]->Data = Data;
499 Hash->Members[PayloadPos]->Destructor = DeleteIt;
502 InsertHashItem(Hash, HashAt + 1, HashBinKey, HKey, HKLen, Data, DeleteIt);
508 * @brief Lookup the Data associated with HKey
509 * @param Hash the Hashlist to search in
510 * @param HKey the hashkey to look up
511 * @param HKLen length of HKey
512 * @param Data returns the Data associated with HKey
513 * \returns 0 if not found, 1 if.
515 int GetHash(HashList *Hash, const char *HKey, long HKLen, void **Data)
527 /** first, find out were we could be... */
528 HashBinKey = CalcHashKey(Hash, HKey, HKLen);
529 HashAt = FindInHash(Hash, HashBinKey);
530 if ((HashAt < 0) || /**< Not found at the lower edge? */
531 (HashAt >= Hash->nLookupTableItems) || /**< Not found at the upper edge? */
532 (Hash->LookupTable[HashAt]->Key != HashBinKey)) { /**< somewhere inbetween but no match? */
536 else { /** GOTCHA! */
539 MemberPosition = Hash->LookupTable[HashAt]->Position;
540 *Data = Hash->Members[MemberPosition]->Data;
546 int GetKey(HashList *Hash, char *HKey, long HKLen, void **Payload)
552 * @brief get the Keys present in this hash, simila to array_keys() in PHP
553 * Attention: List remains to Hash! don't modify or free it!
554 * @param Hash Your Hashlist to extract the keys from
555 * @param List returns the list of hashkeys stored in Hash
557 int GetHashKeys(HashList *Hash, char ***List)
562 if (Hash->MyKeys != NULL)
565 Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nLookupTableItems);
566 for (i=0; i < Hash->nLookupTableItems; i++) {
568 Hash->MyKeys[i] = Hash->LookupTable[i]->HashKey;
570 *List = (char**)Hash->MyKeys;
571 return Hash->nLookupTableItems;
575 * @brief creates a hash-linear iterator object
576 * @param Hash the list we reference
577 * @param in which step width should we iterate?
578 * If negative, the last position matching the
579 * step-raster is provided.
580 * \returns the hash iterator
582 HashPos *GetNewHashPos(HashList *Hash, int StepWidth)
586 Ret = (HashPos*)malloc(sizeof(HashPos));
588 Ret->StepWidth = StepWidth;
591 if (Ret->StepWidth < 0) {
592 Ret->Position = Hash->nLookupTableItems - 1;
601 * @brief Set iterator object to point to key. If not found, don't change iterator
602 * @param Hash the list we reference
603 * @param HKey key to search for
604 * @param HKLen length of key
605 * @param At HashPos to update
606 * \returns 0 if not found
608 int GetHashPosFromKey(HashList *Hash, const char *HKey, long HKLen, HashPos *At)
619 /** first, find out were we could be... */
620 HashBinKey = CalcHashKey(Hash, HKey, HKLen);
621 HashAt = FindInHash(Hash, HashBinKey);
622 if ((HashAt < 0) || /**< Not found at the lower edge? */
623 (HashAt >= Hash->nLookupTableItems) || /**< Not found at the upper edge? */
624 (Hash->LookupTable[HashAt]->Key != HashBinKey)) { /**< somewhere inbetween but no match? */
628 At->Position = Hash->LookupTable[HashAt]->Position;
633 * @brief Delete from the Hash the entry at Position
634 * @param Hash the list we reference
635 * @param At the position within the Hash
636 * \returns 0 if not found
638 int DeleteEntryFromHash(HashList *Hash, HashPos *At)
644 /* if lockable, lock here */
645 if ((Hash == NULL) ||
646 (At->Position >= Hash->nLookupTableItems) ||
647 (At->Position < 0) ||
648 (At->Position > Hash->nLookupTableItems))
654 FreeMe = Hash->Members[Hash->LookupTable[At->Position]->Position];
655 Hash->Members[Hash->LookupTable[At->Position]->Position] = NULL;
658 /** delete our hashing data */
659 if (Hash->LookupTable[At->Position] != NULL)
661 free(Hash->LookupTable[At->Position]->HashKey);
662 free(Hash->LookupTable[At->Position]);
663 if (At->Position < Hash->nLookupTableItems)
665 memmove(&Hash->LookupTable[At->Position],
666 &Hash->LookupTable[At->Position + 1],
667 (Hash->nLookupTableItems - At->Position - 1) *
670 Hash->LookupTable[Hash->nLookupTableItems - 1] = NULL;
673 Hash->LookupTable[At->Position] = NULL;
674 Hash->nLookupTableItems--;
679 /** get rid of our payload */
682 DeleteHashPayload(FreeMe);
689 * @brief retrieve the counter from the itteratoor
690 * @param the Iterator to analyze
691 * \returns the n'th hashposition we point at
693 int GetHashPosCounter(HashList *Hash, HashPos *At)
695 if ((Hash == NULL) ||
696 (At->Position >= Hash->nLookupTableItems) ||
697 (At->Position < 0) ||
698 (At->Position > Hash->nLookupTableItems))
704 * @brief frees a linear hash iterator
706 void DeleteHashPos(HashPos **DelMe)
717 * @brief Get the data located where HashPos Iterator points at, and Move HashPos one forward
718 * @param Hash your Hashlist to follow
719 * @param At the position to retrieve the Item from and move forward afterwards
720 * @param HKLen returns Length of Hashkey Returned
721 * @param HashKey returns the Hashkey corrosponding to HashPos
722 * @param Data returns the Data found at HashPos
723 * \returns whether the item was found or not.
725 int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, const char **HashKey, void **Data)
729 if ((Hash == NULL) ||
730 (At->Position >= Hash->nLookupTableItems) ||
731 (At->Position < 0) ||
732 (At->Position > Hash->nLookupTableItems))
734 *HKLen = Hash->LookupTable[At->Position]->HKLen;
735 *HashKey = Hash->LookupTable[At->Position]->HashKey;
736 PayloadPos = Hash->LookupTable[At->Position]->Position;
737 *Data = Hash->Members[PayloadPos]->Data;
739 /* Position is NULL-Based, while Stepwidth is not... */
740 if ((At->Position % abs(At->StepWidth)) == 0)
741 At->Position += At->StepWidth;
743 At->Position += ((At->Position) % abs(At->StepWidth)) *
744 (At->StepWidth / abs(At->StepWidth));
749 * @brief Get the data located where HashPos Iterator points at
750 * @param Hash your Hashlist to follow
751 * @param At the position retrieve the data from
752 * @param HKLen returns Length of Hashkey Returned
753 * @param HashKey returns the Hashkey corrosponding to HashPos
754 * @param Data returns the Data found at HashPos
755 * \returns whether the item was found or not.
757 int GetHashPos(HashList *Hash, HashPos *At, long *HKLen, const char **HashKey, void **Data)
761 if ((Hash == NULL) ||
762 (At->Position >= Hash->nLookupTableItems) ||
763 (At->Position < 0) ||
764 (At->Position > Hash->nLookupTableItems))
766 *HKLen = Hash->LookupTable[At->Position]->HKLen;
767 *HashKey = Hash->LookupTable[At->Position]->HashKey;
768 PayloadPos = Hash->LookupTable[At->Position]->Position;
769 *Data = Hash->Members[PayloadPos]->Data;
775 * @brief Move HashPos one forward
776 * @param Hash your Hashlist to follow
777 * @param At the position to move forward
778 * \returns whether there is a next item or not.
780 int NextHashPos(HashList *Hash, HashPos *At)
782 if ((Hash == NULL) ||
783 (At->Position >= Hash->nLookupTableItems) ||
784 (At->Position < 0) ||
785 (At->Position > Hash->nLookupTableItems))
788 /* Position is NULL-Based, while Stepwidth is not... */
789 if ((At->Position % abs(At->StepWidth)) == 0)
790 At->Position += At->StepWidth;
792 At->Position += ((At->Position) % abs(At->StepWidth)) *
793 (At->StepWidth / abs(At->StepWidth));
794 return !((At->Position >= Hash->nLookupTableItems) ||
795 (At->Position < 0) ||
796 (At->Position > Hash->nLookupTableItems));
800 * @brief Get the data located where At points to
801 * note: you should prefer iterator operations instead of using me.
802 * @param Hash your Hashlist peek from
803 * @param HKLen returns Length of Hashkey Returned
804 * @param HashKey returns the Hashkey corrosponding to HashPos
805 * @param Data returns the Data found at HashPos
806 * \returns whether the item was found or not.
808 int GetHashAt(HashList *Hash,long At, long *HKLen, const char **HashKey, void **Data)
812 if ((Hash == NULL) ||
814 (At >= Hash->nLookupTableItems))
816 *HKLen = Hash->LookupTable[At]->HKLen;
817 *HashKey = Hash->LookupTable[At]->HashKey;
818 PayloadPos = Hash->LookupTable[At]->Position;
819 *Data = Hash->Members[PayloadPos]->Data;
824 * @brief Get the data located where At points to
825 * note: you should prefer iterator operations instead of using me.
826 * @param Hash your Hashlist peek from
827 * @param HKLen returns Length of Hashkey Returned
828 * @param HashKey returns the Hashkey corrosponding to HashPos
829 * @param Data returns the Data found at HashPos
830 * \returns whether the item was found or not.
833 long GetHashIDAt(HashList *Hash,long At)
835 if ((Hash == NULL) ||
837 (At > Hash->nLookupTableItems))
840 return Hash->LookupTable[At]->Key;
846 * @brief sorting function for sorting the Hash alphabeticaly by their strings
847 * @param Key1 first item
848 * @param Key2 second item
850 static int SortByKeys(const void *Key1, const void* Key2)
852 HashKey *HKey1, *HKey2;
853 HKey1 = *(HashKey**) Key1;
854 HKey2 = *(HashKey**) Key2;
856 return strcasecmp(HKey1->HashKey, HKey2->HashKey);
860 * @brief sorting function for sorting the Hash alphabeticaly reverse by their strings
861 * @param Key1 first item
862 * @param Key2 second item
864 static int SortByKeysRev(const void *Key1, const void* Key2)
866 HashKey *HKey1, *HKey2;
867 HKey1 = *(HashKey**) Key1;
868 HKey2 = *(HashKey**) Key2;
870 return strcasecmp(HKey2->HashKey, HKey1->HashKey);
874 * @brief sorting function to regain hash-sequence and revert tainted status
875 * @param Key1 first item
876 * @param Key2 second item
878 static int SortByHashKeys(const void *Key1, const void* Key2)
880 HashKey *HKey1, *HKey2;
881 HKey1 = *(HashKey**) Key1;
882 HKey2 = *(HashKey**) Key2;
884 return HKey1->Key > HKey2->Key;
889 * @brief sort the hash alphabeticaly by their keys.
890 * Caution: This taints the hashlist, so accessing it later
891 * will be significantly slower! You can un-taint it by SortByHashKeyStr
892 * @param Hash the list to sort
893 * @param Order 0/1 Forward/Backward
895 void SortByHashKey(HashList *Hash, int Order)
897 if (Hash->nLookupTableItems < 2)
899 qsort(Hash->LookupTable, Hash->nLookupTableItems, sizeof(HashKey*),
900 (Order)?SortByKeys:SortByKeysRev);
905 * @brief sort the hash by their keys (so it regains untainted state).
906 * this will result in the sequence the hashing allgorithm produces it by default.
907 * @param Hash the list to sort
909 void SortByHashKeyStr(HashList *Hash)
912 if (Hash->nLookupTableItems < 2)
914 qsort(Hash->LookupTable, Hash->nLookupTableItems, sizeof(HashKey*), SortByHashKeys);
919 * @brief gives user sort routines access to the hash payload
920 * @param Searchentry to retrieve Data to
921 * \returns Data belonging to HashVoid
923 const void *GetSearchPayload(const void *HashVoid)
925 return (*(HashKey**)HashVoid)->PL->Data;
929 * @brief sort the hash by your sort function. see the following sample.
930 * this will result in the sequence the hashing allgorithm produces it by default.
931 * @param Hash the list to sort
932 * @param SortBy Sortfunction; see below how to implement this
934 void SortByPayload(HashList *Hash, CompareFunc SortBy)
936 if (Hash->nLookupTableItems < 2)
938 qsort(Hash->LookupTable, Hash->nLookupTableItems, sizeof(HashKey*), SortBy);
946 * given you've put char * into your hash as a payload, a sort function might
948 * int SortByChar(const void* First, const void* Second)
951 * a = (char*) GetSearchPayload(First);
952 * b = (char*) GetSearchPayload(Second);
953 * return strcmp (a, b);
959 * Generic function to free a reference.
960 * since a reference actualy isn't needed to be freed, do nothing.
962 void reference_free_handler(void *ptr)
969 * This exposes the hashlittle() function to consumers.
971 int HashLittle(const void *key, size_t length) {
972 return (int)hashlittle(key, length, 1);