483 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			483 lines
		
	
	
		
			9.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								Bullet Continuous Collision Detection and Physics Library
							 | 
						||
| 
								 | 
							
								Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This software is provided 'as-is', without any express or implied warranty.
							 | 
						||
| 
								 | 
							
								In no event will the authors be held liable for any damages arising from the use of this software.
							 | 
						||
| 
								 | 
							
								Permission is granted to anyone to use this software for any purpose, 
							 | 
						||
| 
								 | 
							
								including commercial applications, and to alter it and redistribute it freely, 
							 | 
						||
| 
								 | 
							
								subject to the following restrictions:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
							 | 
						||
| 
								 | 
							
								2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
							 | 
						||
| 
								 | 
							
								3. This notice may not be removed or altered from any source distribution.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BT_HASH_MAP_H
							 | 
						||
| 
								 | 
							
								#define BT_HASH_MAP_H
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "btAlignedObjectArray.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								///very basic hashable string implementation, compatible with btHashMap
							 | 
						||
| 
								 | 
							
								struct btHashString
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									const char* m_string;
							 | 
						||
| 
								 | 
							
									unsigned int	m_hash;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									SIMD_FORCE_INLINE	unsigned int getHash()const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return m_hash;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btHashString(const char* name)
							 | 
						||
| 
								 | 
							
										:m_string(name)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
							 | 
						||
| 
								 | 
							
										static const unsigned int  InitialFNV = 2166136261u;
							 | 
						||
| 
								 | 
							
										static const unsigned int FNVMultiple = 16777619u;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/* Fowler / Noll / Vo (FNV) Hash */
							 | 
						||
