+/*
+ * Copyright (c) 1987-2011 by the citadel.org team
+ *
+ * This program is open source software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
*/
int dbg_PrintHash(HashList *Hash, PrintHashContent First, PrintHashContent Second)
{
+#ifdef DEBUG
const char *foo;
const char *bar;
const char *bla = "";
long key;
+#endif
long i;
if (Hash == NULL)
if (Hash->LookupTable[i] == NULL)
{
+#ifdef DEBUG
foo = "";
bar = "";
key = 0;
+#endif
}
else
{
+#ifdef DEBUG
key = Hash->LookupTable[i]->Key;
foo = Hash->LookupTable[i]->HashKey;
+#endif
if (First != NULL)
- bar = First(Hash->Members[Hash->LookupTable[i]->Position]->Data);
+#ifdef DEBUG
+ bar =
+#endif
+ First(Hash->Members[Hash->LookupTable[i]->Position]->Data);
+#ifdef DEBUG
else
bar = "";
+#endif
+
if (Second != NULL)
- bla = Second(Hash->Members[Hash->LookupTable[i]->Position]->Data);
+#ifdef DEBUG
+ bla =
+#endif
+ Second(Hash->Members[Hash->LookupTable[i]->Position]->Data);
+#ifdef DEBUG
+
else
bla = "";
+#endif
+
}
#ifdef DEBUG
printf (" ---- Hashkey[%ld][%ld]: '%s' Value: '%s' ; %s\n", i, key, foo, bar, bla);
}
+int TestValidateHash(HashList *TestHash)
+{
+ long i;
+
+ if (TestHash->nMembersUsed != TestHash->nLookupTableItems)
+ return 1;
+
+ if (TestHash->nMembersUsed > TestHash->MemberSize)
+ return 2;
+
+ for (i=0; i < TestHash->nMembersUsed; i++)
+ {
+
+ if (TestHash->LookupTable[i]->Position > TestHash->nMembersUsed)
+ return 3;
+
+ if (TestHash->Members[TestHash->LookupTable[i]->Position] == NULL)
+ return 4;
+ if (TestHash->Members[TestHash->LookupTable[i]->Position]->Data == NULL)
+ return 5;
+ }
+ return 0;
+}
+
/**
* @ingroup HashListAccess
* @brief instanciate a new hashlist
{
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;
* @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) &&
}
*/
- /** 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;
}
* @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;
Hash->LookupTable[HashPos] = NewHashKey;
Hash->nMembersUsed++;
Hash->nLookupTableItems++;
+ return 1;
}
/**
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) {
InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
- }/** Insert After? */
+ }/** Insert Before? */
else if (Hash->LookupTable[HashAt]->Key > HashBinKey) {
InsertHashItem(Hash, HashAt, HashBinKey, HKey, HKLen, Data, DeleteIt);
- }/** Insert before? */
+ }/** Insert After? */
else if (Hash->LookupTable[HashAt]->Key < HashBinKey) {
InsertHashItem(Hash, HashAt + 1, HashBinKey, HKey, HKLen, Data, DeleteIt);
}
/**
* @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
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;
* 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
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
return 0;
}
/** GOTCHA! */
- At->Position = Hash->LookupTable[HashAt]->Position;
+ At->Position = HashAt;
return 1;
}
* @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;
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;
}
pEndSet = (long*) malloc (sizeof(long));
+ if (pEndSet == NULL)
+ {
+ FreeStrBuf(&OneSet);
+ DeleteHash(&ThisMSet);
+ return 0;
+ }
*pEndSet = EndSet;
Put(ThisMSet, LKEY(StartSet), pEndSet, NULL);