Convert hasher to interface and remove spihash64
Release / release (push) Successful in 3s

This commit is contained in:
Abdelrahman Said
2026-09-16 01:08:06 +01:00
parent 8b3b1816b3
commit f73a870a34
12 changed files with 31 additions and 164 deletions
+5 -1
View File
@@ -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
+5 -34
View File
@@ -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];
}
+5 -24
View File
@@ -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
+4
View File
@@ -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);
+1
View File
@@ -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
+10 -21
View File
@@ -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 *)&params->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) {
+1 -1
View File
@@ -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
-40
View File
@@ -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);
}
-40
View File
@@ -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);
}
-1
View File
@@ -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
-1
View File
@@ -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,
-1
View File
@@ -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,