Add propper debugging for lflathashs, crash if debug and invalid combination of ...
[citadel.git] / libcitadel / lib / hash.c
index e49adb80ab55b8fb500aaf6016a52251717f3a2c..ab7eec1896206b12797b442b4952114414c64285 100644 (file)
@@ -177,8 +177,8 @@ int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Secon
        const char *foo;
        const char *bar;
        const char *bla = "";
-#endif
        long key;
+#endif
        long i;
 
        if (Hash == NULL)
@@ -198,14 +198,15 @@ int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Secon
 #ifdef DEBUG
                        foo = "";
                        bar = "";
-#endif
-
                        key = 0;
+#endif
                }
                else 
                {
+#ifdef DEBUG
                        key = Hash->LookupTable[i]->Key;
                        foo = Hash->LookupTable[i]->HashKey;
+#endif
                        if (First != NULL)
 #ifdef DEBUG
                                bar =
@@ -229,7 +230,12 @@ int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Secon
 
                }
 #ifdef DEBUG
-               printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' ; %s\n", i, key, foo, bar, bla);
+               if ((Hash->Algorithm == lFlathash) || (Hash->Algorithm == Flathash)) {
+                       printf (" ---- Hashkey[%ld][%ld]: %ld '%s' Value: '%s' ; %s\n", i, key, *(long*) foo, foo, bar, bla);
+               }
+               else {
+                       printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' ; %s\n", i, key, foo, bar, bla);
+               }
 #endif
        }
 #ifdef DEBUG
