184 lines
3.7 KiB
C++
184 lines
3.7 KiB
C++
#ifndef _BZ_HASH_TABLE_H_
|
||
#define _BZ_HASH_TABLE_H_
|
||
/************************
|
||
* һ<><D2BB><EFBFBD><EFBFBD>װ<EFBFBD>˱<EFBFBD>ѩhash<73>㷨<EFBFBD><E3B7A8>hashtable
|
||
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ̶<C7B9><CCB6>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>ܶ<EFBFBD>̬<EFBFBD><CCAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<CDAC><CAB1><EFBFBD>ṩɾ<E1B9A9><C9BE><EFBFBD>Ľӿ<C4BD>
|
||
* Ϊ<>ṩ<EFBFBD><E1B9A9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
*************************/
|
||
#include "memory/base_allocator.hpp"
|
||
#include "bzhash.h"
|
||
|
||
template <typename T>
|
||
class BZHashTable
|
||
{
|
||
public:
|
||
BZHashTable(size_t len)
|
||
{
|
||
assert(len > 0);
|
||
|
||
max_size_ = len;
|
||
data_ = NULL;
|
||
size_ = 0;
|
||
}
|
||
|
||
virtual ~BZHashTable()
|
||
{
|
||
clear();
|
||
}
|
||
|
||
// <20><>չ<EFBFBD>ϣ<EFBFBD><CFA3>
|
||
void clear()
|
||
{
|
||
if (size_ > 0)
|
||
{
|
||
for (int i = (int)(max_size_ - 1); i > -1; --i)
|
||
{
|
||
if (data_[i].exists)
|
||
{
|
||
data_[i].value.~T();
|
||
}
|
||
}
|
||
}
|
||
|
||
if (data_) realloc(data_, 0);
|
||
data_ = NULL;
|
||
size_ = 0;
|
||
}
|
||
|
||
inline size_t count() const { return size_; }
|
||
protected:
|
||
template <typename TA>
|
||
class HashNode
|
||
{
|
||
public:
|
||
bool exists; // <20>Ƿ<C7B7><F1B1A3B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
unsigned int hash1; //<2F><>ϣֵ1
|
||
unsigned int hash2; //<2F><>ϣֵ2
|
||
unsigned int hash3; //<2F><>ϣֵ3
|
||
TA value; //<2F><><EFBFBD><EFBFBD>ֵ
|
||
};
|
||
|
||
typedef HashNode<T> NodeType;
|
||
public:
|
||
//ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||
inline T* get(const char* key)
|
||
{
|
||
int idx = getIndex(key);
|
||
return (idx >= 0) ? &data_[idx].value : NULL;
|
||
}
|
||
//ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
||
inline const T* get(const char* key) const
|
||
{
|
||
int idx = getIndex(key);
|
||
return (idx >= 0) ? &data_[idx].value : NULL;
|
||
}
|
||
|
||
inline T* put(const char* key)
|
||
{
|
||
if (size_ >= max_size_)
|
||
{
|
||
#ifdef _DEBUG
|
||
DbgAssert(false);
|
||
#endif
|
||
return NULL; // no free
|
||
}
|
||
if (!data_)
|
||
{
|
||
data_ = (HashNode<T> *)realloc(NULL, sizeof(HashNode<T>) * max_size_);
|
||
for (size_t i = 0; i < max_size_; ++i)
|
||
{
|
||
data_[i].exists = false;
|
||
}
|
||
}
|
||
|
||
unsigned int hash1, hash2, hash3, idx, start;
|
||
hash1 = ::bzhashstr(key, 0);
|
||
hash2 = ::bzhashstr(key, 1);
|
||
hash3 = ::bzhashstr(key, 2);
|
||
start = idx = hash1 % (unsigned int)max_size_;
|
||
do
|
||
{
|
||
NodeType *node = data_ + idx;
|
||
//<2F><><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>û<EFBFBD><C3BB>ֵ<EFBFBD><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5><EFBFBD>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
|
||
if (!node->exists)
|
||
{
|
||
node->exists = true;
|
||
node->hash1 = hash1;
|
||
node->hash2 = hash2;
|
||
node->hash3 = hash3;
|
||
size_++;
|
||
new (&node->value)T();
|
||
return &node->value;
|
||
}
|
||
#ifdef _DEBUG
|
||
else if (node->hash1 == hash1 && node->hash2 == hash2 && node->hash3 == hash3)
|
||
{
|
||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD><EFBFBD><EFBFBD>ȷʵ<C8B7><CAB5><EFBFBD>ִ<EFBFBD><D6B4><EFBFBD>
|
||
//DebugBreak();
|
||
}
|
||
#endif
|
||
idx = (idx + 1) % (unsigned int)max_size_;
|
||
}
|
||
while (start != idx);
|
||
|
||
return NULL;
|
||
}
|
||
|
||
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD>ڱ<EFBFBD><DAB1>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>
|
||
int getIndex(const char* sKey) const
|
||
{
|
||
if (!data_) return -1;
|
||
|
||
unsigned int hash1, hash2, hash3;
|
||
|
||
hash1 = ::bzhashstr(sKey, 0);
|
||
hash2 = ::bzhashstr(sKey, 1);
|
||
hash3 = ::bzhashstr(sKey, 2);
|
||
|
||
size_t start = hash1 % max_size_, idx = start;
|
||
|
||
while (data_[idx].exists)
|
||
{
|
||
if (data_[idx].hash2 == hash2 && data_[idx].hash3 == hash3)
|
||
return (int)idx;
|
||
else
|
||
idx = (idx + 1) % max_size_;
|
||
|
||
if (idx == start)
|
||
break;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
protected:
|
||
//<2F>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD>뺯<EFBFBD><EBBAAF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>c<EFBFBD><63><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>reallocʵ<63><CAB5><EFBFBD><EFBFBD>ͬ<EFBFBD><CDAC>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD>롢<EFBFBD><EBA1A2>չ<EFBFBD>Լ<EFBFBD><D4BC>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
||
virtual void* realloc(void* p, size_t s)
|
||
{
|
||
#ifdef _MSC_VER
|
||
static BaseAllocator alloc("bzhashtable");
|
||
if (s > 0)
|
||
{
|
||
return alloc.ReAllocBuffer(p, s);
|
||
}
|
||
else
|
||
{
|
||
if (p)
|
||
{
|
||
alloc.FreeBuffer(p);
|
||
}
|
||
return NULL;
|
||
}
|
||
return alloc.ReAllocBuffer(p, s);
|
||
#else
|
||
return ::realloc(p, s);
|
||
#endif
|
||
}
|
||
protected:
|
||
size_t max_size_;
|
||
size_t size_;
|
||
HashNode<T> *data_; //<2F><>ϣ<EFBFBD><CFA3>
|
||
};
|
||
|
||
#endif
|