merged changes from SH:TinyHash

This commit is contained in:
Borja Ferrer 2006-01-06 18:52:12 +00:00
parent 86c033a922
commit 04113f8a02

View File

@ -13,38 +13,41 @@
#include "sh_list.h" #include "sh_list.h"
#define _T_INIT_HASH_SIZE 128 #define _T_INIT_HASH_SIZE 512
//namespace SourceHook //namespace SourceHook
//{ //{
template <class K> template <class K>
int HashFunction(const K & k); int HashFunction(const K & k);
template <class K> template <class K>
int Compare(const K & k1, const K & k2); int Compare(const K & k1, const K & k2);
/** /**
* This is a tiny, growable hash class. * This is a tiny, growable hash class.
* Meant for quick and dirty dictionaries only! * Meant for quick and dirty dictionaries only!
*/ */
template <class K, class V> template <class K, class V>
class THash class THash
{ {
public: public:
struct THashNode struct THashNode
{ {
THashNode(const K & k, const V & v) : THashNode(const K & k, const V & v) :
key(k), val(v) key(k), val(v)
{ {
}; };
~THashNode() THashNode & operator =(const THashNode &other)
{ {
key = other.key;
val = other.val;
} }
K key; K key;
V val; V val;
}; };
typedef List<THashNode> * NodePtr; typedef List<THashNode *> * NodePtr;
public: public:
class const_iterator;
THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f), m_NumItems(0) THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f), m_NumItems(0)
{ {
_Refactor(); _Refactor();
@ -90,13 +93,21 @@
THashNode *pNode = _FindOrInsert(key); THashNode *pNode = _FindOrInsert(key);
return pNode->val; return pNode->val;
} }
private: private:
void _Clear() void _Clear()
{ {
typename List<THashNode *>::iterator iter, end;
for (size_t i=0; i<m_numBuckets; i++) for (size_t i=0; i<m_numBuckets; i++)
{ {
if (m_Buckets[i]) if (m_Buckets[i])
{ {
end = m_Buckets[i]->end();
iter = m_Buckets[i]->begin();
while (iter != end)
{
delete (*iter);
iter++;
}
delete m_Buckets[i]; delete m_Buckets[i];
m_Buckets[i] = NULL; m_Buckets[i] = NULL;
} }
@ -113,33 +124,25 @@
THashNode *pNode = NULL; THashNode *pNode = NULL;
if (!m_Buckets[place]) if (!m_Buckets[place])
{ {
m_Buckets[place] = new List<THashNode>; m_Buckets[place] = new List<THashNode *>;
m_Buckets[place]->push_back(THashNode(key, V())); pNode = new THashNode(key, V());
m_Buckets[place]->push_back(pNode);
m_percentUsed += (1.0f / (float)m_numBuckets); m_percentUsed += (1.0f / (float)m_numBuckets);
m_NumItems++; m_NumItems++;
typename List<THashNode>::iterator iter;
iter = m_Buckets[place]->end();
iter--;
pNode = &(*iter);
} else { } else {
typename List<THashNode>::iterator iter, end=m_Buckets[place]->end(); typename List<THashNode *>::iterator iter;
for (iter=m_Buckets[place]->begin(); iter!=end; iter++) for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++)
{ {
if (Compare((*iter).key, key) == 0) if (Compare((*iter)->key, key) == 0)
return &(*iter); return (*iter);
} }
//node does not exist //node does not exist
m_Buckets[place]->push_back(THashNode(key, V())); pNode = new THashNode(key, V());
m_Buckets[place]->push_back(pNode);
m_NumItems++; m_NumItems++;
iter = m_Buckets[place]->end();
iter--;
pNode = &(*iter);
} }
if (PercentUsed() > 0.75f) if (PercentUsed() > 0.75f)
{
_Refactor(); _Refactor();
return _FindOrInsert(key);
}
return pNode; return pNode;
} }
void _Refactor() void _Refactor()
@ -154,7 +157,7 @@
} else { } else {
size_t oldSize = m_numBuckets; size_t oldSize = m_numBuckets;
m_numBuckets *= 2; m_numBuckets *= 2;
typename List<THashNode>::iterator iter, end; typename List<THashNode *>::iterator iter;
size_t place; size_t place;
THashNode *pHashNode; THashNode *pHashNode;
NodePtr *temp = new NodePtr[m_numBuckets]; NodePtr *temp = new NodePtr[m_numBuckets];
@ -167,19 +170,18 @@
if (m_Buckets[i]) if (m_Buckets[i])
{ {
//go through the list of items //go through the list of items
end = m_Buckets[i]->end(); for (iter = m_Buckets[i]->begin(); iter != m_Buckets[i]->end(); iter++)
for (iter = m_Buckets[i]->begin(); iter!=end; iter++)
{ {
pHashNode = &(*iter); pHashNode = (*iter);
//rehash it with the new bucket filter //rehash it with the new bucket filter
place = HashFunction(pHashNode->key) % m_numBuckets; place = HashFunction(pHashNode->key) % m_numBuckets;
//add it to the new hash table //add it to the new hash table
if (!temp[place]) if (!temp[place])
{ {
temp[place] = new List<THashNode>; temp[place] = new List<THashNode *>;
m_percentUsed += (1.0f / (float)m_numBuckets); m_percentUsed += (1.0f / (float)m_numBuckets);
} }
temp[place]->push_back((*iter)); temp[place]->push_back(pHashNode);
} }
//delete that bucket! //delete that bucket!
delete m_Buckets[i]; delete m_Buckets[i];
@ -191,7 +193,7 @@
m_Buckets = temp; m_Buckets = temp;
} }
} }
public: public:
friend class iterator; friend class iterator;
friend class const_iterator; friend class const_iterator;
class iterator class iterator
@ -223,19 +225,19 @@
} }
const THashNode & operator * () const const THashNode & operator * () const
{ {
return (*iter); return *(*iter);
} }
THashNode & operator * () THashNode & operator * ()
{ {
return (*iter); return *(*iter);
} }
const THashNode * operator ->() const const THashNode * operator ->() const
{ {
return &(*iter); return (*iter);
} }
THashNode * operator ->() THashNode * operator ->()
{ {
return &(*iter); return (*iter);
} }
bool operator ==(const iterator &where) const bool operator ==(const iterator &where) const
{ {
@ -262,6 +264,7 @@
// Remove this element and move to the next one // Remove this element and move to the next one
iterator tmp = *this; iterator tmp = *this;
++tmp; ++tmp;
delete (*iter);
hash->m_Buckets[curbucket]->erase(iter); hash->m_Buckets[curbucket]->erase(iter);
*this = tmp; *this = tmp;
m_NumItems--; m_NumItems--;
@ -312,7 +315,7 @@
} }
private: private:
int curbucket; int curbucket;
typename List<THashNode>::iterator iter; typename List<THashNode *>::iterator iter;
THash *hash; THash *hash;
bool end; bool end;
}; };
@ -415,7 +418,7 @@
const THash *hash; const THash *hash;
bool end; bool end;
}; };
public: public:
iterator begin() iterator begin()
{ {
return iterator(this); return iterator(this);
@ -476,12 +479,12 @@
return; return;
iter.erase(); iter.erase();
} }
private: private:
NodePtr *m_Buckets; NodePtr *m_Buckets;
size_t m_numBuckets; size_t m_numBuckets;
float m_percentUsed; float m_percentUsed;
size_t m_NumItems; size_t m_NumItems;
}; };
//}; //};
#endif //_INCLUDE_SH_TINYHASH_H_ #endif //_INCLUDE_SH_TINYHASH_H_