mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2024-11-28 10:24:20 +01:00
e19413dd5b
--HG-- rename : sourcemm/IPluginManager.h => core/IPluginManager.h rename : sourcemm/ISmmAPI.h => core/ISmmAPI.h rename : sourcemm/ISmmPlugin.h => core/ISmmPlugin.h rename : sourcemm/ISmmPluginExt.h => core/ISmmPluginExt.h rename : sourcemm/LICENSE.txt => core/LICENSE.txt rename : sourcemm/Makefile => core/Makefile rename : sourcemm/changelog.txt => core/changelog.txt rename : sourcemm/episode1/console.cpp => core/episode1/console.cpp rename : sourcemm/episode1/console.h => core/episode1/console.h rename : sourcemm/episode1/convar_smm.h => core/episode1/convar_smm.h rename : sourcemm/episode1/msvc8/sourcemm.sln => core/episode1/msvc8/sourcemm.sln rename : sourcemm/episode1/msvc8/sourcemm.vcproj => core/episode1/msvc8/sourcemm.vcproj rename : sourcemm/episode1/provider_ep1.cpp => core/episode1/provider_ep1.cpp rename : sourcemm/episode1/provider_ep1.h => core/episode1/provider_ep1.h rename : sourcemm/episode1/vsp_listener.cpp => core/episode1/vsp_listener.cpp rename : sourcemm/episode1/vsp_listener.h => core/episode1/vsp_listener.h rename : sourcemm/metamod.cpp => core/metamod.cpp rename : sourcemm/metamod.h => core/metamod.h rename : sourcemm/metamod_console.cpp => core/metamod_console.cpp rename : sourcemm/metamod_console.h => core/metamod_console.h rename : sourcemm/metamod_oslink.cpp => core/metamod_oslink.cpp rename : sourcemm/metamod_oslink.h => core/metamod_oslink.h rename : sourcemm/metamod_plugins.cpp => core/metamod_plugins.cpp rename : sourcemm/metamod_plugins.h => core/metamod_plugins.h rename : sourcemm/metamod_provider.h => core/metamod_provider.h rename : sourcemm/metamod_util.cpp => core/metamod_util.cpp rename : sourcemm/metamod_util.h => core/metamod_util.h rename : sourcemm/episode2/console.cpp => core/provider/console.cpp rename : sourcemm/episode2/console.h => core/provider/console.h rename : sourcemm/episode2/msvc8/sourcemm.sln => core/provider/msvc8/sourcemm.sln rename : sourcemm/episode2/msvc8/sourcemm.vcproj => core/provider/msvc8/sourcemm.vcproj rename : sourcemm/episode2/msvc9/sourcemm.sln => core/provider/msvc9/sourcemm.sln rename : sourcemm/episode2/msvc9/sourcemm.vcproj => core/provider/msvc9/sourcemm.vcproj rename : sourcemm/episode2/provider_ep2.cpp => core/provider/provider_ep2.cpp rename : sourcemm/episode2/provider_ep2.h => core/provider/provider_ep2.h rename : sourcemm/episode2/vsp_listener.cpp => core/provider/vsp_listener.cpp rename : sourcemm/episode2/vsp_listener.h => core/provider/vsp_listener.h rename : sourcehook/FastDelegate.h => core/sourcehook/FastDelegate.h rename : sourcehook/generate/FastDelegate.h => core/sourcehook/generate/FastDelegate.h rename : sourcehook/generate/FastDelegate.hxx => core/sourcehook/generate/FastDelegate.hxx rename : sourcehook/generate/generate => core/sourcehook/generate/generate rename : sourcehook/generate/generate.bat => core/sourcehook/generate/generate.bat rename : sourcehook/generate/sh_memfuncinfo.h => core/sourcehook/generate/sh_memfuncinfo.h rename : sourcehook/generate/sh_memfuncinfo.hxx => core/sourcehook/generate/sh_memfuncinfo.hxx rename : sourcehook/generate/shworker.bin => core/sourcehook/generate/shworker.bin rename : sourcehook/generate/shworker.exe => core/sourcehook/generate/shworker.exe rename : sourcehook/generate/shworker/Makefile => core/sourcehook/generate/shworker/Makefile rename : sourcehook/generate/shworker/fd_hopter.cpp => core/sourcehook/generate/shworker/fd_hopter.cpp rename : sourcehook/generate/shworker/msvc7/shworker.vcproj => core/sourcehook/generate/shworker/msvc7/shworker.vcproj rename : sourcehook/generate/shworker/msvc8/shworker.vcproj => core/sourcehook/generate/shworker/msvc8/shworker.vcproj rename : sourcehook/generate/shworker/shworker.cpp => core/sourcehook/generate/shworker/shworker.cpp rename : sourcehook/generate/sourcehook.h => core/sourcehook/generate/sourcehook.h rename : sourcehook/generate/sourcehook.hxx => core/sourcehook/generate/sourcehook.hxx rename : sourcehook/sh_list.h => core/sourcehook/sh_list.h rename : sourcehook/sh_memfuncinfo.h => core/sourcehook/sh_memfuncinfo.h rename : sourcehook/sh_memory.h => core/sourcehook/sh_memory.h rename : sourcehook/sh_pagealloc.h => core/sourcehook/sh_pagealloc.h rename : sourcehook/sh_stack.h => core/sourcehook/sh_stack.h rename : sourcehook/sh_string.h => core/sourcehook/sh_string.h rename : sourcehook/sh_tinyhash.h => core/sourcehook/sh_tinyhash.h rename : sourcehook/sh_vector.h => core/sourcehook/sh_vector.h rename : sourcehook/sourcehook.cpp => core/sourcehook/sourcehook.cpp rename : sourcehook/sourcehook.h => core/sourcehook/sourcehook.h rename : sourcehook/sourcehook_hookmangen.cpp => core/sourcehook/sourcehook_hookmangen.cpp rename : sourcehook/sourcehook_hookmangen.h => core/sourcehook/sourcehook_hookmangen.h rename : sourcehook/sourcehook_hookmangen_x86.h => core/sourcehook/sourcehook_hookmangen_x86.h rename : sourcehook/sourcehook_impl.h => core/sourcehook/sourcehook_impl.h rename : sourcehook/sourcehook_impl_chook.h => core/sourcehook/sourcehook_impl_chook.h rename : sourcehook/sourcehook_impl_chookidman.h => core/sourcehook/sourcehook_impl_chookidman.h rename : sourcehook/sourcehook_impl_chookmaninfo.h => core/sourcehook/sourcehook_impl_chookmaninfo.h rename : sourcehook/sourcehook_impl_ciface.h => core/sourcehook/sourcehook_impl_ciface.h rename : sourcehook/sourcehook_impl_cproto.h => core/sourcehook/sourcehook_impl_cproto.h rename : sourcehook/sourcehook_impl_cvfnptr.h => core/sourcehook/sourcehook_impl_cvfnptr.h rename : sourcehook/sourcehook_pibuilder.h => core/sourcehook/sourcehook_pibuilder.h rename : sourcehook/test/Makefile => core/sourcehook/test/Makefile rename : sourcehook/test/generate.bat => core/sourcehook/test/generate.bat rename : sourcehook/test/main.cpp => core/sourcehook/test/main.cpp rename : sourcehook/test/msvc7/test.vcproj => core/sourcehook/test/msvc7/test.vcproj rename : sourcehook/test/msvc8/test.vcproj => core/sourcehook/test/msvc8/test.vcproj rename : sourcehook/test/sourcehook_test.h => core/sourcehook/test/sourcehook_test.h rename : sourcehook/test/test1.cpp => core/sourcehook/test/test1.cpp rename : sourcehook/test/test2.cpp => core/sourcehook/test/test2.cpp rename : sourcehook/test/test3.cpp => core/sourcehook/test/test3.cpp rename : sourcehook/test/test4.cpp => core/sourcehook/test/test4.cpp rename : sourcehook/test/testbail.cpp => core/sourcehook/test/testbail.cpp rename : sourcehook/test/testbail.h => core/sourcehook/test/testbail.h rename : sourcehook/test/testbail2.cpp => core/sourcehook/test/testbail2.cpp rename : sourcehook/test/testevents.h => core/sourcehook/test/testevents.h rename : sourcehook/test/testhookmangen.cpp => core/sourcehook/test/testhookmangen.cpp rename : sourcehook/test/testhookmangen.h => core/sourcehook/test/testhookmangen.h rename : sourcehook/test/testhookmangen.hxx => core/sourcehook/test/testhookmangen.hxx rename : sourcehook/test/testlist.cpp => core/sourcehook/test/testlist.cpp rename : sourcehook/test/testmanual.cpp => core/sourcehook/test/testmanual.cpp rename : sourcehook/test/testmulti.cpp => core/sourcehook/test/testmulti.cpp rename : sourcehook/test/testrecall.cpp => core/sourcehook/test/testrecall.cpp rename : sourcehook/test/testreentr.cpp => core/sourcehook/test/testreentr.cpp rename : sourcehook/test/testref.cpp => core/sourcehook/test/testref.cpp rename : sourcehook/test/testrefret.cpp => core/sourcehook/test/testrefret.cpp rename : sourcehook/test/testvphooks.cpp => core/sourcehook/test/testvphooks.cpp rename : sourcemm/svn_version.h => core/svn_version.h rename : sourcemm/svn_version.tpl => core/svn_version.tpl rename : sourcemm/version.rc => core/version.rc
535 lines
11 KiB
C++
535 lines
11 KiB
C++
/* ======== SourceMM ========
|
|
* Copyright (C) 2004-2008 Metamod:Source Development Team
|
|
* No warranties of any kind
|
|
*
|
|
* License: zlib/libpng
|
|
*
|
|
* Author(s): David "BAILOPAN" Anderson
|
|
* ============================
|
|
*/
|
|
|
|
#ifndef _INCLUDE_SH_TINYHASH_H_
|
|
#define _INCLUDE_SH_TINYHASH_H_
|
|
|
|
#include "sh_list.h"
|
|
|
|
#define _T_INIT_HASH_SIZE 32
|
|
|
|
namespace SourceHook
|
|
{
|
|
template <class K>
|
|
int HashFunction(const K & k);
|
|
|
|
template <class U>
|
|
int HashAlt(const U &u);
|
|
|
|
template <class U, class K>
|
|
int CompareAlt(const U &k1, const K &k2);
|
|
|
|
template <class K>
|
|
int Compare(const K & k1, const K & k2);
|
|
|
|
/**
|
|
* This is a tiny, growable hash class.
|
|
* Meant for quick and dirty dictionaries only!
|
|
*/
|
|
template <class K, class V>
|
|
class THash
|
|
{
|
|
public:
|
|
struct THashNode
|
|
{
|
|
THashNode(const K & k, const V & v) :
|
|
key(k), val(v)
|
|
{
|
|
};
|
|
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)
|
|
{
|
|
_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;
|
|
}
|
|
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])
|
|
{
|
|
end = m_Buckets[i]->end();
|
|
iter = m_Buckets[i]->begin();
|
|
while (iter != end)
|
|
{
|
|
delete (*iter);
|
|
iter++;
|
|
}
|
|
delete m_Buckets[i];
|
|
m_Buckets[i] = NULL;
|
|
}
|
|
}
|
|
if (m_Buckets)
|
|
delete [] m_Buckets;
|
|
m_Buckets = NULL;
|
|
m_numBuckets = 0;
|
|
}
|
|
public:
|
|
template <typename U>
|
|
V & AltFindOrInsert(const U & ukey)
|
|
{
|
|
size_t place = HashAlt(ukey) % m_numBuckets;
|
|
THashNode *pNode = NULL;
|
|
if (!m_Buckets[place])
|
|
{
|
|
m_Buckets[place] = new List<THashNode *>;
|
|
pNode = new THashNode(ukey, V());
|
|
m_Buckets[place]->push_back(pNode);
|
|
m_percentUsed += (1.0f / (float)m_numBuckets);
|
|
} else {
|
|
typename List<THashNode *>::iterator iter;
|
|
for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++)
|
|
{
|
|
if (CompareAlt(ukey, (*iter)->key) == 0)
|
|
{
|
|
return (*iter)->val;
|
|
}
|
|
}
|
|
//node does not exist
|
|
pNode = new THashNode(ukey, V());
|
|
m_Buckets[place]->push_back(pNode);
|
|
}
|
|
if (PercentUsed() > 0.75f)
|
|
{
|
|
_Refactor();
|
|
}
|
|
return pNode->val;
|
|
}
|
|
private:
|
|
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);
|
|
} else {
|
|
typename List<THashNode *>::iterator iter;
|
|
for (iter=m_Buckets[place]->begin(); iter!=m_Buckets[place]->end(); iter++)
|
|
{
|
|
if (Compare((*iter)->key, key) == 0)
|
|
return (*iter);
|
|
}
|
|
//node does not exist
|
|
pNode = new THashNode(key, V());
|
|
m_Buckets[place]->push_back(pNode);
|
|
}
|
|
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])
|
|
{
|
|
//go through the list of items
|
|
for (iter = m_Buckets[i]->begin(); iter != m_Buckets[i]->end(); iter++)
|
|
{
|
|
pHashNode = (*iter);
|
|
//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;
|
|
}
|
|
}
|
|
//reassign bucket table
|
|
delete [] m_Buckets;
|
|
m_Buckets = temp;
|
|
}
|
|
}
|
|
public:
|
|
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;
|
|
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;
|
|
|
|
// :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++)
|
|
{
|
|
if (hash->m_Buckets[i])
|
|
{
|
|
iter = hash->m_Buckets[i]->begin();
|
|
if (iter == hash->m_Buckets[i]->end())
|
|
continue;
|
|
curbucket = i;
|
|
break;
|
|
}
|
|
}
|
|
if (curbucket < 0)
|
|
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 SourceHook::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();
|
|
if (iter == hash->m_Buckets[i]->end())
|
|
continue;
|
|
curbucket = i;
|
|
break;
|
|
}
|
|
}
|
|
if (curbucket < 0)
|
|
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 SourceHook::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
|
|
{
|
|
return const_iterator(this);
|
|
}
|
|
const_iterator end() const
|
|
{
|
|
const_iterator iter;
|
|
iter.hash = this;
|
|
return iter;
|
|
}
|
|
|
|
template <typename U>
|
|
iterator find(const U & u) const
|
|
{
|
|
iterator b = begin();
|
|
iterator e = end();
|
|
for (iterator iter = b; iter != e; iter++)
|
|
{
|
|
if ( (*iter).key == u )
|
|
return iter;
|
|
}
|
|
return end();
|
|
}
|
|
template <typename U>
|
|
iterator find(const U & u)
|
|
{
|
|
iterator b = begin();
|
|
iterator e = end();
|
|
for (iterator iter = b; iter != e; iter++)
|
|
{
|
|
if ( (*iter).key == u )
|
|
return iter;
|
|
}
|
|
return end();
|
|
}
|
|
template <typename U>
|
|
iterator FindAlt(const U & u)
|
|
{
|
|
iterator b = begin();
|
|
iterator e = end();
|
|
for (iterator iter = b; iter != e; iter++)
|
|
{
|
|
if (CompareAlt(u, (*iter).key) == 0)
|
|
{
|
|
return iter;
|
|
}
|
|
}
|
|
return e;
|
|
}
|
|
iterator erase(iterator where)
|
|
{
|
|
where.erase();
|
|
return where;
|
|
}
|
|
template <typename U>
|
|
void erase(const U & u)
|
|
{
|
|
iterator iter = find(u);
|
|
if (iter == end())
|
|
return;
|
|
iter.erase();
|
|
}
|
|
friend class iterator;
|
|
friend class const_iterator;
|
|
private:
|
|
NodePtr *m_Buckets;
|
|
size_t m_numBuckets;
|
|
float m_percentUsed;
|
|
};
|
|
};
|
|
|
|
#endif //_INCLUDE_SH_TINYHASH_H_
|