#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 = *(unsigned char *)src - *(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(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 { 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; 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)); 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 btHashKeyPtr { int m_uid; public: btHashKeyPtr(int uid) :m_uid(uid) { } int getUid1() const { return m_uid; } bool equals(const btHashKeyPtr& other) const { return getUid1() == other.getUid1(); } //to our success SIMD_FORCE_INLINE unsigned int getHash()const { 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 btHashKey { int m_uid; public: btHashKey(int uid) :m_uid(uid) { } int getUid1() const { return m_uid; } bool equals(const btHashKey& other) const { return getUid1() == other.getUid1(); } //to our success SIMD_FORCE_INLINE unsigned int getHash()const { 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 btHashMap { protected: btAlignedObjectArray m_hashTable; btAlignedObjectArray m_next; btAlignedObjectArray m_valueArray; btAlignedObjectArray 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= (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