Added minor utility method for btHashMap, btHashString
This commit is contained in:
@@ -3,6 +3,59 @@
|
|||||||
|
|
||||||
#include "btAlignedObjectArray.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 = 2166136261;
|
||||||
|
static const unsigned int FNVMultiple = 16777619;
|
||||||
|
|
||||||
|
/* 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
const 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;
|
const int BT_HASH_NULL=0xffffffff;
|
||||||
|
|
||||||
template <class Value>
|
template <class Value>
|
||||||
@@ -16,11 +69,15 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int getUid() const
|
int getUid1() const
|
||||||
{
|
{
|
||||||
return m_uid;
|
return m_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool equals(const btHashKey<Value>& other) const
|
||||||
|
{
|
||||||
|
return getUid1() == other.getUid1();
|
||||||
|
}
|
||||||
//to our success
|
//to our success
|
||||||
SIMD_FORCE_INLINE unsigned int getHash()const
|
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||||
{
|
{
|
||||||
@@ -35,10 +92,7 @@ public:
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
btHashKey getKey(const Value& value) const
|
|
||||||
{
|
|
||||||
return btHashKey(value.getUid());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -53,11 +107,16 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int getUid() const
|
int getUid1() const
|
||||||
{
|
{
|
||||||
return m_uid;
|
return m_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool equals(const btHashKeyPtr<Value>& other) const
|
||||||
|
{
|
||||||
|
return getUid1() == other.getUid1();
|
||||||
|
}
|
||||||
|
|
||||||
//to our success
|
//to our success
|
||||||
SIMD_FORCE_INLINE unsigned int getHash()const
|
SIMD_FORCE_INLINE unsigned int getHash()const
|
||||||
{
|
{
|
||||||
@@ -72,10 +131,7 @@ public:
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
btHashKeyPtr getKey(const Value& value) const
|
|
||||||
{
|
|
||||||
return btHashKeyPtr(value->getUid());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
///The btHashMap template class implements a generic and lightweight hashmap.
|
///The btHashMap template class implements a generic and lightweight hashmap.
|
||||||
@@ -86,9 +142,9 @@ class btHashMap
|
|||||||
|
|
||||||
btAlignedObjectArray<int> m_hashTable;
|
btAlignedObjectArray<int> m_hashTable;
|
||||||
btAlignedObjectArray<int> m_next;
|
btAlignedObjectArray<int> m_next;
|
||||||
|
|
||||||
btAlignedObjectArray<Value> m_valueArray;
|
btAlignedObjectArray<Value> m_valueArray;
|
||||||
|
btAlignedObjectArray<Key> m_keyArray;
|
||||||
|
|
||||||
|
|
||||||
void growTables(const Key& key)
|
void growTables(const Key& key)
|
||||||
{
|
{
|
||||||
@@ -116,8 +172,9 @@ class btHashMap
|
|||||||
for(i=0;i<curHashtableSize;i++)
|
for(i=0;i<curHashtableSize;i++)
|
||||||
{
|
{
|
||||||
const Value& value = m_valueArray[i];
|
const Value& value = m_valueArray[i];
|
||||||
|
const Key& key = m_keyArray[i];
|
||||||
|
|
||||||
int hashValue = key.getKey(value).getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
|
int hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1); // New hash value with new mask
|
||||||
m_next[i] = m_hashTable[hashValue];
|
m_next[i] = m_hashTable[hashValue];
|
||||||
m_hashTable[hashValue] = i;
|
m_hashTable[hashValue] = i;
|
||||||
}
|
}
|
||||||
@@ -130,14 +187,20 @@ class btHashMap
|
|||||||
|
|
||||||
void insert(const Key& key, const Value& value) {
|
void insert(const Key& key, const Value& value) {
|
||||||
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||||
//don't add it if it is already there
|
|
||||||
if (find(key))
|
//replace value if the key is already there
|
||||||
|
int index = findIndex(key);
|
||||||
|
if (index != BT_HASH_NULL)
|
||||||
{
|
{
|
||||||
|
m_valueArray[index]=value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int count = m_valueArray.size();
|
int count = m_valueArray.size();
|
||||||
int oldCapacity = m_valueArray.capacity();
|
int oldCapacity = m_valueArray.capacity();
|
||||||
m_valueArray.push_back(value);
|
m_valueArray.push_back(value);
|
||||||
|
m_keyArray.push_back(key);
|
||||||
|
|
||||||
int newCapacity = m_valueArray.capacity();
|
int newCapacity = m_valueArray.capacity();
|
||||||
if (oldCapacity < newCapacity)
|
if (oldCapacity < newCapacity)
|
||||||
{
|
{
|
||||||
@@ -191,12 +254,13 @@ class btHashMap
|
|||||||
if (lastPairIndex == pairIndex)
|
if (lastPairIndex == pairIndex)
|
||||||
{
|
{
|
||||||
m_valueArray.pop_back();
|
m_valueArray.pop_back();
|
||||||
|
m_keyArray.pop_back();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the last pair from the hash table.
|
// Remove the last pair from the hash table.
|
||||||
const Value* lastValue = &m_valueArray[lastPairIndex];
|
const Value* lastValue = &m_valueArray[lastPairIndex];
|
||||||
int lastHash = key.getKey(*lastValue).getHash() & (m_valueArray.capacity()-1);
|
int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
|
||||||
|
|
||||||
index = m_hashTable[lastHash];
|
index = m_hashTable[lastHash];
|
||||||
btAssert(index != BT_HASH_NULL);
|
btAssert(index != BT_HASH_NULL);
|
||||||
@@ -220,12 +284,14 @@ class btHashMap
|
|||||||
|
|
||||||
// Copy the last pair into the remove pair's spot.
|
// Copy the last pair into the remove pair's spot.
|
||||||
m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
|
m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
|
||||||
|
m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
|
||||||
|
|
||||||
// Insert the last pair into the hash table
|
// Insert the last pair into the hash table
|
||||||
m_next[pairIndex] = m_hashTable[lastHash];
|
m_next[pairIndex] = m_hashTable[lastHash];
|
||||||
m_hashTable[lastHash] = pairIndex;
|
m_hashTable[lastHash] = pairIndex;
|
||||||
|
|
||||||
m_valueArray.pop_back();
|
m_valueArray.pop_back();
|
||||||
|
m_keyArray.pop_back();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,15 +342,15 @@ class btHashMap
|
|||||||
|
|
||||||
int findIndex(const Key& key) const
|
int findIndex(const Key& key) const
|
||||||
{
|
{
|
||||||
int hash = key.getHash() & (m_valueArray.capacity()-1);
|
unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
|
||||||
|
|
||||||
if (hash >= m_hashTable.size())
|
if (hash >= (unsigned int)m_hashTable.size())
|
||||||
{
|
{
|
||||||
return BT_HASH_NULL;
|
return BT_HASH_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int index = m_hashTable[hash];
|
int index = m_hashTable[hash];
|
||||||
while ((index != BT_HASH_NULL) && (key.getUid() == key.getKey(m_valueArray[index]).getUid()) == false)
|
while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
|
||||||
{
|
{
|
||||||
index = m_next[index];
|
index = m_next[index];
|
||||||
}
|
}
|
||||||
@@ -296,6 +362,7 @@ class btHashMap
|
|||||||
m_hashTable.clear();
|
m_hashTable.clear();
|
||||||
m_next.clear();
|
m_next.clear();
|
||||||
m_valueArray.clear();
|
m_valueArray.clear();
|
||||||
|
m_keyArray.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user