@@ -272,12 +278,25 @@ HashList *NewHash(int Uniq, HashFunc F)
 {
        HashList *NewList;
        NewList = malloc (sizeof(HashList));
+       if (NewList == NULL)
+               return NULL;
        memset(NewList, 0, sizeof(HashList));
 
        NewList->Members = malloc(sizeof(Payload*) * 100);
+       if (NewList->Members == NULL)
+       {
+               free(NewList);
+               return NULL;
+       }
        memset(NewList->Members, 0, sizeof(Payload*) * 100);
 
        NewList->LookupTable = malloc(sizeof(HashKey*) * 100);
+       if (NewList->LookupTable == NULL)
+       {
+               free(NewList->Members);
+               free(NewList);
+               return NULL;
+       }
        memset(NewList->LookupTable, 0, sizeof(HashKey*) * 100);
 
        NewList->MemberSize = 100;
@@ -389,14 +408,14 @@ void DeleteHash(HashList **Hash)
  * @brief Private function to increase the hash size.
  * @param Hash the Hasharray to increase
  */
-static void IncreaseHashSize(HashList *Hash)
+static int IncreaseHashSize(HashList *Hash)
 {
        /* Ok, Our space is used up. Double the available space. */
        Payload **NewPayloadArea;
        HashKey **NewTable;
        
        if (Hash == NULL)
-               return ;
+               return 0;
 
        /** If we grew to much, this might be the place to rehash and shrink again.
        if ((Hash->NMembersUsed > Hash->nLookupTableItems) && 
@@ -408,21 +427,30 @@ static void IncreaseHashSize(HashList *Hash)
        }
        */
 
-       /** double our payload area */
        NewPayloadArea = (Payload**) malloc(sizeof(Payload*) * Hash->MemberSize * 2);
+       if (NewPayloadArea == NULL)
+               return 0;
+       NewTable = malloc(sizeof(HashKey*) * Hash->MemberSize * 2);
+       if (NewTable == NULL)
+       {
+               free(NewPayloadArea);
+               return 0;
+       }
+
+       /** double our payload area */
        memset(&NewPayloadArea[Hash->MemberSize], 0, sizeof(Payload*) * Hash->MemberSize);
        memcpy(NewPayloadArea, Hash->Members, sizeof(Payload*) * Hash->MemberSize);
        free(Hash->Members);
        Hash->Members = NewPayloadArea;
        
        /** double our hashtable area */
-       NewTable = malloc(sizeof(HashKey*) * Hash->MemberSize * 2);
        memset(&NewTable[Hash->MemberSize], 0, sizeof(HashKey*) * Hash->MemberSize);
        memcpy(NewTable, Hash->LookupTable, sizeof(HashKey*) * Hash->MemberSize);
        free(Hash->LookupTable);
        Hash->LookupTable = NewTable;
        
        Hash->MemberSize *= 2;
+       return 1;
 }
 
 
@@ -437,31 +465,49 @@ static void IncreaseHashSize(HashList *Hash)
  * @param Data your Payload to add
  * @param Destructor Functionpointer to free Data. if NULL, default free() is used.
  */
-static void InsertHashItem(HashList *Hash, 
-                          long HashPos, 
-                          long HashBinKey, 
-                          const char *HashKeyStr, 
-                          long HKLen, 
-                          void *Data,
-                          DeleteHashDataFunc Destructor)
+static int InsertHashItem(HashList *Hash, 
+                         long HashPos, 
+                         long HashBinKey, 
+                         const char *HashKeyStr, 
+                         long HKLen, 
+                         void *Data,
+                         DeleteHashDataFunc Destructor)
 {
        Payload *NewPayloadItem;
        HashKey *NewHashKey;
+       char *HashKeyOrgVal;
 
        if (Hash == NULL)
-               return;
+               return 0;
 
-       if (Hash->nMembersUsed >= Hash->MemberSize)
-               IncreaseHashSize (Hash);
+       if ((Hash->nMembersUsed >= Hash->MemberSize) &&
+           (!IncreaseHashSize (Hash)))
+           return 0;
 
-       /** Arrange the payload */
        NewPayloadItem = (Payload*) malloc (sizeof(Payload));
+       if (NewPayloadItem == NULL)
+               return 0;
+       NewHashKey = (HashKey*) malloc (sizeof(HashKey));
+       if (NewHashKey == NULL)
+       {
+               free(NewPayloadItem);
+               return 0;
+       }
+       HashKeyOrgVal = (char *) malloc (HKLen + 1);
+       if (HashKeyOrgVal == NULL)
+       {
+               free(NewHashKey);
+               free(NewPayloadItem);
+               return 0;
+       }
+
+
+       /** Arrange the payload */
        NewPayloadItem->Data = Data;
        NewPayloadItem->Destructor = Destructor;
        /** Arrange the hashkey */
-       NewHashKey = (HashKey*) malloc (sizeof(HashKey));
-       NewHashKey->HashKey = (char *) malloc (HKLen + 1);
        NewHashKey->HKLen = HKLen;
+       NewHashKey->HashKey = HashKeyOrgVal;
        memcpy (NewHashKey->HashKey, HashKeyStr, HKLen + 1);
        NewHashKey->Key = HashBinKey;
        NewHashKey->PL = NewPayloadItem;
@@ -486,6 +532,7 @@ static void InsertHashItem(HashList *Hash,
        Hash->LookupTable[HashPos] = NewHashKey;
        Hash->nMembersUsed++;
        Hash->nLookupTableItems++;
+       return 1;
 }
 
 /**
@@ -576,7 +623,13 @@ static long FindInHash(HashList *Hash, long HashBinKey)
 long Flathash(const char *str, long len)
 {
        if (len != sizeof (int))
+       {
+#ifdef DEBUG
+               int *crash = NULL;
+               *crash = 1;
+#endif
                return 0;
+       }
        else return *(int*)str;
 }
 
@@ -590,7 +643,13 @@ long Flathash(const char *str, long len)
 long lFlathash(const char *str, long len)
 {
        if (len != sizeof (long))
+       {
+#ifdef DEBUG
+               int *crash = NULL;
+               *crash = 1;
+#endif
                return 0;
+       }
        else return *(long*)str;
 }
 
@@ -634,8 +693,9 @@ void Put(HashList *Hash, const char *HKey, long HKLen, void *Data, DeleteHashDat
        HashBinKey = CalcHashKey(Hash, HKey, HKLen);
        HashAt = FindInHash(Hash, HashBinKey);
 
-       if (HashAt >= Hash->MemberSize)
-               IncreaseHashSize (Hash);
+       if ((HashAt >= Hash->MemberSize) &&
+           (!IncreaseHashSize (Hash)))
+               return;
 
        /** oh, we're brand new... */
        if (Hash->LookupTable[HashAt] == NULL) {
@@ -709,7 +769,7 @@ int GetKey(HashList *Hash, char *HKey, long HKLen, void **Payload)
 
 /**
  * @ingroup HashListAccess
- * @brief get the Keys present in this hash, simila to array_keys() in PHP
+ * @brief get the Keys present in this hash, similar to array_keys() in PHP
  *  Attention: List remains to Hash! don't modify or free it!
  * @param Hash Your Hashlist to extract the keys from
  * @param List returns the list of hashkeys stored in Hash
@@ -717,14 +777,19 @@ int GetKey(HashList *Hash, char *HKey, long HKLen, void **Payload)
 int GetHashKeys(HashList *Hash, char ***List)
 {
        long i;
+
+       *List = NULL;
        if (Hash == NULL)
                return 0;
        if (Hash->MyKeys != NULL)
                free (Hash->MyKeys);
 
        Hash->MyKeys = (char**) malloc(sizeof(char*) * Hash->nLookupTableItems);
-       for (i=0; i < Hash->nLookupTableItems; i++) {
-       
+       if (Hash->MyKeys == NULL)
+               return 0;
+
+       for (i=0; i < Hash->nLookupTableItems; i++)
+       {
                Hash->MyKeys[i] = Hash->LookupTable[i]->HashKey;
        }
        *List = (char**)Hash->MyKeys;
@@ -740,11 +805,14 @@ int GetHashKeys(HashList *Hash, char ***List)
  *  step-raster is provided.
  * @return the hash iterator
  */
-HashPos *GetNewHashPos(HashList *Hash, int StepWidth)
+HashPos *GetNewHashPos(const HashList *Hash, int StepWidth)
 {
        HashPos *Ret;
        
        Ret = (HashPos*)malloc(sizeof(HashPos));
+       if (Ret == NULL)
+               return NULL;
+
        if (StepWidth != 0)
                Ret->StepWidth = StepWidth;
        else
@@ -758,6 +826,30 @@ HashPos *GetNewHashPos(HashList *Hash, int StepWidth)
        return Ret;
 }
 
+/**
+ * @ingroup HashListAccess
+ * @brief resets a hash-linear iterator object
+ * @param Hash the list we reference
+ * @param StepWidth in which step width should we iterate?
+ * @param it the iterator object to manipulate
+ *  If negative, the last position matching the 
+ *  step-raster is provided.
+ * @return the hash iterator
+ */
+void RewindHashPos(const HashList *Hash, HashPos *it, int StepWidth)
+{
+       if (StepWidth != 0)
+               it->StepWidth = StepWidth;
+       else
+               it->StepWidth = 1;
+       if (it->StepWidth <  0) {
+               it->Position = Hash->nLookupTableItems - 1;
+       }
+       else {
+               it->Position = 0;
+       }
+}
+
 /**
  * @ingroup HashListAccess
  * @brief Set iterator object to point to key. If not found, don't change iterator
@@ -889,7 +981,7 @@ void DeleteHashPos(HashPos **DelMe)
  * @param Data returns the Data found at HashPos
  * @return whether the item was found or not.
  */
-int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, const char **HashKey, void **Data)
+int GetNextHashPos(const HashList *Hash, HashPos *At, long *HKLen, const char **HashKey, void **Data)
 {
        long PayloadPos;
 
@@ -1173,8 +1265,15 @@ int ParseMSet(MSet **MSetList, StrBuf *MSetStr)
            return 0;
            
        OneSet = NewStrBufPlain(NULL, StrLength(MSetStr));
+       if (OneSet == NULL)
+               return 0;
 
        ThisMSet = NewHash(0, lFlathash);
+       if (ThisMSet == NULL)
+       {
+               FreeStrBuf(&OneSet);
+               return 0;
+       }
 
        *MSetList = (MSet*) ThisMSet;
 
@@ -1197,6 +1296,12 @@ int ParseMSet(MSet **MSetList, StrBuf *MSetStr)
                }
 
                pEndSet = (long*) malloc (sizeof(long));
+               if (pEndSet == NULL)
+               {
+                       FreeStrBuf(&OneSet);
+                       DeleteHash(&ThisMSet);
+                       return 0;
+               }
                *pEndSet = EndSet;
 
                Put(ThisMSet, LKEY(StartSet), pEndSet, NULL);