X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=libcitadel%2Flib%2Fhash.c;h=c1e8d4d422bc16b81295b2802257d9f29a8b45d2;hb=19fb2763b48d73c87bf6852d29e84353fd941842;hp=2125cb6f945a57da5a0712162b4867876a175a32;hpb=b82445c48c94aef996ef8d7d52dffa1d264fb561;p=citadel.git diff --git a/libcitadel/lib/hash.c b/libcitadel/lib/hash.c index 2125cb6f9..c1e8d4d42 100644 --- a/libcitadel/lib/hash.c +++ b/libcitadel/lib/hash.c @@ -162,6 +162,10 @@ int PrintHash(HashList *Hash, TransitionFunc Trans, PrintHashDataFunc PrintEntry return i; } +const char *dbg_PrintStrBufPayload(const char *Key, void *Item, int Odd) +{ + return ChrPtr((StrBuf*)Item); +} /** * @ingroup HashListDebug @@ -230,7 +234,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 @@ -273,12 +282,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; @@ -390,14 +412,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) && @@ -409,21 +431,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; } @@ -438,31 +469,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; @@ -487,6 +536,7 @@ static void InsertHashItem(HashList *Hash, Hash->LookupTable[HashPos] = NewHashKey; Hash->nMembersUsed++; Hash->nLookupTableItems++; + return 1; } /** @@ -577,7 +627,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; } @@ -591,7 +647,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; } @@ -635,8 +697,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) { @@ -710,7 +773,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 @@ -718,14 +781,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; @@ -741,11 +809,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 @@ -759,6 +830,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 @@ -890,7 +985,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; @@ -1174,8 +1269,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; @@ -1198,6 +1300,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);