| 
								 | 
							
										unsigned int hash = InitialFNV;
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										for(int i = 0; m_string[i]; i++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											hash = hash ^ (m_string[i]);       /* xor  the low 8 bits */
							 | 
						||
| 
								 | 
							
											hash = hash * FNVMultiple;  /* multiply by the magic number */
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										m_hash = hash;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int portableStringCompare(const char* src,	const char* dst) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
											int ret = 0 ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											while( ! (ret = *(const unsigned char *)src - *(const unsigned char *)dst) && *dst)
							 | 
						||
| 
								 | 
							
													++src, ++dst;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if ( ret < 0 )
							 | 
						||
| 
								 | 
							
													ret = -1 ;
							 | 
						||
| 
								 | 
							
											else if ( ret > 0 )
							 | 
						||
| 
								 | 
							
													ret = 1 ;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return( ret );
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bool equals(const btHashString& other) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return (m_string == other.m_string) ||
							 | 
						||
| 
								 | 
							
											(0==portableStringCompare(m_string,other.m_string));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const int BT_HASH_NULL=0xffffffff;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class btHashInt
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int	m_uid;
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btHashInt()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btHashInt(int uid)	:m_uid(uid)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int	getUid1() const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return m_uid;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void	setUid1(int uid)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										m_uid = uid;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bool equals(const btHashInt& other) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return getUid1() == other.getUid1();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									//to our success
							 | 
						||
| 
								 | 
							
									SIMD_FORCE_INLINE	unsigned int getHash()const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										unsigned int key = m_uid;
							 | 
						||
| 
								 | 
							
										// Thomas Wang's hash
							 | 
						||
| 
								 | 
							
										key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										return key;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class btHashPtr
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									union
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const void*	m_pointer;
							 | 
						||
| 
								 | 
							
										unsigned int	m_hashValues[2];
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btHashPtr(const void* ptr)
							 | 
						||
| 
								 | 
							
										:m_pointer(ptr)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const void*	getPointer() const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return m_pointer;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bool equals(const btHashPtr& other) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return getPointer() == other.getPointer();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//to our success
							 | 
						||
| 
								 | 
							
									SIMD_FORCE_INLINE	unsigned int getHash()const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										const bool VOID_IS_8 = ((sizeof(void*)==8));
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										unsigned int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
							 | 
						||
| 
								 | 
							
										// Thomas Wang's hash
							 | 
						||
| 
								 | 
							
										key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
							 | 
						||
| 
								 | 
							
										return key;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class Value>
							 | 
						||
| 
								 | 
							
								class btHashKeyPtr
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								        int     m_uid;
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        btHashKeyPtr(int uid)    :m_uid(uid)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        int     getUid1() const
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								                return m_uid;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        bool equals(const btHashKeyPtr<Value>& other) const
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								                return getUid1() == other.getUid1();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        //to our success
							 | 
						||
| 
								 | 
							
								        SIMD_FORCE_INLINE       unsigned int getHash()const
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								                unsigned int key = m_uid;
							 | 
						||
| 
								 | 
							
								                // Thomas Wang's hash
							 | 
						||
| 
								 | 
							
								                key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
							 | 
						||
| 
								 | 
							
								                return key;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class Value>
							 | 
						||
| 
								 | 
							
								class btHashKey
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									int	m_uid;
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									btHashKey(int uid)	:m_uid(uid)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int	getUid1() const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return m_uid;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									bool equals(const btHashKey<Value>& other) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return getUid1() == other.getUid1();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									//to our success
							 | 
						||
| 
								 | 
							
									SIMD_FORCE_INLINE	unsigned int getHash()const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										unsigned int key = m_uid;
							 | 
						||
| 
								 | 
							
										// Thomas Wang's hash
							 | 
						||
| 
								 | 
							
										key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
							 | 
						||
| 
								 | 
							
										return key;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								///The btHashMap template class implements a generic and lightweight hashmap.
							 | 
						||
| 
								 | 
							
								///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
							 | 
						||
| 
								 | 
							
								template <class Key, class Value>
							 | 
						||
| 
								 | 
							
								class btHashMap
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								protected:
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<int>		m_hashTable;
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<int>		m_next;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<Value>		m_valueArray;
							 | 
						||
| 
								 | 
							
									btAlignedObjectArray<Key>		m_keyArray;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void	growTables(const Key& /*key*/)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int newCapacity = m_valueArray.capacity();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (m_hashTable.size() < newCapacity)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											//grow hashtable and next table
							 | 
						||
| 
								 | 
							
											int curHashtableSize = m_hashTable.size();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											m_hashTable.resize(newCapacity);
							 | 
						||
| 
								 | 
							
											m_next.resize(newCapacity);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											int i;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for (i= 0; i < newCapacity; ++i)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												m_hashTable[i] = BT_HASH_NULL;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											for (i = 0; i < newCapacity; ++i)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												m_next[i] = BT_HASH_NULL;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for(i=0;i<curHashtableSize;i++)
							 | 
						||
| 
								 | 
							
											{
							 | 
						||
| 
								 | 
							
												//const Value& value = m_valueArray[i];
							 | 
						||
| 
								 | 
							
												//const Key& key = m_keyArray[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												int	hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1);	// New hash value with new mask
							 | 
						||
| 
								 | 
							
												m_next[i] = m_hashTable[hashValue];
							 | 
						||
| 
								 | 
							
												m_hashTable[hashValue] = i;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void insert(const Key& key, const Value& value) {
							 | 
						||
| 
								 | 
							
										int hash = key.getHash() & (m_valueArray.capacity()-1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										//replace value if the key is already there
							 | 
						||
| 
								 | 
							
										int index = findIndex(key);
							 | 
						||
| 
								 | 
							
										if (index != BT_HASH_NULL)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											m_valueArray[index]=value;
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int count = m_valueArray.size();
							 | 
						||
| 
								 | 
							
										int oldCapacity = m_valueArray.capacity();
							 | 
						||
| 
								 | 
							
										m_valueArray.push_back(value);
							 | 
						||
| 
								 | 
							
										m_keyArray.push_back(key);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int newCapacity = m_valueArray.capacity();
							 | 
						||
| 
								 | 
							
										if (oldCapacity < newCapacity)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											growTables(key);
							 | 
						||
| 
								 | 
							
											//hash with new capacity
							 | 
						||
| 
								 | 
							
											hash = key.getHash() & (m_valueArray.capacity()-1);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										m_next[count] = m_hashTable[hash];
							 | 
						||
| 
								 | 
							
										m_hashTable[hash] = count;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void remove(const Key& key) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int hash = key.getHash() & (m_valueArray.capacity()-1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int pairIndex = findIndex(key);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										if (pairIndex ==BT_HASH_NULL)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Remove the pair from the hash table.
							 | 
						||
| 
								 | 
							
										int index = m_hashTable[hash];
							 | 
						||
| 
								 | 
							
										btAssert(index != BT_HASH_NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int previous = BT_HASH_NULL;
							 | 
						||
| 
								 | 
							
										while (index != pairIndex)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											previous = index;
							 | 
						||
| 
								 | 
							
											index = m_next[index];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (previous != BT_HASH_NULL)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btAssert(m_next[previous] == pairIndex);
							 | 
						||
| 
								 | 
							
											m_next[previous] = m_next[pairIndex];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											m_hashTable[hash] = m_next[pairIndex];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// We now move the last pair into spot of the
							 | 
						||
| 
								 | 
							
										// pair being removed. We need to fix the hash
							 | 
						||
| 
								 | 
							
										// table indices to support the move.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int lastPairIndex = m_valueArray.size() - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// If the removed pair is the last pair, we are done.
							 | 
						||
| 
								 | 
							
										if (lastPairIndex == pairIndex)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											m_valueArray.pop_back();
							 | 
						||
| 
								 | 
							
											m_keyArray.pop_back();
							 | 
						||
| 
								 | 
							
											return;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Remove the last pair from the hash table.
							 | 
						||
| 
								 | 
							
										int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										index = m_hashTable[lastHash];
							 | 
						||
| 
								 | 
							
										btAssert(index != BT_HASH_NULL);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										previous = BT_HASH_NULL;
							 | 
						||
| 
								 | 
							
										while (index != lastPairIndex)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											previous = index;
							 | 
						||
| 
								 | 
							
											index = m_next[index];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (previous != BT_HASH_NULL)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											btAssert(m_next[previous] == lastPairIndex);
							 | 
						||
| 
								 | 
							
											m_next[previous] = m_next[lastPairIndex];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										else
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											m_hashTable[lastHash] = m_next[lastPairIndex];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Copy the last pair into the remove pair's spot.
							 | 
						||
| 
								 | 
							
										m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
							 | 
						||
| 
								 | 
							
										m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Insert the last pair into the hash table
							 | 
						||
| 
								 | 
							
										m_next[pairIndex] = m_hashTable[lastHash];
							 | 
						||
| 
								 | 
							
										m_hashTable[lastHash] = pairIndex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										m_valueArray.pop_back();
							 | 
						||
| 
								 | 
							
										m_keyArray.pop_back();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int size() const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return m_valueArray.size();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const Value* getAtIndex(int index) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btAssert(index < m_valueArray.size());
							 | 
						||
| 
								 | 
							
										btAssert(index>=0);
							 | 
						||
| 
								 | 
							
										if (index>=0 && index < m_valueArray.size())
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return &m_valueArray[index];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Value* getAtIndex(int index)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										btAssert(index < m_valueArray.size());
							 | 
						||
| 
								 | 
							
										btAssert(index>=0);
							 | 
						||
| 
								 | 
							
										if (index>=0 && index < m_valueArray.size())
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return &m_valueArray[index];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return 0;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Key getKeyAtIndex(int index)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        btAssert(index < m_keyArray.size());
							 | 
						||
| 
								 | 
							
										btAssert(index>=0);
							 | 
						||
| 
								 | 
							
										return m_keyArray[index];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    const Key getKeyAtIndex(int index) const
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        btAssert(index < m_keyArray.size());
							 | 
						||
| 
								 | 
							
										btAssert(index>=0);
							 | 
						||
| 
								 | 
							
										return m_keyArray[index];
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Value* operator[](const Key& key) {
							 | 
						||
| 
								 | 
							
										return find(key);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const Value* operator[](const Key& key) const {
							 | 
						||
| 
								 | 
							
										return find(key);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									const Value*	find(const Key& key) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int index = findIndex(key);
							 | 
						||
| 
								 | 
							
										if (index == BT_HASH_NULL)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return NULL;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return &m_valueArray[index];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Value*	find(const Key& key)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										int index = findIndex(key);
							 | 
						||
| 
								 | 
							
										if (index == BT_HASH_NULL)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return NULL;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return &m_valueArray[index];
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int	findIndex(const Key& key) const
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if (hash >= (unsigned int)m_hashTable.size())
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return BT_HASH_NULL;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										int index = m_hashTable[hash];
							 | 
						||
| 
								 | 
							
										while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											index = m_next[index];
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return index;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									void	clear()
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										m_hashTable.clear();
							 | 
						||
| 
								 | 
							
										m_next.clear();
							 | 
						||
| 
								 | 
							
										m_valueArray.clear();
							 | 
						||
| 
								 | 
							
										m_keyArray.clear();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif //BT_HASH_MAP_H
							 |