84 lines
3.2 KiB
C
84 lines
3.2 KiB
C
// vim:fileencoding=utf-8:foldmethod=marker
|
|
|
|
#include "map.h"
|
|
#include "../table/table.h"
|
|
|
|
WpHashMap hashMapAlloc(const WpAllocator *allocator, WpU8StreamEncoder encoder, WpKeyEqualTest key_eq,
|
|
u64 capacity, u64 key_size, u64 value_size) {
|
|
return hashMapAllocWithCustomHasher(allocator, WP_HASH_TABLE_DEFAULT_HASHER, encoder, key_eq,
|
|
capacity, key_size, value_size);
|
|
}
|
|
|
|
WpHashMap hashMapAllocWithCustomHasher(const WpAllocator *allocator, WpHasher hasher,
|
|
WpU8StreamEncoder encoder, WpKeyEqualTest key_eq,
|
|
u64 capacity, u64 key_size, u64 value_size) {
|
|
WpHashMap map = {0};
|
|
hashTableAlloc(allocator, &map, hasher, encoder, key_eq, capacity, key_size, value_size, true);
|
|
return map;
|
|
}
|
|
|
|
WpHashLookupResult hashMapFind(WpHashMap *map, void *key, u64 key_size) {
|
|
u64 hash = hashTableCalcHash(map, key, key_size);
|
|
WpHashBucketRef ref = hashTableBucketRef(map, hash);
|
|
return hashTableLookup(map, key, ref, key_size);
|
|
}
|
|
|
|
void hashMapUpdate(WpHashMap *map, void *key, void *value, u64 key_size, u64 value_size) {
|
|
WpHashLookupResult result = hashMapFind(map, key, key_size);
|
|
if (result.found) {
|
|
hashTableUpdate(map, value, result.ref, value_size);
|
|
}
|
|
}
|
|
|
|
void hashMapInsertCapped(WpHashMap *map, void *key, void *value, u64 key_size, u64 value_size) {
|
|
WpHashLookupResult result = hashMapFind(map, key, key_size);
|
|
if (!result.found && map->load_factor < WP_HASH_MAX_LOAD_FACTOR) {
|
|
hashTableInsert(map, key, value, result.ref, key_size, value_size);
|
|
}
|
|
}
|
|
|
|
void hashMapInsertOrUpdateCapped(WpHashMap *map, void *key, void *value, u64 key_size, u64 value_size) {
|
|
WpHashLookupResult result = hashMapFind(map, key, key_size);
|
|
if (result.found) {
|
|
hashTableUpdate(map, value, result.ref, value_size);
|
|
} else if (map->load_factor < WP_HASH_MAX_LOAD_FACTOR) {
|
|
hashTableInsert(map, key, value, result.ref, key_size, value_size);
|
|
}
|
|
}
|
|
|
|
void hashMapInsertAlloc(const WpAllocator *allocator, WpHashMap *map, void *key, void *value,
|
|
u64 key_size, u64 value_size) {
|
|
WpHashLookupResult result = hashMapFind(map, key, key_size);
|
|
if (!result.found) {
|
|
if (map->load_factor >= WP_HASH_MAX_LOAD_FACTOR) {
|
|
hashTableGrow(allocator, map, key_size, value_size);
|
|
// Rerun key lookup after growing
|
|
result = hashMapFind(map, key, key_size);
|
|
}
|
|
|
|
hashTableInsert(map, key, value, result.ref, key_size, value_size);
|
|
}
|
|
}
|
|
|
|
void hashMapInsertOrUpdateAlloc(const WpAllocator *allocator, WpHashMap *map, void *key, void *value,
|
|
u64 key_size, u64 value_size) {
|
|
WpHashLookupResult result = hashMapFind(map, key, key_size);
|
|
if (result.found) {
|
|
hashTableUpdate(map, value, result.ref, value_size);
|
|
} else {
|
|
if (map->load_factor >= WP_HASH_MAX_LOAD_FACTOR) {
|
|
hashTableGrow(allocator, map, key_size, value_size);
|
|
// Rerun key lookup after growing
|
|
result = hashMapFind(map, key, key_size);
|
|
}
|
|
hashTableInsert(map, key, value, result.ref, key_size, value_size);
|
|
}
|
|
}
|
|
|
|
void hashMapRemove(WpHashMap *map, void *key, u64 key_size, u64 value_size) {
|
|
WpHashLookupResult result = hashMapFind(map, key, key_size);
|
|
if (result.found) {
|
|
hashTableRemove(map, result.ref, key_size, value_size);
|
|
}
|
|
}
|