// 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