LCOV - code coverage report
Current view: top level - lib - hash.c (source / functions) Hit Total Coverage
Test: libcitadel.info Lines: 225 406 55.4 %
Date: 2010-12-07 Functions: 19 39 48.7 %
Branches: 115 238 48.3 %

           Branch data     Line data    Source code
       1                 :            : #include <stdint.h>
       2                 :            : #include <stdlib.h>
       3                 :            : #include <string.h>
       4                 :            : #include <limits.h>
       5                 :            : //dbg
       6                 :            : #include <stdio.h>
       7                 :            : #include "libcitadel.h"
       8                 :            : #include "lookup3.h"
       9                 :            : 
      10                 :            : typedef struct Payload Payload;
      11                 :            : 
      12                 :            : /**
      13                 :            :  * @brief Hash Payload storage Structure; filled in linear.
      14                 :            :  */
      15                 :            : struct Payload {
      16                 :            :         void *Data; /**< the Data belonging to this storage */
      17                 :            :         DeleteHashDataFunc Destructor; /**< if we want to destroy Data, do it with this function. */
      18                 :            : };
      19                 :            : 
      20                 :            : 
      21                 :            : /**
      22                 :            :  * @brief Hash key element; sorted by key
      23                 :            :  */
      24                 :            : struct HashKey {
      25                 :            :         long Key;         /**< Numeric Hashkey comperator for hash sorting */
      26                 :            :         long Position;    /**< Pointer to a Payload struct in the Payload Aray */
      27                 :            :         char *HashKey;    /**< the Plaintext Hashkey */
      28                 :            :         long HKLen;       /**< length of the Plaintext Hashkey */
      29                 :            :         Payload *PL;      /**< pointer to our payload for sorting */
      30                 :            : };
      31                 :            : 
      32                 :            : /**
      33                 :            :  * @brief Hash structure; holds arrays of Hashkey and Payload. 
      34                 :            :  */
      35                 :            : struct HashList {
      36                 :            :         Payload **Members;     /**< Our Payload members. This fills up linear */
      37                 :            :         HashKey **LookupTable; /**< Hash Lookup table. Elements point to members, and are sorted by their hashvalue */
      38                 :            :         char **MyKeys;         /**< this keeps the members for a call of GetHashKeys */
      39                 :            :         HashFunc Algorithm;    /**< should we use an alternating algorithm to calc the hash values? */
      40                 :            :         long nMembersUsed;     /**< how many pointers inside of the array are used? */
      41                 :            :         long nLookupTableItems; /**< how many items of the lookup table are used? */
      42                 :            :         long MemberSize;       /**< how big is Members and LookupTable? */
      43                 :            :         long tainted;          /**< if 0, we're hashed, else s.b. else sorted us in his own way. */
      44                 :            :         long uniq;             /**< are the keys going to be uniq? */
      45                 :            : };
      46                 :            : 
      47                 :            : /**
      48                 :            :  * @brief Anonymous Hash Iterator Object. used for traversing the whole array from outside 
      49                 :            :  */
      50                 :            : struct HashPos {
      51                 :            :         long Position;        /**< Position inside of the hash */
      52                 :            :         int StepWidth;        /**< small? big? forward? backward? */
      53                 :            : };
      54                 :            : 
      55                 :            : 
      56                 :            : /**
      57                 :            :  * @brief Iterate over the hash and call PrintEntry. 
      58                 :            :  * @param Hash your Hashlist structure
      59                 :            :  * @param Trans is called so you could for example print 'A:' if the next entries are like that.
      60                 :            :  *        Must be aware to receive NULL in both pointers.
      61                 :            :  * @param PrintEntry print entry one by one
      62                 :            :  * \returns the number of items printed
      63                 :            :  */
      64                 :          0 : int PrintHash(HashList *Hash, TransitionFunc Trans, PrintHashDataFunc PrintEntry)
      65                 :            : {
      66                 :            :         int i;
      67                 :            :         void *Previous;
      68                 :            :         void *Next;
      69                 :            :         const char* KeyStr;
      70                 :            : 
      71         [ #  # ]:          0 :         if (Hash == NULL)
      72                 :          0 :                 return 0;
      73                 :            : 
      74         [ #  # ]:          0 :         for (i=0; i < Hash->nLookupTableItems; i++) {
      75         [ #  # ]:          0 :                 if (i==0) {
      76                 :          0 :                         Previous = NULL;
      77                 :            :                 }
      78                 :            :                 else {
      79         [ #  # ]:          0 :                         if (Hash->LookupTable[i - 1] == NULL)
      80                 :          0 :                                 Previous = NULL;
      81                 :            :                         else
      82                 :          0 :                                 Previous = Hash->Members[Hash->LookupTable[i-1]->Position]->Data;
      83                 :            :                 }
      84         [ #  # ]:          0 :                 if (Hash->LookupTable[i] == NULL) {
      85                 :          0 :                         KeyStr = "";
      86                 :          0 :                         Next = NULL;
      87                 :            :                 }
      88                 :            :                 else {
      89                 :          0 :                         Next = Hash->Members[Hash->LookupTable[i]->Position]->Data;
      90                 :          0 :                         KeyStr = Hash->LookupTable[i]->HashKey;
      91                 :            :                 }
      92                 :            : 
      93                 :          0 :                 Trans(Previous, Next, i % 2);
      94                 :          0 :                 PrintEntry(KeyStr, Next, i % 2);
      95                 :            :         }
      96                 :          0 :         return i;
      97                 :            : }
      98                 :            : 
      99                 :            : 
     100                 :            : /**
     101                 :            :  * @brief verify the contents of a hash list; here for debugging purposes.
     102                 :            :  * @param Hash your Hashlist structure
     103                 :            :  * @param First Functionpointer to allow you to print your payload
     104                 :            :  * @param Second Functionpointer to allow you to print your payload
     105                 :            :  * \returns 0
     106                 :            :  */
     107                 :          0 : int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Second)
     108                 :            : {
     109                 :            :         const char *foo;
     110                 :            :         const char *bar;
     111                 :          0 :         const char *bla = "";
     112                 :            :         long key;
     113                 :            :         long i;
     114                 :            : 
     115         [ #  # ]:          0 :         if (Hash == NULL)
     116                 :          0 :                 return 0;
     117                 :            : 
     118         [ #  # ]:          0 :         if (Hash->MyKeys != NULL)
     119                 :          0 :                 free (Hash->MyKeys);
     120                 :            : 
     121                 :          0 :         Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nLookupTableItems);
     122                 :            : #ifdef DEBUG
     123                 :          0 :         printf("----------------------------------\n");
     124                 :            : #endif
     125         [ #  # ]:          0 :         for (i=0; i < Hash->nLookupTableItems; i++) {
     126                 :            :                 
     127         [ #  # ]:          0 :                 if (Hash->LookupTable[i] == NULL)
     128                 :            :                 {
     129                 :          0 :                         foo = "";
     130                 :          0 :                         bar = "";
     131                 :          0 :                         key = 0;
     132                 :            :                 }
     133                 :            :                 else 
     134                 :            :                 {
     135                 :          0 :                         key = Hash->LookupTable[i]->Key;
     136                 :          0 :                         foo = Hash->LookupTable[i]->HashKey;
     137         [ #  # ]:          0 :                         if (First != NULL)
     138                 :          0 :                                 bar = First(Hash->Members[Hash->LookupTable[i]->Position]->Data);
     139                 :            :                         else 
     140                 :          0 :                                 bar = "";
     141         [ #  # ]:          0 :                         if (Second != NULL)
     142                 :          0 :                                 bla = Second(Hash->Members[Hash->LookupTable[i]->Position]->Data);
     143                 :            :                         else
     144                 :          0 :                                 bla = "";
     145                 :            :                 }
     146                 :            : #ifdef DEBUG
     147                 :          0 :                 printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' ; %s\n", i, key, foo, bar, bla);
     148                 :            : #endif
     149                 :            :         }
     150                 :            : #ifdef DEBUG
     151                 :          0 :         printf("----------------------------------\n");
     152                 :            : #endif
     153                 :          0 :         return 0;
     154                 :            : }
     155                 :            : 
     156                 :            : 
     157                 :            : /**
     158                 :            :  * @brief instanciate a new hashlist
     159                 :            :  * \returns the newly allocated list. 
     160                 :            :  */
     161                 :        107 : HashList *NewHash(int Uniq, HashFunc F)
     162                 :            : {
     163                 :            :         HashList *NewList;
     164                 :        107 :         NewList = malloc (sizeof(HashList));
     165                 :        107 :         memset(NewList, 0, sizeof(HashList));
     166                 :            : 
     167                 :        107 :         NewList->Members = malloc(sizeof(Payload*) * 100);
     168                 :        107 :         memset(NewList->Members, 0, sizeof(Payload*) * 100);
     169                 :            : 
     170                 :        107 :         NewList->LookupTable = malloc(sizeof(HashKey*) * 100);
     171                 :        107 :         memset(NewList->LookupTable, 0, sizeof(HashKey*) * 100);
     172                 :            : 
     173                 :        107 :         NewList->MemberSize = 100;
     174                 :        107 :         NewList->tainted = 0;
     175                 :        107 :         NewList->uniq = Uniq;
     176                 :        107 :         NewList->Algorithm = F;
     177                 :            : 
     178                 :        107 :         return NewList;
     179                 :            : }
     180                 :            : 
     181                 :         43 : int GetCount(HashList *Hash)
     182                 :            : {
     183         [ -  + ]:         43 :         if(Hash==NULL) return 0;
     184                 :         43 :         return Hash->nLookupTableItems;
     185                 :            : }
     186                 :            : 
     187                 :            : 
     188                 :            : /**
     189                 :            :  * @brief private destructor for one hash element.
     190                 :            :  * Crashing? go one frame up and do 'print *FreeMe->LookupTable[i]'
     191                 :            :  * @param Data an element to free using the user provided destructor, or just plain free
     192                 :            :  */
     193                 :        220 : static void DeleteHashPayload (Payload *Data)
     194                 :            : {
     195                 :            :         /** do we have a destructor for our payload? */
     196         [ +  + ]:        220 :         if (Data->Destructor)
     197                 :        190 :                 Data->Destructor(Data->Data);
     198                 :            :         else
     199                 :         30 :                 free(Data->Data);
     200                 :        220 : }
     201                 :            : 
     202                 :            : /**
     203                 :            :  * @brief Destructor for nested hashes
     204                 :            :  */
     205                 :          0 : void HDeleteHash(void *vHash)
     206                 :            : {
     207                 :          0 :         HashList *FreeMe = (HashList*)vHash;
     208                 :          0 :         DeleteHash(&FreeMe);
     209                 :          0 : }
     210                 :            : 
     211                 :            : /**
     212                 :            :  * @brief destroy a hashlist and all of its members
     213                 :            :  * Crashing? do 'print *FreeMe->LookupTable[i]'
     214                 :            :  * @param Hash Hash to destroy. Is NULL'ed so you are shure its done.
     215                 :            :  */
     216                 :        235 : void DeleteHash(HashList **Hash)
     217                 :            : {
     218                 :            :         int i;
     219                 :            :         HashList *FreeMe;
     220                 :            : 
     221                 :        235 :         FreeMe = *Hash;
     222         [ +  + ]:        235 :         if (FreeMe == NULL)
     223                 :        128 :                 return;
     224                 :            :         /* even if there are sparse members already deleted... */
     225         [ +  + ]:        327 :         for (i=0; i < FreeMe->nMembersUsed; i++)
     226                 :            :         {
     227                 :            :                 /** get rid of our payload */
     228         [ +  + ]:        220 :                 if (FreeMe->Members[i] != NULL)
     229                 :            :                 {
     230                 :        218 :                         DeleteHashPayload(FreeMe->Members[i]);
     231                 :        218 :                         free(FreeMe->Members[i]);
     232                 :            :                 }
     233                 :            :                 /** delete our hashing data */
     234         [ +  + ]:        220 :                 if (FreeMe->LookupTable[i] != NULL)
     235                 :            :                 {
     236                 :        218 :                         free(FreeMe->LookupTable[i]->HashKey);
     237                 :        218 :                         free(FreeMe->LookupTable[i]);
     238                 :            :                 }
     239                 :            :         }
     240                 :            :         /** now, free our arrays... */
     241                 :        107 :         free(FreeMe->LookupTable);
     242                 :        107 :         free(FreeMe->Members);
     243                 :            :         /** did s.b. want an array of our keys? free them. */
     244         [ -  + ]:        107 :         if (FreeMe->MyKeys != NULL)
     245                 :          0 :                 free(FreeMe->MyKeys);
     246                 :            :         /** buye bye cruel world. */    
     247                 :        107 :         free (FreeMe);
     248                 :        235 :         *Hash = NULL;
     249                 :            : }
     250                 :            : 
     251                 :            : /**
     252                 :            :  * @brief Private function to increase the hash size.
     253                 :            :  * @param Hash the Hasharray to increase
     254                 :            :  */
     255                 :          0 : static void IncreaseHashSize(HashList *Hash)
     256                 :            : {
     257                 :            :         /* Ok, Our space is used up. Double the available space. */
     258                 :            :         Payload **NewPayloadArea;
     259                 :            :         HashKey **NewTable;
     260                 :            :         
     261         [ #  # ]:          0 :         if (Hash == NULL)
     262                 :          0 :                 return ;
     263                 :            : 
     264                 :            :         /** If we grew to much, this might be the place to rehash and shrink again.
     265                 :            :         if ((Hash->NMembersUsed > Hash->nLookupTableItems) && 
     266                 :            :             ((Hash->NMembersUsed - Hash->nLookupTableItems) > 
     267                 :            :              (Hash->nLookupTableItems / 10)))
     268                 :            :         {
     269                 :            : 
     270                 :            : 
     271                 :            :         }
     272                 :            :         */
     273                 :            : 
     274                 :            :         /** double our payload area */
     275                 :          0 :         NewPayloadArea = (Payload**) malloc(sizeof(Payload*) * Hash->MemberSize * 2);
     276                 :          0 :         memset(&NewPayloadArea[Hash->MemberSize], 0, sizeof(Payload*) * Hash->MemberSize);
     277                 :          0 :         memcpy(NewPayloadArea, Hash->Members, sizeof(Payload*) * Hash->MemberSize);
     278                 :          0 :         free(Hash->Members);
     279                 :          0 :         Hash->Members = NewPayloadArea;
     280                 :            :         
     281                 :            :         /** double our hashtable area */
     282                 :          0 :         NewTable = malloc(sizeof(HashKey*) * Hash->MemberSize * 2);
     283                 :          0 :         memset(&NewTable[Hash->MemberSize], 0, sizeof(HashKey*) * Hash->MemberSize);
     284                 :          0 :         memcpy(NewTable, Hash->LookupTable, sizeof(HashKey*) * Hash->MemberSize);
     285                 :          0 :         free(Hash->LookupTable);
     286                 :          0 :         Hash->LookupTable = NewTable;
     287                 :            :         
     288                 :          0 :         Hash->MemberSize *= 2;
     289                 :            : }
     290                 :            : 
     291                 :            : 
     292                 :            : /**
     293                 :            :  * @brief private function to add a new item to / replace an existing in -  the hashlist
     294                 :            :  * if the hash list is full, its re-alloced with double size.
     295                 :            :  * \parame Hash our hashlist to manipulate
     296                 :            :  * @param HashPos where should we insert / replace?
     297                 :            :  * @param HashKeyStr the Hash-String
     298                 :            :  * @param HKLen length of HashKeyStr
     299                 :            :  * @param Data your Payload to add
     300                 :            :  * @param Destructor Functionpointer to free Data. if NULL, default free() is used.
     301                 :            :  */
     302                 :        220 : static void InsertHashItem(HashList *Hash, 
     303                 :            :                            long HashPos, 
     304                 :            :                            long HashBinKey, 
     305                 :            :                            const char *HashKeyStr, 
     306                 :            :                            long HKLen, 
     307                 :            :                            void *Data,
     308                 :            :                            DeleteHashDataFunc Destructor)
     309                 :            : {
     310                 :            :         Payload *NewPayloadItem;
     311                 :            :         HashKey *NewHashKey;
     312                 :            : 
     313         [ -  + ]:        220 :         if (Hash == NULL)
     314                 :          0 :                 return;
     315                 :            : 
     316         [ -  + ]:        220 :         if (Hash->nMembersUsed >= Hash->MemberSize)
     317                 :          0 :                 IncreaseHashSize (Hash);
     318                 :            : 
     319                 :            :         /** Arrange the payload */
     320                 :        220 :         NewPayloadItem = (Payload*) malloc (sizeof(Payload));
     321                 :        220 :         NewPayloadItem->Data = Data;
     322                 :        220 :         NewPayloadItem->Destructor = Destructor;
     323                 :            :         /** Arrange the hashkey */
     324                 :        220 :         NewHashKey = (HashKey*) malloc (sizeof(HashKey));
     325                 :        220 :         NewHashKey->HashKey = (char *) malloc (HKLen + 1);
     326                 :        220 :         NewHashKey->HKLen = HKLen;
     327                 :        220 :         memcpy (NewHashKey->HashKey, HashKeyStr, HKLen + 1);
     328                 :        220 :         NewHashKey->Key = HashBinKey;
     329                 :        220 :         NewHashKey->PL = NewPayloadItem;
     330                 :            :         /** our payload is queued at the end... */
     331                 :        220 :         NewHashKey->Position = Hash->nMembersUsed;
     332                 :            :         /** but if we should be sorted into a specific place... */
     333 [ +  + ][ +  + ]:        220 :         if ((Hash->nLookupTableItems != 0) && 
     334                 :        155 :             (HashPos != Hash->nLookupTableItems) ) {
     335                 :            :                 long ItemsAfter;
     336                 :            : 
     337                 :         47 :                 ItemsAfter = Hash->nLookupTableItems - HashPos;
     338                 :            :                 /** make space were we can fill us in */
     339         [ +  - ]:         47 :                 if (ItemsAfter > 0)
     340                 :            :                 {
     341                 :         47 :                         memmove(&Hash->LookupTable[HashPos + 1],
     342                 :         47 :                                 &Hash->LookupTable[HashPos],
     343                 :         47 :                                 ItemsAfter * sizeof(HashKey*));
     344                 :            :                 } 
     345                 :            :         }
     346                 :            :         
     347                 :        220 :         Hash->Members[Hash->nMembersUsed] = NewPayloadItem;
     348                 :        220 :         Hash->LookupTable[HashPos] = NewHashKey;
     349                 :        220 :         Hash->nMembersUsed++;
     350                 :        220 :         Hash->nLookupTableItems++;
     351                 :            : }
     352                 :            : 
     353                 :            : /**
     354                 :            :  * @brief if the user has tainted the hash, but wants to insert / search items by their key
     355                 :            :  *  we need to search linear through the array. You have been warned that this will take more time!
     356                 :            :  * @param Hash Our Hash to manipulate
     357                 :            :  * @param HashBinKey the Hash-Number to lookup. 
     358                 :            :  * \returns the position (most closely) matching HashBinKey (-> Caller needs to compare! )
     359                 :            :  */
     360                 :          0 : static long FindInTaintedHash(HashList *Hash, long HashBinKey)
     361                 :            : {
     362                 :            :         long SearchPos;
     363                 :            : 
     364         [ #  # ]:          0 :         if (Hash == NULL)
     365                 :          0 :                 return 0;
     366                 :            : 
     367         [ #  # ]:          0 :         for (SearchPos = 0; SearchPos < Hash->nLookupTableItems; SearchPos ++) {
     368         [ #  # ]:          0 :                 if (Hash->LookupTable[SearchPos]->Key == HashBinKey){
     369                 :          0 :                         return SearchPos;
     370                 :            :                 }
     371                 :            :         }
     372                 :          0 :         return SearchPos;
     373                 :            : }
     374                 :            : 
     375                 :            : /**
     376                 :            :  * @brief Private function to lookup the Item / the closest position to put it in
     377                 :            :  * @param Hash Our Hash to manipulate
     378                 :            :  * @param HashBinKey the Hash-Number to lookup. 
     379                 :            :  * \returns the position (most closely) matching HashBinKey (-> Caller needs to compare! )
     380                 :            :  */
     381                 :        302 : static long FindInHash(HashList *Hash, long HashBinKey)
     382                 :            : {
     383                 :            :         long SearchPos;
     384                 :            :         long StepWidth;
     385                 :            : 
     386         [ -  + ]:        302 :         if (Hash == NULL)
     387                 :          0 :                 return 0;
     388                 :            : 
     389         [ -  + ]:        302 :         if (Hash->tainted)
     390                 :          0 :                 return FindInTaintedHash(Hash, HashBinKey);
     391                 :            : 
     392                 :        302 :         SearchPos = Hash->nLookupTableItems / 2;
     393                 :        302 :         StepWidth = SearchPos / 2;
     394 [ +  + ][ +  + ]:        428 :         while ((SearchPos > 0) && 
     395                 :        215 :                (SearchPos < Hash->nLookupTableItems)) 
     396                 :            :         {
     397                 :            :                 /** Did we find it? */
     398         [ +  + ]:        159 :                 if (Hash->LookupTable[SearchPos]->Key == HashBinKey){
     399                 :          4 :                         return SearchPos;
     400                 :            :                 }
     401                 :            :                 /** are we Aproximating in big steps? */
     402         [ +  + ]:        155 :                 if (StepWidth > 1){
     403         [ +  + ]:          6 :                         if (Hash->LookupTable[SearchPos]->Key > HashBinKey)
     404                 :          1 :                                 SearchPos -= StepWidth;
     405                 :            :                         else
     406                 :          5 :                                 SearchPos += StepWidth;
     407                 :          6 :                         StepWidth /= 2;                 
     408                 :            :                 }
     409                 :            :                 else { /** We are right next to our target, within 4 positions */
     410         [ +  + ]:        149 :                         if (Hash->LookupTable[SearchPos]->Key > HashBinKey) {
     411 [ +  - ][ +  + ]:         50 :                                 if ((SearchPos > 0) && 
     412                 :         50 :                                     (Hash->LookupTable[SearchPos - 1]->Key < HashBinKey))
     413                 :         25 :                                         return SearchPos;
     414                 :         25 :                                 SearchPos --;
     415                 :            :                         }
     416                 :            :                         else {
     417 [ +  + ][ +  + ]:         99 :                                 if ((SearchPos + 1 < Hash->nLookupTableItems) && 
     418                 :         43 :                                     (Hash->LookupTable[SearchPos + 1]->Key > HashBinKey))
     419                 :          4 :                                         return SearchPos;
     420                 :         95 :                                 SearchPos ++;
     421                 :            :                         }
     422                 :        120 :                         StepWidth--;
     423                 :            :                 }
     424                 :            :         }
     425                 :        302 :         return SearchPos;
     426                 :            : }
     427                 :            : 
     428                 :            : 
     429                 :            : /**
     430                 :            :  * @brief another hashing algorithm; treat it as just a pointer to int.
     431                 :            :  * @param str Our pointer to the int value
     432                 :            :  * @param len the length of the data pointed to; needs to be sizeof int, else we won't use it!
     433                 :            :  * \returns the calculated hash value
     434                 :            :  */
     435                 :         65 : long Flathash(const char *str, long len)
     436                 :            : {
     437         [ -  + ]:         65 :         if (len != sizeof (int))
     438                 :          0 :                 return 0;
     439                 :         65 :         else return *(int*)str;
     440                 :            : }
     441                 :            : 
     442                 :            : /**
     443                 :            :  * @brief another hashing algorithm; treat it as just a pointer to long.
     444                 :            :  * @param str Our pointer to the long value
     445                 :            :  * @param len the length of the data pointed to; needs to be sizeof long, else we won't use it!
     446                 :            :  * \returns the calculated hash value
     447                 :            :  */
     448                 :          8 : long lFlathash(const char *str, long len)
     449                 :            : {
     450         [ -  + ]:          8 :         if (len != sizeof (long))
     451                 :          0 :                 return 0;
     452                 :          8 :         else return *(long*)str;
     453                 :            : }
     454                 :            : 
     455                 :            : /**
     456                 :            :  * @brief private abstract wrapper around the hashing algorithm
     457                 :            :  * @param HKey the hash string
     458                 :            :  * @param HKLen length of HKey
     459                 :            :  * \returns the calculated hash value
     460                 :            :  */
     461                 :        270 : inline static long CalcHashKey (HashList *Hash, const char *HKey, long HKLen)
     462                 :            : {
     463         [ -  + ]:        270 :         if (Hash == NULL)
     464                 :          0 :                 return 0;
     465                 :            : 
     466         [ +  + ]:        270 :         if (Hash->Algorithm == NULL)
     467                 :        197 :                 return hashlittle(HKey, HKLen, 9283457);
     468                 :            :         else
     469                 :        270 :                 return Hash->Algorithm(HKey, HKLen);
     470                 :            : }
     471                 :            : 
     472                 :            : 
     473                 :            : /**
     474                 :            :  * @brief Add a new / Replace an existing item in the Hash
     475                 :            :  * @param HashList the list to manipulate
     476                 :            :  * @param HKey the hash-string to store Data under
     477                 :            :  * @param HKeyLen Length of HKey
     478                 :            :  * @param Data the payload you want to associate with HKey
     479                 :            :  * @param DeleteIt if not free() should be used to delete Data set to NULL, else DeleteIt is used.
     480                 :            :  */
     481                 :        220 : void Put(HashList *Hash, const char *HKey, long HKLen, void *Data, DeleteHashDataFunc DeleteIt)
     482                 :            : {
     483                 :            :         long HashBinKey;
     484                 :            :         long HashAt;
     485                 :            : 
     486         [ -  + ]:        220 :         if (Hash == NULL)
     487                 :          0 :                 return;
     488                 :            : 
     489                 :            :         /** first, find out were we could fit in... */
     490                 :        220 :         HashBinKey = CalcHashKey(Hash, HKey, HKLen);
     491                 :        220 :         HashAt = FindInHash(Hash, HashBinKey);
     492                 :            : 
     493         [ -  + ]:        220 :         if (HashAt >= Hash->MemberSize)
     494                 :          0 :                 IncreaseHashSize (Hash);
     495                 :            : 
     496                 :            :         /** oh, we're brand new... */
     497         [ +  + ]:        220 :         if (Hash->LookupTable[HashAt] == NULL) {
     498                 :        118 :                 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
     499                 :            :         }/** Insert After? */
     500         [ +  + ]:        102 :         else if (Hash->LookupTable[HashAt]->Key > HashBinKey) {
     501                 :         47 :                 InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
     502                 :            :         }/** Insert before? */
     503         [ +  - ]:         55 :         else if (Hash->LookupTable[HashAt]->Key < HashBinKey) {
     504                 :         55 :                 InsertHashItem(Hash, HashAt + 1, HashBinKey, HKey, HKLen, Data, DeleteIt);
     505                 :            :         }
     506                 :            :         else { /** Ok, we have a colision. replace it. */
     507         [ #  # ]:          0 :                 if (Hash->uniq) {
     508                 :            :                         long PayloadPos;
     509                 :            :                         
     510                 :          0 :                         PayloadPos = Hash->LookupTable[HashAt]->Position;
     511                 :          0 :                         DeleteHashPayload(Hash->Members[PayloadPos]);
     512                 :          0 :                         Hash->Members[PayloadPos]->Data = Data;
     513                 :          0 :                         Hash->Members[PayloadPos]->Destructor = DeleteIt;
     514                 :            :                 }
     515                 :            :                 else {
     516                 :        220 :                         InsertHashItem(Hash, HashAt + 1, HashBinKey, HKey, HKLen, Data, DeleteIt);
     517                 :            :                 }
     518                 :            :         }
     519                 :            : }
     520                 :            : 
     521                 :            : /**
     522                 :            :  * @brief Lookup the Data associated with HKey
     523                 :            :  * @param Hash the Hashlist to search in
     524                 :            :  * @param HKey the hashkey to look up
     525                 :            :  * @param HKLen length of HKey
     526                 :            :  * @param Data returns the Data associated with HKey
     527                 :            :  * \returns 0 if not found, 1 if.
     528                 :            :  */
     529                 :         50 : int GetHash(HashList *Hash, const char *HKey, long HKLen, void **Data)
     530                 :            : {
     531                 :            :         long HashBinKey;
     532                 :            :         long HashAt;
     533                 :            : 
     534         [ -  + ]:         50 :         if (Hash == NULL)
     535                 :          0 :                 return 0;
     536                 :            : 
     537         [ -  + ]:         50 :         if (HKLen <= 0) {
     538                 :          0 :                 *Data = NULL;
     539                 :          0 :                 return  0;
     540                 :            :         }
     541                 :            :         /** first, find out were we could be... */
     542                 :         50 :         HashBinKey = CalcHashKey(Hash, HKey, HKLen);
     543                 :         50 :         HashAt = FindInHash(Hash, HashBinKey);
     544   [ +  -  -  + ]:         50 :         if ((HashAt < 0) || /**< Not found at the lower edge? */
                 [ #  # ]
     545                 :         50 :             (HashAt >= Hash->nLookupTableItems) || /**< Not found at the upper edge? */
     546                 :          0 :             (Hash->LookupTable[HashAt]->Key != HashBinKey)) { /**< somewhere inbetween but no match? */
     547                 :         50 :                 *Data = NULL;
     548                 :         50 :                 return 0;
     549                 :            :         }
     550                 :            :         else { /** GOTCHA! */
     551                 :            :                 long MemberPosition;
     552                 :            : 
     553                 :          0 :                 MemberPosition = Hash->LookupTable[HashAt]->Position;
     554                 :          0 :                 *Data = Hash->Members[MemberPosition]->Data;
     555                 :         50 :                 return 1;
     556                 :            :         }
     557                 :            : }
     558                 :            : 
     559                 :            : /* TODO? */
     560                 :          0 : int GetKey(HashList *Hash, char *HKey, long HKLen, void **Payload)
     561                 :            : {
     562                 :          0 :         return 0;
     563                 :            : }
     564                 :            : 
     565                 :            : /**
     566                 :            :  * @brief get the Keys present in this hash, simila to array_keys() in PHP
     567                 :            :  *  Attention: List remains to Hash! don't modify or free it!
     568                 :            :  * @param Hash Your Hashlist to extract the keys from
     569                 :            :  * @param List returns the list of hashkeys stored in Hash
     570                 :            :  */
     571                 :          0 : int GetHashKeys(HashList *Hash, char ***List)
     572                 :            : {
     573                 :            :         long i;
     574         [ #  # ]:          0 :         if (Hash == NULL)
     575                 :          0 :                 return 0;
     576         [ #  # ]:          0 :         if (Hash->MyKeys != NULL)
     577                 :          0 :                 free (Hash->MyKeys);
     578                 :            : 
     579                 :          0 :         Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nLookupTableItems);
     580         [ #  # ]:          0 :         for (i=0; i < Hash->nLookupTableItems; i++) {
     581                 :            :         
     582                 :          0 :                 Hash->MyKeys[i] = Hash->LookupTable[i]->HashKey;
     583                 :            :         }
     584                 :          0 :         *List = (char**)Hash->MyKeys;
     585                 :          0 :         return Hash->nLookupTableItems;
     586                 :            : }
     587                 :            : 
     588                 :            : /**
     589                 :            :  * @brief creates a hash-linear iterator object
     590                 :            :  * @param Hash the list we reference
     591                 :            :  * @param in which step width should we iterate?
     592                 :            :  *  If negative, the last position matching the 
     593                 :            :  *  step-raster is provided.
     594                 :            :  * \returns the hash iterator
     595                 :            :  */
     596                 :        112 : HashPos *GetNewHashPos(HashList *Hash, int StepWidth)
     597                 :            : {
     598                 :            :         HashPos *Ret;
     599                 :            :         
     600                 :        112 :         Ret = (HashPos*)malloc(sizeof(HashPos));
     601         [ +  + ]:        112 :         if (StepWidth != 0)
     602                 :         30 :                 Ret->StepWidth = StepWidth;
     603                 :            :         else
     604                 :         82 :                 Ret->StepWidth = 1;
     605         [ +  + ]:        112 :         if (Ret->StepWidth <  0) {
     606                 :         15 :                 Ret->Position = Hash->nLookupTableItems - 1;
     607                 :            :         }
     608                 :            :         else {
     609                 :         97 :                 Ret->Position = 0;
     610                 :            :         }
     611                 :        112 :         return Ret;
     612                 :            : }
     613                 :            : 
     614                 :            : /**
     615                 :            :  * @brief Set iterator object to point to key. If not found, don't change iterator
     616                 :            :  * @param Hash the list we reference
     617                 :            :  * @param HKey key to search for
     618                 :            :  * @param HKLen length of key
     619                 :            :  * @param At HashPos to update
     620                 :            :  * \returns 0 if not found
     621                 :            :  */
     622                 :          0 : int GetHashPosFromKey(HashList *Hash, const char *HKey, long HKLen, HashPos *At)
     623                 :            : {
     624                 :            :         long HashBinKey;
     625                 :            :         long HashAt;
     626                 :            : 
     627         [ #  # ]:          0 :         if (Hash == NULL)
     628                 :          0 :                 return 0;
     629                 :            : 
     630         [ #  # ]:          0 :         if (HKLen <= 0) {
     631                 :          0 :                 return  0;
     632                 :            :         }
     633                 :            :         /** first, find out were we could be... */
     634                 :          0 :         HashBinKey = CalcHashKey(Hash, HKey, HKLen);
     635                 :          0 :         HashAt = FindInHash(Hash, HashBinKey);
     636   [ #  #  #  # ]:          0 :         if ((HashAt < 0) || /**< Not found at the lower edge? */
                 [ #  # ]
     637                 :          0 :             (HashAt >= Hash->nLookupTableItems) || /**< Not found at the upper edge? */
     638                 :          0 :             (Hash->LookupTable[HashAt]->Key != HashBinKey)) { /**< somewhere inbetween but no match? */
     639                 :          0 :                 return 0;
     640                 :            :         }
     641                 :            :         /** GOTCHA! */
     642                 :          0 :         At->Position = Hash->LookupTable[HashAt]->Position;
     643                 :          0 :         return 1;
     644                 :            : }
     645                 :            : 
     646                 :            : /**
     647                 :            :  * @brief Delete from the Hash the entry at Position
     648                 :            :  * @param Hash the list we reference
     649                 :            :  * @param At the position within the Hash
     650                 :            :  * \returns 0 if not found
     651                 :            :  */
     652                 :          2 : int DeleteEntryFromHash(HashList *Hash, HashPos *At)
     653                 :            : {
     654                 :            :         Payload *FreeMe;
     655         [ -  + ]:          2 :         if (Hash == NULL)
     656                 :          0 :                 return 0;
     657                 :            : 
     658                 :            :         /* if lockable, lock here */
     659 [ +  - ][ +  - ]:          2 :         if ((Hash == NULL) || 
         [ +  - ][ -  + ]
     660                 :          2 :             (At->Position >= Hash->nLookupTableItems) || 
     661                 :          2 :             (At->Position < 0) ||
     662                 :          2 :             (At->Position > Hash->nLookupTableItems))
     663                 :            :         {
     664                 :            :                 /* unlock... */
     665                 :          0 :                 return 0;
     666                 :            :         }
     667                 :            : 
     668                 :          2 :         FreeMe = Hash->Members[Hash->LookupTable[At->Position]->Position];
     669                 :          2 :         Hash->Members[Hash->LookupTable[At->Position]->Position] = NULL;
     670                 :            : 
     671                 :            : 
     672                 :            :         /** delete our hashing data */
     673         [ +  - ]:          2 :         if (Hash->LookupTable[At->Position] != NULL)
     674                 :            :         {
     675                 :          2 :                 free(Hash->LookupTable[At->Position]->HashKey);
     676                 :          2 :                 free(Hash->LookupTable[At->Position]);
     677         [ +  - ]:          2 :                 if (At->Position < Hash->nLookupTableItems)
     678                 :            :                 {
     679                 :          4 :                         memmove(&Hash->LookupTable[At->Position],
     680                 :          2 :                                 &Hash->LookupTable[At->Position + 1],
     681                 :          2 :                                 (Hash->nLookupTableItems - At->Position - 1) * 
     682                 :            :                                 sizeof(HashKey*));
     683                 :            : 
     684                 :          2 :                         Hash->LookupTable[Hash->nLookupTableItems - 1] = NULL;
     685                 :            :                 }
     686                 :            :                 else 
     687                 :          0 :                         Hash->LookupTable[At->Position] = NULL;
     688                 :          2 :                 Hash->nLookupTableItems--;
     689                 :            :         }
     690                 :            :         /* unlock... */
     691                 :            : 
     692                 :            : 
     693                 :            :         /** get rid of our payload */
     694         [ +  - ]:          2 :         if (FreeMe != NULL)
     695                 :            :         {
     696                 :          2 :                 DeleteHashPayload(FreeMe);
     697                 :          2 :                 free(FreeMe);
     698                 :            :         }
     699                 :          2 :         return 1;
     700                 :            : }
     701                 :            : 
     702                 :            : /**
     703                 :            :  * @brief retrieve the counter from the itteratoor
     704                 :            :  * @param the Iterator to analyze
     705                 :            :  * \returns the n'th hashposition we point at
     706                 :            :  */
     707                 :          0 : int GetHashPosCounter(HashList *Hash, HashPos *At)
     708                 :            : {
     709 [ #  # ][ #  # ]:          0 :         if ((Hash == NULL) || 
         [ #  # ][ #  # ]
     710                 :          0 :             (At->Position >= Hash->nLookupTableItems) || 
     711                 :          0 :             (At->Position < 0) ||
     712                 :          0 :             (At->Position > Hash->nLookupTableItems))
     713                 :          0 :                 return 0;
     714                 :          0 :         return At->Position;
     715                 :            : }
     716                 :            : 
     717                 :            : /**
     718                 :            :  * @brief frees a linear hash iterator
     719                 :            :  */
     720                 :        110 : void DeleteHashPos(HashPos **DelMe)
     721                 :            : {
     722         [ +  - ]:        110 :         if (*DelMe != NULL)
     723                 :            :         {
     724                 :        110 :                 free(*DelMe);
     725                 :        110 :                 *DelMe = NULL;
     726                 :            :         }
     727                 :        110 : }
     728                 :            : 
     729                 :            : 
     730                 :            : /**
     731                 :            :  * @brief Get the data located where HashPos Iterator points at, and Move HashPos one forward
     732                 :            :  * @param Hash your Hashlist to follow
     733                 :            :  * @param At the position to retrieve the Item from and move forward afterwards
     734                 :            :  * @param HKLen returns Length of Hashkey Returned
     735                 :            :  * @param HashKey returns the Hashkey corrosponding to HashPos
     736                 :            :  * @param Data returns the Data found at HashPos
     737                 :            :  * \returns whether the item was found or not.
     738                 :            :  */
     739                 :        495 : int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, const char **HashKey, void **Data)
     740                 :            : {
     741                 :            :         long PayloadPos;
     742                 :            : 
     743 [ +  - ][ +  + ]:        495 :         if ((Hash == NULL) || 
         [ +  + ][ -  + ]
     744                 :        495 :             (At->Position >= Hash->nLookupTableItems) || 
     745                 :        400 :             (At->Position < 0) ||
     746                 :        385 :             (At->Position > Hash->nLookupTableItems))
     747                 :        110 :                 return 0;
     748                 :        385 :         *HKLen = Hash->LookupTable[At->Position]->HKLen;
     749                 :        385 :         *HashKey = Hash->LookupTable[At->Position]->HashKey;
     750                 :        385 :         PayloadPos = Hash->LookupTable[At->Position]->Position;
     751                 :        385 :         *Data = Hash->Members[PayloadPos]->Data;
     752                 :            : 
     753                 :            :         /* Position is NULL-Based, while Stepwidth is not... */
     754         [ +  + ]:        385 :         if ((At->Position % abs(At->StepWidth)) == 0)
     755                 :        380 :                 At->Position += At->StepWidth;
     756                 :            :         else 
     757                 :          5 :                 At->Position += ((At->Position) % abs(At->StepWidth)) * 
     758                 :         10 :                         (At->StepWidth / abs(At->StepWidth));
     759                 :        495 :         return 1;
     760                 :            : }
     761                 :            : 
     762                 :            : /**
     763                 :            :  * @brief Get the data located where HashPos Iterator points at
     764                 :            :  * @param Hash your Hashlist to follow
     765                 :            :  * @param At the position retrieve the data from
     766                 :            :  * @param HKLen returns Length of Hashkey Returned
     767                 :            :  * @param HashKey returns the Hashkey corrosponding to HashPos
     768                 :            :  * @param Data returns the Data found at HashPos
     769                 :            :  * \returns whether the item was found or not.
     770                 :            :  */
     771                 :          0 : int GetHashPos(HashList *Hash, HashPos *At, long *HKLen, const char **HashKey, void **Data)
     772                 :            : {
     773                 :            :         long PayloadPos;
     774                 :            : 
     775 [ #  # ][ #  # ]:          0 :         if ((Hash == NULL) || 
         [ #  # ][ #  # ]
     776                 :          0 :             (At->Position >= Hash->nLookupTableItems) || 
     777                 :          0 :             (At->Position < 0) ||
     778                 :          0 :             (At->Position > Hash->nLookupTableItems))
     779                 :          0 :                 return 0;
     780                 :          0 :         *HKLen = Hash->LookupTable[At->Position]->HKLen;
     781                 :          0 :         *HashKey = Hash->LookupTable[At->Position]->HashKey;
     782                 :          0 :         PayloadPos = Hash->LookupTable[At->Position]->Position;
     783                 :          0 :         *Data = Hash->Members[PayloadPos]->Data;
     784                 :            : 
     785                 :          0 :         return 1;
     786                 :            : }
     787                 :            : 
     788                 :            : /**
     789                 :            :  * @brief Move HashPos one forward
     790                 :            :  * @param Hash your Hashlist to follow
     791                 :            :  * @param At the position to move forward
     792                 :            :  * \returns whether there is a next item or not.
     793                 :            :  */
     794                 :          3 : int NextHashPos(HashList *Hash, HashPos *At)
     795                 :            : {
     796 [ +  - ][ +  - ]:          3 :         if ((Hash == NULL) || 
         [ +  - ][ -  + ]
     797                 :          3 :             (At->Position >= Hash->nLookupTableItems) || 
     798                 :          3 :             (At->Position < 0) ||
     799                 :          3 :             (At->Position > Hash->nLookupTableItems))
     800                 :          0 :                 return 0;
     801                 :            : 
     802                 :            :         /* Position is NULL-Based, while Stepwidth is not... */
     803         [ +  - ]:          3 :         if ((At->Position % abs(At->StepWidth)) == 0)
     804                 :          3 :                 At->Position += At->StepWidth;
     805                 :            :         else 
     806                 :          0 :                 At->Position += ((At->Position) % abs(At->StepWidth)) * 
     807                 :          0 :                         (At->StepWidth / abs(At->StepWidth));
     808 [ +  - ][ +  - ]:          3 :         return !((At->Position >= Hash->nLookupTableItems) || 
                 [ +  - ]
     809                 :            :                  (At->Position < 0) ||
     810                 :            :                  (At->Position > Hash->nLookupTableItems));
     811                 :            : }
     812                 :            : 
     813                 :            : /**
     814                 :            :  * @brief Get the data located where At points to
     815                 :            :  * note: you should prefer iterator operations instead of using me.
     816                 :            :  * @param Hash your Hashlist peek from
     817                 :            :  * @param HKLen returns Length of Hashkey Returned
     818                 :            :  * @param HashKey returns the Hashkey corrosponding to HashPos
     819                 :            :  * @param Data returns the Data found at HashPos
     820                 :            :  * \returns whether the item was found or not.
     821                 :            :  */
     822                 :          0 : int GetHashAt(HashList *Hash,long At, long *HKLen, const char **HashKey, void **Data)
     823                 :            : {
     824                 :            :         long PayloadPos;
     825                 :            : 
     826 [ #  # ][ #  # ]:          0 :         if ((Hash == NULL) || 
                 [ #  # ]
     827                 :            :             (At < 0) || 
     828                 :          0 :             (At >= Hash->nLookupTableItems))
     829                 :          0 :                 return 0;
     830                 :          0 :         *HKLen = Hash->LookupTable[At]->HKLen;
     831                 :          0 :         *HashKey = Hash->LookupTable[At]->HashKey;
     832                 :          0 :         PayloadPos = Hash->LookupTable[At]->Position;
     833                 :          0 :         *Data = Hash->Members[PayloadPos]->Data;
     834                 :          0 :         return 1;
     835                 :            : }
     836                 :            : 
     837                 :            : /**
     838                 :            :  * @brief Get the data located where At points to
     839                 :            :  * note: you should prefer iterator operations instead of using me.
     840                 :            :  * @param Hash your Hashlist peek from
     841                 :            :  * @param HKLen returns Length of Hashkey Returned
     842                 :            :  * @param HashKey returns the Hashkey corrosponding to HashPos
     843                 :            :  * @param Data returns the Data found at HashPos
     844                 :            :  * \returns whether the item was found or not.
     845                 :            :  */
     846                 :            : /*
     847                 :            : long GetHashIDAt(HashList *Hash,long At)
     848                 :            : {
     849                 :            :         if ((Hash == NULL) || 
     850                 :            :             (At < 0) || 
     851                 :            :             (At > Hash->nLookupTableItems))
     852                 :            :                 return 0;
     853                 :            : 
     854                 :            :         return Hash->LookupTable[At]->Key;
     855                 :            : }
     856                 :            : */
     857                 :            : 
     858                 :            : 
     859                 :            : /**
     860                 :            :  * @brief sorting function for sorting the Hash alphabeticaly by their strings
     861                 :            :  * @param Key1 first item
     862                 :            :  * @param Key2 second item
     863                 :            :  */
     864                 :          0 : static int SortByKeys(const void *Key1, const void* Key2)
     865                 :            : {
     866                 :            :         HashKey *HKey1, *HKey2;
     867                 :          0 :         HKey1 = *(HashKey**) Key1;
     868                 :          0 :         HKey2 = *(HashKey**) Key2;
     869                 :            : 
     870                 :          0 :         return strcasecmp(HKey1->HashKey, HKey2->HashKey);
     871                 :            : }
     872                 :            : 
     873                 :            : /**
     874                 :            :  * @brief sorting function for sorting the Hash alphabeticaly reverse by their strings
     875                 :            :  * @param Key1 first item
     876                 :            :  * @param Key2 second item
     877                 :            :  */
     878                 :          0 : static int SortByKeysRev(const void *Key1, const void* Key2)
     879                 :            : {
     880                 :            :         HashKey *HKey1, *HKey2;
     881                 :          0 :         HKey1 = *(HashKey**) Key1;
     882                 :          0 :         HKey2 = *(HashKey**) Key2;
     883                 :            : 
     884                 :          0 :         return strcasecmp(HKey2->HashKey, HKey1->HashKey);
     885                 :            : }
     886                 :            : 
     887                 :            : /**
     888                 :            :  * @brief sorting function to regain hash-sequence and revert tainted status
     889                 :            :  * @param Key1 first item
     890                 :            :  * @param Key2 second item
     891                 :            :  */
     892                 :          0 : static int SortByHashKeys(const void *Key1, const void* Key2)
     893                 :            : {
     894                 :            :         HashKey *HKey1, *HKey2;
     895                 :          0 :         HKey1 = *(HashKey**) Key1;
     896                 :          0 :         HKey2 = *(HashKey**) Key2;
     897                 :            : 
     898                 :          0 :         return HKey1->Key > HKey2->Key;
     899                 :            : }
     900                 :            : 
     901                 :            : 
     902                 :            : /**
     903                 :            :  * @brief sort the hash alphabeticaly by their keys.
     904                 :            :  * Caution: This taints the hashlist, so accessing it later 
     905                 :            :  * will be significantly slower! You can un-taint it by SortByHashKeyStr
     906                 :            :  * @param Hash the list to sort
     907                 :            :  * @param Order 0/1 Forward/Backward
     908                 :            :  */
     909                 :          0 : void SortByHashKey(HashList *Hash, int Order)
     910                 :            : {
     911         [ #  # ]:          0 :         if (Hash->nLookupTableItems < 2)
     912                 :          0 :                 return;
     913         [ #  # ]:          0 :         qsort(Hash->LookupTable, Hash->nLookupTableItems, sizeof(HashKey*), 
     914                 :            :               (Order)?SortByKeys:SortByKeysRev);
     915                 :          0 :         Hash->tainted = 1;
     916                 :            : }
     917                 :            : 
     918                 :            : /**
     919                 :            :  * @brief sort the hash by their keys (so it regains untainted state).
     920                 :            :  * this will result in the sequence the hashing allgorithm produces it by default.
     921                 :            :  * @param Hash the list to sort
     922                 :            :  */
     923                 :          0 : void SortByHashKeyStr(HashList *Hash)
     924                 :            : {
     925                 :          0 :         Hash->tainted = 0;
     926         [ #  # ]:          0 :         if (Hash->nLookupTableItems < 2)
     927                 :          0 :                 return;
     928                 :          0 :         qsort(Hash->LookupTable, Hash->nLookupTableItems, sizeof(HashKey*), SortByHashKeys);
     929                 :            : }
     930                 :            : 
     931                 :            : 
     932                 :            : /**
     933                 :            :  * @brief gives user sort routines access to the hash payload
     934                 :            :  * @param Searchentry to retrieve Data to
     935                 :            :  * \returns Data belonging to HashVoid
     936                 :            :  */
     937                 :          0 : const void *GetSearchPayload(const void *HashVoid)
     938                 :            : {
     939                 :          0 :         return (*(HashKey**)HashVoid)->PL->Data;
     940                 :            : }
     941                 :            : 
     942                 :            : /**
     943                 :            :  * @brief sort the hash by your sort function. see the following sample.
     944                 :            :  * this will result in the sequence the hashing allgorithm produces it by default.
     945                 :            :  * @param Hash the list to sort
     946                 :            :  * @param SortBy Sortfunction; see below how to implement this
     947                 :            :  */
     948                 :          0 : void SortByPayload(HashList *Hash, CompareFunc SortBy)
     949                 :            : {
     950         [ #  # ]:          0 :         if (Hash->nLookupTableItems < 2)
     951                 :          0 :                 return;
     952                 :          0 :         qsort(Hash->LookupTable, Hash->nLookupTableItems, sizeof(HashKey*), SortBy);
     953                 :          0 :         Hash->tainted = 1;
     954                 :            : }
     955                 :            : 
     956                 :            : 
     957                 :            : 
     958                 :            : 
     959                 :            : /**
     960                 :            :  * given you've put char * into your hash as a payload, a sort function might
     961                 :            :  * look like this:
     962                 :            :  * int SortByChar(const void* First, const void* Second)
     963                 :            :  * {
     964                 :            :  *      char *a, *b;
     965                 :            :  *      a = (char*) GetSearchPayload(First);
     966                 :            :  *      b = (char*) GetSearchPayload(Second);
     967                 :            :  *      return strcmp (a, b);
     968                 :            :  * }
     969                 :            :  */
     970                 :            : 
     971                 :            : 
     972                 :            : /*
     973                 :            :  * Generic function to free a reference.  
     974                 :            :  * since a reference actualy isn't needed to be freed, do nothing.
     975                 :            :  */
     976                 :          0 : void reference_free_handler(void *ptr) 
     977                 :            : {
     978                 :            :         return;
     979                 :            : }
     980                 :            : 
     981                 :            : 
     982                 :            : /*
     983                 :            :  * This exposes the hashlittle() function to consumers.
     984                 :            :  */
     985                 :          0 : int HashLittle(const void *key, size_t length) {
     986                 :          0 :         return (int)hashlittle(key, length, 1);
     987                 :            : }
     988                 :            : 
     989                 :            : 
     990                 :            : /**
     991                 :            :  * \brief parses an MSet string into a list for later use
     992                 :            :  * \param MSetList List to be read from MSetStr
     993                 :            :  * \param MSetStr String containing the list
     994                 :            :  */
     995                 :          4 : int ParseMSet(MSet **MSetList, StrBuf *MSetStr)
     996                 :            : {
     997                 :          4 :         const char *POS = NULL, *SetPOS = NULL;
     998                 :            :         StrBuf *OneSet;
     999                 :            :         HashList *ThisMSet;
    1000                 :            :         long StartSet, EndSet;
    1001                 :            :         long *pEndSet;
    1002                 :            :         
    1003                 :          4 :         *MSetList = NULL;
    1004 [ +  - ][ -  + ]:          4 :         if ((MSetStr == NULL) || (StrLength(MSetStr) == 0))
    1005                 :          0 :             return 0;
    1006                 :            :             
    1007                 :          4 :         OneSet = NewStrBufPlain(NULL, StrLength(MSetStr));
    1008                 :            : 
    1009                 :          4 :         ThisMSet = NewHash(0, lFlathash);
    1010                 :            : 
    1011                 :          4 :         *MSetList = (MSet*) ThisMSet;
    1012                 :            : 
    1013                 :            :         /* an MSet is a coma separated value list. */
    1014                 :          4 :         StrBufExtract_NextToken(OneSet, MSetStr, &POS, ',');
    1015                 :            :         do {
    1016                 :          8 :                 SetPOS = NULL;
    1017                 :            : 
    1018                 :            :                 /* One set may consist of two Numbers: Start + optional End */
    1019                 :          8 :                 StartSet = StrBufExtractNext_long(OneSet, &SetPOS, ':');
    1020                 :          8 :                 EndSet = 0; /* no range is our default. */
    1021                 :            :                 /* do we have an end (aka range?) */
    1022   [ +  -  +  + ]:          8 :                 if ((SetPOS != NULL) && (SetPOS != StrBufNOTNULL))
    1023                 :            :                 {
    1024         [ +  + ]:          3 :                         if (*(SetPOS) == '*')
    1025                 :          1 :                                 EndSet = LONG_MAX; /* ranges with '*' go until infinity */
    1026                 :            :                         else 
    1027                 :            :                                 /* in other cases, get the EndPoint */
    1028                 :          2 :                                 EndSet = StrBufExtractNext_long(OneSet, &SetPOS, ':');
    1029                 :            :                 }
    1030                 :            : 
    1031                 :          8 :                 pEndSet = (long*) malloc (sizeof(long));
    1032                 :          8 :                 *pEndSet = EndSet;
    1033                 :            : 
    1034                 :          8 :                 Put(ThisMSet, LKEY(StartSet), pEndSet, NULL);
    1035                 :            :                 /* if we don't have another, we're done. */
    1036         [ +  + ]:          8 :                 if (POS == StrBufNOTNULL)
    1037                 :            :                         break;
    1038                 :          4 :                 StrBufExtract_NextToken(OneSet, MSetStr, &POS, ',');
    1039                 :          8 :         } while (1);
    1040                 :          4 :         FreeStrBuf(&OneSet);
    1041                 :            : 
    1042                 :          4 :         return 1;
    1043                 :            : }
    1044                 :            : 
    1045                 :            : /**
    1046                 :            :  * \brief checks whether a message is inside a mset
    1047                 :            :  * \param MSetList List to search for MsgNo
    1048                 :            :  * \param MsgNo number to search in mset
    1049                 :            :  */
    1050                 :         32 : int IsInMSetList(MSet *MSetList, long MsgNo)
    1051                 :            : {
    1052                 :            :         /* basicaly we are a ... */
    1053                 :            :         long MemberPosition;
    1054                 :         32 :         HashList *Hash = (HashList*) MSetList;
    1055                 :            :         long HashAt;
    1056                 :            :         long EndAt;
    1057                 :            :         long StartAt;
    1058                 :            : 
    1059         [ -  + ]:         32 :         if (Hash == NULL)
    1060                 :          0 :                 return 0;
    1061         [ -  + ]:         32 :         if (Hash->MemberSize == 0)
    1062                 :          0 :                 return 0;
    1063                 :            :         /** first, find out were we could fit in... */
    1064                 :         32 :         HashAt = FindInHash(Hash, MsgNo);
    1065                 :            :         
    1066                 :            :         /* we're below the first entry, so not found. */
    1067         [ -  + ]:         32 :         if (HashAt < 0)
    1068                 :          0 :                 return 0;
    1069                 :            :         /* upper edge? move to last item */
    1070         [ +  + ]:         32 :         if (HashAt >= Hash->nMembersUsed)
    1071                 :          3 :                 HashAt = Hash->nMembersUsed - 1;
    1072                 :            :         /* Match? then we got it. */
    1073         [ +  + ]:         29 :         else if (Hash->LookupTable[HashAt]->Key == MsgNo)
    1074                 :          8 :                 return 1;
    1075                 :            :         /* One above possible range start? we need to move to the lower one. */ 
    1076 [ +  + ][ +  + ]:         21 :         else if ((HashAt > 0) && 
    1077                 :         12 :                  (Hash->LookupTable[HashAt]->Key > MsgNo))
    1078                 :          8 :                 HashAt -=1;
    1079                 :            : 
    1080                 :            :         /* Fetch the actual data */
    1081                 :         24 :         StartAt = Hash->LookupTable[HashAt]->Key;
    1082                 :         24 :         MemberPosition = Hash->LookupTable[HashAt]->Position;
    1083                 :         24 :         EndAt = *(long*) Hash->Members[MemberPosition]->Data;
    1084 [ +  + ][ +  + ]:         24 :         if ((MsgNo >= StartAt) && (EndAt == LONG_MAX))
    1085                 :          2 :                 return 1;
    1086                 :            :         /* no range? */
    1087         [ +  + ]:         22 :         if (EndAt == 0)
    1088                 :         10 :                 return 0;
    1089                 :            :         /* inside of range? */
    1090 [ +  + ][ +  + ]:         12 :         if ((StartAt <= MsgNo) && (EndAt >= MsgNo))
    1091                 :          6 :                 return 1;
    1092                 :         32 :         return 0;
    1093                 :            : }
    1094                 :            : 
    1095                 :            : 
    1096                 :            : /**
    1097                 :            :  * \brief frees a mset [redirects to @ref DeleteHash
    1098                 :            :  * \param FreeMe to be free'd
    1099                 :            :  */
    1100                 :          4 : void DeleteMSet(MSet **FreeMe)
    1101                 :            : {
    1102                 :          4 :         DeleteHash((HashList**) FreeMe);
    1103                 :          4 : }

Generated by: LCOV version 1.8