/* Hashtable - a general purpose hash table
**
** Copyright 2001 pinc Software. All Rights Reserved.
** Released under the terms of the MIT license.
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "Hashtable.h"
/************************** standard string hash functions **************************/
unsigned int stringHash(const char *c)
{
int len = strlen(c);
return(*(int *)(c + len - 4)); // erstmal zum Testen
}
bool stringCompare(const char *a, const char *b)
{
return(!strcmp(a, b));
}
// #pragma mark - Hashtable
Hashtable::Hashtable(int capacity, float loadFactor)
:
fIteratorIndex(-1)
{
if (capacity < 0 || loadFactor <= 0)
return;
if (!capacity)
capacity = 1;
if (!(fTable = (struct Entry **)malloc(capacity * sizeof(void *))))
return;
memset(fTable,0,capacity * sizeof(void *));
fThreshold = (int)(capacity * loadFactor);
fModCount = 0;
fLoadFactor = loadFactor;
fCapacity = capacity;
fHashFunc = (uint32 (*)(const void *))stringHash;
fCompareFunc = (bool (*)(const void *, const void *))stringCompare;
}
Hashtable::~Hashtable()
{
struct Entry **table = fTable;
for(int32 index = fCapacity;--index >= 0;)
{
struct Entry *entry,*next;
for(entry = table[index];entry;entry = next)
{
next = entry->next;
delete entry;
}
}
free(table);
}
void Hashtable::SetHashFunction(uint32 (*func)(const void *))
{
fHashFunc = func;
}
void Hashtable::SetCompareFunction(bool (*func)(const void *, const void *))
{
fCompareFunc = func;
}
bool Hashtable::IsEmpty() const
{
return fCount == 0;
}
bool Hashtable::ContainsKey(const void *key)
{
return GetHashEntry(key) ? true : false;
}
void *Hashtable::GetValue(const void *key)
{
Entry *entry = GetHashEntry(key);
return entry ? entry->value : NULL;
}
bool Hashtable::Put(const void *key, void *value)
{
Entry *entry = GetHashEntry(key);
int hash = fHashFunc(key);
int index;
if (entry)
return true;
fModCount++;
if (fCount >= fThreshold)
Rehash();
index = hash % fCapacity;
fTable[index] = new Entry(fTable[index], key, value);
fCount++;
return true;
}
void *Hashtable::Remove(const void *key)
{
Entry **table,*entry,*prev;
uint32 hash,(*func)(const void *);
int32 index;
table = fTable;
hash = (func = fHashFunc)(key);
index = hash % fCapacity;
for(entry = table[index],prev = NULL;entry;entry = entry->next)
{
if ((func(entry->key) == hash) && fCompareFunc(entry->key,key))
{
void *value;
fModCount++;
if (prev)
prev->next = entry->next;
else
table[index] = entry->next;
fCount--;
value = entry->value;
delete entry;
return value;
}
prev = entry;
}
return NULL;
}
status_t Hashtable::GetNextEntry(void **value)
{
if (fIteratorIndex == -1)
{
fIteratorIndex = 0;
fIteratorEntry = fTable[0];
}
else if (fIteratorEntry)
fIteratorEntry = fIteratorEntry->next;
// get next filled slot
while (!fIteratorEntry && fIteratorIndex + 1 < fCapacity)
fIteratorEntry = fTable[++fIteratorIndex];
if (fIteratorEntry)
{
*value = fIteratorEntry->value;
return B_OK;
}
return B_ENTRY_NOT_FOUND;
}
void Hashtable::Rewind()
{
fIteratorIndex = -1;
}
void
Hashtable::MakeEmpty(int8 keyMode,int8 valueMode)
{
fModCount++;
for (int32 index = fCapacity; --index >= 0;) {
Entry *entry, *next;
for (entry = fTable[index]; entry; entry = next) {
switch (keyMode) {
case HASH_EMPTY_DELETE:
// TODO: destructors are not called!
delete (void*)entry->key;
break;
case HASH_EMPTY_FREE:
free((void*)entry->key);
break;
}
switch (valueMode) {
case HASH_EMPTY_DELETE:
// TODO: destructors are not called!
delete entry->value;
break;
case HASH_EMPTY_FREE:
free(entry->value);
break;
}
next = entry->next;
delete entry;
}
fTable[index] = NULL;
}
fCount = 0;
}
size_t
Hashtable::Size() const
{
return fCount;
}
/** The hash table will be doubled in size, and rebuild.
* @return true on success
*/
bool Hashtable::Rehash()
{
uint32 (*hashCode)(const void *) = fHashFunc;
struct Entry **oldTable = fTable,**newtable;
int oldCapacity = fCapacity;
int newCapacity,i;
newCapacity = oldCapacity * 2 + 1;
if (!(newtable = (struct Entry **)malloc(newCapacity * sizeof(struct Entry *))))
return false;
memset(newtable,0,newCapacity*sizeof(struct Entry *));
fModCount++;
fThreshold = (int)(newCapacity * fLoadFactor);
fTable = newtable;
fCapacity = newCapacity;
for (i = oldCapacity;i-- > 0;) {
Entry *oldEntry,*entry = NULL;
int index;
for (oldEntry = oldTable[i];oldEntry;) {
entry = oldEntry; oldEntry = oldEntry->next;
index = hashCode(entry->key) % newCapacity;
entry->next = newtable[index];
newtable[index] = entry;
}
}
free(oldTable);
return true;
}
Hashtable::Entry *Hashtable::GetHashEntry(const void *key)
{
Entry **table,*entry;
uint32 hash,(*func)(const void *);
table = fTable;
hash = (func = fHashFunc)(key);
for(entry = table[hash % fCapacity];entry;entry = entry->next)
{
if ((func(entry->key) == hash) && fCompareFunc(entry->key,key))
return entry;
}
return NULL;
}
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: fCount, fIteratorEntry.
↑ V772 Calling a 'delete' operator for a void pointer will cause undefined behavior.
↑ V772 Calling a 'delete' operator for a void pointer will cause undefined behavior.