From f73a870a348afb77a27cfd8defd8a62d433ebe2a Mon Sep 17 00:00:00 2001 From: Abdelrahman Said Date: Wed, 16 Sep 2026 01:08:06 +0100 Subject: [PATCH] Convert hasher to interface and remove spihash64 --- CHANGELOG.md | 6 ++++- src/base/hash/hasher/hasher.c | 39 +++++---------------------------- src/base/hash/hasher/hasher.h | 29 +++++------------------- src/base/hash/hasher/murmur3.c | 4 ++++ src/base/hash/hasher/murmur3.h | 1 + src/base/hash/hasher/siphash.c | 31 +++++++++----------------- src/base/hash/hasher/siphash.h | 2 +- tests/hasher/test_hasher.c | 40 ---------------------------------- tests/hasher/test_hasher.cc | 40 ---------------------------------- tests/hasher/test_hasher.h | 1 - tests/wapptest.c | 1 - tests/wapptest.cc | 1 - 12 files changed, 31 insertions(+), 164 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65bc119..d620b55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `wpMiscUtilsRotl64` utility +- `WpHasher` interface +- `wpHasherGetHash128` and `wpHasherGetHash64` utilities - `wpMur3HasherData` to setup the MurmurHash3 data struct +- `wpX64Mur3Hasher` constructor for the hasher interface - `wpX64Mur3Hasher128` implementation for the x64 128-bit variant of the MurmurHash3 algorithm - `wpSip24HasherData` and `wpSip48HasherData` to setup the siphash data structs for the different variants -- `wpSipHasher128` and `wpSipHasher64` implementation for the 128 and 64 variants of siphash +- `wpSipHasher` constructor for the hasher interface +- `wpSipHasher128` implementation for the 128 variant of siphash - Add `wpU8Const`, `wpU16Const`, `wpU32Const`, `wpU64Const`, `wpI8Const`, `wpI16Const`, `wpI32Const`, and `wpI64Const` - `wpPrngXorshiftInitWithSeed` to allow for user control with PRNG - `wpPrngXorshift256InRange`, `wpPrngXorshift256ssInRange`, `wpPrngXorshift256pInRange`, `wpPrngXorshift256Choice`, `wpPrngXorshift256ssChoice` and `wpPrngXorshift256pChoice` utilities diff --git a/src/base/hash/hasher/hasher.c b/src/base/hash/hasher/hasher.c index fc4f227..2c18714 100644 --- a/src/base/hash/hasher/hasher.c +++ b/src/base/hash/hasher/hasher.c @@ -3,42 +3,13 @@ #include "hasher.h" #include "../../../common/assert/assert.h" -WpU128Hash wpHasherGetHash128(const WpHasher *hasher, WpU8Stream *stream, void *hasher_data) { +WpU128Hash wpHasherGetHash128(const WpHasher *hasher, WpU8Stream *stream) { wpDebugAssert(hasher != NULL && stream != NULL, "hasher and stream shouldn't be NULL"); - - WpU128Hash output; - switch (hasher->type) { - case WP_HASH_TYPE_64: { - output.hash[0] = hasher->hasher_64(stream, hasher_data); - output.hash[1] = hasher->hasher_64(stream, hasher_data); - } break; - case WP_HASH_TYPE_128: { - output = hasher->hasher_128(stream, hasher_data); - } break; - default: { - wpRuntimeAssert(0, "Invalid hasher type"); - } break; - } - - return output; + return hasher->func(stream, hasher->data); } -u64 wpHasherGetHash64(const WpHasher *hasher, WpU8Stream *stream, void *hasher_data) { +u64 wpHasherGetHash64(const WpHasher *hasher, WpU8Stream *stream) { wpDebugAssert(hasher != NULL && stream != NULL, "hasher and stream shouldn't be NULL"); - - u64 output; - switch (hasher->type) { - case WP_HASH_TYPE_64: { - output = hasher->hasher_64(stream, hasher_data); - } break; - case WP_HASH_TYPE_128: { - WpU128Hash hash = hasher->hasher_128(stream, hasher_data); - output = hash.hash[0] ^ hash.hash[1]; - } break; - default: { - wpRuntimeAssert(0, "Invalid hasher type"); - } break; - } - - return output; + WpU128Hash result = hasher->func(stream, hasher->data); + return result.hash[0] ^ result.hash[1]; } diff --git a/src/base/hash/hasher/hasher.h b/src/base/hash/hasher/hasher.h index a7ae456..66ce4b7 100644 --- a/src/base/hash/hasher/hasher.h +++ b/src/base/hash/hasher/hasher.h @@ -13,34 +13,15 @@ typedef struct WpU128Hash { u64 hash[2]; } WpU128Hash; -typedef enum WpHasherType { - WP_HASH_TYPE_64, - WP_HASH_TYPE_128, - - COUNT_HASH_TYPES, -} WpHasherType; - -typedef u64 (*WpHasher64) (WpU8Stream *stream, void *hasher_data); -typedef WpU128Hash (*WpHasher128)(WpU8Stream *stream, void *hasher_data); +typedef WpU128Hash (*WpHashFunc)(WpU8Stream *stream, void *hasher_data); typedef struct WpHasher { - WpHasherType type; - union { - WpHasher64 hasher_64; - WpHasher128 hasher_128; - }; + WpHashFunc func; + void *data; } WpHasher; -#ifdef WP_PLATFORM_CPP -#define wpHasher64(HASHER) (WpHasher{ WP_HASH_TYPE_64, (HASHER) }) -#define wpHasher128(HASHER) (WpHasher{ WP_HASH_TYPE_128, (HASHER) }) -#else -#define wpHasher64(HASHER) ((WpHasher){ .type = WP_HASH_TYPE_64, .hasher_64 = (HASHER) }) -#define wpHasher128(HASHER) ((WpHasher){ .type = WP_HASH_TYPE_128, .hasher_128 = (HASHER) }) -#endif - -WpU128Hash wpHasherGetHash128(const WpHasher *hasher, WpU8Stream *stream, void *hasher_data); -u64 wpHasherGetHash64 (const WpHasher *hasher, WpU8Stream *stream, void *hasher_data); +WpU128Hash wpHasherGetHash128(const WpHasher *hasher, WpU8Stream *stream); +u64 wpHasherGetHash64 (const WpHasher *hasher, WpU8Stream *stream); #ifdef WP_PLATFORM_CPP END_C_LINKAGE diff --git a/src/base/hash/hasher/murmur3.c b/src/base/hash/hasher/murmur3.c index b00f5d1..1167b8d 100644 --- a/src/base/hash/hasher/murmur3.c +++ b/src/base/hash/hasher/murmur3.c @@ -9,6 +9,10 @@ wp_intern inline void validateMur3HasherData(const WpMur3HasherData *io); wp_intern inline u64 fmix64(u64 k); +WpHasher wpX64Mur3Hasher(WpMur3HasherData *data) { + return (WpHasher){ .func = wpX64Mur3Hasher128, .data = (void *)data }; +} + WpU128Hash wpX64Mur3Hasher128(WpU8Stream *bytes, void *hasher_io) { WpMur3HasherData *io = (WpMur3HasherData *)hasher_io; validateMur3HasherData(io); diff --git a/src/base/hash/hasher/murmur3.h b/src/base/hash/hasher/murmur3.h index 1d1efd2..03870fb 100644 --- a/src/base/hash/hasher/murmur3.h +++ b/src/base/hash/hasher/murmur3.h @@ -30,6 +30,7 @@ typedef struct WpMur3HasherData { #define wpMur3HasherData(SEED) ((WpMur3HasherData){ .magic = WP_MUR3_HASHER_MAGIC, .seed = SEED }) #endif +WpHasher wpX64Mur3Hasher(WpMur3HasherData *data); WpU128Hash wpX64Mur3Hasher128(WpU8Stream *bytes, void *hasher_io); #ifdef WP_PLATFORM_CPP diff --git a/src/base/hash/hasher/siphash.c b/src/base/hash/hasher/siphash.c index b4aefec..70916f3 100644 --- a/src/base/hash/hasher/siphash.c +++ b/src/base/hash/hasher/siphash.c @@ -44,6 +44,10 @@ wp_intern inline b8 checkRounds(const WpSipHasherData *params); v2 = wpMiscUtilsRotl64(v2, 32); \ } while (0) +WpHasher wpSipHasher(WpSipHasherData *data) { + return (WpHasher){ .func = wpSipHasher128, .data = (void *)data }; +} + WpU128Hash wpSipHasher128(WpStream *bytes, void *hasher_data) { WpSipHasherData *data = (WpSipHasherData *)hasher_data; validateSipHasherData(data); @@ -52,20 +56,15 @@ WpU128Hash wpSipHasher128(WpStream *bytes, void *hasher_data) { return output; } -u64 wpSipHasher64(WpStream *bytes, void *hasher_data) { - WpSipHasherData *data = (WpSipHasherData *)hasher_data; - validateSipHasherData(data); - u64 output = 0; - siphash(bytes, data, (u8 *)&output, sizeof(u64)); - return output; -} - +/** + * Implementation of the 128-variant of the siphash algorithm + */ wp_intern inline void siphash(WpStream *bytes, const WpSipHasherData *params, u8 *out, u64 outlen) { const u8 *kk = (const u8 *)¶ms->key; u64 inlen = bytes->count * bytes->item_size; - wpRuntimeAssert((outlen == 8) || (outlen == 16), "outlen should be 8 or 16"); + wpRuntimeAssert(outlen == 16, "outlen should be 16"); u64 v0 = wpU64Const(0x736f6d6570736575); u64 v1 = wpU64Const(0x646f72616e646f6d); @@ -82,9 +81,7 @@ wp_intern inline void siphash(WpStream *bytes, const WpSipHasherData *params, u8 v1 ^= k1; v0 ^= k0; - if (outlen == 16) { - v1 ^= 0xee; - } + v1 ^= 0xee; u8 *data; while (wpStreamHasCount(bytes, sizeof(u64))) { @@ -134,11 +131,7 @@ wp_intern inline void siphash(WpStream *bytes, const WpSipHasherData *params, u8 v0 ^= b; - if (outlen == 16) { - v2 ^= 0xee; - } else { - v2 ^= 0xff; - } + v2 ^= 0xee; for (i = 0; i < params->finalisation; ++i) { _sipRound; @@ -147,10 +140,6 @@ wp_intern inline void siphash(WpStream *bytes, const WpSipHasherData *params, u8 b = v0 ^ v1 ^ v2 ^ v3; _u64To8LE(out, b); - if (outlen == 8) { - return; - } - v1 ^= 0xdd; for (i = 0; i < params->finalisation; ++i) { diff --git a/src/base/hash/hasher/siphash.h b/src/base/hash/hasher/siphash.h index 54562e0..8abae82 100644 --- a/src/base/hash/hasher/siphash.h +++ b/src/base/hash/hasher/siphash.h @@ -49,8 +49,8 @@ typedef struct WpSipHasherData { }) #endif +WpHasher wpSipHasher(WpSipHasherData *data); WpU128Hash wpSipHasher128(WpU8Stream *bytes, void *hasher_io); -u64 wpSipHasher64(WpU8Stream *bytes, void *hasher_io); #ifdef WP_PLATFORM_CPP END_C_LINKAGE diff --git a/tests/hasher/test_hasher.c b/tests/hasher/test_hasher.c index 0559efc..c6a65e5 100644 --- a/tests/hasher/test_hasher.c +++ b/tests/hasher/test_hasher.c @@ -80,43 +80,3 @@ WpTestFuncResult test_siphash_128(void) { return wpTesterResult(result); } - -WpTestFuncResult test_siphash_64(void) { - b8 result = true; - - WpStr8 str = wpStr8Lit("Hello world"); - WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5); - u64 num = 287324; - - WpSipHasherKey key = { .lo = 238742, .hi = 671734 }; - WpSipHasherData data = wpSip24HasherData(key); - - WpU8Stream str_bytes = wpStream(u8, str.buf, str.size); - WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr)); - WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64)); - - u64 hash = {0}; - - // Sring hash - u64 sip_hash = wpSipHasher64(&str_bytes, (void *)&data); - siphash(str_bytes.data, str_bytes.count * str_bytes.item_size, (void *)&data.key, - (u8 *)&hash, sizeof(u64)); - - result = result && sip_hash == hash; - - // Array hash - sip_hash = wpSipHasher64(&arr_bytes, (void *)&data); - siphash(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, (void *)&data.key, - (u8 *)&hash, sizeof(u64)); - - result = result && sip_hash == hash; - - // Number hash - sip_hash = wpSipHasher64(&num_bytes, (void *)&data); - siphash(num_bytes.data, num_bytes.count * num_bytes.item_size, (void *)&data.key, - (u8 *)&hash, sizeof(u64)); - - result = result && sip_hash == hash; - - return wpTesterResult(result); -} diff --git a/tests/hasher/test_hasher.cc b/tests/hasher/test_hasher.cc index 2297d32..7084641 100644 --- a/tests/hasher/test_hasher.cc +++ b/tests/hasher/test_hasher.cc @@ -80,43 +80,3 @@ WpTestFuncResult test_siphash_128(void) { return wpTesterResult(result); } - -WpTestFuncResult test_siphash_64(void) { - b8 result = true; - - WpStr8 str = wpStr8Lit("Hello world"); - WpI32Array arr = wpArray(i32, 1, 2, 3, 4, 5); - u64 num = 287324; - - WpSipHasherKey key = { 238742, 671734 }; - WpSipHasherData data = wpSip24HasherData(key); - - WpU8Stream str_bytes = wpStream(u8, str.buf, str.size); - WpU8Stream arr_bytes = wpStream(u8, (u8 *)arr, wpArrayCount(arr) * wpArrayItemSize(arr)); - WpU8Stream num_bytes = wpStream(u8, (u8 *)&num, sizeof(u64)); - - u64 hash = {0}; - - // Sring hash - u64 sip_hash = wpSipHasher64(&str_bytes, (void *)&data); - siphash(str_bytes.data, str_bytes.count * str_bytes.item_size, (void *)&data.key, - (u8 *)&hash, sizeof(u64)); - - result = result && sip_hash == hash; - - // Array hash - sip_hash = wpSipHasher64(&arr_bytes, (void *)&data); - siphash(arr_bytes.data, arr_bytes.count * arr_bytes.item_size, (void *)&data.key, - (u8 *)&hash, sizeof(u64)); - - result = result && sip_hash == hash; - - // Number hash - sip_hash = wpSipHasher64(&num_bytes, (void *)&data); - siphash(num_bytes.data, num_bytes.count * num_bytes.item_size, (void *)&data.key, - (u8 *)&hash, sizeof(u64)); - - result = result && sip_hash == hash; - - return wpTesterResult(result); -} diff --git a/tests/hasher/test_hasher.h b/tests/hasher/test_hasher.h index b738fb9..db1cd75 100644 --- a/tests/hasher/test_hasher.h +++ b/tests/hasher/test_hasher.h @@ -10,6 +10,5 @@ WpTestFuncResult test_murmur3(void); // Test Sip hash implementation against the reference implementation WpTestFuncResult test_siphash_128(void); -WpTestFuncResult test_siphash_64(void); #endif // !TEST_HASHER_H diff --git a/tests/wapptest.c b/tests/wapptest.c index 1e86f3d..ea44e46 100644 --- a/tests/wapptest.c +++ b/tests/wapptest.c @@ -104,7 +104,6 @@ int main(void) { test_wapp_file_remove, test_murmur3, test_siphash_128, - test_siphash_64, test_commander_cmd_success, test_commander_cmd_failure, test_commander_cmd_out_buf_success, diff --git a/tests/wapptest.cc b/tests/wapptest.cc index 1e86f3d..ea44e46 100644 --- a/tests/wapptest.cc +++ b/tests/wapptest.cc @@ -104,7 +104,6 @@ int main(void) { test_wapp_file_remove, test_murmur3, test_siphash_128, - test_siphash_64, test_commander_cmd_success, test_commander_cmd_failure, test_commander_cmd_out_buf_success,