sync
This commit is contained in:
		@@ -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_
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user