hostile-takeover/game/hashtablecode.cpp
2016-08-31 23:55:30 -04:00

131 lines
2.7 KiB
C++

#include "ht.h"
HashTableCode ghstCode;
// CacheEntry for TBitmapCode code that also understands how to be part of a hash table
void HashEntryCode::Discard()
{
CacheEntry::Discard();
ghstCode.FreeEntry(this);
}
#define kcHashEntries 1024 // must be power of 2
#define kwIndexMask (kcHashEntries - 1)
HashTableCode::HashTableCode()
{
m_aphec = NULL;
m_phecFree = NULL;
}
HashTableCode::~HashTableCode()
{
Assert(m_aphec == NULL);
Assert(m_phecFree == NULL);
}
bool HashTableCode::Init()
{
m_aphec = new HashEntryCode *[kcHashEntries];
Assert(m_aphec != NULL);
if (m_aphec == NULL)
return false;
memset(m_aphec, 0, sizeof(HashEntryCode *) * kcHashEntries);
return true;
}
void HashTableCode::Exit()
{
DiscardHashEntries();
delete[] m_aphec;
m_aphec = NULL;
// Free free list entries
HashEntryCode *phec = m_phecFree;
while (phec != NULL) {
HashEntryCode *phecNext = phec->m_phecNext;
delete phec;
phec = phecNext;
}
m_phecFree = NULL;
}
void HashTableCode::DiscardHashEntries()
{
// Free hash table entries
for (int i = 0; i < kcHashEntries; i++) {
while (m_aphec[i] != NULL)
m_aphec[i]->Discard();
}
}
void HashTableCode::FreeEntry(HashEntryCode *phec)
{
HashEntryCode **pphec = &m_aphec[(int)(phec->m_hk & kwIndexMask)];
for (; (*pphec) != NULL; pphec = &(*pphec)->m_phecNext) {
if (*pphec == phec) {
*pphec = phec->m_phecNext;
phec->m_phecNext = m_phecFree;
m_phecFree = phec;
return;
}
}
Assert(false);
}
HashEntryCode *HashTableCode::FindEntry(dword hkName, int x, int y, int cx, int cy, bool fOdd)
{
// Try to find it
//dword hk = hkName ^ (cy << (y & 7)) + (y << (cy & 7)) + (cx << (x & 7)) + (x << (cx & 7)) + (fEven ? 0x5050 : 0);
dword hk = hkName ^ ((y << 8) + cy) + ((x << 8) + cx) + (fOdd ? 0x5050 : 0);
HashEntryCode *phec = m_aphec[(int)(hk & kwIndexMask)];
for (; phec != NULL; phec = phec->m_phecNext) {
if (phec->m_hk != hk)
continue;
if (fOdd == phec->m_fOdd && x == phec->m_x && y == phec->m_y && cx == phec->m_cx && cy == phec->m_cy)
return phec;
// This is a legal condition, but the assert is to notify me of collision.
//Assert(false);
}
// Can't find it, so create it
// Alloc entry
if (m_phecFree != NULL) {
phec = m_phecFree;
m_phecFree = phec->m_phecNext;
} else {
phec = new HashEntryCode;
if (phec == NULL)
return NULL;
}
// Init
phec->m_x = x;
phec->m_y = y;
phec->m_cx = cx;
phec->m_cy = cy;
phec->m_fOdd = fOdd;
phec->m_hk = hk;
// Add to table
HashEntryCode **pphec = &m_aphec[(int)(phec->m_hk & kwIndexMask)];
if (*pphec != NULL) {
phec->m_phecNext = *pphec;
} else {
phec->m_phecNext = NULL;
}
*pphec = phec;
// Add to cache
gcam.Add((CacheEntry *)phec);
return phec;
}