102 lines
3.9 KiB
C
102 lines
3.9 KiB
C
// vim:fileencoding=utf-8:foldmethod=marker
|
|
|
|
/**
|
|
* A hash table implementation with Robin Hood open addressing for collision resolution.
|
|
*
|
|
* The implementation is based on a version of this C++ implementation:
|
|
* https://github.com/martinus/unordered_dense
|
|
*
|
|
* Extra references:
|
|
* - https://faultlore.com/blah/robinhood-part-1/
|
|
* - https://blog.hieunt.me/blog/robinhood-hashing
|
|
*
|
|
* IMPORTANT:
|
|
* This is the internal hash table implementation and it is not intended to be used directly.
|
|
* Please check ../map/map.h and ../set/set.h for the public APIs.
|
|
*/
|
|
|
|
#ifndef TABLE_H
|
|
#define TABLE_H
|
|
|
|
#include "../hasher/hasher.h"
|
|
#include "../hasher/murmur3.h"
|
|
#include "../../array/array.h"
|
|
#include "../../mem/allocator/mem_allocator.h"
|
|
#include "../../stream/stream.h"
|
|
#include "../../../common/aliases/aliases.h"
|
|
#include "../../../common/platform/platform.h"
|
|
|
|
#ifdef WP_PLATFORM_CPP
|
|
BEGIN_C_LINKAGE
|
|
#endif // !WP_PLATFORM_CPP
|
|
|
|
#define WP_HASH_TABLE_MAGIC wpU64Const(0x57504854424c)
|
|
#define WP_HASH_TAG_BITS wpU64Const(32)
|
|
#define WP_HASH_DIST_INC (wpU64Const(1) << WP_HASH_TAG_BITS)
|
|
#define WP_HASH_TAG_MASK (WP_HASH_DIST_INC - wpU64Const(1))
|
|
#define WP_HASH_MAX_LOAD_FACTOR 0.65f
|
|
#define WP_HASH_TABLE_DEFAULT_HASHER wpX64Mur3Hasher()
|
|
|
|
typedef WpU8Stream (*WpU8StreamEncoder)(void *data);
|
|
typedef b8 (*WpKeyEqualTest)(void *a, void *b);
|
|
|
|
typedef struct WpHashBucket {
|
|
u64 dist_and_tag;
|
|
u64 item_index;
|
|
} WpHashBucket;
|
|
typedef WpHashBucket *WpHashBucketArray;
|
|
|
|
typedef struct WpHashTable {
|
|
WpHasher hasher;
|
|
WpU8StreamEncoder encoder;
|
|
WpKeyEqualTest key_eq;
|
|
WpArray keys;
|
|
WpArray values;
|
|
WpHashBucketArray buckets;
|
|
u64 magic;
|
|
u64 bucket_mask;
|
|
f32 load_factor;
|
|
b8 has_values;
|
|
} WpHashTable;
|
|
|
|
typedef struct WpHashBucketRef {
|
|
u64 dist_and_tag;
|
|
u64 bucket_index;
|
|
} WpHashBucketRef;
|
|
|
|
typedef struct WpHashLookupResult {
|
|
WpHashBucketRef ref;
|
|
b8 found;
|
|
} WpHashLookupResult;
|
|
|
|
void hashTableAlloc(const WpAllocator *allocator, WpHashTable *table,
|
|
WpHasher hasher, WpU8StreamEncoder encoder,
|
|
WpKeyEqualTest key_eq, u64 capacity, u64 key_size,
|
|
u64 value_size, b8 has_values);
|
|
u64 hashTableCalcHash(WpHashTable *table, void *key, u64 key_size);
|
|
WpHashBucketRef hashTableBucketRef(WpHashTable *table, u64 hash);
|
|
void *hashTableKeys(WpHashTable *table, u64 key_size);
|
|
void *hashTableValues(WpHashTable *table, u64 value_size);
|
|
void *hashTableGetKeyFromBucketRef(WpHashTable *table, WpHashBucketRef ref, u64 key_size);
|
|
void *hashTableGetValueFromBucketRef(WpHashTable *table, WpHashBucketRef ref, u64 value_size);
|
|
u64 hashTableCapacity(WpHashTable *table);
|
|
u64 hashTableCount(WpHashTable *table);
|
|
u64 hashTableKeySize(WpHashTable *table);
|
|
u64 hashTableValueSize(WpHashTable *table);
|
|
void hashTableGrow(const WpAllocator *allocator, WpHashTable *table, u64 key_size,
|
|
u64 value_size);
|
|
WpHashLookupResult hashTableLookup(WpHashTable *table, void *key, WpHashBucketRef ref, u64 key_size);
|
|
void hashTableUpdate(WpHashTable *table, void *value, WpHashBucketRef ref, u64 value_size);
|
|
void hashTableInsert(WpHashTable *table, void *key, void *value, WpHashBucketRef ref,
|
|
u64 key_size, u64 value_size);
|
|
void hashTableRemove(WpHashTable *table, WpHashBucketRef ref, u64 key_size, u64 value_size);
|
|
void hashTableClear(WpHashTable *table, u64 key_size, u64 value_size);
|
|
void hashTableDealloc(const WpAllocator *allocator, WpHashTable *table, u64 key_size,
|
|
u64 value_size);
|
|
|
|
#ifdef WP_PLATFORM_CPP
|
|
END_C_LINKAGE
|
|
#endif // !WP_PLATFORM_CPP
|
|
|
|
#endif // !TABLE_H
|