This commit is contained in:
David Anderson 2006-01-30 21:40:10 +00:00
parent 44db80bc75
commit cb291dbdd5

View File

@ -17,287 +17,269 @@
//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:
struct THashNode
{ {
THashNode(const K & k, const V & v) : public:
key(k), val(v) struct THashNode
{
};
THashNode & operator =(const THashNode &other)
{
key = other.key;
val = other.val;
}
K key;
V val;
};
typedef List<THashNode *> * NodePtr;
public:
class const_iterator;
THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f), m_NumItems(0)
{
_Refactor();
}
THash(const THash &other) : m_Buckets(new NodePtr[other.m_numBuckets]),
m_numBuckets(other.m_numBuckets), m_percentUsed(other.m_percentUsed)
{
for (size_t i=0; i<m_numBuckets; i++)
m_Buckets[i] = NULL;
for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
_FindOrInsert(iter->key)->val = iter->val;
}
void operator=(const THash &other)
{
clear();
for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
_FindOrInsert(iter->key)->val = iter->val;
}
~THash()
{
_Clear();
}
void clear()
{
_Clear();
_Refactor();
}
size_t GetBuckets()
{
return m_numBuckets;
}
float PercentUsed()
{
return m_percentUsed;
}
size_t size()
{
return m_NumItems;
}
V & operator [](const K & key)
{
THashNode *pNode = _FindOrInsert(key);
return pNode->val;
}
private:
void _Clear()
{
typename List<THashNode *>::iterator iter, end;
for (size_t i=0; i<m_numBuckets; i++)
{ {
if (m_Buckets[i]) THashNode(const K & k, const V & v) :
{ key(k), val(v)
end = m_Buckets[i]->end();
iter = m_Buckets[i]->begin();
while (iter != end)
{ {
delete (*iter); };
iter++; THashNode & operator =(const THashNode &other)
}
delete m_Buckets[i];
m_Buckets[i] = NULL;
}
}
if (m_Buckets)
delete [] m_Buckets;
m_Buckets = NULL;
m_numBuckets = 0;
m_NumItems = 0;
}
THashNode *_FindOrInsert(const K & key)
{
size_t place = HashFunction(key) % m_numBuckets;
THashNode *pNode = NULL;
if (!m_Buckets[place])
{
m_Buckets[place] = new List<THashNode *>;
pNode = new THashNode(key, V());
m_Buckets[place]->push_back(pNode);
m_percentUsed += (1.0f / (float)m_numBuckets);
m_NumItems++;
} else {
typename List<THashNode *>::iterator iter;
for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++)
{ {
if (Compare((*iter)->key, key) == 0) key = other.key;
return (*iter); val = other.val;
} }
//node does not exist K key;
pNode = new THashNode(key, V()); V val;
m_Buckets[place]->push_back(pNode); };
m_NumItems++; typedef List<THashNode *> * NodePtr;
} public:
if (PercentUsed() > 0.75f) class const_iterator;
THash() : m_Buckets(NULL), m_numBuckets(0), m_percentUsed(0.0f), m_items(0)
{
_Refactor(); _Refactor();
return pNode; }
} THash(const THash &other) : m_Buckets(new NodePtr[other.m_numBuckets]),
void _Refactor() m_numBuckets(other.m_numBuckets), m_percentUsed(other.m_percentUsed), m_items(0)
{
m_percentUsed = 0.0f;
if (!m_numBuckets)
{ {
m_numBuckets = _T_INIT_HASH_SIZE;
m_Buckets = new NodePtr[m_numBuckets];
for (size_t i=0; i<m_numBuckets; i++) for (size_t i=0; i<m_numBuckets; i++)
m_Buckets[i] = NULL; m_Buckets[i] = NULL;
} else { for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
size_t oldSize = m_numBuckets; _FindOrInsert(iter->key)->val = iter->val;
m_numBuckets *= 2; }
typename List<THashNode *>::iterator iter; void operator=(const THash &other)
size_t place; {
THashNode *pHashNode; clear();
NodePtr *temp = new NodePtr[m_numBuckets]; for (const_iterator iter = other.begin(); iter != other.end(); ++iter)
_FindOrInsert(iter->key)->val = iter->val;
}
~THash()
{
_Clear();
}
void clear()
{
_Clear();
_Refactor();
}
size_t size()
{
return m_items;
}
size_t GetBuckets()
{
return m_numBuckets;
}
float PercentUsed()
{
return m_percentUsed;
}
V & operator [](const K & key)
{
THashNode *pNode = _FindOrInsert(key);
return pNode->val;
}
private:
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++)
temp[i] = NULL;
//look in old hash table
for (size_t i=0; i<oldSize; i++)
{ {
//does a bucket have anything?
if (m_Buckets[i]) if (m_Buckets[i])
{ {
//go through the list of items end = m_Buckets[i]->end();
for (iter = m_Buckets[i]->begin(); iter != m_Buckets[i]->end(); iter++) iter = m_Buckets[i]->begin();
while (iter != end)
{ {
pHashNode = (*iter); delete (*iter);
//rehash it with the new bucket filter iter++;
place = HashFunction(pHashNode->key) % m_numBuckets;
//add it to the new hash table
if (!temp[place])
{
temp[place] = new List<THashNode *>;
m_percentUsed += (1.0f / (float)m_numBuckets);
}
temp[place]->push_back(pHashNode);
} }
//delete that bucket!
delete m_Buckets[i]; delete m_Buckets[i];
m_Buckets[i] = NULL; m_Buckets[i] = NULL;
} }
} }
//reassign bucket table if (m_Buckets)
delete [] m_Buckets; delete [] m_Buckets;
m_Buckets = temp; m_Buckets = NULL;
m_numBuckets = 0;
m_items = 0;
} }
} THashNode *_FindOrInsert(const K & key)
public:
friend class iterator;
friend class const_iterator;
class iterator
{
friend class THash;
public:
iterator() : curbucket(-1), hash(NULL), end(true)
{ {
}; size_t place = HashFunction(key) % m_numBuckets;
iterator(THash *h) : curbucket(-1), hash(h), end(false) THashNode *pNode = NULL;
{ if (!m_Buckets[place])
if (!h->m_Buckets)
end = true;
else
_Inc();
};
//pre increment
iterator & operator++()
{
_Inc();
return *this;
}
//post increment
iterator operator++(int)
{
iterator old(*this);
_Inc();
return old;
}
const THashNode & operator * () const
{
return *(*iter);
}
THashNode & operator * ()
{
return *(*iter);
}
const THashNode * operator ->() const
{
return (*iter);
}
THashNode * operator ->()
{
return (*iter);
}
bool operator ==(const iterator &where) const
{
if (where.hash == this->hash
&& where.end == this->end
&&
(this->end ||
((where.curbucket == this->curbucket)
&& (where.iter == iter))
))
return true;
return false;
}
bool operator !=(const iterator &where) const
{
return !( (*this) == where );
}
void erase()
{
if (end || !hash || curbucket < 0 || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
// Remove this element and move to the next one
iterator tmp = *this;
++tmp;
delete (*iter);
hash->m_Buckets[curbucket]->erase(iter);
*this = tmp;
m_NumItems--;
// :TODO: Maybe refactor to a lower size if required
}
private:
void _Inc()
{
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
if (curbucket < 0)
{ {
for (int i=0; i<(int)hash->m_numBuckets; i++) m_Buckets[place] = new List<THashNode *>;
pNode = new THashNode(key, V());
m_Buckets[place]->push_back(pNode);
m_percentUsed += (1.0f / (float)m_numBuckets);
m_items++;
} else {
typename List<THashNode *>::iterator iter;
for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++)
{ {
if (hash->m_Buckets[i]) if (Compare((*iter)->key, key) == 0)
return (*iter);
}
//node does not exist
pNode = new THashNode(key, V());
m_Buckets[place]->push_back(pNode);
m_items++;
}
if (PercentUsed() > 0.75f)
_Refactor();
return pNode;
}
void _Refactor()
{
m_percentUsed = 0.0f;
if (!m_numBuckets)
{
m_numBuckets = _T_INIT_HASH_SIZE;
m_Buckets = new NodePtr[m_numBuckets];
for (size_t i=0; i<m_numBuckets; i++)
m_Buckets[i] = NULL;
} else {
size_t oldSize = m_numBuckets;
m_numBuckets *= 2;
typename List<THashNode *>::iterator iter;
size_t place;
THashNode *pHashNode;
NodePtr *temp = new NodePtr[m_numBuckets];
for (size_t i=0; i<m_numBuckets; i++)
temp[i] = NULL;
//look in old hash table
for (size_t i=0; i<oldSize; i++)
{
//does a bucket have anything?
if (m_Buckets[i])
{ {
iter = hash->m_Buckets[i]->begin(); //go through the list of items
if (iter == hash->m_Buckets[i]->end()) for (iter = m_Buckets[i]->begin(); iter != m_Buckets[i]->end(); iter++)
continue; {
curbucket = i; pHashNode = (*iter);
break; //rehash it with the new bucket filter
place = HashFunction(pHashNode->key) % m_numBuckets;
//add it to the new hash table
if (!temp[place])
{
temp[place] = new List<THashNode *>;
m_percentUsed += (1.0f / (float)m_numBuckets);
}
temp[place]->push_back(pHashNode);
}
//delete that bucket!
delete m_Buckets[i];
m_Buckets[i] = NULL;
} }
} }
if (curbucket < 0) //reassign bucket table
delete [] m_Buckets;
m_Buckets = temp;
}
}
public:
friend class iterator;
friend class const_iterator;
class iterator
{
friend class THash;
public:
iterator() : curbucket(-1), hash(NULL), end(true)
{
};
iterator(THash *h) : curbucket(-1), hash(h), end(false)
{
if (!h->m_Buckets)
end = true; end = true;
} else { else
if (iter != hash->m_Buckets[curbucket]->end()) _Inc();
iter++; };
if (iter == hash->m_Buckets[curbucket]->end()) //pre increment
iterator & operator++()
{
_Inc();
return *this;
}
//post increment
iterator operator++(int)
{
iterator old(*this);
_Inc();
return old;
}
const THashNode & operator * () const
{
return *(*iter);
}
THashNode & operator * ()
{
return *(*iter);
}
const THashNode * operator ->() const
{
return (*iter);
}
THashNode * operator ->()
{
return (*iter);
}
bool operator ==(const iterator &where) const
{
if (where.hash == this->hash
&& where.end == this->end
&&
(this->end ||
((where.curbucket == this->curbucket)
&& (where.iter == iter))
))
return true;
return false;
}
bool operator !=(const iterator &where) const
{
return !( (*this) == where );
}
void erase()
{
if (end || !hash || curbucket < 0 || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
// Remove this element and move to the next one
iterator tmp = *this;
++tmp;
delete (*iter);
hash->m_Buckets[curbucket]->erase(iter);
*this = tmp;
// :TODO: Maybe refactor to a lower size if required
m_items--;
}
private:
void _Inc()
{
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
if (curbucket < 0)
{ {
int oldbucket = curbucket; for (int i=0; i<(int)hash->m_numBuckets; i++)
for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
{ {
if (hash->m_Buckets[i]) if (hash->m_Buckets[i])
{ {
@ -308,95 +290,95 @@ public:
break; break;
} }
} }
if (curbucket == oldbucket) if (curbucket < 0)
end = true; end = true;
} } else {
} if (iter != hash->m_Buckets[curbucket]->end())
} iter++;
private: if (iter == hash->m_Buckets[curbucket]->end())
int curbucket;
typename List<THashNode *>::iterator iter;
THash *hash;
bool end;
};
class const_iterator
{
friend class THash;
public:
const_iterator() : curbucket(-1), hash(NULL), end(true)
{
};
const_iterator(const THash *h) : curbucket(-1), hash(h), end(false)
{
if (!h->m_Buckets)
end = true;
else
_Inc();
};
//pre increment
const_iterator & operator++()
{
_Inc();
return *this;
}
//post increment
const_iterator operator++(int)
{
iterator old(*this);
_Inc();
return old;
}
const THashNode & operator * () const
{
return *(*iter);
}
const THashNode * operator ->() const
{
return (*iter);
}
bool operator ==(const const_iterator &where) const
{
if (where.hash == this->hash
&& where.end == this->end
&&
(this->end ||
((where.curbucket == this->curbucket)
&& (where.iter == iter))
))
return true;
return false;
}
bool operator !=(const const_iterator &where) const
{
return !( (*this) == where );
}
private:
void _Inc()
{
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
if (curbucket < 0)
{
for (int i=0; i<(int)hash->m_numBuckets; i++)
{
if (hash->m_Buckets[i])
{ {
iter = hash->m_Buckets[i]->begin(); int oldbucket = curbucket;
if (iter == hash->m_Buckets[i]->end()) for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
continue; {
curbucket = i; if (hash->m_Buckets[i])
break; {
iter = hash->m_Buckets[i]->begin();
if (iter == hash->m_Buckets[i]->end())
continue;
curbucket = i;
break;
}
}
if (curbucket == oldbucket)
end = true;
} }
} }
if (curbucket < 0) }
private:
int curbucket;
typename List<THashNode *>::iterator iter;
THash *hash;
bool end;
};
class const_iterator
{
friend class THash;
public:
const_iterator() : curbucket(-1), hash(NULL), end(true)
{
};
const_iterator(const THash *h) : curbucket(-1), hash(h), end(false)
{
if (!h->m_Buckets)
end = true; end = true;
} else { else
if (iter != hash->m_Buckets[curbucket]->end()) _Inc();
iter++; };
if (iter == hash->m_Buckets[curbucket]->end()) //pre increment
const_iterator & operator++()
{
_Inc();
return *this;
}
//post increment
const_iterator operator++(int)
{
iterator old(*this);
_Inc();
return old;
}
const THashNode & operator * () const
{
return *(*iter);
}
const THashNode * operator ->() const
{
return (*iter);
}
bool operator ==(const const_iterator &where) const
{
if (where.hash == this->hash
&& where.end == this->end
&&
(this->end ||
((where.curbucket == this->curbucket)
&& (where.iter == iter))
))
return true;
return false;
}
bool operator !=(const const_iterator &where) const
{
return !( (*this) == where );
}
private:
void _Inc()
{
if (end || !hash || curbucket >= static_cast<int>(hash->m_numBuckets))
return;
if (curbucket < 0)
{ {
int oldbucket = curbucket; for (int i=0; i<(int)hash->m_numBuckets; i++)
for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
{ {
if (hash->m_Buckets[i]) if (hash->m_Buckets[i])
{ {
@ -407,84 +389,103 @@ public:
break; break;
} }
} }
if (curbucket == oldbucket) if (curbucket < 0)
end = true; end = true;
} else {
if (iter != hash->m_Buckets[curbucket]->end())
iter++;
if (iter == hash->m_Buckets[curbucket]->end())
{
int oldbucket = curbucket;
for (int i=curbucket+1; i<(int)hash->m_numBuckets; i++)
{
if (hash->m_Buckets[i])
{
iter = hash->m_Buckets[i]->begin();
if (iter == hash->m_Buckets[i]->end())
continue;
curbucket = i;
break;
}
}
if (curbucket == oldbucket)
end = true;
}
} }
} }
private:
int curbucket;
typename List<THashNode *>::iterator iter;
const THash *hash;
bool end;
};
public:
iterator begin()
{
return iterator(this);
}
iterator end()
{
iterator iter;
iter.hash = this;
return iter;
} }
private:
int curbucket;
typename List<THashNode *>::iterator iter;
const THash *hash;
bool end;
};
public:
iterator begin()
{
return iterator(this);
}
iterator end()
{
iterator iter;
iter.hash = this;
return iter;
}
const_iterator begin() const const_iterator begin() const
{ {
return const_iterator(this); return const_iterator(this);
} }
const_iterator end() const const_iterator end() const
{ {
const_iterator iter; const_iterator iter;
iter.hash = this; iter.hash = this;
return iter; return iter;
} }
template <typename U> template <typename U>
iterator find(const U & u) const iterator find(const U & u) const
{
iterator b = begin();
iterator e = end();
for (iterator iter = b; iter != e; iter++)
{ {
if ( (*iter).key == u ) iterator b = begin();
return iter; iterator e = end();
for (iterator iter = b; iter != e; iter++)
{
if ( (*iter).key == u )
return iter;
}
return end();
} }
return end(); template <typename U>
}
template <typename U>
iterator find(const U & u) iterator find(const U & u)
{
iterator b = begin();
iterator e = end();
for (iterator iter = b; iter != e; iter++)
{ {
if ( (*iter).key == u ) iterator b = begin();
return iter; iterator e = end();
for (iterator iter = b; iter != e; iter++)
{
if ( (*iter).key == u )
return iter;
}
return end();
} }
return end();
}
iterator erase(iterator where) iterator erase(iterator where)
{ {
where.erase(); where.erase();
return where; return where;
} }
template <typename U> template <typename U>
void erase(const U & u) void erase(const U & u)
{ {
iterator iter = find(u); iterator iter = find(u);
if (iter == end()) if (iter == end())
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_items;
}; };
//}; //};
#endif //_INCLUDE_SH_TINYHASH_H_ #endif //_INCLUDE_SH_TINYHASH_H_