Files

184 lines
3.7 KiB
C
Raw Permalink Normal View History

2025-01-09 17:45:40 +08:00
#ifndef _BZ_HASH_TABLE_H_
#define _BZ_HASH_TABLE_H_
/************************
* һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD>˱<EFBFBD>ѩhash<EFBFBD><EFBFBD><EFBFBD>hashtable
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǹ̶<EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܶ<EFBFBD>̬<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͬʱ<EFBFBD><EFBFBD><EFBFBD>ɾ<EFBFBD><EFBFBD><EFBFBD>Ľӿ<EFBFBD>
* Ϊ<EFBFBD><EFBFBD><EFBFBD><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