This commit is contained in:
+5
-1
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user