758b1d0e05
categories: * Missing includes (like <stdlib.h> and <string.h>). * Linking against $(TARGET_LIBSTDC++) instead of libstdc++.r4.so. * Local variables shadowing parameters. * Default parameters in function definitions (as opposed to function declarations). * All C++ stuff (nothrow, map, set, vector, min, max,...) must be imported explicitly from the std:: namespace now. * "new (sometype)[...]" must read "new sometype[...]", even if sometype is something like "const char *". * __FUNCTION__ is no longer a string literal (but a string expression), i.e. 'printf(__FUNCTION__ ": ...\n")' is invalid code. * A type cast results in a non-lvalue. E.g. "(char *)buffer += bytes" is an invalid expression. * "friend class SomeClass" only works when SomeClass is known before. Otherwise the an inner class with that name is considered as friend. gcc 4 is much pickier about scopes. * gcc 4 is generally stricter with respect to type conversions in C. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14878 a95241bf-73f2-0310-859d-f6bbb57e9c96
206 lines
3.3 KiB
C++
206 lines
3.3 KiB
C++
/*
|
|
* Copyright 2005, Haiku.
|
|
* Distributed under the terms of the MIT License.
|
|
*
|
|
* Authors:
|
|
* Axel Dörfler, axeld@pinc-software.de
|
|
*/
|
|
|
|
|
|
#include "HashTable.h"
|
|
|
|
#include <new>
|
|
|
|
#include <stdlib.h>
|
|
//#include <stdarg.h>
|
|
#include <string.h>
|
|
|
|
using std::nothrow;
|
|
|
|
struct HashTable::entry {
|
|
entry* next;
|
|
Hashable* value;
|
|
};
|
|
|
|
|
|
HashTable::HashTable(bool owning, int32 capacity, float loadFactor)
|
|
:
|
|
fTable(NULL),
|
|
fCount(0),
|
|
fThreshold(0),
|
|
fOwning(owning)
|
|
{
|
|
if (capacity < 10)
|
|
capacity = 10;
|
|
if (loadFactor <= 0.3)
|
|
loadFactor = 0.3;
|
|
|
|
fLoadFactor = loadFactor;
|
|
fCapacity = capacity;
|
|
}
|
|
|
|
|
|
HashTable::~HashTable()
|
|
{
|
|
MakeEmpty(fOwning);
|
|
}
|
|
|
|
|
|
void
|
|
HashTable::MakeEmpty(bool deleteValues)
|
|
{
|
|
if (fTable == NULL)
|
|
return;
|
|
|
|
for (int32 index = fCapacity; --index >= 0;) {
|
|
struct entry *entry, *next;
|
|
|
|
for (entry = fTable[index]; entry != NULL; entry = next) {
|
|
next = entry->next;
|
|
|
|
if (deleteValues)
|
|
delete entry->value;
|
|
delete entry;
|
|
}
|
|
}
|
|
|
|
free(fTable);
|
|
fTable = NULL;
|
|
}
|
|
|
|
|
|
Hashable *
|
|
HashTable::GetValue(Hashable& key) const
|
|
{
|
|
struct entry* entry = _GetHashEntry(key);
|
|
|
|
return entry != NULL ? entry->value : NULL;
|
|
}
|
|
|
|
|
|
bool
|
|
HashTable::AddItem(Hashable *value)
|
|
{
|
|
struct entry *entry = _GetHashEntry(*value);
|
|
int32 hash = value->Hash();
|
|
int32 index;
|
|
|
|
// already in hash?
|
|
if (entry != NULL)
|
|
return true;
|
|
|
|
if (fCount >= fThreshold)
|
|
_Rehash();
|
|
|
|
index = hash % fCapacity;
|
|
|
|
entry = new (nothrow) HashTable::entry;
|
|
if (entry == NULL)
|
|
return false;
|
|
|
|
entry->value = value;
|
|
entry->next = fTable[index];
|
|
fTable[index] = entry;
|
|
fCount++;
|
|
return true;
|
|
}
|
|
|
|
|
|
Hashable *
|
|
HashTable::RemoveItem(Hashable& key)
|
|
{
|
|
struct entry* previous = NULL;
|
|
struct entry* entry;
|
|
uint32 hash;
|
|
int32 index;
|
|
|
|
if (fTable == NULL)
|
|
return NULL;
|
|
|
|
hash = key.Hash();
|
|
index = hash % fCapacity;
|
|
|
|
for (entry = fTable[index]; entry != NULL; entry = entry->next) {
|
|
if (entry->value->Hash() == hash && entry->value->CompareTo(key)) {
|
|
// found value in array
|
|
Hashable* value;
|
|
|
|
if (previous)
|
|
previous->next = entry->next;
|
|
else
|
|
fTable[index] = entry->next;
|
|
|
|
fCount--;
|
|
value = entry->value;
|
|
delete entry;
|
|
return value;
|
|
}
|
|
|
|
previous = entry;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
bool
|
|
HashTable::_Rehash()
|
|
{
|
|
struct entry** newTable;
|
|
int32 oldCapacity = fCapacity;
|
|
int32 newCapacity, i;
|
|
|
|
if (fCount != 0)
|
|
newCapacity = oldCapacity * 2 + 1;
|
|
else
|
|
newCapacity = fCapacity;
|
|
|
|
newTable = (struct entry **)malloc(newCapacity * sizeof(struct entry *));
|
|
if (newTable == NULL)
|
|
return false;
|
|
|
|
memset(newTable, 0, newCapacity * sizeof(struct entry *));
|
|
|
|
if (fTable != NULL) {
|
|
// repopulate the entries into the new array
|
|
for (i = fCapacity; i-- > 0;) {
|
|
struct entry* entry;
|
|
struct entry* next;
|
|
|
|
for (entry = fTable[i]; entry != NULL; entry = next) {
|
|
next = entry->next;
|
|
|
|
int32 index = entry->value->Hash() % newCapacity;
|
|
entry->next = newTable[index];
|
|
newTable[index] = entry;
|
|
}
|
|
}
|
|
|
|
free(fTable);
|
|
}
|
|
|
|
fTable = newTable;
|
|
fCapacity = newCapacity;
|
|
fThreshold = int32(newCapacity * fLoadFactor);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
struct HashTable::entry *
|
|
HashTable::_GetHashEntry(Hashable& key) const
|
|
{
|
|
struct entry* entry;
|
|
uint32 hash = key.Hash();
|
|
|
|
if (fTable == NULL)
|
|
return NULL;
|
|
|
|
for (entry = fTable[hash % fCapacity]; entry != NULL; entry = entry->next) {
|
|
if (entry->value->Hash() == hash && entry->value->CompareTo(key))
|
|
return entry;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|