mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
288 lines
8.3 KiB
C++
288 lines
8.3 KiB
C++
/*****************************************************************************/
|
|
/* Map.cpp Copyright (c) Ladislav Zezula 2014 */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Implementation of map for CascLib */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Date Ver Who Comment */
|
|
/* -------- ---- --- ------- */
|
|
/* 10.06.14 1.00 Lad The first version of Map.cpp */
|
|
/*****************************************************************************/
|
|
|
|
#define __CASCLIB_SELF__
|
|
#include "../CascLib.h"
|
|
#include "../CascCommon.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local functions
|
|
|
|
// Returns the extension, right after "."
|
|
static const char * String_GetExtension(const char * szString)
|
|
{
|
|
const char * szExtension = strrchr(szString, '.');
|
|
return (szExtension != NULL) ? szExtension + 1 : NULL;
|
|
}
|
|
|
|
static DWORD CalcHashIndex_Key(PCASC_MAP pMap, void * pvKey)
|
|
{
|
|
LPBYTE pbKey = (LPBYTE)pvKey;
|
|
DWORD dwHash = 0x7EEE7EEE;
|
|
|
|
// Construct the hash from the first 8 digits
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[0];
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[1];
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[2];
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[3];
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[4];
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[5];
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[6];
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ pbKey[7];
|
|
|
|
// Return the hash limited by the table size
|
|
return (dwHash % pMap->TableSize);
|
|
}
|
|
|
|
static DWORD CalcHashIndex_String(PCASC_MAP pMap, const char * szString, const char * szStringEnd)
|
|
{
|
|
LPBYTE pbKeyEnd = (LPBYTE)szStringEnd;
|
|
LPBYTE pbKey = (LPBYTE)szString;
|
|
DWORD dwHash = 0x7EEE7EEE;
|
|
|
|
// Hash the string itself
|
|
while(pbKey < pbKeyEnd)
|
|
{
|
|
dwHash = (dwHash >> 24) ^ (dwHash << 5) ^ dwHash ^ AsciiToUpperTable_BkSlash[pbKey[0]];
|
|
pbKey++;
|
|
}
|
|
|
|
// Return the hash limited by the table size
|
|
return (dwHash % pMap->TableSize);
|
|
}
|
|
|
|
static bool CompareObject_Key(PCASC_MAP pMap, void * pvObject, void * pvKey)
|
|
{
|
|
LPBYTE pbObjectKey = (LPBYTE)pvObject + pMap->KeyOffset;
|
|
|
|
return (memcmp(pbObjectKey, pvKey, pMap->KeyLength) == 0);
|
|
}
|
|
|
|
static bool CompareObject_String(
|
|
PCASC_MAP pMap,
|
|
const char * szExistingString,
|
|
const char * szString,
|
|
const char * szStringEnd)
|
|
{
|
|
// Keep compiler happy
|
|
CASCLIB_UNUSED(pMap);
|
|
|
|
// Compare the whole part, case insensitive
|
|
while(szString < szStringEnd)
|
|
{
|
|
if(AsciiToUpperTable_BkSlash[*szExistingString] != AsciiToUpperTable_BkSlash[*szString])
|
|
return false;
|
|
|
|
szExistingString++;
|
|
szString++;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Public functions
|
|
|
|
PCASC_MAP Map_Create(DWORD dwMaxItems, DWORD dwKeyLength, DWORD dwKeyOffset)
|
|
{
|
|
PCASC_MAP pMap;
|
|
size_t cbToAllocate;
|
|
size_t dwTableSize;
|
|
|
|
// Calculate the size of the table
|
|
dwTableSize = (dwMaxItems * 3 / 2) | 0x01;
|
|
|
|
// Allocate new map for the objects
|
|
cbToAllocate = sizeof(CASC_MAP) + (dwTableSize * sizeof(void *));
|
|
pMap = (PCASC_MAP)CASC_ALLOC(LPBYTE, cbToAllocate);
|
|
if(pMap != NULL)
|
|
{
|
|
memset(pMap, 0, cbToAllocate);
|
|
pMap->KeyLength = dwKeyLength;
|
|
pMap->TableSize = dwTableSize;
|
|
pMap->KeyOffset = dwKeyOffset;
|
|
}
|
|
|
|
// Return the allocated map
|
|
return pMap;
|
|
}
|
|
|
|
size_t Map_EnumObjects(PCASC_MAP pMap, void **ppvArray)
|
|
{
|
|
size_t nIndex = 0;
|
|
|
|
// Verify pointer to the map
|
|
if(pMap != NULL && ppvArray != NULL)
|
|
{
|
|
// Enumerate all items in main table
|
|
for(size_t i = 0; i < pMap->TableSize; i++)
|
|
{
|
|
// Is that cell valid?
|
|
if(pMap->HashTable[i] != NULL)
|
|
{
|
|
ppvArray[nIndex++] = pMap->HashTable[i];
|
|
}
|
|
}
|
|
|
|
return pMap->ItemCount;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void * Map_FindObject(PCASC_MAP pMap, void * pvKey, PDWORD PtrIndex)
|
|
{
|
|
void * pvObject;
|
|
DWORD dwHashIndex;
|
|
|
|
// Verify pointer to the map
|
|
if(pMap != NULL)
|
|
{
|
|
// Construct the main index
|
|
dwHashIndex = CalcHashIndex_Key(pMap, pvKey);
|
|
while(pMap->HashTable[dwHashIndex] != NULL)
|
|
{
|
|
// Get the pointer at that position
|
|
pvObject = pMap->HashTable[dwHashIndex];
|
|
|
|
// Compare the hash
|
|
if(CompareObject_Key(pMap, pvObject, pvKey))
|
|
{
|
|
if(PtrIndex != NULL)
|
|
PtrIndex[0] = dwHashIndex;
|
|
return pvObject;
|
|
}
|
|
|
|
// Move to the next entry
|
|
dwHashIndex = (dwHashIndex + 1) % pMap->TableSize;
|
|
}
|
|
}
|
|
|
|
// Not found, sorry
|
|
return NULL;
|
|
}
|
|
|
|
bool Map_InsertObject(PCASC_MAP pMap, void * pvNewObject, void * pvKey)
|
|
{
|
|
void * pvExistingObject;
|
|
DWORD dwHashIndex;
|
|
|
|
// Verify pointer to the map
|
|
if(pMap != NULL)
|
|
{
|
|
// Limit check
|
|
if((pMap->ItemCount + 1) >= pMap->TableSize)
|
|
return false;
|
|
|
|
// Construct the hash index
|
|
dwHashIndex = CalcHashIndex_Key(pMap, pvKey);
|
|
while(pMap->HashTable[dwHashIndex] != NULL)
|
|
{
|
|
// Get the pointer at that position
|
|
pvExistingObject = pMap->HashTable[dwHashIndex];
|
|
|
|
// Check if hash being inserted conflicts with an existing hash
|
|
if(CompareObject_Key(pMap, pvExistingObject, pvKey))
|
|
return false;
|
|
|
|
// Move to the next entry
|
|
dwHashIndex = (dwHashIndex + 1) % pMap->TableSize;
|
|
}
|
|
|
|
// Insert at that position
|
|
pMap->HashTable[dwHashIndex] = pvNewObject;
|
|
pMap->ItemCount++;
|
|
return true;
|
|
}
|
|
|
|
// Failed
|
|
return false;
|
|
}
|
|
|
|
bool Map_InsertString(PCASC_MAP pMap, const char * szString, bool bCutExtension)
|
|
{
|
|
const char * szExistingString;
|
|
const char * szStringEnd = NULL;
|
|
DWORD dwHashIndex;
|
|
|
|
// Verify pointer to the map
|
|
if(pMap != NULL)
|
|
{
|
|
// Limit check
|
|
if((pMap->ItemCount + 1) >= pMap->TableSize)
|
|
return false;
|
|
|
|
// Retrieve the length of the string without extension
|
|
if(bCutExtension)
|
|
szStringEnd = String_GetExtension(szString);
|
|
if(szStringEnd == NULL)
|
|
szStringEnd = szString + strlen(szString);
|
|
|
|
// Construct the hash index
|
|
dwHashIndex = CalcHashIndex_String(pMap, szString, szStringEnd);
|
|
while(pMap->HashTable[dwHashIndex] != NULL)
|
|
{
|
|
// Get the pointer at that position
|
|
szExistingString = (const char *)pMap->HashTable[dwHashIndex];
|
|
|
|
// Check if hash being inserted conflicts with an existing hash
|
|
if(CompareObject_String(pMap, szExistingString, szString, szStringEnd))
|
|
return false;
|
|
|
|
// Move to the next entry
|
|
dwHashIndex = (dwHashIndex + 1) % pMap->TableSize;
|
|
}
|
|
|
|
// Insert at that position
|
|
pMap->HashTable[dwHashIndex] = (void *)szString;
|
|
pMap->ItemCount++;
|
|
return true;
|
|
}
|
|
|
|
// Failed
|
|
return false;
|
|
}
|
|
|
|
const char * Map_FindString(PCASC_MAP pMap, const char * szString, const char * szStringEnd)
|
|
{
|
|
const char * szExistingString;
|
|
DWORD dwHashIndex;
|
|
|
|
// Verify pointer to the map
|
|
if(pMap != NULL)
|
|
{
|
|
// Construct the main index
|
|
dwHashIndex = CalcHashIndex_String(pMap, szString, szStringEnd);
|
|
while(pMap->HashTable[dwHashIndex] != NULL)
|
|
{
|
|
// Get the pointer at that position
|
|
szExistingString = (const char *)pMap->HashTable[dwHashIndex];
|
|
|
|
// Compare the hash
|
|
if(CompareObject_String(pMap, szExistingString, szString, szStringEnd))
|
|
return szExistingString;
|
|
|
|
// Move to the next entry
|
|
dwHashIndex = (dwHashIndex + 1) % pMap->TableSize;
|
|
}
|
|
}
|
|
|
|
// Not found, sorry
|
|
return NULL;
|
|
}
|
|
|
|
void Map_Free(PCASC_MAP pMap)
|
|
{
|
|
if(pMap != NULL)
|
|
{
|
|
CASC_FREE(pMap);
|
|
}
|
|
}
|