1
0
pl-libs/pl_ds.h

638 lines
26 KiB
C

/*
pl_ds.h
* data structures
*/
// library version
#define PL_DS_VERSION "0.5.2"
#define PL_DS_VERSION_NUM 00502
/*
Index of this file:
// [SECTION] documentation
// [SECTION] header mess
// [SECTION] includes
// [SECTION] forward declarations
// [SECTION] public api (stretchy buffer)
// [SECTION] public api (hashmap)
// [SECTION] internal
// [SECTION] public api implementation (hashmap)
*/
//-----------------------------------------------------------------------------
// [SECTION] documentation
//-----------------------------------------------------------------------------
/*
STRETCHY BUFFER (dynamic array)
pl_sb_capacity:
uint32_t pl_sb_capacity(T*);
Returns capacity (max number of items with current allocation)
pl_sb_size:
uint32_t pl_sb_size(T*);
Returns number of items in buffer
pl_sb_reserve:
void pl_sb_reserve(T*, n);
Reserves enough memory for n items
pl_sb_resize:
void pl_sb_resize(T*, n);
Changes size of buffer to n items.
pl_sb_pop:
T pl_sb_pop(T*);
Returns last item added to buffer and shrinks the buffer by 1(ensure buffer isn't empty!)
pl_sb_pop_n:
void pl_sb_pop_n(T*, uint32_t n);
Pops the last n items from the buffer (ensure buffer isn't empty!)
pl_sb_top:
T pl_sb_top(T*);
Returns last item added to buffer(ensure buffer isn't empty!)
pl_sb_back:
T pl_sb_back(T*);
Returns last item added to buffer(ensure buffer isn't empty!)
pl_sb_free:
void pl_sb_free(T*);
Frees memory held by buffer and sets pointer to NULL
pl_sb_reset:
void pl_sb_reset(T*)
Sets size of buffer back to zero without freeing any memory
pl_sb_end:
T* pl_sb_end(T*);
Returns a pointer to the end of the buffer (after the last item!)
pl_sb_add:
uint32_t pl_sb_add(T*);
Adds room for 1 more item and returns the index to that item
pl_sb_add_n:
uint32_t pl_sb_add_(T*, n);
Adds room for n more item and returns the index to the first new item
pl_sb_add_ptr:
T* pl_sb_add_ptr(T*);
Adds room for 1 more item and returns the pointer to it
pl_sb_add_ptr_n:
T* pl_sb_add_ptr_n(T*, n);
Adds room for n more item and returns the pointer to the first new item
pl_sb_push:
T pl_sb_push(T*, T);
Pushes an item into the buffer and returns a copy of it.
pl_sb_del:
void pl_sb_del(T*, i);
Deletes the ith item from the buffer (uses memmove)
pl_sb_del_n:
void pl_sb_del_n(T*, i, n);
Deletes n items starting at the ith index (uses memmove)
pl_sb_del_swap:
void pl_sb_del_swap(T*, i);
Deletes the ith item from the buffer (swaps with last item, so faster but doesn't preserve order)
pl_sb_insert:
void pl_sb_insert(T*, i, T);
Inserts new item v at the ith index (uses memmove)
pl_sb_insert_n:
void pl_sb_insert_n(T*, i, N);
Inserts n new items starting at the ith index (uses memmove)
pl_sb_sprintf:
void pl_sb_sprintf(char*, pcFormat, ...);
Inserts characters into a char stretchy buffer (similar to sprintf)
HASHMAPS
pl_hm_hash_str:
uint64_t pl_hm_hash_str(const char*);
Returns the CRC64 hash of a string.
pl_hm_hash:
uint64_t pl_hm_hash(const void* pData, size_t szDataSize, uint64_t uSeed);
Returns the CRC64 hash of some arbitrary data.
pl__hm_resize:
void pl__hm_resize(plHashMap*, uint32_t);
Resizes the hashmap or frees it if zero is used.
pl_hm_free:
void pl_hm_free(plHashMap*);
Frees the hashmap internal memory.
pl__hm_insert:
void pl__hm_insert(plHashMap*, uint64_t ulKey, uint64_t ulValue);
Adds an entry to the hashmap where ulKey is a hashed key (usually a string) and
ulValue is the index into the value array.
pl_hm_remove:
void pl_hm_remove(plHashMap*, uint64_t ulKey);
Removes an entry from the hashmap and adds the index to the free index list.
pl_hm_lookup:
uint64_t pl_hm_lookup(plHashMap*, uint64_t ulKey);
Returns the index into the value array if it already exists or UINT64_MAX if not.
pl_hm_get_free_index:
uint64_t pl_hm_get_free_index(plHashMap*);
Returns a free index if one exists or UINT64_MAX if not.
pl_hm_has_key:
bool pl_hm_has_key(plHashMap*, uint64_t);
Checks if key exists.
pl_hm_has_key_str:
bool pl_hm_has_key(plHashMap*, const char*);
Same as pl_hm_has_key but performs the hash for you.
pl__hm_insert_str:
void pl__hm_insert_str(plHashMap*, const char* pcKey, uint64_t ulValue);
Same as pl__hm_insert but performs the hash for you.
pl_hm_lookup_str:
uint64_t pl_hm_lookup_str(plHashMap*, const char* pcKey);
Same as pl_hm_lookup but performs the hash for you.
pl_hm_remove_str:
void pl_hm_remove_str(plHashMap*, const char* pcKey);
Same as pl_hm_remove but performs the hash for you.
COMPILE TIME OPTIONS
* Change allocators by defining both:
PL_LOG_ALLOC(x)
PL_LOG_FREE(x)
* Change initial hashmap size:
PL_DS_HASHMAP_INITIAL_SIZE (default is 256)
*/
//-----------------------------------------------------------------------------
// [SECTION] header mess
//-----------------------------------------------------------------------------
#ifndef PL_DS_H
#define PL_DS_H
#if defined(PL_DS_ALLOC) && defined(PL_DS_FREE) && defined(PL_DS_ALLOC_INDIRECT)
// ok
#elif !defined(PL_DS_ALLOC) && !defined(PL_DS_FREE) && !defined(PL_DS_ALLOC_INDIRECT)
// ok
#else
#error "Must define all or none of PL_DS_ALLOC and PL_DS_FREE and PL_DS_ALLOC_INDIRECT"
#endif
#ifndef PL_DS_ALLOC
#include <stdlib.h>
#define PL_DS_ALLOC(x) malloc((x))
#define PL_DS_ALLOC_INDIRECT(x, FILE, LINE) malloc((x))
#define PL_DS_FREE(x) free((x))
#endif
#ifndef PL_DS_ASSERT
#include <assert.h>
#define PL_DS_ASSERT(x) assert((x))
#endif
#ifndef PL_DS_HASHMAP_INITIAL_SIZE
#define PL_DS_HASHMAP_INITIAL_SIZE 256
#endif
//-----------------------------------------------------------------------------
// [SECTION] includes
//-----------------------------------------------------------------------------
#include <stdint.h> // uint32_t
#include <stdlib.h> // malloc, free
#include <string.h> // memset, memmove
#include <stdbool.h> // bool
#include <stdarg.h> // arg vars
#include <stdio.h> // vsprintf
//-----------------------------------------------------------------------------
// [SECTION] documentation
//-----------------------------------------------------------------------------
typedef struct _plHashMap
{
uint32_t _uItemCount;
uint32_t _uBucketCount;
uint64_t* _aulKeys; // stored keys used for rehashing during growth
uint64_t* _aulValueIndices; // indices into value array (user held)
uint64_t* _sbulFreeIndices; // free list of available indices
} plHashMap;
//-----------------------------------------------------------------------------
// [SECTION] public api (stretchy buffer)
//-----------------------------------------------------------------------------
#define pl_sb_capacity(buf) \
((buf) ? pl__sb_header((buf))->uCapacity : 0u)
#define pl_sb_size(buf) \
((buf) ? pl__sb_header((buf))->uSize : 0u)
#define pl_sb_pop(buf) \
(buf)[--pl__sb_header((buf))->uSize]
#define pl_sb_pop_n(buf, n) \
pl__sb_header((buf))->uSize-=(n)
#define pl_sb_top(buf) \
((buf)[pl__sb_header((buf))->uSize-1])
#define pl_sb_last(buf) \
pl_sb_top((buf))
#define pl_sb_free(buf) \
if((buf)){ PL_DS_FREE(pl__sb_header(buf));} (buf) = NULL;
#define pl_sb_reset(buf) \
if((buf)){ pl__sb_header((buf))->uSize = 0u;}
#define pl_sb_back(buf) \
pl_sb_top((buf))
#define pl_sb_end(buf) \
((buf) ? (buf) + pl__sb_header((buf))->uSize : (buf))
#define pl_sb_add_n(buf, n) \
(pl__sb_may_grow((buf), sizeof(*(buf)), (n), (n), __FILE__, __LINE__), (n) ? (pl__sb_header(buf)->uSize += (n), pl__sb_header(buf)->uSize - (n)) : pl_sb_size(buf))
#define pl_sb_add(buf) \
pl_sb_add_n((buf), 1)
#define pl_sb_add_ptr_n(buf, n) \
(pl__sb_may_grow((buf), sizeof(*(buf)), (n), (n), __FILE__, __LINE__), (n) ? (pl__sb_header(buf)->uSize += (n), &(buf)[pl__sb_header(buf)->uSize - (n)]) : (buf))
#define pl_sb_add_ptr(buf, n) \
pl_sb_add_ptr_n((buf), 1)
#define pl_sb_push(buf, v) \
(pl__sb_may_grow((buf), sizeof(*(buf)), 1, 8, __FILE__, __LINE__), (buf)[pl__sb_header((buf))->uSize++] = (v))
#define pl_sb_reserve(buf, n) \
(pl__sb_may_grow((buf), sizeof(*(buf)), (n), (n), __FILE__, __LINE__))
#define pl_sb_resize(buf, n) \
(pl__sb_may_grow((buf), sizeof(*(buf)), (n), (n), __FILE__, __LINE__), pl__sb_header((buf))->uSize = (n))
#define pl_sb_del_n(buf, i, n) \
(memmove(&(buf)[i], &(buf)[(i) + (n)], sizeof *(buf) * (pl__sb_header(buf)->uSize - (n) - (i))), pl__sb_header(buf)->uSize -= (n))
#define pl_sb_del(buf, i) \
pl_sb_del_n((buf), (i), 1)
#define pl_sb_del_swap(buf, i) \
((buf)[i] = pl_sb_last(buf), pl__sb_header(buf)->uSize -= 1)
#define pl_sb_insert_n(buf, i, n) \
(pl_sb_add_n((buf), (n)), memmove(&(buf)[(i) + (n)], &(buf)[i], sizeof *(buf) * (pl__sb_header(buf)->uSize - (n) - (i))))
#define pl_sb_insert(buf, i, v) \
(pl_sb_insert_n((buf), (i), 1), (buf)[i] = (v))
#define pl_sb_sprintf(buf, pcFormat, ...) \
pl__sb_sprintf(&(buf), (pcFormat), __VA_ARGS__)
//-----------------------------------------------------------------------------
// [SECTION] public api (hashmap)
//-----------------------------------------------------------------------------
#define pl_hm_resize(ptHashMap, uBucketCount) \
pl__hm_resize(ptHashMap, uBucketCount, __FILE__, __LINE__)
#define pl_hm_insert(ptHashMap, ulKey, ulValue) \
pl__hm_insert(ptHashMap, ulKey, ulValue, __FILE__, __LINE__)
#define pl_hm_insert_str(ptHashMap, pcKey, ulValue) \
pl__hm_insert_str(ptHashMap, pcKey, ulValue, __FILE__, __LINE__)
static inline void pl__hm_resize (plHashMap* ptHashMap, uint32_t uBucketCount, const char* pcFile, int iLine);
static inline void pl_hm_free (plHashMap* ptHashMap) { pl__hm_resize(ptHashMap, 0, "", 0);}
static inline void pl__hm_insert (plHashMap* ptHashMap, uint64_t ulKey, uint64_t ulValue, const char* pcFile, int iLine);
static inline void pl_hm_remove (plHashMap* ptHashMap, uint64_t ulKey);
static inline uint64_t pl_hm_lookup (plHashMap* ptHashMap, uint64_t ulKey);
static inline uint64_t pl_hm_get_free_index(plHashMap* ptHashMap);
static inline bool pl_hm_has_key (plHashMap* ptHashMap, uint64_t ulKey);
static inline uint64_t pl_hm_hash_str (const char* pcKey);
static inline uint64_t pl_hm_hash (const void* pData, size_t szDataSize, uint64_t uSeed);
static inline void pl__hm_insert_str (plHashMap* ptHashMap, const char* pcKey, uint64_t ulValue, const char* pcFile, int iLine);
static inline void pl_hm_remove_str (plHashMap* ptHashMap, const char* pcKey);
static inline uint64_t pl_hm_lookup_str (plHashMap* ptHashMap, const char* pcKey);
static inline bool pl_hm_has_key_str (plHashMap* ptHashMap, const char* pcKey);
//-----------------------------------------------------------------------------
// [SECTION] internal
//-----------------------------------------------------------------------------
#define pl__sb_header(buf) ((plSbHeader_*)(((char*)(buf)) - sizeof(plSbHeader_)))
#define pl__sb_may_grow(buf, s, n, m, X, Y) pl__sb_may_grow_((void**)&(buf), (s), (n), (m), __FILE__, __LINE__)
typedef struct
{
uint32_t uSize;
uint32_t uCapacity;
} plSbHeader_;
static void
pl__sb_grow(void** ptrBuffer, size_t szElementSize, size_t szNewItems, const char* pcFile, int iLine)
{
plSbHeader_* ptOldHeader = pl__sb_header(*ptrBuffer);
const size_t szNewSize = (ptOldHeader->uCapacity + szNewItems) * szElementSize + sizeof(plSbHeader_);
plSbHeader_* ptNewHeader = (plSbHeader_*)PL_DS_ALLOC_INDIRECT(szNewSize, pcFile, iLine); //-V592
memset(ptNewHeader, 0, (ptOldHeader->uCapacity + szNewItems) * szElementSize + sizeof(plSbHeader_));
if(ptNewHeader)
{
ptNewHeader->uSize = ptOldHeader->uSize;
ptNewHeader->uCapacity = ptOldHeader->uCapacity + (uint32_t)szNewItems;
memcpy(&ptNewHeader[1], *ptrBuffer, ptOldHeader->uSize * szElementSize);
PL_DS_FREE(ptOldHeader);
*ptrBuffer = &ptNewHeader[1];
}
}
static void
pl__sb_may_grow_(void** ptrBuffer, size_t szElementSize, size_t szNewItems, size_t szMinCapacity, const char* pcFile, int iLine)
{
if(*ptrBuffer)
{
plSbHeader_* ptOriginalHeader = pl__sb_header(*ptrBuffer);
if(ptOriginalHeader->uSize + szNewItems > ptOriginalHeader->uCapacity)
{
pl__sb_grow(ptrBuffer, szElementSize, szNewItems, pcFile, iLine);
}
}
else // first run
{
const size_t szNewSize = szMinCapacity * szElementSize + sizeof(plSbHeader_);
plSbHeader_* ptHeader = (plSbHeader_*)PL_DS_ALLOC_INDIRECT(szNewSize, pcFile, iLine);
memset(ptHeader, 0, szMinCapacity * szElementSize + sizeof(plSbHeader_));
if(ptHeader)
{
*ptrBuffer = &ptHeader[1];
ptHeader->uSize = 0u;
ptHeader->uCapacity = (uint32_t)szMinCapacity;
}
}
}
static void
pl__sb_vsprintf(char** ppcBuffer, const char* pcFormat, va_list args)
{
va_list args2;
va_copy(args2, args);
int32_t n = vsnprintf(NULL, 0, pcFormat, args2);
va_end(args2);
uint32_t an = pl_sb_size(*ppcBuffer);
pl_sb_resize(*ppcBuffer, an + n + 1);
vsnprintf(*ppcBuffer + an, n + 1, pcFormat, args);
}
static void
pl__sb_sprintf(char** ppcBuffer, const char* pcFormat, ...)
{
va_list args;
va_start(args, pcFormat);
pl__sb_vsprintf(ppcBuffer, pcFormat, args);
va_end(args);
}
//-----------------------------------------------------------------------------
// [SECTION] public api implementation (hashmap)
//-----------------------------------------------------------------------------
static inline void
pl__hm_resize(plHashMap* ptHashMap, uint32_t uBucketCount, const char* pcFile, int iLine)
{
const uint32_t uOldBucketCount = ptHashMap->_uBucketCount;
uint64_t* sbulOldValueIndices = ptHashMap->_aulValueIndices;
uint64_t* aulOldKeys = ptHashMap->_aulKeys;
ptHashMap->_uBucketCount = uBucketCount < PL_DS_HASHMAP_INITIAL_SIZE ? PL_DS_HASHMAP_INITIAL_SIZE : uBucketCount;
if(uBucketCount > 0)
{
ptHashMap->_aulValueIndices = (uint64_t*)PL_DS_ALLOC_INDIRECT(sizeof(uint64_t) * ptHashMap->_uBucketCount, pcFile, iLine);
ptHashMap->_aulKeys = (uint64_t*)PL_DS_ALLOC_INDIRECT(sizeof(uint64_t) * ptHashMap->_uBucketCount, pcFile, iLine);
memset(ptHashMap->_aulValueIndices, 0xff, sizeof(uint64_t) * ptHashMap->_uBucketCount);
memset(ptHashMap->_aulKeys, 0xff, sizeof(uint64_t) * ptHashMap->_uBucketCount);
for(uint32_t i = 0; i < uOldBucketCount; i++)
{
const uint64_t ulKey = aulOldKeys[i];
uint64_t ulOldModKey = ulKey % uOldBucketCount;
while(aulOldKeys[ulOldModKey] != ulKey && aulOldKeys[ulOldModKey] != UINT64_MAX)
ulOldModKey = (ulOldModKey + 1) % uOldBucketCount;
const uint64_t ulValue = sbulOldValueIndices[ulOldModKey];
ptHashMap->_uItemCount--;
pl__hm_insert(ptHashMap, ulKey, ulValue, pcFile, iLine);
}
}
else
{
ptHashMap->_aulValueIndices = NULL;
ptHashMap->_aulKeys = NULL;
pl_sb_free(ptHashMap->_sbulFreeIndices);
ptHashMap->_uItemCount = 0;
}
if(sbulOldValueIndices)
{
PL_DS_FREE(sbulOldValueIndices);
}
if(aulOldKeys)
{
PL_DS_FREE(aulOldKeys);
}
}
static inline void
pl__hm_insert(plHashMap* ptHashMap, uint64_t ulKey, uint64_t ulValue, const char* pcFile, int iLine)
{
if(ptHashMap->_uBucketCount == 0)
pl__hm_resize(ptHashMap, PL_DS_HASHMAP_INITIAL_SIZE, pcFile, iLine);
else if(((float)ptHashMap->_uItemCount / (float)ptHashMap->_uBucketCount) > 0.60f)
pl__hm_resize(ptHashMap, ptHashMap->_uBucketCount * 2, pcFile, iLine);
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
{
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
if(ptHashMap->_aulKeys[ulModKey] == UINT64_MAX - 1)
break;
}
ptHashMap->_aulKeys[ulModKey] = ulKey;
ptHashMap->_aulValueIndices[ulModKey] = ulValue;
ptHashMap->_uItemCount++;
}
static inline void
pl_hm_remove(plHashMap* ptHashMap, uint64_t ulKey)
{
PL_DS_ASSERT(ptHashMap->_uBucketCount > 0 && "hashmap has no items");
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
const uint64_t ulValue = ptHashMap->_aulValueIndices[ulModKey];
pl_sb_push(ptHashMap->_sbulFreeIndices, ulValue);
ptHashMap->_aulValueIndices[ulModKey] = UINT64_MAX;
ptHashMap->_aulKeys[ulModKey] = UINT64_MAX - 1;
ptHashMap->_uItemCount--;
}
static const uint64_t __gauCrc64LookupTableDS[256] =
{
0x0000000000000000ULL, 0x01B0000000000000ULL, 0x0360000000000000ULL, 0x02D0000000000000ULL, 0x06C0000000000000ULL, 0x0770000000000000ULL, 0x05A0000000000000ULL, 0x0410000000000000ULL,
0x0D80000000000000ULL, 0x0C30000000000000ULL, 0x0EE0000000000000ULL, 0x0F50000000000000ULL, 0x0B40000000000000ULL, 0x0AF0000000000000ULL, 0x0820000000000000ULL, 0x0990000000000000ULL,
0x1B00000000000000ULL, 0x1AB0000000000000ULL, 0x1860000000000000ULL, 0x19D0000000000000ULL, 0x1DC0000000000000ULL, 0x1C70000000000000ULL, 0x1EA0000000000000ULL, 0x1F10000000000000ULL,
0x1680000000000000ULL, 0x1730000000000000ULL, 0x15E0000000000000ULL, 0x1450000000000000ULL, 0x1040000000000000ULL, 0x11F0000000000000ULL, 0x1320000000000000ULL, 0x1290000000000000ULL,
0x3600000000000000ULL, 0x37B0000000000000ULL, 0x3560000000000000ULL, 0x34D0000000000000ULL, 0x30C0000000000000ULL, 0x3170000000000000ULL, 0x33A0000000000000ULL, 0x3210000000000000ULL,
0x3B80000000000000ULL, 0x3A30000000000000ULL, 0x38E0000000000000ULL, 0x3950000000000000ULL, 0x3D40000000000000ULL, 0x3CF0000000000000ULL, 0x3E20000000000000ULL, 0x3F90000000000000ULL,
0x2D00000000000000ULL, 0x2CB0000000000000ULL, 0x2E60000000000000ULL, 0x2FD0000000000000ULL, 0x2BC0000000000000ULL, 0x2A70000000000000ULL, 0x28A0000000000000ULL, 0x2910000000000000ULL,
0x2080000000000000ULL, 0x2130000000000000ULL, 0x23E0000000000000ULL, 0x2250000000000000ULL, 0x2640000000000000ULL, 0x27F0000000000000ULL, 0x2520000000000000ULL, 0x2490000000000000ULL,
0x6C00000000000000ULL, 0x6DB0000000000000ULL, 0x6F60000000000000ULL, 0x6ED0000000000000ULL, 0x6AC0000000000000ULL, 0x6B70000000000000ULL, 0x69A0000000000000ULL, 0x6810000000000000ULL,
0x6180000000000000ULL, 0x6030000000000000ULL, 0x62E0000000000000ULL, 0x6350000000000000ULL, 0x6740000000000000ULL, 0x66F0000000000000ULL, 0x6420000000000000ULL, 0x6590000000000000ULL,
0x7700000000000000ULL, 0x76B0000000000000ULL, 0x7460000000000000ULL, 0x75D0000000000000ULL, 0x71C0000000000000ULL, 0x7070000000000000ULL, 0x72A0000000000000ULL, 0x7310000000000000ULL,
0x7A80000000000000ULL, 0x7B30000000000000ULL, 0x79E0000000000000ULL, 0x7850000000000000ULL, 0x7C40000000000000ULL, 0x7DF0000000000000ULL, 0x7F20000000000000ULL, 0x7E90000000000000ULL,
0x5A00000000000000ULL, 0x5BB0000000000000ULL, 0x5960000000000000ULL, 0x58D0000000000000ULL, 0x5CC0000000000000ULL, 0x5D70000000000000ULL, 0x5FA0000000000000ULL, 0x5E10000000000000ULL,
0x5780000000000000ULL, 0x5630000000000000ULL, 0x54E0000000000000ULL, 0x5550000000000000ULL, 0x5140000000000000ULL, 0x50F0000000000000ULL, 0x5220000000000000ULL, 0x5390000000000000ULL,
0x4100000000000000ULL, 0x40B0000000000000ULL, 0x4260000000000000ULL, 0x43D0000000000000ULL, 0x47C0000000000000ULL, 0x4670000000000000ULL, 0x44A0000000000000ULL, 0x4510000000000000ULL,
0x4C80000000000000ULL, 0x4D30000000000000ULL, 0x4FE0000000000000ULL, 0x4E50000000000000ULL, 0x4A40000000000000ULL, 0x4BF0000000000000ULL, 0x4920000000000000ULL, 0x4890000000000000ULL,
0xD800000000000000ULL, 0xD9B0000000000000ULL, 0xDB60000000000000ULL, 0xDAD0000000000000ULL, 0xDEC0000000000000ULL, 0xDF70000000000000ULL, 0xDDA0000000000000ULL, 0xDC10000000000000ULL,
0xD580000000000000ULL, 0xD430000000000000ULL, 0xD6E0000000000000ULL, 0xD750000000000000ULL, 0xD340000000000000ULL, 0xD2F0000000000000ULL, 0xD020000000000000ULL, 0xD190000000000000ULL,
0xC300000000000000ULL, 0xC2B0000000000000ULL, 0xC060000000000000ULL, 0xC1D0000000000000ULL, 0xC5C0000000000000ULL, 0xC470000000000000ULL, 0xC6A0000000000000ULL, 0xC710000000000000ULL,
0xCE80000000000000ULL, 0xCF30000000000000ULL, 0xCDE0000000000000ULL, 0xCC50000000000000ULL, 0xC840000000000000ULL, 0xC9F0000000000000ULL, 0xCB20000000000000ULL, 0xCA90000000000000ULL,
0xEE00000000000000ULL, 0xEFB0000000000000ULL, 0xED60000000000000ULL, 0xECD0000000000000ULL, 0xE8C0000000000000ULL, 0xE970000000000000ULL, 0xEBA0000000000000ULL, 0xEA10000000000000ULL,
0xE380000000000000ULL, 0xE230000000000000ULL, 0xE0E0000000000000ULL, 0xE150000000000000ULL, 0xE540000000000000ULL, 0xE4F0000000000000ULL, 0xE620000000000000ULL, 0xE790000000000000ULL,
0xF500000000000000ULL, 0xF4B0000000000000ULL, 0xF660000000000000ULL, 0xF7D0000000000000ULL, 0xF3C0000000000000ULL, 0xF270000000000000ULL, 0xF0A0000000000000ULL, 0xF110000000000000ULL,
0xF880000000000000ULL, 0xF930000000000000ULL, 0xFBE0000000000000ULL, 0xFA50000000000000ULL, 0xFE40000000000000ULL, 0xFFF0000000000000ULL, 0xFD20000000000000ULL, 0xFC90000000000000ULL,
0xB400000000000000ULL, 0xB5B0000000000000ULL, 0xB760000000000000ULL, 0xB6D0000000000000ULL, 0xB2C0000000000000ULL, 0xB370000000000000ULL, 0xB1A0000000000000ULL, 0xB010000000000000ULL,
0xB980000000000000ULL, 0xB830000000000000ULL, 0xBAE0000000000000ULL, 0xBB50000000000000ULL, 0xBF40000000000000ULL, 0xBEF0000000000000ULL, 0xBC20000000000000ULL, 0xBD90000000000000ULL,
0xAF00000000000000ULL, 0xAEB0000000000000ULL, 0xAC60000000000000ULL, 0xADD0000000000000ULL, 0xA9C0000000000000ULL, 0xA870000000000000ULL, 0xAAA0000000000000ULL, 0xAB10000000000000ULL,
0xA280000000000000ULL, 0xA330000000000000ULL, 0xA1E0000000000000ULL, 0xA050000000000000ULL, 0xA440000000000000ULL, 0xA5F0000000000000ULL, 0xA720000000000000ULL, 0xA690000000000000ULL,
0x8200000000000000ULL, 0x83B0000000000000ULL, 0x8160000000000000ULL, 0x80D0000000000000ULL, 0x84C0000000000000ULL, 0x8570000000000000ULL, 0x87A0000000000000ULL, 0x8610000000000000ULL,
0x8F80000000000000ULL, 0x8E30000000000000ULL, 0x8CE0000000000000ULL, 0x8D50000000000000ULL, 0x8940000000000000ULL, 0x88F0000000000000ULL, 0x8A20000000000000ULL, 0x8B90000000000000ULL,
0x9900000000000000ULL, 0x98B0000000000000ULL, 0x9A60000000000000ULL, 0x9BD0000000000000ULL, 0x9FC0000000000000ULL, 0x9E70000000000000ULL, 0x9CA0000000000000ULL, 0x9D10000000000000ULL,
0x9480000000000000ULL, 0x9530000000000000ULL, 0x97E0000000000000ULL, 0x9650000000000000ULL, 0x9240000000000000ULL, 0x93F0000000000000ULL, 0x9120000000000000ULL, 0x9090000000000000ULL
};
static inline uint64_t
pl_hm_hash_str(const char* pcKey)
{
uint64_t uCrc = 0;
const unsigned char* pucData = (const unsigned char*)pcKey;
unsigned char c = *pucData++;
while (c)
{
uCrc = (uCrc >> 8) ^ __gauCrc64LookupTableDS[(uCrc & 0xFF) ^ c];
c = *pucData;
pucData++;
}
return ~uCrc;
}
static inline uint64_t
pl_hm_hash(const void* pData, size_t szDataSize, uint64_t uSeed)
{
uint64_t uCrc = ~uSeed;
const unsigned char* pucData = (const unsigned char*)pData;
while (szDataSize-- != 0)
uCrc = (uCrc >> 8) ^ __gauCrc64LookupTableDS[(uCrc & 0xFF) ^ *pucData++];
return ~uCrc;
}
static inline uint64_t
pl_hm_lookup(plHashMap* ptHashMap, uint64_t ulKey)
{
if(ptHashMap->_uBucketCount == 0)
return UINT64_MAX;
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
if(ptHashMap->_aulKeys[ulModKey] == UINT64_MAX)
return UINT64_MAX;
return ptHashMap->_aulValueIndices[ulModKey];
}
static inline uint64_t
pl_hm_get_free_index(plHashMap* ptHashMap)
{
uint64_t ulResult = UINT64_MAX;
if(pl_sb_size(ptHashMap->_sbulFreeIndices) > 0)
{
ulResult = pl_sb_pop(ptHashMap->_sbulFreeIndices);
}
return ulResult;
}
static inline void
pl__hm_insert_str(plHashMap* ptHashMap, const char* pcKey, uint64_t ulValue, const char* pcFile, int iLine)
{
pl__hm_insert(ptHashMap, pl_hm_hash_str(pcKey), ulValue, pcFile, iLine);
}
static inline void
pl_hm_remove_str(plHashMap* ptHashMap, const char* pcKey)
{
pl_hm_remove(ptHashMap, pl_hm_hash_str(pcKey));
}
static inline uint64_t
pl_hm_lookup_str(plHashMap* ptHashMap, const char* pcKey)
{
return pl_hm_lookup(ptHashMap, pl_hm_hash_str(pcKey));
}
static inline bool
pl_hm_has_key(plHashMap* ptHashMap, uint64_t ulKey)
{
if(ptHashMap->_uItemCount == 0)
return false;
uint64_t ulModKey = ulKey % ptHashMap->_uBucketCount;
while(ptHashMap->_aulKeys[ulModKey] != ulKey && ptHashMap->_aulKeys[ulModKey] != UINT64_MAX)
ulModKey = (ulModKey + 1) % ptHashMap->_uBucketCount;
return ptHashMap->_aulKeys[ulModKey] != UINT64_MAX;
}
static inline bool
pl_hm_has_key_str(plHashMap* ptHashMap, const char* pcKey)
{
return pl_hm_has_key(ptHashMap, pl_hm_hash_str(pcKey));
}
#endif // PL_DS_H