]> code.citadel.org Git - citadel.git/blobdiff - libcitadel/lib/hash.c
* reference free handler (Don't free payload ;-)
[citadel.git] / libcitadel / lib / hash.c
index 3908121d90c13a13bf54e3f774f8ee49436dd006..a8340f493532ba042afcfa698a25e0a763b6c0e2 100644 (file)
@@ -64,6 +64,9 @@ int PrintHash(HashList *Hash, TransitionFunc Trans, PrintHashDataFunc PrintEntry
        void *Next;
        const char* KeyStr;
 
+       if (Hash == NULL)
+               return 0;
+
        for (i=0; i < Hash->nMembersUsed; i++) {
                if (i==0) {
                        Previous = NULL;
@@ -104,6 +107,10 @@ int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Secon
        const char *bla = "";
        long key;
        long i;
+
+       if (Hash == NULL)
+               return 0;
+
        if (Hash->MyKeys != NULL)
                free (Hash->MyKeys);
 
@@ -125,8 +132,12 @@ int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Secon
                        foo = Hash->LookupTable[i]->HashKey;
                        if (First != NULL)
                                bar = First(Hash->Members[Hash->LookupTable[i]->Position]->Data);
+                       else 
+                               bar = "";
                        if (Second != NULL)
                                bla = Second(Hash->Members[Hash->LookupTable[i]->Position]->Data);
+                       else
+                               bla = "";
                }
 #ifdef DEBUG
                printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' ; %s\n", i, key, foo, bar, bla);
@@ -165,12 +176,14 @@ HashList *NewHash(int Uniq, HashFunc F)
 
 int GetCount(HashList *Hash)
 {
+       if(Hash==NULL) return 0;
        return Hash->nMembersUsed;
 }
 
 
 /**
  * \brief private destructor for one hash element.
+ * Crashing? go one frame up and do 'print *FreeMe->LookupTable[i]'
  * \param Data an element to free using the user provided destructor, or just plain free
  */
 static void DeleteHashPayload (Payload *Data)
@@ -182,8 +195,18 @@ static void DeleteHashPayload (Payload *Data)
                free(Data->Data);
 }
 
+/**
+ * \brief Destructor for nested hashes
+ */
+void HDeleteHash(void *vHash)
+{
+       HashList *FreeMe = (HashList*)vHash;
+       DeleteHash(&FreeMe);
+}
+
 /**
  * \brief destroy a hashlist and all of its members
+ * Crashing? do 'print *FreeMe->LookupTable[i]'
  * \param Hash Hash to destroy. Is NULL'ed so you are shure its done.
  */
 void DeleteHash(HashList **Hash)
@@ -230,6 +253,9 @@ static void IncreaseHashSize(HashList *Hash)
        Payload **NewPayloadArea;
        HashKey **NewTable;
        
+       if (Hash == NULL)
+               return ;
+
        /** double our payload area */
        NewPayloadArea = (Payload**) malloc(sizeof(Payload*) * Hash->MemberSize * 2);
        memset(&NewPayloadArea[Hash->MemberSize], 0, sizeof(Payload*) * Hash->MemberSize);
@@ -269,6 +295,9 @@ static void InsertHashItem(HashList *Hash,
        Payload *NewPayloadItem;
        HashKey *NewHashKey;
 
+       if (Hash == NULL)
+               return;
+
        if (Hash->nMembersUsed >= Hash->MemberSize)
                IncreaseHashSize (Hash);
 
@@ -316,6 +345,9 @@ static long FindInTaintedHash(HashList *Hash, long HashBinKey)
 {
        long SearchPos;
 
+       if (Hash == NULL)
+               return 0;
+
        for (SearchPos = 0; SearchPos < Hash->nMembersUsed; SearchPos ++) {
                if (Hash->LookupTable[SearchPos]->Key == HashBinKey){
                        return SearchPos;
@@ -335,6 +367,9 @@ static long FindInHash(HashList *Hash, long HashBinKey)
        long SearchPos;
        long StepWidth;
 
+       if (Hash == NULL)
+               return 0;
+
        if (Hash->tainted)
                return FindInTaintedHash(Hash, HashBinKey);
 
@@ -382,6 +417,9 @@ static long FindInHash(HashList *Hash, long HashBinKey)
  */
 inline static long CalcHashKey (HashList *Hash, const char *HKey, long HKLen)
 {
+       if (Hash == NULL)
+               return 0;
+
        if (Hash->Algorithm == NULL)
                return hashlittle(HKey, HKLen, 9283457);
        else
@@ -402,6 +440,9 @@ void Put(HashList *Hash, const char *HKey, long HKLen, void *Data, DeleteHashDat
        long HashBinKey;
        long HashAt;
 
+       if (Hash == NULL)
+               return;
+
        /** first, find out were we could fit in... */
        HashBinKey = CalcHashKey(Hash, HKey, HKLen);
        HashAt = FindInHash(Hash, HashBinKey);
@@ -447,6 +488,9 @@ int GetHash(HashList *Hash, const char *HKey, long HKLen, void **Data)
        long HashBinKey;
        long HashAt;
 
+       if (Hash == NULL)
+               return 0;
+
        if (HKLen <= 0) {
                *Data = NULL;
                return  0;
@@ -484,6 +528,8 @@ int GetKey(HashList *Hash, char *HKey, long HKLen, void **Payload)
 int GetHashKeys(HashList *Hash, char ***List)
 {
        long i;
+       if (Hash == NULL)
+               return 0;
        if (Hash->MyKeys != NULL)
                free (Hash->MyKeys);
 
@@ -514,8 +560,11 @@ HashPos *GetNewHashPos(void)
  */
 void DeleteHashPos(HashPos **DelMe)
 {
-       free(*DelMe);
-       *DelMe = NULL;
+       if (*DelMe != NULL)
+       {
+               free(*DelMe);
+               *DelMe = NULL;
+       }
 }
 
 
@@ -527,11 +576,11 @@ void DeleteHashPos(HashPos **DelMe)
  * \param Data returns the Data found at HashPos
  * \returns whether the item was found or not.
  */
-int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, char **HashKey, void **Data)
+int GetNextHashPos(HashList *Hash, HashPos *At, long *HKLen, const char **HashKey, void **Data)
 {
        long PayloadPos;
 
-       if (Hash->nMembersUsed <= At->Position)
+       if ((Hash == NULL) || (Hash->nMembersUsed <= At->Position))
                return 0;
        *HKLen = Hash->LookupTable[At->Position]->HKLen;
        *HashKey = Hash->LookupTable[At->Position]->HashKey;
@@ -652,3 +701,25 @@ void SortByPayload(HashList *Hash, CompareFunc SortBy)
  *      return strcmp (a, b);
  * }
  */
+
+
+/*
+ * Generic function to free a pointer.  This can be used as a callback with the
+ * hash table, even on systems where free() is defined as a macro or has had other
+ * horrible things done to it.
+ */
+void generic_free_handler(void *ptr) {
+       free(ptr);
+}
+
+/*
+ * Generic function to free a reference.  
+ * since a reference actualy isn't needed to be freed, do nothing.
+ */
+void reference_free_handler(void *ptr) 
+{
+       1;
+}
+
+
+