mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
201
IDEHelper/StrHashMap.h
Normal file
201
IDEHelper/StrHashMap.h
Normal file
|
@ -0,0 +1,201 @@
|
|||
#pragma once
|
||||
|
||||
#include "DebugCommon.h"
|
||||
#include "BeefySysLib/util/BumpAllocator.h"
|
||||
|
||||
NS_BF_DBG_BEGIN
|
||||
|
||||
template <typename T>
|
||||
class StrHashMap
|
||||
{
|
||||
public:
|
||||
struct Entry
|
||||
{
|
||||
T mValue;
|
||||
Entry* mNext;
|
||||
int mHash;
|
||||
};
|
||||
|
||||
struct Iterator
|
||||
{
|
||||
public:
|
||||
StrHashMap* mMap;
|
||||
Entry* mCurEntry;
|
||||
int mCurBucket;
|
||||
|
||||
public:
|
||||
Iterator(StrHashMap* map)
|
||||
{
|
||||
mMap = map;
|
||||
mCurBucket = 0;
|
||||
mCurEntry = NULL;
|
||||
}
|
||||
|
||||
Iterator& operator++()
|
||||
{
|
||||
if (mCurEntry != NULL)
|
||||
{
|
||||
mCurEntry = mCurEntry->mNext;
|
||||
if (mCurEntry != NULL)
|
||||
return *this;
|
||||
mCurBucket++;
|
||||
}
|
||||
|
||||
if (mMap->mHashHeads == NULL)
|
||||
return *this; // At end
|
||||
|
||||
while (mCurBucket < mMap->mHashSize)
|
||||
{
|
||||
mCurEntry = mMap->mHashHeads[mCurBucket];
|
||||
if (mCurEntry != NULL)
|
||||
return *this;
|
||||
mCurBucket++;
|
||||
}
|
||||
|
||||
return *this; // At end
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& itr) const
|
||||
{
|
||||
return ((itr.mCurEntry != mCurEntry) || (itr.mCurBucket != mCurBucket));
|
||||
}
|
||||
|
||||
Entry* operator*()
|
||||
{
|
||||
return mCurEntry;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
int GetHash(const char* str)
|
||||
{
|
||||
int curHash = 0;
|
||||
const char* curHashPtr = str;
|
||||
while (*curHashPtr != 0)
|
||||
{
|
||||
char c = *curHashPtr;
|
||||
if (c != ' ')
|
||||
curHash = ((curHash ^ *curHashPtr) << 5) - curHash;
|
||||
curHashPtr++;
|
||||
}
|
||||
return curHash & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
bool StrEqual(const char* strA, const char* strB)
|
||||
{
|
||||
const char* ptrA = strA;
|
||||
const char* ptrB = strB;
|
||||
|
||||
while (true)
|
||||
{
|
||||
char ca;
|
||||
do { ca = *(strA++); } while (ca == ' ');
|
||||
char cb;
|
||||
do { cb = *(strB++); } while (cb == ' ');
|
||||
if (ca != cb)
|
||||
return false;
|
||||
if (ca == '\0')
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
Beefy::BumpAllocator mAlloc;
|
||||
Entry** mHashHeads;
|
||||
int mHashSize;
|
||||
int mCount;
|
||||
|
||||
public:
|
||||
StrHashMap()
|
||||
{
|
||||
mHashHeads = NULL;
|
||||
mHashSize = 9973;
|
||||
mCount = 0;
|
||||
}
|
||||
|
||||
void Insert(T value)
|
||||
{
|
||||
if (mHashHeads == NULL)
|
||||
mHashHeads = (Entry**)mAlloc.AllocBytes(sizeof(Entry*) * mHashSize, alignof(Entry*));
|
||||
|
||||
int hash = GetHash(value->mName);
|
||||
int hashIdx = hash % mHashSize;
|
||||
Entry* headEntry = mHashHeads[hashIdx];
|
||||
|
||||
Entry* newEntry = mAlloc.Alloc<Entry>();
|
||||
newEntry->mValue = value;
|
||||
newEntry->mNext = headEntry;
|
||||
newEntry->mHash = hash;
|
||||
mCount++;
|
||||
|
||||
mHashHeads[hashIdx] = newEntry;
|
||||
}
|
||||
|
||||
void Rehash(int newHashSize)
|
||||
{
|
||||
auto newHashHeads = (Entry**)mAlloc.AllocBytes(sizeof(Entry*) * newHashSize, alignof(Entry*));
|
||||
|
||||
for (int hashIdx = 0; hashIdx < mHashSize; hashIdx++)
|
||||
{
|
||||
Entry* checkEntry = mHashHeads[hashIdx];
|
||||
while (checkEntry != NULL)
|
||||
{
|
||||
auto nextEntry = checkEntry->mNext;
|
||||
int newHashIdx = checkEntry->mHash % newHashSize;
|
||||
checkEntry->mNext = newHashHeads[newHashIdx];
|
||||
newHashHeads[newHashIdx] = checkEntry;
|
||||
|
||||
checkEntry = nextEntry;
|
||||
}
|
||||
}
|
||||
|
||||
mHashHeads = newHashHeads;
|
||||
mHashSize = newHashSize;
|
||||
}
|
||||
|
||||
Entry* Find(const char* name)
|
||||
{
|
||||
if (mHashHeads == NULL)
|
||||
return NULL;
|
||||
|
||||
// Make the lookup load reasonable
|
||||
if (mHashSize < mCount / 2)
|
||||
{
|
||||
Rehash(mCount / 2 + 123);
|
||||
}
|
||||
|
||||
int hash = GetHash(name);
|
||||
int hashIdx = hash % mHashSize;
|
||||
Entry* checkEntry = mHashHeads[hashIdx];
|
||||
while (checkEntry != NULL)
|
||||
{
|
||||
if ((checkEntry->mHash == hash) && (StrEqual(name, checkEntry->mValue->mName)))
|
||||
return checkEntry;
|
||||
checkEntry = checkEntry->mNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mHashSize = 9973;
|
||||
mHashHeads = NULL;
|
||||
mAlloc.Clear();
|
||||
mCount = 0;
|
||||
}
|
||||
|
||||
Iterator begin()
|
||||
{
|
||||
return ++Iterator(this);
|
||||
}
|
||||
|
||||
Iterator end()
|
||||
{
|
||||
Iterator itr(this);
|
||||
itr.mCurBucket = mHashSize;
|
||||
return itr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
NS_BF_DBG_END
|
Loading…
Add table
Add a link
Reference in a new issue