openmohaa/code/gamespy/hashtable.c

230 lines
4.7 KiB
C
Raw Permalink Normal View History

2023-02-04 21:00:01 +01:00
/*
*
* File: hashtable.c
* ---------------
* David Wright
* 10/8/98
*
* See hashtable.h for function comments
* Implmentation is straight-forward, using a fixed dynamically allocated
* array for the buckets, and a DArray for each individual bucket
*/
#include <stdlib.h>
#include <string.h>
#include "darray.h"
#include "hashtable.h"
#ifdef _MFC_MEM_DEBUG
#define _CRTDBG_MAP_ALLOC 1
#include <crtdbg.h>
#endif
#ifdef _NO_NOPORT_H_
2025-02-28 18:11:09 +01:00
#define gsimalloc malloc
#define gsifree free
#define gsirealloc realloc
#include <assert.h>
2023-02-04 21:00:01 +01:00
#else
2025-02-28 18:11:09 +01:00
#include "nonport.h" //for gsimalloc/realloc/free/assert
2023-02-04 21:00:01 +01:00
#endif
struct HashImplementation
{
2025-02-28 18:11:09 +01:00
DArray *buckets;
int nbuckets;
TableElementFreeFn freefn;
TableHashFn hashfn;
TableCompareFn compfn;
2023-02-04 21:00:01 +01:00
};
HashTable TableNew(int elemSize, int nBuckets,
TableHashFn hashFn, TableCompareFn compFn,
2025-02-28 18:11:09 +01:00
TableElementFreeFn freeFn)
2023-02-04 21:00:01 +01:00
{
2025-02-28 18:11:09 +01:00
return TableNew2(elemSize, nBuckets, 4, hashFn, compFn, freeFn);
2023-02-04 21:00:01 +01:00
}
HashTable TableNew2(int elemSize, int nBuckets, int nChains,
TableHashFn hashFn, TableCompareFn compFn,
2025-02-28 18:11:09 +01:00
TableElementFreeFn freeFn)
2023-02-04 21:00:01 +01:00
{
2025-02-28 18:11:09 +01:00
HashTable table;
int i;
assert(hashFn);
assert(compFn);
assert(elemSize);
assert(nBuckets);
table = (HashTable)gsimalloc(sizeof(struct HashImplementation));
assert(table);
table->buckets = (DArray *)gsimalloc(nBuckets * sizeof(DArray));
assert(table->buckets);
for (i = 0; i < nBuckets; i++) //ArrayNew will assert if allocation fails
table->buckets[i] = ArrayNew(elemSize, nChains, freeFn);
table->nbuckets = nBuckets;
table->freefn = freeFn;
table->compfn = compFn;
table->hashfn = hashFn;
return table;
2023-02-04 21:00:01 +01:00
}
void TableFree(HashTable table)
{
2025-02-28 18:11:09 +01:00
int i;
assert(table);
if (NULL == table )
return;
for (i = 0 ; i < table->nbuckets ; i++)
ArrayFree(table->buckets[i]);
gsifree(table->buckets);
gsifree(table);
2023-02-04 21:00:01 +01:00
}
int TableCount(HashTable table)
{
2025-02-28 18:11:09 +01:00
int i, count = 0;
assert(table);
2023-02-04 21:00:01 +01:00
2025-02-28 18:11:09 +01:00
if (NULL == table )
return count;
2023-02-04 21:00:01 +01:00
2025-02-28 18:11:09 +01:00
for (i = 0 ; i < table->nbuckets ; i++)
count += ArrayLength(table->buckets[i]);
return count;
2023-02-04 21:00:01 +01:00
}
void TableEnter(HashTable table, const void *newElem)
{
2025-02-28 18:11:09 +01:00
int hash, itempos;
assert(table);
if (NULL == table )
return;
hash = table->hashfn(newElem, table->nbuckets);
itempos = ArraySearch(table->buckets[hash], newElem, table->compfn, 0,0);
if (itempos == NOT_FOUND)
ArrayAppend(table->buckets[hash], newElem);
else
ArrayReplaceAt(table->buckets[hash], newElem, itempos);
2023-02-04 21:00:01 +01:00
}
int TableRemove(HashTable table, const void *delElem)
{
2025-02-28 18:11:09 +01:00
int hash, itempos;
assert(table);
if (NULL == table )
return 0;
hash = table->hashfn(delElem, table->nbuckets);
itempos = ArraySearch(table->buckets[hash], delElem, table->compfn, 0,0);
if (itempos == NOT_FOUND)
return 0;
else
ArrayDeleteAt(table->buckets[hash], itempos);
return 1;
2023-02-04 21:00:01 +01:00
}
void *TableLookup(HashTable table, const void *elemKey)
{
2025-02-28 18:11:09 +01:00
int hash, itempos;
assert(table);
if (NULL == table )
return NULL;
hash = table->hashfn(elemKey, table->nbuckets);
itempos = ArraySearch(table->buckets[hash], elemKey, table->compfn, 0,
0);
if (itempos == NOT_FOUND)
return NULL;
else
return ArrayNth(table->buckets[hash], itempos);
2023-02-04 21:00:01 +01:00
}
void TableMap(HashTable table, TableMapFn fn, void *clientData)
{
2025-02-28 18:11:09 +01:00
int i;
assert(table);
assert(fn);
if (NULL == table || NULL == fn)
return;
for (i = 0 ; i < table->nbuckets ; i++)
ArrayMap(table->buckets[i], fn, clientData);
2023-02-04 21:00:01 +01:00
}
void TableMapSafe(HashTable table, TableMapFn fn, void *clientData)
{
2025-02-28 18:11:09 +01:00
int i;
assert(fn);
for (i = 0 ; i < table->nbuckets ; i++)
ArrayMapBackwards(table->buckets[i], fn, clientData);
2023-02-04 21:00:01 +01:00
}
void * TableMap2(HashTable table, TableMapFn2 fn, void *clientData)
{
2025-02-28 18:11:09 +01:00
int i;
void * pcurr;
assert(fn);
for (i = 0 ; i < table->nbuckets ; i++)
{
pcurr = ArrayMap2(table->buckets[i], fn, clientData);
if(pcurr)
return pcurr;
}
return NULL;
2023-02-04 21:00:01 +01:00
}
void * TableMapSafe2(HashTable table, TableMapFn2 fn, void *clientData)
{
2025-02-28 18:11:09 +01:00
int i;
void * pcurr;
assert(fn);
for (i = 0 ; i < table->nbuckets ; i++)
{
pcurr = ArrayMapBackwards2(table->buckets[i], fn, clientData);
if(pcurr)
return pcurr;
}
return NULL;
2023-02-04 21:00:01 +01:00
}
void TableClear(HashTable table)
{
2025-02-28 18:11:09 +01:00
int i;
2023-02-04 21:00:01 +01:00
2025-02-28 18:11:09 +01:00
for (i = 0 ; i < table->nbuckets ; i++)
ArrayClear(table->buckets[i]);
2023-02-04 21:00:01 +01:00
}