Files
mir_server/Gateway/srvlib/include/container/str_hash_table.h
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

332 lines
8.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef _STR_HASH_TABLE_H_
#define _STR_HASH_TABLE_H_
/************************************************************************
* <20><>ϣ<EFBFBD><CFA3>
*
* <20><>ϣ<EFBFBD><EFBFBD><E3B7A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD>ѩ<EFBFBD><D1A9>ϣ<EFBFBD><EFBFBD><E3B7A8>ÿ<EFBFBD><C3BF><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>3<EFBFBD><33><EFBFBD><EFBFBD>ϣֵ<CFA3><D6B5><EFBFBD><EFBFBD><EFBFBD>жϣ<D0B6>һ<EFBFBD><D2BB><EFBFBD>̶<EFBFBD><CCB6>Ͽ<EFBFBD><CFBF>Լ<EFBFBD>
* <20><>ķ<EFBFBD>ֹ<EFBFBD><D6B9><EFBFBD>ֳ<EFBFBD>ͻ<EFBFBD><CDBB>
*
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>hash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><C3A3><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><CDB7>
* ʼ<><CABC><EFBFBD>ҿ<EFBFBD>λ<EFBFBD><CEBB>ֱ֪<D6AA><D6B1><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>α<EFBFBD><CEB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* <20>ӱ<EFBFBD><D3B1>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>hashֵ<68><D6B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD><32><EFBFBD><EFBFBD>ϣֵ<CFA3><D6B5>ͬ<EFBFBD><CDAC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ʼ<EFBFBD><CABC><EFBFBD>ҿ<EFBFBD>λ<EFBFBD><CEBB>ֱ֪<D6AA><D6B1><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>α<EFBFBD><CEB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
*
************************************************************************/
#include "bzhash.h"
template <typename T>
class StrHashTable;
template <typename T>
class StrHashTableIterator
{
public:
StrHashTableIterator()
{
m_pTable = NULL;
m_nIndex = 0;
}
StrHashTableIterator(const StrHashTable<T>& table)
{
setTable(table);
}
inline void setTable(const StrHashTable<T>& table)
{
m_pTable = &table;
m_nIndex = 0;
}
inline T* first()
{
int nLen = (int)(m_pTable->m_nLen);
m_nIndex = 0;
while (m_nIndex < nLen)
{
typename StrHashTable<T>::NodeType* pNode =
&m_pTable->m_pTable[m_nIndex];
m_nIndex++;
if (pNode->hash1)
return &pNode->value;
}
return NULL;
}
inline T* next()
{
int nLen = (int)(m_pTable->m_nLen);
while (m_nIndex < nLen)
{
typename StrHashTable<T>::NodeType* pNode =
&m_pTable->m_pTable[m_nIndex];
m_nIndex++;
if (pNode->hash1) return &pNode->value;
}
return NULL;
}
private:
const StrHashTable<T>* m_pTable;
int m_nIndex;
};
template <typename T>
class StrHashTable
{
friend class StrHashTableIterator<T>;
public:
typedef StrHashTable<T> ClassType;
public:
StrHashTable(size_t len = 0)
{
m_pTable = NULL;
m_nLen = m_nFree = 0;
m_nInitSize = len;
if (len > MiniSize)
{
// <20><><EFBFBD>Ƴ<EFBFBD><C6B3>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>±<EFBFBD><C2B1><EFBFBD>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>
size_t val;
for (int i = 0; i < 32; ++i)
{
val = size_t(1 << i);
if (len <= val)
{
m_nInitSize = val;
break;
}
}
}
else
{
m_nInitSize = MiniSize; // <20><><EFBFBD>Ƴ<EFBFBD><C6B3>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>±<EFBFBD><C2B1><EFBFBD>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>
}
}
virtual ~StrHashTable()
{
clear();
}
//<2F><>չ<EFBFBD>ϣ<EFBFBD><CFA3>
void clear()
{
//ѭ<><D1AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
for (int i = (int)m_nLen - 1; i > -1; --i)
{
if (m_pTable[i].hash1)
{
m_pTable[i].value.~T();
}
}
//<2F>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
if (m_pTable) realloc(m_pTable, 0);
m_pTable = NULL;
m_nLen = m_nFree = 0;
}
//<2F><>ȡ<EFBFBD><C8A1>Ч<EFBFBD><D0A7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
inline size_t count() const
{
return m_nLen - m_nFree;
}
protected:
/** <20><><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD>ʹ<EFBFBD>õĹ<C3B5>ϣ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD>ݽṹ **/
template <typename TA>
class HashNode
{
public:
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* sKey)
{
int idx = getIndex(sKey);
return (idx >= 0) ? &m_pTable[idx].value : NULL;
}
//ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
inline const T* get(const char* sKey) const
{
int idx = getIndex(sKey);
return (idx >= 0) ? &m_pTable[idx].value : NULL;
}
/* ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
* <20><><EFBFBD>һ<EFBFBD><D2BB>hash<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* <20><><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7>ʼ<EFBFBD><CABC><EFBFBD>ҿ<EFBFBD>λ<EFBFBD><CEBB>ֱ֪<D6AA><D6B1><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD>α<EFBFBD><CEB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
inline T* put(const char* sKey)
{
unsigned int hash1, idx, start;
#ifdef _MSC_VER
unsigned int hash2, hash3;
#else
unsigned int __attribute__ ((unused)) hash2, hash3;
#endif
//<2F>ڴ<EFBFBD>ռ<D5BC><EFBFBD><E3A3AC><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ռ<EFBFBD>
if (m_nFree <= 0)
{
size_t oldlen = m_nLen;
m_nLen = (oldlen <= 0) ? m_nInitSize : m_nLen << 1;//<2F><><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4>
m_nFree = m_nLen - oldlen;
m_pTable = (NodeType*)realloc(m_pTable, m_nLen * sizeof(m_pTable[0]));
memset(&m_pTable[oldlen], 0, m_nFree * sizeof(m_pTable[0]));
}
hash1 = ::bzhashstr(sKey, 0);
hash2 = ::bzhashstr(sKey, 1);
hash3 = ::bzhashstr(sKey, 2);
start = idx = hash1 & ((unsigned int)m_nLen - 1);//<2F><><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4>
do
{
NodeType* pNode = &m_pTable[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 (!pNode->hash1)
{
pNode->hash1 = hash1;
pNode->hash2 = ::bzhashstr(sKey, 1);
pNode->hash3 = ::bzhashstr(sKey, 2);
m_nFree--;
new(&pNode->value)T();
return &pNode->value;
}
#ifdef _DEBUG
else if (pNode->hash1 == hash1 && pNode->hash2 == hash2 && pNode->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)m_nLen - 1);//<2F><><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4>
}
while (start != idx);
return NULL;
}
//ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
inline int update(const char* sKey, const T& value)
{
int idx = getIndex(sKey);
if (idx >= 0)
m_pTable[idx].value = value;
return idx;
}
//ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>ֵ<EFBFBD><D6B5>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD><D2B5>򷵻<EFBFBD>-1
inline int remove(const char* sKey)
{
int idx = getIndex(sKey);
if (idx >= 0)
{
NodeType* pNode = &m_pTable[idx];
pNode->hash1 = pNode->hash2 = pNode->hash3 = 0;
m_nFree++;
pNode->value.~T();
return idx;
}
return -1;
}
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD>ڱ<EFBFBD><DAB1>е<EFBFBD><D0B5><EFBFBD><EFBFBD><EFBFBD>
int getIndex(const char* sKey) const
{
unsigned int idx, start;
size_t len;
if (m_nLen <= 0)
return -1;
unsigned int hash1 = ::bzhashstr(sKey, 0);
unsigned int hash2 = ::bzhashstr(sKey, 1);
unsigned int hash3 = ::bzhashstr(sKey, 2);
//<2F><><EFBFBD>ȿ<EFBFBD>ʼ<EFBFBD>۰<EFBFBD><DBB0><EFBFBD><EFBFBD>
len = m_nLen;
while (len >= m_nInitSize)
{
idx = hash1 & ((unsigned int)len - 1);//<2F><><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4>
NodeType* pNode = &m_pTable[idx];
if (pNode->hash1 == hash1 && pNode->hash2 == hash2 && pNode->hash3 == hash3)
{
return idx;
}
len >>= 1;
}
//<2F>۰<EFBFBD><DBB0><EFBFBD>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>hashλ<68>ÿ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
start = idx = hash1 & ((unsigned int)m_nLen - 1);//<2F><><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4>
do
{
NodeType* pNode = &m_pTable[idx];
if (pNode->hash1 == hash1 && pNode->hash2 == hash2 && pNode->hash3 == hash3)
{
return idx;
}
idx = (idx + 1) & ((unsigned int)m_nLen - 1);//<2F><><EFBFBD><EFBFBD><EFBFBD>ȱ<EFBFBD><C8B1><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4>
}
while (start != idx);
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 m_nInitSize;//<2F><><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
size_t m_nLen; //<2F><>ϣ<EFBFBD><CFA3><EFBFBD>ij<EFBFBD><C4B3><EFBFBD>,<2C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>±<EFBFBD><C2B1><EFBFBD>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>
size_t m_nFree; //<2F><><EFBFBD>нڵ<D0BD><DAB5><EFBFBD><EFBFBD><EFBFBD>
HashNode<T>* m_pTable; //<2F><>ϣ<EFBFBD><CFA3>
public:
static const size_t MiniSize = 16;//<2F><>ϣ<EFBFBD><CFA3><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>ȣ<EFBFBD><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2<EFBFBD>Ĵη<C4B4><CEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϣ<EFBFBD>±<EFBFBD><C2B1><EFBFBD>޷<EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>
};
#endif