aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2021-09-15 20:05:44 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2021-09-15 20:06:07 +0200
commit662d27b79650176d27cdc5589a0862a33dbcc313 (patch)
tree617abf65fd96de7cae8db4883027f325a44c8212 /core
parentde00c7c9a8e428d3510fb81ea09f4c3519509d18 (diff)
Finish xxHash implementation.
Diffstat (limited to 'core')
-rw-r--r--core/hash/xxhash/common.odin2
-rw-r--r--core/hash/xxhash/streaming.odin372
-rw-r--r--core/hash/xxhash/xxhash_3.odin596
-rw-r--r--core/hash/xxhash/xxhash_32.odin10
-rw-r--r--core/hash/xxhash/xxhash_64.odin10
5 files changed, 439 insertions, 551 deletions
diff --git a/core/hash/xxhash/common.odin b/core/hash/xxhash/common.odin
index 434ebb905..908dfaa87 100644
--- a/core/hash/xxhash/common.odin
+++ b/core/hash/xxhash/common.odin
@@ -41,7 +41,7 @@ Alignment :: enum {
}
Error :: enum {
- Okay = 0,
+ None = 0,
Error,
}
diff --git a/core/hash/xxhash/streaming.odin b/core/hash/xxhash/streaming.odin
new file mode 100644
index 000000000..95ff38f78
--- /dev/null
+++ b/core/hash/xxhash/streaming.odin
@@ -0,0 +1,372 @@
+/*
+ An implementation of Yann Collet's [xxhash Fast Hash Algorithm](https://cyan4973.github.io/xxHash/).
+ Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
+
+ Made available under Odin's BSD-3 license, based on the original C code.
+
+ List of contributors:
+ Jeroen van Rijn: Initial implementation.
+*/
+package xxhash
+
+import "core:mem"
+import "core:intrinsics"
+
+/*
+ === XXH3 128-bit streaming ===
+
+ All the functions are actually the same as for 64-bit streaming variant.
+ The only difference is the finalization routine.
+*/
+XXH3_128_reset :: proc(state: ^XXH3_state) -> (err: Error) {
+ if state == nil {
+ return .Error
+ }
+ XXH3_reset_internal(state, 0, XXH3_kSecret[:])
+ return .None
+}
+XXH3_64_reset :: XXH3_128_reset
+
+XXH3_128_reset_with_secret :: proc(state: ^XXH3_state, secret: []u8) -> (err: Error) {
+ if state == nil {
+ return .Error
+ }
+ if secret == nil || len(secret) < XXH3_SECRET_SIZE_MIN {
+ return .Error
+ }
+ XXH3_reset_internal(state, 0, secret)
+ return .None
+}
+XXH3_64_reset_with_secret :: XXH3_128_reset_with_secret
+
+XXH3_128_reset_with_seed :: proc(state: ^XXH3_state, seed: XXH64_hash) -> (err: Error) {
+ if seed == 0 {
+ return XXH3_128_reset(state)
+ }
+ if seed != state.seed {
+ XXH3_init_custom_secret(state.custom_secret[:], seed)
+ }
+
+ XXH3_reset_internal(state, seed, nil)
+ return .None
+}
+XXH3_64_reset_with_seed :: XXH3_128_reset_with_seed
+
+XXH3_128_update :: proc(state: ^XXH3_state, input: []u8) -> (err: Error) {
+ return XXH3_update(state, input, XXH3_accumulate_512, XXH3_scramble_accumulator)
+}
+
+XXH3_128_digest :: proc(state: ^XXH3_state) -> (hash: XXH3_128_hash) {
+ secret := state.custom_secret[:] if len(state.external_secret) == 0 else state.external_secret[:]
+
+ if state.total_length > XXH3_MIDSIZE_MAX {
+ acc: [XXH_ACC_NB]XXH64_hash
+ XXH3_digest_long(acc[:], state, secret)
+
+ assert(state.secret_limit + XXH_STRIPE_LEN >= XXH_ACC_NB + XXH_SECRET_MERGEACCS_START)
+ {
+ h128 := XXH128_hash_t{}
+
+ h128.low = XXH3_mergeAccs(
+ acc[:],
+ secret[XXH_SECRET_MERGEACCS_START:],
+ state.total_length * XXH_PRIME64_1)
+
+ h128.high = XXH3_mergeAccs(
+ acc[:],
+ secret[state.secret_limit + XXH_STRIPE_LEN - size_of(acc) - XXH_SECRET_MERGEACCS_START:],
+ ~(u64(state.total_length) * XXH_PRIME64_2))
+
+ return h128.h
+ }
+ }
+ /* len <= XXH3_MIDSIZE_MAX : short code */
+ if state.seed != 0 {
+ return XXH3_128_with_seed(state.buffer[:state.total_length], state.seed)
+ }
+ return XXH3_128_with_secret(state.buffer[:state.total_length], secret[:state.secret_limit + XXH_STRIPE_LEN])
+}
+
+/*====== Canonical representation ======*/
+
+XXH3_128_canonical_from_hash :: proc(hash: XXH128_hash_t) -> (canonical: XXH128_canonical) {
+ #assert(size_of(XXH128_canonical) == size_of(XXH128_hash_t))
+
+ t := hash
+ when ODIN_ENDIAN == "little" {
+ t.high = byte_swap(t.high)
+ t.low = byte_swap(t.low)
+ }
+ mem_copy(&canonical.digest, &t.high, size_of(u64))
+ mem_copy(&canonical.digest[8], &t.low, size_of(u64))
+ return
+}
+
+XXH3_128_hash_from_canonical :: proc(src: ^XXH128_canonical) -> (hash: u128) {
+ h := XXH128_hash_t{}
+
+ high := (^u64be)(&src.digest[0])^
+ low := (^u64be)(&src.digest[8])^
+
+ h.high = u64(high)
+ h.low = u64(low)
+ return h.h
+}
+
+/* === XXH3 streaming === */
+
+XXH3_init_state :: proc(state: ^XXH3_state) {
+ state.seed = 0
+}
+
+XXH3_create_state :: proc(allocator := context.allocator) -> (res: ^XXH3_state, err: Error) {
+ state, mem_error := mem.new_aligned(XXH3_state, 64, allocator)
+ err = nil if mem_error == nil else .Error
+
+ XXH3_init_state(state)
+ return state, nil
+}
+
+XXH3_destroy_state :: proc(state: ^XXH3_state, allocator := context.allocator) -> (err: Error) {
+ free(state)
+ return .None
+}
+
+XXH3_copy_state :: proc(dest, src: ^XXH3_state) {
+ assert(dest != nil && src != nil)
+ mem_copy(dest, src, size_of(XXH3_state))
+}
+
+XXH3_reset_internal :: proc(state: ^XXH3_state, seed: XXH64_hash, secret: []u8) {
+ assert(state != nil)
+
+ init_start := offset_of(XXH3_state, buffered_size)
+ init_length := offset_of(XXH3_state, stripes_per_block) - init_start
+
+ assert(offset_of(XXH3_state, stripes_per_block) > init_start)
+
+ /*
+ Set members from buffered_size to stripes_per_block (excluded) to 0
+ */
+ offset := rawptr(uintptr(state) + uintptr(init_start))
+ intrinsics.mem_zero(offset, init_length)
+
+ state.acc[0] = XXH_PRIME32_3
+ state.acc[1] = XXH_PRIME64_1
+ state.acc[2] = XXH_PRIME64_2
+ state.acc[3] = XXH_PRIME64_3
+ state.acc[4] = XXH_PRIME64_4
+ state.acc[5] = XXH_PRIME32_2
+ state.acc[6] = XXH_PRIME64_5
+ state.acc[7] = XXH_PRIME32_1
+ state.seed = seed
+ state.external_secret = secret
+
+ secret_length := uint(len(secret))
+ assert(secret_length > XXH3_SECRET_SIZE_MIN)
+
+ state.secret_limit = secret_length - XXH_STRIPE_LEN
+ state.stripes_per_block = state.secret_limit / XXH_SECRET_CONSUME_RATE
+}
+
+/*
+ Note: when XXH3_consumeStripes() is invoked, there must be a guarantee that at least
+ one more byte must be consumed from input so that the function can blindly consume
+ all stripes using the "normal" secret segment.
+*/
+
+XXH3_consume_stripes :: #force_inline proc(
+ acc: []xxh_u64, stripes_so_far: ^uint, stripes_per_block: uint, input: []u8,
+ number_of_stripes: uint, secret: []u8, secret_limit: uint,
+ f_acc512: XXH3_accumulate_512_f, f_scramble: XXH3_scramble_accumulator_f) {
+
+ assert(number_of_stripes <= stripes_per_block) /* can handle max 1 scramble per invocation */
+ assert(stripes_so_far^ < stripes_per_block)
+
+ if stripes_per_block - stripes_so_far^ <= number_of_stripes {
+ /* need a scrambling operation */
+ stripes_to_end_of_block := stripes_per_block - stripes_so_far^
+ stripes_after_block := number_of_stripes - stripes_to_end_of_block
+
+ XXH3_accumulate(acc, input, secret[stripes_so_far^ * XXH_SECRET_CONSUME_RATE:], stripes_to_end_of_block, f_acc512)
+
+ f_scramble(acc, secret[secret_limit:])
+ XXH3_accumulate(acc, input[stripes_to_end_of_block * XXH_STRIPE_LEN:], secret, stripes_after_block, f_acc512)
+ stripes_so_far^ = stripes_after_block
+ } else {
+ XXH3_accumulate(acc, input, secret[stripes_so_far^ * XXH_SECRET_CONSUME_RATE:], number_of_stripes, f_acc512)
+ stripes_so_far^ += number_of_stripes
+ }
+}
+
+/*
+ Both XXH3_64bits_update and XXH3_128bits_update use this routine.
+*/
+XXH3_update :: #force_inline proc(
+ state: ^XXH3_state, input: []u8,
+ f_acc512: XXH3_accumulate_512_f,
+ f_scramble: XXH3_scramble_accumulator_f) -> (err: Error) {
+
+ input := input
+ length := len(input)
+ secret := state.custom_secret[:] if len(state.external_secret) == 0 else state.external_secret[:]
+
+ state.total_length += u64(length)
+ assert(state.buffered_size <= XXH3_INTERNAL_BUFFER_SIZE)
+
+ if int(state.buffered_size) + length <= XXH3_INTERNAL_BUFFER_SIZE { /* fill in tmp buffer */
+ mem_copy(&state.buffer[state.buffered_size], &input[0], length)
+ state.buffered_size += u32(length)
+ return .None
+ }
+
+ /* total input is now > XXH3_INTERNAL_BUFFER_SIZE */
+ XXH3_INTERNAL_BUFFER_STRIPES :: XXH3_INTERNAL_BUFFER_SIZE / XXH_STRIPE_LEN
+ #assert(XXH3_INTERNAL_BUFFER_SIZE % XXH_STRIPE_LEN == 0) /* clean multiple */
+
+ /*
+ Internal buffer is partially filled (always, except at beginning)
+ Complete it, then consume it.
+ */
+ if state.buffered_size > 0 {
+ load_size := int(XXH3_INTERNAL_BUFFER_SIZE - state.buffered_size)
+ mem_copy(&state.buffer[state.buffered_size], &input[0], load_size)
+ input = input[load_size:]
+
+ XXH3_consume_stripes(
+ state.acc[:], &state.stripes_so_far, state.stripes_per_block,
+ state.buffer[:], XXH3_INTERNAL_BUFFER_STRIPES,
+ secret, state.secret_limit, f_acc512, f_scramble)
+ state.buffered_size = 0
+ }
+ assert(len(input) > 0)
+
+ /* Consume input by a multiple of internal buffer size */
+ if len(input) > XXH3_INTERNAL_BUFFER_SIZE {
+ tail := input[:len(input) - XXH_STRIPE_LEN]
+ for len(input) > XXH3_INTERNAL_BUFFER_SIZE {
+ XXH3_consume_stripes(
+ state.acc[:], &state.stripes_so_far, state.stripes_per_block,
+ input, XXH3_INTERNAL_BUFFER_STRIPES,
+ secret, state.secret_limit, f_acc512, f_scramble)
+
+ input = input[XXH3_INTERNAL_BUFFER_SIZE:]
+ }
+ /* for last partial stripe */
+ mem_copy(&state.buffer[XXH3_INTERNAL_BUFFER_SIZE - XXH_STRIPE_LEN], &tail[0], XXH_STRIPE_LEN)
+ }
+
+ length = len(input)
+ assert(length > 0)
+
+ /* Some remaining input (always) : buffer it */
+ mem_copy(&state.buffer[0], &input[0], length)
+ state.buffered_size = u32(length)
+ return .None
+}
+
+XXH3_64_update :: proc(state: ^XXH3_state, input: []u8) -> (err: Error) {
+ return XXH3_update(state, input, XXH3_accumulate_512, XXH3_scramble_accumulator)
+}
+
+XXH3_digest_long :: #force_inline proc(acc: []u64, state: ^XXH3_state, secret: []u8) {
+ /*
+ Digest on a local copy. This way, the state remains unaltered, and it can
+ continue ingesting more input afterwards.
+ */
+ mem_copy(&acc[0], &state.acc[0], size_of(state.acc))
+
+ if state.buffered_size >= XXH_STRIPE_LEN {
+ number_of_stripes := uint((state.buffered_size - 1) / XXH_STRIPE_LEN)
+ stripes_so_far := state.stripes_so_far
+
+ XXH3_consume_stripes(
+ acc[:], &stripes_so_far, state.stripes_per_block, state.buffer[:], number_of_stripes,
+ secret, state.secret_limit, XXH3_accumulate_512, XXH3_scramble_accumulator)
+
+ /* last stripe */
+ XXH3_accumulate_512(
+ acc[:],
+ state.buffer[state.buffered_size - XXH_STRIPE_LEN:],
+ secret[state.secret_limit - XXH_SECRET_LASTACC_START:])
+
+ } else { /* bufferedSize < XXH_STRIPE_LEN */
+ last_stripe: [XXH_STRIPE_LEN]u8
+ catchup_size := int(XXH_STRIPE_LEN) - int(state.buffered_size)
+ assert(state.buffered_size > 0) /* there is always some input buffered */
+
+ mem_copy(&last_stripe[0], &state.buffer[XXH3_INTERNAL_BUFFER_SIZE - catchup_size], catchup_size)
+ mem_copy(&last_stripe[catchup_size], &state.buffer[0], int(state.buffered_size))
+ XXH3_accumulate_512(acc[:], last_stripe[:], secret[state.secret_limit - XXH_SECRET_LASTACC_START:])
+ }
+}
+
+XXH3_64_digest :: proc(state: ^XXH3_state) -> (hash: XXH64_hash) {
+ secret := state.custom_secret[:] if len(state.external_secret) == 0 else state.external_secret[:]
+
+ if state.total_length > XXH3_MIDSIZE_MAX {
+ acc: [XXH_ACC_NB]xxh_u64
+ XXH3_digest_long(acc[:], state, secret[:])
+
+ return XXH3_mergeAccs(acc[:], secret[ XXH_SECRET_MERGEACCS_START:], state.total_length * XXH_PRIME64_1)
+ }
+
+ /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */
+ if state.seed == 0 {
+ return XXH3_64_with_seed(state.buffer[:state.total_length], state.seed)
+ }
+ return XXH3_64_with_secret(state.buffer[:state.total_length], secret[:state.secret_limit + XXH_STRIPE_LEN])
+}
+
+XXH3_generate_secret :: proc(secret_buffer: []u8, custom_seed: []u8) {
+ secret_length := len(secret_buffer)
+ assert(secret_length >= XXH3_SECRET_SIZE_MIN)
+
+ custom_seed_size := len(custom_seed)
+ if custom_seed_size == 0 {
+ k := XXH3_kSecret
+ mem_copy(&secret_buffer[0], &k[0], XXH_SECRET_DEFAULT_SIZE)
+ return
+ }
+
+ {
+ segment_size :: size_of(XXH128_hash_t)
+ number_of_segments := u64(XXH_SECRET_DEFAULT_SIZE / segment_size)
+
+ seeds: [12]u64le
+ assert(number_of_segments == 12)
+ assert(segment_size * number_of_segments == XXH_SECRET_DEFAULT_SIZE) /* exact multiple */
+
+ scrambler := XXH3_128_canonical_from_hash(XXH128_hash_t{h=XXH3_128(custom_seed[:])})
+
+ /*
+ Copy customSeed to seeds[], truncating or repeating as necessary.
+ TODO: Convert `mem_copy` to slice copies.
+ */
+ {
+ to_fill := min(custom_seed_size, size_of(seeds))
+ filled := to_fill
+ mem_copy(&seeds[0], &custom_seed[0], to_fill)
+ for filled < size_of(seeds) {
+ to_fill = min(filled, size_of(seeds) - filled)
+ seed_offset := rawptr(uintptr(&seeds[0]) + uintptr(filled))
+ mem_copy(seed_offset, &seeds[0], to_fill)
+ filled += to_fill
+ }
+ }
+
+ /*
+ Generate secret
+ */
+ mem_copy(&secret_buffer[0], &scrambler, size_of(scrambler))
+
+ for segment_number := u64(1); segment_number < number_of_segments; segment_number += 1 {
+ segment_start := segment_number * segment_size
+
+ this_seed := u64(seeds[segment_number]) + segment_number
+ segment := XXH3_128_canonical_from_hash(XXH128_hash_t{h=XXH3_128(scrambler.digest[:], this_seed)})
+
+ mem_copy(&secret_buffer[segment_start], &segment, size_of(segment))
+ }
+ }
+} \ No newline at end of file
diff --git a/core/hash/xxhash/xxhash_3.odin b/core/hash/xxhash/xxhash_3.odin
index b43a72005..5bd5537b1 100644
--- a/core/hash/xxhash/xxhash_3.odin
+++ b/core/hash/xxhash/xxhash_3.odin
@@ -30,7 +30,7 @@ import "core:intrinsics"
XXH_SECRET_DEFAULT_SIZE :: max(XXH3_SECRET_SIZE_MIN, #config(XXH_SECRET_DEFAULT_SIZE, 192))
#assert(XXH_SECRET_DEFAULT_SIZE % 64 == 0)
-XXH3_kSecret :: [?]u8{
+XXH3_kSecret := [XXH_SECRET_DEFAULT_SIZE]u8{
0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c,
0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f,
0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21,
@@ -48,7 +48,7 @@ XXH3_kSecret :: [?]u8{
Do not change this constant.
*/
XXH3_SECRET_SIZE_MIN :: 136
-#assert(size_of(XXH3_kSecret) == 192 && size_of(XXH3_kSecret) > XXH3_SECRET_SIZE_MIN)
+#assert(len(XXH3_kSecret) == 192 && len(XXH3_kSecret) > XXH3_SECRET_SIZE_MIN)
XXH_ACC_ALIGN :: 8 /* scalar */
@@ -71,15 +71,15 @@ XXH3_state :: struct {
buffered_size: u32,
reserved32: u32,
stripes_so_far: uint,
- total_len: u64,
+ total_length: u64,
stripes_per_block: uint,
secret_limit: uint,
seed: u64,
reserved64: u64,
- external_secret: ^[]u8,
+ external_secret: []u8,
}
#assert(offset_of(XXH3_state, acc) % 64 == 0 && offset_of(XXH3_state, custom_secret) % 64 == 0 &&
- offset_of(XXH3_state, buffer) % 64 == 0)
+ offset_of(XXH3_state, buffer) % 64 == 0)
/************************************************************************
* XXH3 128-bit variant
@@ -100,6 +100,10 @@ XXH128_hash_t :: struct #raw_union {
}
#assert(size_of(xxh_u128) == size_of(XXH128_hash_t))
+XXH128_canonical :: struct {
+ digest: [size_of(XXH128_hash_t)]u8,
+}
+
/*
The reason for the separate function is to prevent passing too many structs
around by value. This will hopefully inline the multiply, but we don't force it.
@@ -146,12 +150,12 @@ XXH3_rrmxmx :: #force_inline proc(h64, length: xxh_u64) -> (res: xxh_u64) {
/*
==========================================
- XXH3 128 bits (a.k.a XXH128)
+ XXH3 128 bits (a.k.a XXH128)
==========================================
XXH3's 128-bit variant has better mixing and strength than the 64-bit variant,
even without counting the significantly larger output size.
- For example, extra steps are taken to avoid the seed-dependent collisions
+ For example, extra steps are taken to avoid the seed-dependent collisions
in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B).
This strength naturally comes at the cost of some speed, especially on short
@@ -289,9 +293,6 @@ XXH128_mix32B :: #force_inline proc(acc: xxh_u128, input_1: []u8, input_2: []u8,
}
}
-
-
-
@(optimization_mode="speed")
XXH3_len_17to128_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res: xxh_u128) {
length := len(input)
@@ -335,18 +336,18 @@ XXH3_len_129to240_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xx
i: int
#no_bounds_check for i = 0; i < 4; i += 1 {
acc.h = XXH128_mix32B(acc.h,
- input[32 * i:],
- input [32 * i + 16:],
- secret[32 * i:],
- seed)
+ input[32 * i:],
+ input [32 * i + 16:],
+ secret[32 * i:],
+ seed)
}
acc.low = XXH3_avalanche(acc.low)
acc.high = XXH3_avalanche(acc.high)
#no_bounds_check for i = 4; i < nbRounds; i += 1 {
acc.h = XXH128_mix32B(acc.h,
- input[32 * i:], input[32 * i + 16:],
- secret[XXH3_MIDSIZE_STARTOFFSET + (32 * (i - 4)):],
+ input[32 * i:], input[32 * i + 16:],
+ secret[XXH3_MIDSIZE_STARTOFFSET + (32 * (i - 4)):],
seed)
}
/* last bytes */
@@ -360,9 +361,9 @@ XXH3_len_129to240_128b :: #force_inline proc(input: []u8, secret: []u8, seed: xx
h128 := XXH128_hash_t{}
h128.low = acc.low + acc.high
h128.high = u64(
- u128(acc.low * XXH_PRIME64_1) \
- + u128(acc.high * XXH_PRIME64_4) \
- + u128((u64(length) - seed) * XXH_PRIME64_2))
+ u128(acc.low * XXH_PRIME64_1) \
+ + u128(acc.high * XXH_PRIME64_4) \
+ + u128((u64(length) - seed) * XXH_PRIME64_2))
h128.low = XXH3_avalanche(h128.low)
h128.high = u64(i64(0) - i64(XXH3_avalanche(h128.high)))
return h128.h
@@ -406,18 +407,20 @@ XXH3_hashLong_128b_internal :: #force_inline proc(
/*
* It's important for performance that XXH3_hashLong is not inlined.
*/
+@(optimization_mode="speed")
XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
- k_secret := XXH3_kSecret
- return XXH3_hashLong_128b_internal(input, k_secret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
+ return XXH3_hashLong_128b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
}
/*
* It's important for performance that XXH3_hashLong is not inlined.
*/
+@(optimization_mode="speed")
XXH3_hashLong_128b_withSecret :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
return XXH3_hashLong_128b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
}
+@(optimization_mode="speed")
XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
input: []u8, seed: xxh_u64, secret: []u8,
f_acc512: XXH3_accumulate_512_f,
@@ -425,8 +428,7 @@ XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
f_initSec: XXH3_init_custom_secret_f) -> (res: XXH3_128_hash) {
if seed == 0 {
- k := XXH3_kSecret
- return XXH3_hashLong_128b_internal(input, k[:], f_acc512, f_scramble)
+ return XXH3_hashLong_128b_internal(input, XXH3_kSecret[:], f_acc512, f_scramble)
}
{
@@ -439,12 +441,14 @@ XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
/*
* It's important for performance that XXH3_hashLong is not inlined.
*/
+ @(optimization_mode="speed")
XXH3_hashLong_128b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
return XXH3_hashLong_128b_withSeed_internal(input, seed, secret, XXH3_accumulate_512, XXH3_scramble_accumulator , XXH3_init_custom_secret)
}
XXH3_hashLong128_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash)
+@(optimization_mode="speed")
XXH3_128bits_internal :: #force_inline proc(
input: []u8, seed: xxh_u64, secret: []u8, f_hl128: XXH3_hashLong128_f) -> (res: XXH3_128_hash) {
@@ -470,150 +474,22 @@ XXH3_128bits_internal :: #force_inline proc(
}
/* === Public XXH128 API === */
-
+@(optimization_mode="speed")
XXH3_128_default :: proc(input: []u8) -> (hash: XXH3_128_hash) {
- k := XXH3_kSecret
- return XXH3_128bits_internal(input, 0, k[:], XXH3_hashLong_128b_withSeed)
+ return XXH3_128bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed)
}
+@(optimization_mode="speed")
XXH3_128_with_seed :: proc(input: []u8, seed: xxh_u64) -> (hash: XXH3_128_hash) {
- k := XXH3_kSecret
- return XXH3_128bits_internal(input, seed, k[:], XXH3_hashLong_128b_withSeed)
+ return XXH3_128bits_internal(input, seed, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed)
}
+@(optimization_mode="speed")
XXH3_128_with_secret :: proc(input: []u8, secret: []u8) -> (hash: XXH3_128_hash) {
return XXH3_128bits_internal(input, 0, secret, XXH3_hashLong_128b_withSecret)
}
XXH3_128 :: proc { XXH3_128_default, XXH3_128_with_seed, XXH3_128_with_secret }
-/* === XXH3 128-bit streaming === */
-
-/*
- All the functions are actually the same as for 64-bit streaming variant.
- The only difference is the finalization routine.
-*/
-
-/*
-
-XXH_PUBLIC_API XXH_errorcode
-XXH3_128bits_reset(XXH3_state_t* statePtr)
-{
- if (statePtr == NULL) return XXH_ERROR;
- XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE);
- return XXH_OK;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode
-XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize)
-{
- if (statePtr == NULL) return XXH_ERROR;
- XXH3_reset_internal(statePtr, 0, secret, secretSize);
- if (secret == NULL) return XXH_ERROR;
- if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
- return XXH_OK;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode
-XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed)
-{
- if (statePtr == NULL) return XXH_ERROR;
- if (seed==0) return XXH3_128bits_reset(statePtr);
- if (seed != statePtr->seed) XXH3_initCustomSecret(statePtr->customSecret, seed);
- XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE);
- return XXH_OK;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode
-XXH3_128bits_update(XXH3_state_t* state, const void* input, size_t len)
-{
- return XXH3_update(state, (const xxh_u8*)input, len,
- XXH3_accumulate_512, XXH3_scrambleAcc);
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* state)
-{
- const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
- if (state->totalLen > XXH3_MIDSIZE_MAX) {
- XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];
- XXH3_digest_long(acc, state, secret);
- XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START);
- { XXH128_hash_t h128;
- h128.low64 = XXH3_mergeAccs(acc,
- secret + XXH_SECRET_MERGEACCS_START,
- (xxh_u64)state->totalLen * XXH_PRIME64_1);
- h128.high64 = XXH3_mergeAccs(acc,
- secret + state->secretLimit + XXH_STRIPE_LEN
- - sizeof(acc) - XXH_SECRET_MERGEACCS_START,
- ~((xxh_u64)state->totalLen * XXH_PRIME64_2));
- return h128;
- }
- }
- /* len <= XXH3_MIDSIZE_MAX : short code */
- if (state->seed)
- return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);
- return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen),
- secret, state->secretLimit + XXH_STRIPE_LEN);
-}
-
-/* 128-bit utility functions */
-
-#include <string.h> /* memcmp, memcpy */
-
-/* return : 1 is equal, 0 if different */
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2)
-{
- /* note : XXH128_hash_t is compact, it has no padding byte */
- return !(memcmp(&h1, &h2, sizeof(h1)));
-}
-
-/* This prototype is compatible with stdlib's qsort().
- * return : >0 if *h128_1 > *h128_2
- * <0 if *h128_1 < *h128_2
- * =0 if *h128_1 == *h128_2 */
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2)
-{
- XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1;
- XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2;
- int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64);
- /* note : bets that, in most cases, hash values are different */
- if (hcmp) return hcmp;
- return (h1.low64 > h2.low64) - (h2.low64 > h1.low64);
-}
-
-
-/*====== Canonical representation ======*/
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API void
-XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash)
-{
- XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t));
- if (XXH_CPU_LITTLE_ENDIAN) {
- hash.high64 = XXH_swap64(hash.high64);
- hash.low64 = XXH_swap64(hash.low64);
- }
- memcpy(dst, &hash.high64, sizeof(hash.high64));
- memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64));
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH128_hash_t
-XXH128_hashFromCanonical(const XXH128_canonical_t* src)
-{
- XXH128_hash_t h;
- h.high64 = XXH_readBE64(src);
- h.low64 = XXH_readBE64(src->digest + 8);
- return h;
-}
-
-*/
-
-
/*
==========================================
Short keys
@@ -818,9 +694,10 @@ XXH3_len_129to240_64b :: proc(input: []u8, secret: []u8, seed: xxh_u64) -> (res:
/* ======= Long Keys ======= */
-XXH_STRIPE_LEN :: 64
-XXH_SECRET_CONSUME_RATE :: 8 /* nb of secret bytes consumed at each accumulation */
-XXH_ACC_NB :: (XXH_STRIPE_LEN / size_of(xxh_u64))
+XXH_STRIPE_LEN :: 64
+XXH_SECRET_CONSUME_RATE :: 8 /* nb of secret bytes consumed at each accumulation */
+XXH_ACC_NB :: (XXH_STRIPE_LEN / size_of(xxh_u64))
+XXH_SECRET_LASTACC_START :: 7 /* not aligned on 8, last secret is different from acc & scrambler */
@(optimization_mode="speed")
XXH_writeLE64 :: #force_inline proc(dst: []u8, v64: u64le) {
@@ -870,9 +747,10 @@ XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, se
#no_bounds_check for i := uint(0); i < XXH_ACC_NB; i += 1 {
data_val := XXH64_read64(xinput[8 * i:])
- data_key := data_val ~ XXH64_read64(xsecret[8 * i:])
+ sec := XXH64_read64(xsecret[8 * i:])
+ data_key := data_val ~ sec
xacc[i ~ 1] += data_val /* swap adjacent lanes */
- xacc[i ] += u64(u32(data_key)) * u64(data_key >> 32)
+ xacc[i ] += u64(u128(u32(data_key)) * u128(u64(data_key >> 32)))
}
}
@@ -897,12 +775,10 @@ XXH3_scramble_accumulator_scalar :: #force_inline proc(acc: []xxh_u64, secret: [
XXH3_init_custom_secret_scalar :: #force_inline proc(custom_secret: []u8, seed64: xxh_u64) {
#assert((XXH_SECRET_DEFAULT_SIZE & 15) == 0)
- kSecretPtr := XXH3_kSecret
-
nbRounds := XXH_SECRET_DEFAULT_SIZE / 16
#no_bounds_check for i := 0; i < nbRounds; i += 1 {
- lo := XXH64_read64(kSecretPtr[16 * i: ]) + seed64
- hi := XXH64_read64(kSecretPtr[16 * i + 8:]) - seed64
+ lo := XXH64_read64(XXH3_kSecret[16 * i: ]) + seed64
+ hi := XXH64_read64(XXH3_kSecret[16 * i + 8:]) - seed64
XXH_writeLE64(custom_secret[16 * i: ], u64le(lo))
XXH_writeLE64(custom_secret[16 * i + 8:], u64le(hi))
}
@@ -916,8 +792,8 @@ XXH_PREFETCH_DIST :: 320
* Assumption: nbStripes will not overflow the secret size
*/
@(optimization_mode="speed")
-XXH3_accumulate :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8, nbStripes: uint,
- f_acc512: XXH3_accumulate_512_f) {
+XXH3_accumulate :: #force_inline proc(
+ acc: []xxh_u64, input: []u8, secret: []u8, nbStripes: uint, f_acc512: XXH3_accumulate_512_f) {
for n := uint(0); n < nbStripes; n += 1 {
when !XXH_DISABLE_PREFETCH {
@@ -952,7 +828,6 @@ XXH3_hashLong_internal_loop :: #force_inline proc(acc: []xxh_u64, input: []u8, s
/* last stripe */
#no_bounds_check {
p := input[length - XXH_STRIPE_LEN:]
- XXH_SECRET_LASTACC_START :: 7 /* not aligned on 8, last secret is different from acc & scrambler */
f_acc512(acc, p, secret[secret_size - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START:])
}
}
@@ -993,6 +868,7 @@ XXH3_hashLong_64b_internal :: #force_inline proc(input: []u8, secret: []u8,
/*
It's important for performance that XXH3_hashLong is not inlined.
*/
+@(optimization_mode="speed")
XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
return XXH3_hashLong_64b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
}
@@ -1004,9 +880,9 @@ XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u
This variant enforces that the compiler can detect that,
and uses this opportunity to streamline the generated code for better performance.
*/
+@(optimization_mode="speed")
XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
- k := XXH3_kSecret
- return XXH3_hashLong_64b_internal(input, k[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
+ return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
}
/*
@@ -1020,14 +896,14 @@ XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64,
It's important for performance that XXH3_hashLong is not inlined. Not sure
why (uop cache maybe?), but the difference is large and easily measurable.
*/
+@(optimization_mode="speed")
XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc(input: []u8,
seed: xxh_u64,
f_acc512: XXH3_accumulate_512_f,
f_scramble: XXH3_scramble_accumulator_f,
f_init_sec: XXH3_init_custom_secret_f) -> (hash: xxh_u64) {
if seed == 0 {
- k := XXH3_kSecret
- return XXH3_hashLong_64b_internal(input, k[:], f_acc512, f_scramble)
+ return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], f_acc512, f_scramble)
}
{
secret: [XXH_SECRET_DEFAULT_SIZE]u8
@@ -1039,6 +915,7 @@ XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc(input: []u8,
/*
It's important for performance that XXH3_hashLong is not inlined.
*/
+@(optimization_mode="speed")
XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
return XXH3_hashLong_64b_withSeed_internal(input, seed, XXH3_accumulate_512, XXH3_scramble_accumulator, XXH3_init_custom_secret)
}
@@ -1046,11 +923,8 @@ XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64,
XXH3_hashLong64_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: xxh_u64)
+@(optimization_mode="speed")
XXH3_64bits_internal :: proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLong: XXH3_hashLong64_f) -> (hash: xxh_u64) {
-
-
-
-
assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
/*
If an action is to be taken if len(secret) condition is not respected, it should be done here.
@@ -1069,377 +943,19 @@ XXH3_64bits_internal :: proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLon
}
/* === Public entry point === */
-
+@(optimization_mode="speed")
XXH3_64_default :: proc(input: []u8) -> (hash: xxh_u64) {
- k := XXH3_kSecret
- return XXH3_64bits_internal(input, 0, k[:], XXH3_hashLong_64b_default)
+ return XXH3_64bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_64b_default)
}
+@(optimization_mode="speed")
XXH3_64_with_seed :: proc(input: []u8, seed: xxh_u64) -> (hash: xxh_u64) {
- k := XXH3_kSecret
- return XXH3_64bits_internal(input, seed, k[:], XXH3_hashLong_64b_withSeed)
+ return XXH3_64bits_internal(input, seed, XXH3_kSecret[:], XXH3_hashLong_64b_withSeed)
}
+@(optimization_mode="speed")
XXH3_64_with_secret :: proc(input, secret: []u8) -> (hash: xxh_u64) {
return XXH3_64bits_internal(input, 0, secret, XXH3_hashLong_64b_withSecret)
}
-XXH3_64 :: proc { XXH3_64_default, XXH3_64_with_seed, XXH3_64_with_secret }
-
-/*
-
-/* === XXH3 streaming === */
-
-/*
- * Malloc's a pointer that is always aligned to align.
- *
- * This must be freed with `XXH_alignedFree()`.
- *
- * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte
- * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2
- * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON.
- *
- * This underalignment previously caused a rather obvious crash which went
- * completely unnoticed due to XXH3_createState() not actually being tested.
- * Credit to RedSpah for noticing this bug.
- *
- * The alignment is done manually: Functions like posix_memalign or _mm_malloc
- * are avoided: To maintain portability, we would have to write a fallback
- * like this anyways, and besides, testing for the existence of library
- * functions without relying on external build tools is impossible.
- *
- * The method is simple: Overallocate, manually align, and store the offset
- * to the original behind the returned pointer.
- *
- * Align must be a power of 2 and 8 <= align <= 128.
- */
-static void* XXH_alignedMalloc(size_t s, size_t align)
-{
- XXH_ASSERT(align <= 128 && align >= 8); /* range check */
- XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */
- XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */
- { /* Overallocate to make room for manual realignment and an offset byte */
- xxh_u8* base = (xxh_u8*)XXH_malloc(s + align);
- if (base != NULL) {
- /*
- * Get the offset needed to align this pointer.
- *
- * Even if the returned pointer is aligned, there will always be
- * at least one byte to store the offset to the original pointer.
- */
- size_t offset = align - ((size_t)base & (align - 1)); /* base % align */
- /* Add the offset for the now-aligned pointer */
- xxh_u8* ptr = base + offset;
-
- XXH_ASSERT((size_t)ptr % align == 0);
-
- /* Store the offset immediately before the returned pointer. */
- ptr[-1] = (xxh_u8)offset;
- return ptr;
- }
- return NULL;
- }
-}
-/*
- * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass
- * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout.
- */
-static void XXH_alignedFree(void* p)
-{
- if (p != NULL) {
- xxh_u8* ptr = (xxh_u8*)p;
- /* Get the offset byte we added in XXH_malloc. */
- xxh_u8 offset = ptr[-1];
- /* Free the original malloc'd pointer */
- xxh_u8* base = ptr - offset;
- XXH_free(base);
- }
-}
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void)
-{
- XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64);
- if (state==NULL) return NULL;
- XXH3_INITSTATE(state);
- return state;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr)
-{
- XXH_alignedFree(statePtr);
- return XXH_OK;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API void
-XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state)
-{
- memcpy(dst_state, src_state, sizeof(*dst_state));
-}
-
-static void
-XXH3_reset_internal(XXH3_state_t* statePtr,
- XXH64_hash_t seed,
- const void* secret, size_t secretSize)
-{
- size_t const initStart = offsetof(XXH3_state_t, bufferedSize);
- size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart;
- XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart);
- XXH_ASSERT(statePtr != NULL);
- /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */
- memset((char*)statePtr + initStart, 0, initLength);
- statePtr->acc[0] = XXH_XXH_PRIME32_3;
- statePtr->acc[1] = XXH_PRIME64_1;
- statePtr->acc[2] = XXH_PRIME64_2;
- statePtr->acc[3] = XXH_PRIME64_3;
- statePtr->acc[4] = XXH_PRIME64_4;
- statePtr->acc[5] = XXH_XXH_PRIME32_2;
- statePtr->acc[6] = XXH_PRIME64_5;
- statePtr->acc[7] = XXH_XXH_PRIME32_1;
- statePtr->seed = seed;
- statePtr->extSecret = (const unsigned char*)secret;
- XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN);
- statePtr->secretLimit = secretSize - XXH_STRIPE_LEN;
- statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode
-XXH3_64bits_reset(XXH3_state_t* statePtr)
-{
- if (statePtr == NULL) return XXH_ERROR;
- XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE);
- return XXH_OK;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode
-XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize)
-{
- if (statePtr == NULL) return XXH_ERROR;
- XXH3_reset_internal(statePtr, 0, secret, secretSize);
- if (secret == NULL) return XXH_ERROR;
- if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR;
- return XXH_OK;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode
-XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed)
-{
- if (statePtr == NULL) return XXH_ERROR;
- if (seed==0) return XXH3_64bits_reset(statePtr);
- if (seed != statePtr->seed) XXH3_initCustomSecret(statePtr->customSecret, seed);
- XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE);
- return XXH_OK;
-}
-
-/* Note : when XXH3_consumeStripes() is invoked,
- * there must be a guarantee that at least one more byte must be consumed from input
- * so that the function can blindly consume all stripes using the "normal" secret segment */
-XXH_FORCE_INLINE void
-XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc,
- size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock,
- const xxh_u8* XXH_RESTRICT input, size_t nbStripes,
- const xxh_u8* XXH_RESTRICT secret, size_t secretLimit,
- XXH3_f_accumulate_512 f_acc512,
- XXH3_f_scrambleAcc f_scramble)
-{
- XXH_ASSERT(nbStripes <= nbStripesPerBlock); /* can handle max 1 scramble per invocation */
- XXH_ASSERT(*nbStripesSoFarPtr < nbStripesPerBlock);
- if (nbStripesPerBlock - *nbStripesSoFarPtr <= nbStripes) {
- /* need a scrambling operation */
- size_t const nbStripesToEndofBlock = nbStripesPerBlock - *nbStripesSoFarPtr;
- size_t const nbStripesAfterBlock = nbStripes - nbStripesToEndofBlock;
- XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripesToEndofBlock, f_acc512);
- f_scramble(acc, secret + secretLimit);
- XXH3_accumulate(acc, input + nbStripesToEndofBlock * XXH_STRIPE_LEN, secret, nbStripesAfterBlock, f_acc512);
- *nbStripesSoFarPtr = nbStripesAfterBlock;
- } else {
- XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripes, f_acc512);
- *nbStripesSoFarPtr += nbStripes;
- }
-}
-
-/*
- * Both XXH3_64bits_update and XXH3_128bits_update use this routine.
- */
-XXH_FORCE_INLINE XXH_errorcode
-XXH3_update(XXH3_state_t* state,
- const xxh_u8* input, size_t len,
- XXH3_f_accumulate_512 f_acc512,
- XXH3_f_scrambleAcc f_scramble)
-{
- if (input==NULL)
-#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
- return XXH_OK;
-#else
- return XXH_ERROR;
-#endif
-
- { const xxh_u8* const bEnd = input + len;
- const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
-
- state->totalLen += len;
- XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE);
-
- if (state->bufferedSize + len <= XXH3_INTERNALBUFFER_SIZE) { /* fill in tmp buffer */
- XXH_memcpy(state->buffer + state->bufferedSize, input, len);
- state->bufferedSize += (XXH32_hash_t)len;
- return XXH_OK;
- }
- /* total input is now > XXH3_INTERNALBUFFER_SIZE */
-
- #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN)
- XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */
-
- /*
- * Internal buffer is partially filled (always, except at beginning)
- * Complete it, then consume it.
- */
- if (state->bufferedSize) {
- size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize;
- XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize);
- input += loadSize;
- XXH3_consumeStripes(state->acc,
- &state->nbStripesSoFar, state->nbStripesPerBlock,
- state->buffer, XXH3_INTERNALBUFFER_STRIPES,
- secret, state->secretLimit,
- f_acc512, f_scramble);
- state->bufferedSize = 0;
- }
- XXH_ASSERT(input < bEnd);
-
- /* Consume input by a multiple of internal buffer size */
- if (bEnd - input > XXH3_INTERNALBUFFER_SIZE) {
- const xxh_u8* const limit = bEnd - XXH3_INTERNALBUFFER_SIZE;
- do {
- XXH3_consumeStripes(state->acc,
- &state->nbStripesSoFar, state->nbStripesPerBlock,
- input, XXH3_INTERNALBUFFER_STRIPES,
- secret, state->secretLimit,
- f_acc512, f_scramble);
- input += XXH3_INTERNALBUFFER_SIZE;
- } while (input<limit);
- /* for last partial stripe */
- memcpy(state->buffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN);
- }
- XXH_ASSERT(input < bEnd);
-
- /* Some remaining input (always) : buffer it */
- XXH_memcpy(state->buffer, input, (size_t)(bEnd-input));
- state->bufferedSize = (XXH32_hash_t)(bEnd-input);
- }
-
- return XXH_OK;
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH_errorcode
-XXH3_64bits_update(XXH3_state_t* state, const void* input, size_t len)
-{
- return XXH3_update(state, (const xxh_u8*)input, len,
- XXH3_accumulate_512, XXH3_scrambleAcc);
-}
-
-
-XXH_FORCE_INLINE void
-XXH3_digest_long (XXH64_hash_t* acc,
- const XXH3_state_t* state,
- const unsigned char* secret)
-{
- /*
- * Digest on a local copy. This way, the state remains unaltered, and it can
- * continue ingesting more input afterwards.
- */
- memcpy(acc, state->acc, sizeof(state->acc));
- if (state->bufferedSize >= XXH_STRIPE_LEN) {
- size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN;
- size_t nbStripesSoFar = state->nbStripesSoFar;
- XXH3_consumeStripes(acc,
- &nbStripesSoFar, state->nbStripesPerBlock,
- state->buffer, nbStripes,
- secret, state->secretLimit,
- XXH3_accumulate_512, XXH3_scrambleAcc);
- /* last stripe */
- XXH3_accumulate_512(acc,
- state->buffer + state->bufferedSize - XXH_STRIPE_LEN,
- secret + state->secretLimit - XXH_SECRET_LASTACC_START);
- } else { /* bufferedSize < XXH_STRIPE_LEN */
- xxh_u8 lastStripe[XXH_STRIPE_LEN];
- size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize;
- XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */
- memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize);
- memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize);
- XXH3_accumulate_512(acc,
- lastStripe,
- secret + state->secretLimit - XXH_SECRET_LASTACC_START);
- }
-}
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* state)
-{
- const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret;
- if (state->totalLen > XXH3_MIDSIZE_MAX) {
- XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB];
- XXH3_digest_long(acc, state, secret);
- return XXH3_mergeAccs(acc,
- secret + XXH_SECRET_MERGEACCS_START,
- (xxh_u64)state->totalLen * XXH_PRIME64_1);
- }
- /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */
- if (state->seed)
- return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed);
- return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen),
- secret, state->secretLimit + XXH_STRIPE_LEN);
-}
-
-
-#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x))
-
-/*! @ingroup xxh3_family */
-XXH_PUBLIC_API void
-XXH3_generateSecret(void* secretBuffer, const void* customSeed, size_t customSeedSize)
-{
- XXH_ASSERT(secretBuffer != NULL);
- if (customSeedSize == 0) {
- memcpy(secretBuffer, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE);
- return;
- }
- XXH_ASSERT(customSeed != NULL);
-
- { size_t const segmentSize = sizeof(XXH128_hash_t);
- size_t const nbSegments = XXH_SECRET_DEFAULT_SIZE / segmentSize;
- XXH128_canonical_t scrambler;
- XXH64_hash_t seeds[12];
- size_t segnb;
- XXH_ASSERT(nbSegments == 12);
- XXH_ASSERT(segmentSize * nbSegments == XXH_SECRET_DEFAULT_SIZE); /* exact multiple */
- XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0));
-
- /*
- * Copy customSeed to seeds[], truncating or repeating as necessary.
- */
- { size_t toFill = XXH_MIN(customSeedSize, sizeof(seeds));
- size_t filled = toFill;
- memcpy(seeds, customSeed, toFill);
- while (filled < sizeof(seeds)) {
- toFill = XXH_MIN(filled, sizeof(seeds) - filled);
- memcpy((char*)seeds + filled, seeds, toFill);
- filled += toFill;
- } }
-
- /* generate secret */
- memcpy(secretBuffer, &scrambler, sizeof(scrambler));
- for (segnb=1; segnb < nbSegments; segnb++) {
- size_t const segmentStart = segnb * segmentSize;
- XXH128_canonical_t segment;
- XXH128_canonicalFromHash(&segment,
- XXH128(&scrambler, sizeof(scrambler), XXH64_read64(seeds + segnb) + segnb) );
- memcpy((char*)secretBuffer + segmentStart, &segment, sizeof(segment));
- } }
-}
-
-*/
+XXH3_64 :: proc { XXH3_64_default, XXH3_64_with_seed, XXH3_64_with_secret } \ No newline at end of file
diff --git a/core/hash/xxhash/xxhash_32.odin b/core/hash/xxhash/xxhash_32.odin
index f41161133..e63d998dd 100644
--- a/core/hash/xxhash/xxhash_32.odin
+++ b/core/hash/xxhash/xxhash_32.odin
@@ -197,12 +197,12 @@ XXH32 :: proc(input: []u8, seed := XXH32_DEFAULT_SEED) -> (digest: XXH32_hash) {
*/
XXH32_create_state :: proc(allocator := context.allocator) -> (res: ^XXH32_state, err: Error) {
state := new(XXH32_state, allocator)
- return state, nil if state != nil else .Error
+ return state, .None if state != nil else .Error
}
XXH32_destroy_state :: proc(state: ^XXH32_state, allocator := context.allocator) -> (err: Error) {
free(state, allocator)
- return nil
+ return .None
}
XXH32_copy_state :: proc(dest, src: ^XXH32_state) {
@@ -221,7 +221,7 @@ XXH32_reset_state :: proc(state_ptr: ^XXH32_state, seed := XXH32_DEFAULT_SEED) -
Do not write into reserved, planned to be removed in a future version.
*/
mem_copy(state_ptr, &state, size_of(state) - size_of(state.reserved))
- return nil
+ return .None
}
XXH32_update :: proc(state: ^XXH32_state, input: []u8) -> (err: Error) {
@@ -236,7 +236,7 @@ XXH32_update :: proc(state: ^XXH32_state, input: []u8) -> (err: Error) {
ptr := uintptr(raw_data(state.mem32[:])) + uintptr(state.memsize)
mem_copy(rawptr(ptr), raw_data(input), int(length))
state.memsize += XXH32_hash(length)
- return nil
+ return .None
}
if state.memsize > 0 {/* Some data left from previous update */
@@ -276,7 +276,7 @@ XXH32_update :: proc(state: ^XXH32_state, input: []u8) -> (err: Error) {
mem_copy(raw_data(state.mem32[:]), raw_data(buf[:]), int(length))
state.memsize = u32(length)
}
- return nil
+ return .None
}
XXH32_digest :: proc(state: ^XXH32_state) -> (res: XXH32_hash) {
diff --git a/core/hash/xxhash/xxhash_64.odin b/core/hash/xxhash/xxhash_64.odin
index d535a134c..e95842168 100644
--- a/core/hash/xxhash/xxhash_64.odin
+++ b/core/hash/xxhash/xxhash_64.odin
@@ -163,12 +163,12 @@ XXH64 :: proc(input: []u8, seed := XXH64_DEFAULT_SEED) -> (digest: XXH64_hash) {
*/
XXH64_create_state :: proc(allocator := context.allocator) -> (res: ^XXH64_state, err: Error) {
state := new(XXH64_state, allocator)
- return state, nil if state != nil else .Error
+ return state, .None if state != nil else .Error
}
XXH64_destroy_state :: proc(state: ^XXH64_state, allocator := context.allocator) -> (err: Error) {
free(state, allocator)
- return nil
+ return .None
}
XXH64_copy_state :: proc(dest, src: ^XXH64_state) {
@@ -187,7 +187,7 @@ XXH64_reset_state :: proc(state_ptr: ^XXH64_state, seed := XXH64_DEFAULT_SEED) -
Fo not write into reserved64, might be removed in a future version.
*/
mem_copy(state_ptr, &state, size_of(state) - size_of(state.reserved64))
- return nil
+ return .None
}
@(optimization_mode="speed")
@@ -201,7 +201,7 @@ XXH64_update :: proc(state: ^XXH64_state, input: []u8) -> (err: Error) {
ptr := uintptr(raw_data(state.mem64[:])) + uintptr(state.memsize)
mem_copy(rawptr(ptr), raw_data(input), int(length))
state.memsize += u32(length)
- return nil
+ return .None
}
if state.memsize > 0 { /* tmp buffer is full */
@@ -241,7 +241,7 @@ XXH64_update :: proc(state: ^XXH64_state, input: []u8) -> (err: Error) {
mem_copy(raw_data(state.mem64[:]), raw_data(buf[:]), int(length))
state.memsize = u32(length)
}
- return nil
+ return .None
}
@(optimization_mode="speed")