@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `wpX64Mur3GetHash128` implementation for the x64 128-bit variant of the MurmurHash3 algorithm
|
- `wpX64Mur3GetHash128` implementation for the x64 128-bit variant of the MurmurHash3 algorithm
|
||||||
- `wpSip24Hasher`, `wpSip48Hasher`, `wpSip24HasherWithKey` and `wpSip48HasherWithKey` constructors for the hasher interface
|
- `wpSip24Hasher`, `wpSip48Hasher`, `wpSip24HasherWithKey` and `wpSip48HasherWithKey` constructors for the hasher interface
|
||||||
- `wpSipGetHash128` implementation for the 128 variant of siphash
|
- `wpSipGetHash128` implementation for the 128 variant of siphash
|
||||||
|
- `wpHashSet`, `wpHashSetCustomHasher`, `wpHashSetAlloc` and `wpHashSetCustomHasherAlloc` constructors
|
||||||
|
- `wpHashSetFind`, `wpHashSetInsertCapped`, `wpHashSetInsertAlloc`, `wpHashSetRemove`, `wpHashSetItems`, `wpHashSetCapacity`, `wpHashSetCount`, `wpHashSetItemSize`, `wpHashSetClear` and `wpHashSetDealloc` utilities
|
||||||
- `wpU8Const`, `wpU16Const`, `wpU32Const`, `wpU64Const`, `wpI8Const`, `wpI16Const`, `wpI32Const`, and `wpI64Const` aliases
|
- `wpU8Const`, `wpU16Const`, `wpU32Const`, `wpU64Const`, `wpI8Const`, `wpI16Const`, `wpI32Const`, and `wpI64Const` aliases
|
||||||
- `wpPrngXorshiftInitWithSeed` to allow for user control with PRNG
|
- `wpPrngXorshiftInitWithSeed` to allow for user control with PRNG
|
||||||
- `wpPrngXorshift256InRange`, `wpPrngXorshift256ssInRange`, `wpPrngXorshift256pInRange`, `wpPrngXorshift256Choice`, `wpPrngXorshift256ssChoice` and `wpPrngXorshift256pChoice` utilities
|
- `wpPrngXorshift256InRange`, `wpPrngXorshift256ssInRange`, `wpPrngXorshift256pInRange`, `wpPrngXorshift256Choice`, `wpPrngXorshift256ssChoice` and `wpPrngXorshift256pChoice` utilities
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "set.h"
|
||||||
|
#include "../table/table.h"
|
||||||
|
|
||||||
|
WpHashSet hashSetAlloc(const WpAllocator *allocator, WpU8StreamEncoder encoder, WpKeyEqualTest key_eq,
|
||||||
|
u64 capacity, u64 key_size) {
|
||||||
|
return hashSetAllocWithCustomHasher(allocator, WP_HASH_TABLE_DEFAULT_HASHER, encoder, key_eq,
|
||||||
|
capacity, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpHashSet hashSetAllocWithCustomHasher(const WpAllocator *allocator, WpHasher hasher,
|
||||||
|
WpU8StreamEncoder encoder, WpKeyEqualTest key_eq, u64 capacity,
|
||||||
|
u64 key_size) {
|
||||||
|
WpHashSet set = {0};
|
||||||
|
hashTableAlloc(allocator, &set, hasher, encoder, key_eq, capacity, key_size, 0, false);
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
WpHashLookupResult hashSetFind(WpHashSet *set, void *item, u64 item_size) {
|
||||||
|
u64 hash = hashTableCalcHash(set, item, item_size);
|
||||||
|
WpHashBucketRef ref = hashTableBucketRef(set, hash);
|
||||||
|
return hashTableLookup(set, item, ref, item_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hashSetInsertCapped(WpHashSet *set, void *item, u64 item_size) {
|
||||||
|
WpHashLookupResult result = hashSetFind(set, item, item_size);
|
||||||
|
if (!result.found && set->load_factor < WP_HASH_MAX_LOAD_FACTOR) {
|
||||||
|
hashTableInsert(set, item, NULL, result.ref, item_size, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hashSetInsertAlloc(const WpAllocator *allocator, WpHashSet *set, void *item, u64 item_size) {
|
||||||
|
WpHashLookupResult result = hashSetFind(set, item, item_size);
|
||||||
|
if (!result.found) {
|
||||||
|
if (set->load_factor >= WP_HASH_MAX_LOAD_FACTOR) {
|
||||||
|
hashTableGrow(allocator, set, item_size, 0);
|
||||||
|
// Rerun item lookup after growing
|
||||||
|
result = hashSetFind(set, item, item_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
hashTableInsert(set, item, NULL, result.ref, item_size, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hashSetRemove(WpHashSet *set, void *item, u64 item_size) {
|
||||||
|
WpHashLookupResult result = hashSetFind(set, item, item_size);
|
||||||
|
if (result.found) {
|
||||||
|
hashTableRemove(set, result.ref, item_size, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#ifndef SET_H
|
||||||
|
#define SET_H
|
||||||
|
|
||||||
|
#include "../table/table.h"
|
||||||
|
#include "../../../common/misc/misc_utils.h"
|
||||||
|
#include "../../../common/platform/platform.h"
|
||||||
|
|
||||||
|
#ifdef WP_PLATFORM_CPP
|
||||||
|
BEGIN_C_LINKAGE
|
||||||
|
#endif // !WP_PLATFORM_CPP
|
||||||
|
|
||||||
|
typedef WpHashTable WpHashSet;
|
||||||
|
|
||||||
|
#ifdef WP_PLATFORM_CPP
|
||||||
|
#define wpHashSet(TYPE, U8_STREAM_ENCODER, ITEM_EQ_TEST, CAPACITY) \
|
||||||
|
(WpHashSet{ \
|
||||||
|
WP_HASH_TABLE_DEFAULT_HASHER, \
|
||||||
|
U8_STREAM_ENCODER, \
|
||||||
|
ITEM_EQ_TEST, \
|
||||||
|
wpArrayWithCapacity(TYPE, wpMiscUtilsU64RoundUpPow2(CAPACITY), WP_ARRAY_INIT_NONE), \
|
||||||
|
NULL, \
|
||||||
|
wpArrayWithCapacity(WpHashBucket, wpMiscUtilsU64RoundUpPow2(CAPACITY), WP_ARRAY_INIT_FILLED), \
|
||||||
|
WP_HASH_TABLE_MAGIC, \
|
||||||
|
wpMiscUtilsU64RoundUpPow2(CAPACITY) - 1, \
|
||||||
|
0.0f, \
|
||||||
|
false, \
|
||||||
|
})
|
||||||
|
#define wpHashSetCustomHasher(TYPE, HASHER, U8_STREAM_ENCODER, ITEM_EQ_TEST, CAPACITY) \
|
||||||
|
(WpHashSet{ \
|
||||||
|
HASHER, \
|
||||||
|
U8_STREAM_ENCODER, \
|
||||||
|
ITEM_EQ_TEST, \
|
||||||
|
wpArrayWithCapacity(TYPE, wpMiscUtilsU64RoundUpPow2(CAPACITY), WP_ARRAY_INIT_NONE), \
|
||||||
|
NULL, \
|
||||||
|
wpArrayWithCapacity(WpHashBucket, wpMiscUtilsU64RoundUpPow2(CAPACITY), WP_ARRAY_INIT_FILLED), \
|
||||||
|
WP_HASH_TABLE_MAGIC, \
|
||||||
|
wpMiscUtilsU64RoundUpPow2(CAPACITY) - 1, \
|
||||||
|
0.0f, \
|
||||||
|
false, \
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
#define wpHashSet(TYPE, U8_STREAM_ENCODER, ITEM_EQ_TEST, CAPACITY) \
|
||||||
|
((WpHashSet){ \
|
||||||
|
.hasher = WP_HASH_TABLE_DEFAULT_HASHER, \
|
||||||
|
.encoder = U8_STREAM_ENCODER, \
|
||||||
|
.key_eq = ITEM_EQ_TEST, \
|
||||||
|
.keys = wpArrayWithCapacity(TYPE, wpMiscUtilsU64RoundUpPow2(CAPACITY), \
|
||||||
|
WP_ARRAY_INIT_NONE), \
|
||||||
|
.buckets = wpArrayWithCapacity(WpHashBucket, wpMiscUtilsU64RoundUpPow2(CAPACITY), \
|
||||||
|
WP_ARRAY_INIT_FILLED), \
|
||||||
|
.magic = WP_HASH_TABLE_MAGIC, \
|
||||||
|
.bucket_mask = wpMiscUtilsU64RoundUpPow2(CAPACITY) - 1, \
|
||||||
|
})
|
||||||
|
#define wpHashSetCustomHasher(TYPE, HASHER, U8_STREAM_ENCODER, ITEM_EQ_TEST, CAPACITY) \
|
||||||
|
((WpHashSet){ \
|
||||||
|
.hasher = HASHER, \
|
||||||
|
.encoder = U8_STREAM_ENCODER, \
|
||||||
|
.key_eq = ITEM_EQ_TEST, \
|
||||||
|
.keys = wpArrayWithCapacity(TYPE, wpMiscUtilsU64RoundUpPow2(CAPACITY), \
|
||||||
|
WP_ARRAY_INIT_NONE), \
|
||||||
|
.buckets = wpArrayWithCapacity(WpHashBucket, wpMiscUtilsU64RoundUpPow2(CAPACITY), \
|
||||||
|
WP_ARRAY_INIT_FILLED), \
|
||||||
|
.magic = WP_HASH_TABLE_MAGIC, \
|
||||||
|
.bucket_mask = wpMiscUtilsU64RoundUpPow2(CAPACITY) - 1, \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define wpHashSetAlloc(TYPE, ALLOCATOR_PTR, U8_STREAM_ENCODER, ITEM_EQ_TEST, CAPACITY) \
|
||||||
|
hashSetAlloc(ALLOCATOR_PTR, U8_STREAM_ENCODER, ITEM_EQ_TEST, CAPACITY, sizeof(TYPE))
|
||||||
|
#define wpHashSetCustomHasherAlloc(TYPE, ALLOCATOR_PTR, HASHER, U8_STREAM_ENCODER, ITEM_EQ_TEST, \
|
||||||
|
CAPACITY) \
|
||||||
|
hashSetAllocWithCustomHasher(ALLOCATOR_PTR, HASHER, U8_STREAM_ENCODER, ITEM_EQ_TEST, CAPACITY, \
|
||||||
|
sizeof(TYPE))
|
||||||
|
#define wpHashSetFind(TYPE, SET_PTR, ITEM_PTR) hashSetFind(SET_PTR, ITEM_PTR, sizeof(TYPE))
|
||||||
|
#define wpHashSetInsertCapped(TYPE, SET_PTR, ITEM_PTR) \
|
||||||
|
hashSetInsertCapped(SET_PTR, ITEM_PTR, sizeof(TYPE))
|
||||||
|
#define wpHashSetInsertAlloc(TYPE, ALLOCATOR_PTR, SET_PTR, ITEM_PTR) \
|
||||||
|
hashSetInsertAlloc(ALLOCATOR_PTR, SET_PTR, ITEM_PTR, sizeof(TYPE))
|
||||||
|
#define wpHashSetRemove(TYPE, SET_PTR, ITEM_PTR) hashSetRemove(SET_PTR, ITEM_PTR, sizeof(TYPE))
|
||||||
|
#define wpHashSetItems(TYPE, SET_PTR) ((TYPE *)hashTableKeys(SET_PTR, sizeof(TYPE)))
|
||||||
|
#define wpHashSetCapacity(SET_PTR) hashTableCapacity(SET_PTR)
|
||||||
|
#define wpHashSetCount(SET_PTR) hashTableCount(SET_PTR)
|
||||||
|
#define wpHashSetItemSize(SET_PTR) hashTableKeySize(SET_PTR)
|
||||||
|
#define wpHashSetClear(TYPE, SET_PTR) hashTableClear(SET_PTR, sizeof(TYPE), 0)
|
||||||
|
#define wpHashSetDealloc(TYPE, ALLOCATOR_PTR, SET_PTR) \
|
||||||
|
hashTableDealloc(ALLOCATOR_PTR, SET_PTR, sizeof(TYPE), 0)
|
||||||
|
|
||||||
|
WpHashSet hashSetAlloc(const WpAllocator *allocator, WpU8StreamEncoder encoder,
|
||||||
|
WpKeyEqualTest key_eq, u64 capacity, u64 key_size);
|
||||||
|
WpHashSet hashSetAllocWithCustomHasher(const WpAllocator *allocator, WpHasher hasher,
|
||||||
|
WpU8StreamEncoder encoder, WpKeyEqualTest key_eq,
|
||||||
|
u64 capacity, u64 key_size);
|
||||||
|
WpHashLookupResult hashSetFind(WpHashSet *set, void *item, u64 item_size);
|
||||||
|
void hashSetInsertCapped(WpHashSet *set, void *item, u64 item_size);
|
||||||
|
void hashSetInsertAlloc(const WpAllocator *allocator, WpHashSet *set, void *item,
|
||||||
|
u64 item_size);
|
||||||
|
void hashSetRemove(WpHashSet *set, void *item, u64 item_size);
|
||||||
|
|
||||||
|
#ifdef WP_PLATFORM_CPP
|
||||||
|
END_C_LINKAGE
|
||||||
|
#endif // !WP_PLATFORM_CPP
|
||||||
|
|
||||||
|
#endif // !SET_H
|
||||||
+76
-32
@@ -8,26 +8,62 @@
|
|||||||
#include "../../../common/assert/assert.h"
|
#include "../../../common/assert/assert.h"
|
||||||
#include "../../../common/misc/misc_utils.h"
|
#include "../../../common/misc/misc_utils.h"
|
||||||
|
|
||||||
|
wp_persist inline void *hashTableGetKeyFromBucket(WpHashTable *table, WpHashBucket bucket, u64 key_size);
|
||||||
|
wp_persist inline void *hashTableGetValueFromBucket(WpHashTable *table, WpHashBucket bucket, u64 value_size);
|
||||||
|
wp_persist inline u64 hashTableGetDist(u64 dist_and_tag);
|
||||||
|
wp_persist inline u64 hashTableNextBucket(WpHashTable *table, u64 bucket_index);
|
||||||
|
wp_persist inline u64 hashTableDistInc(u64 dist_and_tag);
|
||||||
|
wp_persist inline u64 hashTableDistDec(u64 dist_and_tag);
|
||||||
wp_persist inline void hashTableValidate(const WpHashTable *table, u64 key_size, u64 value_size);
|
wp_persist inline void hashTableValidate(const WpHashTable *table, u64 key_size, u64 value_size);
|
||||||
|
|
||||||
void *hashTableKeys(WpHashTable *table) {
|
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) {
|
||||||
|
wpDebugAssert(allocator != NULL && table != NULL && encoder != NULL && key_eq != NULL,
|
||||||
|
"`allocator`, `table`, `encoder` and `key_eq` should not be NULL");
|
||||||
|
|
||||||
|
u64 table_capacity = wpMiscUtilsU64RoundUpPow2(capacity);
|
||||||
|
table->hasher = hasher;
|
||||||
|
table->encoder = encoder;
|
||||||
|
table->key_eq = key_eq;
|
||||||
|
table->keys = arrayAllocCapacity(allocator, table_capacity, WP_ARRAY_INIT_NONE, key_size);;
|
||||||
|
table->buckets = wpArrayAllocCapacity(WpHashBucket, allocator, table_capacity, WP_ARRAY_INIT_FILLED);
|
||||||
|
table->magic = WP_HASH_TABLE_MAGIC;
|
||||||
|
table->bucket_mask = table_capacity - 1;
|
||||||
|
table->load_factor = WP_HASH_MAX_LOAD_FACTOR;
|
||||||
|
table->has_values = has_values;
|
||||||
|
|
||||||
|
wpRuntimeAssert(table->keys != NULL && table->buckets != NULL, "Failed to allocate keys, buckets or both");
|
||||||
|
|
||||||
|
if (has_values) {
|
||||||
|
table->values = arrayAllocCapacity(allocator, table_capacity, WP_ARRAY_INIT_NONE, value_size);;
|
||||||
|
wpRuntimeAssert(table->values != NULL, "Failed to allocate values");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 hashTableCalcHash(WpHashTable *table, void *key, u64 key_size) {
|
||||||
|
hashTableValidate(table, key_size, 0);
|
||||||
|
wpDebugAssert(key != NULL, "`key` should not be NULL");
|
||||||
|
WpU8Stream stream = table->encoder(key);
|
||||||
|
return wpHasherGetHash64(&table->hasher, &stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpHashBucketRef hashTableBucketRef(WpHashTable *table, u64 hash) {
|
||||||
hashTableValidate(table, 0, 0);
|
hashTableValidate(table, 0, 0);
|
||||||
|
return (WpHashBucketRef){
|
||||||
|
.dist_and_tag = WP_HASH_DIST_INC | (hash & WP_HASH_TAG_MASK),
|
||||||
|
.bucket_index = hash & table->bucket_mask,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void *hashTableKeys(WpHashTable *table, u64 key_size) {
|
||||||
|
hashTableValidate(table, key_size, 0);
|
||||||
return table->keys;
|
return table->keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *hashTableValues(WpHashTable *table) {
|
void *hashTableValues(WpHashTable *table, u64 value_size) {
|
||||||
hashTableValidate(table, 0, 0);
|
|
||||||
return table->values;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *hashTableGetKeyFromBucket(WpHashTable *table, WpHashBucket bucket, u64 key_size) {
|
|
||||||
hashTableValidate(table, key_size, 0);
|
|
||||||
return arrayGet(table->keys, bucket.item_index, key_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *hashTableGetValueFromBucket(WpHashTable *table, WpHashBucket bucket, u64 value_size) {
|
|
||||||
hashTableValidate(table, 0, value_size);
|
hashTableValidate(table, 0, value_size);
|
||||||
return table->has_values ? arrayGet(table->values, bucket.item_index, value_size) : NULL;
|
return table->values;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *hashTableGetKeyFromBucketRef(WpHashTable *table, WpHashBucketRef ref, u64 key_size) {
|
void *hashTableGetKeyFromBucketRef(WpHashTable *table, WpHashBucketRef ref, u64 key_size) {
|
||||||
@@ -58,25 +94,21 @@ u64 hashTableValueSize(WpHashTable *table) {
|
|||||||
return table->has_values ? wpArrayItemSize(table->values) : 0;
|
return table->has_values ? wpArrayItemSize(table->values) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 hashTableCalcHash(WpHashTable *table, void *key, u64 key_size) {
|
void hashTableGrow(const WpAllocator *allocator, WpHashTable *table, u64 key_size, u64 value_size) {
|
||||||
hashTableValidate(table, key_size, 0);
|
|
||||||
wpDebugAssert(key != NULL, "`key` should not be NULL");
|
|
||||||
WpU8Stream stream = table->encoder(key);
|
|
||||||
return wpHasherGetHash64(&table->hasher, &stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hashTableGrow(WpHashTable *table, const WpAllocator *allocator, u64 key_size, u64 value_size) {
|
|
||||||
hashTableValidate(table, key_size, value_size);
|
hashTableValidate(table, key_size, value_size);
|
||||||
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
|
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
|
|
||||||
u64 capacity = hashTableCapacity(table) * 2;
|
u64 capacity = wpMiscUtilsU64RoundUpPow2(hashTableCapacity(table) * 2);
|
||||||
u64 mask = capacity - wpU64Const(1);
|
u64 mask = capacity - wpU64Const(1);
|
||||||
WpArray keys = arrayAllocCapacity(allocator, capacity, WP_ARRAY_INIT_NONE, key_size);
|
WpArray keys = arrayAllocCapacity(allocator, capacity, WP_ARRAY_INIT_NONE, key_size);
|
||||||
WpArray values = NULL;
|
WpArray values = NULL;
|
||||||
WpHashBucketArray buckets = wpArrayAllocCapacity(WpHashBucket, allocator, capacity, WP_ARRAY_INIT_FILLED);
|
WpHashBucketArray buckets = wpArrayAllocCapacity(WpHashBucket, allocator, capacity, WP_ARRAY_INIT_FILLED);
|
||||||
|
|
||||||
|
wpRuntimeAssert(keys != NULL && buckets != NULL, "Failed to allocate keys, buckets or both");
|
||||||
|
|
||||||
if (table->has_values) {
|
if (table->has_values) {
|
||||||
values = arrayAllocCapacity(allocator, capacity, WP_ARRAY_INIT_NONE, value_size);
|
values = arrayAllocCapacity(allocator, capacity, WP_ARRAY_INIT_NONE, value_size);
|
||||||
|
wpRuntimeAssert(values != NULL, "Failed to allocate values");
|
||||||
}
|
}
|
||||||
|
|
||||||
WpArray old_keys = table->keys;
|
WpArray old_keys = table->keys;
|
||||||
@@ -212,27 +244,39 @@ void hashTableClear(WpHashTable *table, u64 key_size, u64 value_size) {
|
|||||||
wpArrayZero(WpHashBucket, table->buckets);
|
wpArrayZero(WpHashBucket, table->buckets);
|
||||||
}
|
}
|
||||||
|
|
||||||
WpHashBucketRef hashTableBucketRef(WpHashTable *table, u64 hash) {
|
void hashTableDealloc(const WpAllocator *allocator, WpHashTable *table, u64 key_size, u64 value_size) {
|
||||||
hashTableValidate(table, 0, 0);
|
wpDebugAssert(allocator != NULL, "`allocator` should not be NULL");
|
||||||
return (WpHashBucketRef){
|
hashTableValidate(table, key_size, value_size);
|
||||||
.dist_and_tag = WP_HASH_DIST_INC | (hash & WP_HASH_TAG_MASK),
|
arrayDealloc(allocator, table->keys, key_size);
|
||||||
.bucket_index = hash & table->bucket_mask,
|
wpArrayDealloc(WpHashBucket, allocator, table->buckets);
|
||||||
};
|
if (table->has_values) {
|
||||||
|
arrayDealloc(allocator, table->values, value_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 hashTableGetDist(u64 dist_and_tag) {
|
wp_persist inline void *hashTableGetKeyFromBucket(WpHashTable *table, WpHashBucket bucket, u64 key_size) {
|
||||||
|
hashTableValidate(table, key_size, 0);
|
||||||
|
return arrayGet(table->keys, bucket.item_index, key_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_persist inline void *hashTableGetValueFromBucket(WpHashTable *table, WpHashBucket bucket, u64 value_size) {
|
||||||
|
hashTableValidate(table, 0, value_size);
|
||||||
|
return table->has_values ? arrayGet(table->values, bucket.item_index, value_size) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_persist inline u64 hashTableGetDist(u64 dist_and_tag) {
|
||||||
return dist_and_tag & (~WP_HASH_TAG_MASK);
|
return dist_and_tag & (~WP_HASH_TAG_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 hashTableNextBucket(WpHashTable *table, u64 bucket_index) {
|
wp_persist inline u64 hashTableNextBucket(WpHashTable *table, u64 bucket_index) {
|
||||||
return (++bucket_index) & table->bucket_mask;
|
return (++bucket_index) & table->bucket_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 hashTableDistInc(u64 dist_and_tag) {
|
wp_persist inline u64 hashTableDistInc(u64 dist_and_tag) {
|
||||||
return dist_and_tag + WP_HASH_DIST_INC;
|
return dist_and_tag + WP_HASH_DIST_INC;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 hashTableDistDec(u64 dist_and_tag) {
|
wp_persist inline u64 hashTableDistDec(u64 dist_and_tag) {
|
||||||
return dist_and_tag - WP_HASH_DIST_INC;
|
return dist_and_tag - WP_HASH_DIST_INC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-11
@@ -69,18 +69,21 @@ typedef struct WpHashLookupResult {
|
|||||||
b8 found;
|
b8 found;
|
||||||
} WpHashLookupResult;
|
} WpHashLookupResult;
|
||||||
|
|
||||||
void *hashTableKeys(WpHashTable *table);
|
void hashTableAlloc(const WpAllocator *allocator, WpHashTable *table,
|
||||||
void *hashTableValues(WpHashTable *table);
|
WpHasher hasher, WpU8StreamEncoder encoder,
|
||||||
void *hashTableGetKeyFromBucket(WpHashTable *table, WpHashBucket bucket, u64 key_size);
|
WpKeyEqualTest key_eq, u64 capacity, u64 key_size,
|
||||||
void *hashTableGetValueFromBucket(WpHashTable *table, WpHashBucket bucket, u64 value_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 *hashTableGetKeyFromBucketRef(WpHashTable *table, WpHashBucketRef ref, u64 key_size);
|
||||||
void *hashTableGetValueFromBucketRef(WpHashTable *table, WpHashBucketRef ref, u64 value_size);
|
void *hashTableGetValueFromBucketRef(WpHashTable *table, WpHashBucketRef ref, u64 value_size);
|
||||||
u64 hashTableCapacity(WpHashTable *table);
|
u64 hashTableCapacity(WpHashTable *table);
|
||||||
u64 hashTableCount(WpHashTable *table);
|
u64 hashTableCount(WpHashTable *table);
|
||||||
u64 hashTableKeySize(WpHashTable *table);
|
u64 hashTableKeySize(WpHashTable *table);
|
||||||
u64 hashTableValueSize(WpHashTable *table);
|
u64 hashTableValueSize(WpHashTable *table);
|
||||||
u64 hashTableCalcHash(WpHashTable *table, void *key, u64 key_size);
|
void hashTableGrow(const WpAllocator *allocator, WpHashTable *table, u64 key_size,
|
||||||
void hashTableGrow(WpHashTable *table, const WpAllocator *allocator, u64 key_size,
|
|
||||||
u64 value_size);
|
u64 value_size);
|
||||||
WpHashLookupResult hashTableLookup(WpHashTable *table, void *key, WpHashBucketRef ref, u64 key_size);
|
WpHashLookupResult hashTableLookup(WpHashTable *table, void *key, WpHashBucketRef ref, u64 key_size);
|
||||||
void hashTableUpdate(WpHashTable *table, void *value, WpHashBucketRef ref, u64 value_size);
|
void hashTableUpdate(WpHashTable *table, void *value, WpHashBucketRef ref, u64 value_size);
|
||||||
@@ -88,11 +91,8 @@ void hashTableInsert(WpHashTable *table, void *key, void *value, W
|
|||||||
u64 key_size, u64 value_size);
|
u64 key_size, u64 value_size);
|
||||||
void hashTableRemove(WpHashTable *table, 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 hashTableClear(WpHashTable *table, u64 key_size, u64 value_size);
|
||||||
WpHashBucketRef hashTableBucketRef(WpHashTable *table, u64 hash);
|
void hashTableDealloc(const WpAllocator *allocator, WpHashTable *table, u64 key_size,
|
||||||
u64 hashTableGetDist(u64 dist_and_tag);
|
u64 value_size);
|
||||||
u64 hashTableNextBucket(WpHashTable *table, u64 bucket_index);
|
|
||||||
u64 hashTableDistInc(u64 dist_and_tag);
|
|
||||||
u64 hashTableDistDec(u64 dist_and_tag);
|
|
||||||
|
|
||||||
#ifdef WP_PLATFORM_CPP
|
#ifdef WP_PLATFORM_CPP
|
||||||
END_C_LINKAGE
|
END_C_LINKAGE
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "hash/hasher/murmur3.c"
|
#include "hash/hasher/murmur3.c"
|
||||||
#include "hash/hasher/siphash.c"
|
#include "hash/hasher/siphash.c"
|
||||||
#include "hash/table/table.c"
|
#include "hash/table/table.c"
|
||||||
|
#include "hash/set/set.c"
|
||||||
#include "queue/queue.c"
|
#include "queue/queue.c"
|
||||||
#include "stream/stream.c"
|
#include "stream/stream.c"
|
||||||
#include "mem/allocator/mem_allocator.c"
|
#include "mem/allocator/mem_allocator.c"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "hash/hasher/murmur3.h"
|
#include "hash/hasher/murmur3.h"
|
||||||
#include "hash/hasher/siphash.h"
|
#include "hash/hasher/siphash.h"
|
||||||
#include "hash/table/table.h"
|
#include "hash/table/table.h"
|
||||||
|
#include "hash/set/set.h"
|
||||||
#include "queue/queue.h"
|
#include "queue/queue.h"
|
||||||
#include "stream/stream.h"
|
#include "stream/stream.h"
|
||||||
#include "mem/allocator/mem_allocator.h"
|
#include "mem/allocator/mem_allocator.h"
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "wapp.h"
|
||||||
|
|
||||||
|
wp_persist inline WpU8Stream encoder(void *data);
|
||||||
|
wp_persist inline b8 key_eq(void *a, void *b);
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 8);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 8 && wpHashSetCount(&set) == 0;
|
||||||
|
set = wpHashSet(WpStr8, encoder, key_eq, 3);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 0;
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_alloc(void) {
|
||||||
|
WpAllocator arena = wpMemArenaAllocatorInit(KiB(4));
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSetAlloc(WpStr8, &arena, encoder, key_eq, 8);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 8 && wpHashSetCount(&set) == 0;
|
||||||
|
set = wpHashSetAlloc(WpStr8, &arena, encoder, key_eq, 3);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 0;
|
||||||
|
|
||||||
|
wpMemArenaAllocatorDestroy(&arena);
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_find(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 8);
|
||||||
|
WpStr8Array keys = wpArray(
|
||||||
|
WpStr8,
|
||||||
|
wpStr8Lit("key1"),
|
||||||
|
wpStr8Lit("key2"),
|
||||||
|
wpStr8Lit("key3"),
|
||||||
|
wpStr8Lit("key4")
|
||||||
|
);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpHashLookupResult res = wpHashSetFind(WpStr8, &set, &keys[3]);
|
||||||
|
|
||||||
|
result = result && res.found && res.ref.dist_and_tag > 0;
|
||||||
|
|
||||||
|
WpStr8 key = wpStr8Lit("key0");
|
||||||
|
res = wpHashSetFind(WpStr8, &set, &key);
|
||||||
|
result = result && !res.found;
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_insert_capped(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 4);
|
||||||
|
WpStr8Array keys = wpArray(
|
||||||
|
WpStr8,
|
||||||
|
wpStr8Lit("key1"),
|
||||||
|
wpStr8Lit("key2"),
|
||||||
|
wpStr8Lit("key3"),
|
||||||
|
wpStr8Lit("key4")
|
||||||
|
);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 3;
|
||||||
|
for (u64 i = 0; i < 3; ++i) {
|
||||||
|
result = result && wpStr8Equal(wpArrayGet(WpStr8, set.keys, i), &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_insert_alloc(void) {
|
||||||
|
WpAllocator arena = wpMemArenaAllocatorInit(KiB(4));
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 4);
|
||||||
|
WpStr8Array keys = wpArray(
|
||||||
|
WpStr8,
|
||||||
|
wpStr8Lit("key1"),
|
||||||
|
wpStr8Lit("key2"),
|
||||||
|
wpStr8Lit("key3"),
|
||||||
|
wpStr8Lit("key4")
|
||||||
|
);
|
||||||
|
|
||||||
|
WpStr8Array set_keys = set.keys;
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertAlloc(WpStr8, &arena, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result && set.keys != set_keys && wpHashSetCapacity(&set) == 8 && wpHashSetCount(&set) == 4;
|
||||||
|
for (u64 i = 0; i < 3; ++i) {
|
||||||
|
result = result && wpStr8Equal(&wpHashSetItems(WpStr8, &set)[i], &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpMemArenaAllocatorDestroy(&arena);
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_remove(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 4);
|
||||||
|
WpStr8Array keys = wpArray(
|
||||||
|
WpStr8,
|
||||||
|
wpStr8Lit("key1"),
|
||||||
|
wpStr8Lit("key2"),
|
||||||
|
wpStr8Lit("key3"),
|
||||||
|
wpStr8Lit("key4")
|
||||||
|
);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpHashSetRemove(WpStr8, &set, &keys[0]);
|
||||||
|
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 2;
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_clear(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 8);
|
||||||
|
WpStr8Array keys = wpArray(
|
||||||
|
WpStr8,
|
||||||
|
wpStr8Lit("key1"),
|
||||||
|
wpStr8Lit("key2"),
|
||||||
|
wpStr8Lit("key3"),
|
||||||
|
wpStr8Lit("key4")
|
||||||
|
);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpHashSetClear(WpStr8, &set);
|
||||||
|
|
||||||
|
result = result && wpHashSetCount(&set) == 0;
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_persist inline WpU8Stream encoder(void *data) {
|
||||||
|
WpStr8 *str = (WpStr8 *)data;
|
||||||
|
return wpStream(u8, str->buf, str->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_persist inline b8 key_eq(void *a, void *b) {
|
||||||
|
WpStr8 *a_str = (WpStr8 *)a;
|
||||||
|
WpStr8 *b_str = (WpStr8 *)b;
|
||||||
|
return wpStr8Equal(a_str, b_str);
|
||||||
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#include "wapp.h"
|
||||||
|
|
||||||
|
wp_persist inline WpU8Stream encoder(void *data);
|
||||||
|
wp_persist inline b8 key_eq(void *a, void *b);
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 8);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 8 && wpHashSetCount(&set) == 0;
|
||||||
|
set = wpHashSet(WpStr8, encoder, key_eq, 3);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 0;
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_alloc(void) {
|
||||||
|
WpAllocator arena = wpMemArenaAllocatorInit(KiB(4));
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSetAlloc(WpStr8, &arena, encoder, key_eq, 8);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 8 && wpHashSetCount(&set) == 0;
|
||||||
|
set = wpHashSetAlloc(WpStr8, &arena, encoder, key_eq, 3);
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 0;
|
||||||
|
|
||||||
|
wpMemArenaAllocatorDestroy(&arena);
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_find(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 8);
|
||||||
|
WpStr8 key1 = wpStr8Lit("key1");
|
||||||
|
WpStr8 key2 = wpStr8Lit("key2");
|
||||||
|
WpStr8 key3 = wpStr8Lit("key3");
|
||||||
|
WpStr8 key4 = wpStr8Lit("key4");
|
||||||
|
WpStr8Array keys = wpArray(WpStr8, key1, key2, key3, key4);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpHashLookupResult res = wpHashSetFind(WpStr8, &set, &keys[3]);
|
||||||
|
|
||||||
|
result = result && res.found && res.ref.dist_and_tag > 0;
|
||||||
|
|
||||||
|
WpStr8 key = wpStr8Lit("key0");
|
||||||
|
res = wpHashSetFind(WpStr8, &set, &key);
|
||||||
|
result = result && !res.found;
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_insert_capped(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 4);
|
||||||
|
WpStr8 key1 = wpStr8Lit("key1");
|
||||||
|
WpStr8 key2 = wpStr8Lit("key2");
|
||||||
|
WpStr8 key3 = wpStr8Lit("key3");
|
||||||
|
WpStr8 key4 = wpStr8Lit("key4");
|
||||||
|
WpStr8Array keys = wpArray(WpStr8, key1, key2, key3, key4);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 3;
|
||||||
|
for (u64 i = 0; i < 3; ++i) {
|
||||||
|
result = result && wpStr8Equal(wpArrayGet(WpStr8, set.keys, i), &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_insert_alloc(void) {
|
||||||
|
WpAllocator arena = wpMemArenaAllocatorInit(KiB(4));
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 4);
|
||||||
|
WpStr8 key1 = wpStr8Lit("key1");
|
||||||
|
WpStr8 key2 = wpStr8Lit("key2");
|
||||||
|
WpStr8 key3 = wpStr8Lit("key3");
|
||||||
|
WpStr8 key4 = wpStr8Lit("key4");
|
||||||
|
WpStr8Array keys = wpArray(WpStr8, key1, key2, key3, key4);
|
||||||
|
|
||||||
|
WpStr8Array set_keys = (WpStr8Array)set.keys;
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertAlloc(WpStr8, &arena, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = result && set.keys != set_keys && wpHashSetCapacity(&set) == 8 && wpHashSetCount(&set) == 4;
|
||||||
|
for (u64 i = 0; i < 3; ++i) {
|
||||||
|
result = result && wpStr8Equal(&wpHashSetItems(WpStr8, &set)[i], &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpMemArenaAllocatorDestroy(&arena);
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_remove(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 4);
|
||||||
|
WpStr8 key1 = wpStr8Lit("key1");
|
||||||
|
WpStr8 key2 = wpStr8Lit("key2");
|
||||||
|
WpStr8 key3 = wpStr8Lit("key3");
|
||||||
|
WpStr8 key4 = wpStr8Lit("key4");
|
||||||
|
WpStr8Array keys = wpArray(WpStr8, key1, key2, key3, key4);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpHashSetRemove(WpStr8, &set, &keys[0]);
|
||||||
|
|
||||||
|
result = result && wpHashSetCapacity(&set) == 4 && wpHashSetCount(&set) == 2;
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset_clear(void) {
|
||||||
|
b8 result = true;
|
||||||
|
WpHashSet set = wpHashSet(WpStr8, encoder, key_eq, 8);
|
||||||
|
WpStr8 key1 = wpStr8Lit("key1");
|
||||||
|
WpStr8 key2 = wpStr8Lit("key2");
|
||||||
|
WpStr8 key3 = wpStr8Lit("key3");
|
||||||
|
WpStr8 key4 = wpStr8Lit("key4");
|
||||||
|
WpStr8Array keys = wpArray(WpStr8, key1, key2, key3, key4);
|
||||||
|
|
||||||
|
for (u64 i = 0; i < wpArrayCount(keys); ++i) {
|
||||||
|
wpHashSetInsertCapped(WpStr8, &set, &keys[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpHashSetClear(WpStr8, &set);
|
||||||
|
|
||||||
|
result = result && wpHashSetCount(&set) == 0;
|
||||||
|
|
||||||
|
return wpTesterResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_persist inline WpU8Stream encoder(void *data) {
|
||||||
|
WpStr8 *str = (WpStr8 *)data;
|
||||||
|
return wpStream(u8, str->buf, str->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_persist inline b8 key_eq(void *a, void *b) {
|
||||||
|
WpStr8 *a_str = (WpStr8 *)a;
|
||||||
|
WpStr8 *b_str = (WpStr8 *)b;
|
||||||
|
return wpStr8Equal(a_str, b_str);
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// vim:fileencoding=utf-8:foldmethod=marker
|
||||||
|
|
||||||
|
#ifndef TEST_HASHSET_H
|
||||||
|
#define TEST_HASHSET_H
|
||||||
|
|
||||||
|
#include "wapp.h"
|
||||||
|
|
||||||
|
WpTestFuncResult test_hashset(void);
|
||||||
|
WpTestFuncResult test_hashset_alloc(void);
|
||||||
|
WpTestFuncResult test_hashset_find(void);
|
||||||
|
WpTestFuncResult test_hashset_insert_capped(void);
|
||||||
|
WpTestFuncResult test_hashset_insert_alloc(void);
|
||||||
|
WpTestFuncResult test_hashset_remove(void);
|
||||||
|
WpTestFuncResult test_hashset_clear(void);
|
||||||
|
|
||||||
|
#endif // !TEST_HASHSET_H
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "test_cpath.h"
|
#include "test_cpath.h"
|
||||||
#include "test_file.h"
|
#include "test_file.h"
|
||||||
#include "test_hasher.h"
|
#include "test_hasher.h"
|
||||||
|
#include "test_hashset.h"
|
||||||
#include "test_shell_commander.h"
|
#include "test_shell_commander.h"
|
||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -105,6 +106,13 @@ int main(void) {
|
|||||||
test_wapp_file_remove,
|
test_wapp_file_remove,
|
||||||
test_murmur3,
|
test_murmur3,
|
||||||
test_siphash_128,
|
test_siphash_128,
|
||||||
|
test_hashset,
|
||||||
|
test_hashset_alloc,
|
||||||
|
test_hashset_find,
|
||||||
|
test_hashset_insert_capped,
|
||||||
|
test_hashset_insert_alloc,
|
||||||
|
test_hashset_remove,
|
||||||
|
test_hashset_clear,
|
||||||
test_commander_cmd_success,
|
test_commander_cmd_success,
|
||||||
test_commander_cmd_failure,
|
test_commander_cmd_failure,
|
||||||
test_commander_cmd_out_buf_success,
|
test_commander_cmd_out_buf_success,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "test_cpath.h"
|
#include "test_cpath.h"
|
||||||
#include "test_file.h"
|
#include "test_file.h"
|
||||||
#include "test_hasher.h"
|
#include "test_hasher.h"
|
||||||
|
#include "test_hashset.h"
|
||||||
#include "test_shell_commander.h"
|
#include "test_shell_commander.h"
|
||||||
#include "wapp.h"
|
#include "wapp.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -105,6 +106,13 @@ int main(void) {
|
|||||||
test_wapp_file_remove,
|
test_wapp_file_remove,
|
||||||
test_murmur3,
|
test_murmur3,
|
||||||
test_siphash_128,
|
test_siphash_128,
|
||||||
|
test_hashset,
|
||||||
|
test_hashset_alloc,
|
||||||
|
test_hashset_find,
|
||||||
|
test_hashset_insert_capped,
|
||||||
|
test_hashset_insert_alloc,
|
||||||
|
test_hashset_remove,
|
||||||
|
test_hashset_clear,
|
||||||
test_commander_cmd_success,
|
test_commander_cmd_success,
|
||||||
test_commander_cmd_failure,
|
test_commander_cmd_failure,
|
||||||
test_commander_cmd_out_buf_success,
|
test_commander_cmd_out_buf_success,
|
||||||
|
|||||||
Reference in New Issue
Block a user