diff --git a/contrib/linux-kernel/include/linux/xxhash.h b/contrib/linux-kernel/include/linux/xxhash.h new file mode 100644 index 00000000..46443370 --- /dev/null +++ b/contrib/linux-kernel/include/linux/xxhash.h @@ -0,0 +1,230 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2012-2016, Yann Collet. + * + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: http://cyan4973.github.io/xxHash/ + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * Notice extracted from xxHash homepage: + * + * xxHash is an extremely fast Hash algorithm, running at RAM speed limits. + * It also successfully passes all tests from the SMHasher suite. + * + * Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 + * Duo @3GHz) + * + * Name Speed Q.Score Author + * xxHash 5.4 GB/s 10 + * CrapWow 3.2 GB/s 2 Andrew + * MumurHash 3a 2.7 GB/s 10 Austin Appleby + * SpookyHash 2.0 GB/s 10 Bob Jenkins + * SBox 1.4 GB/s 9 Bret Mulvey + * Lookup3 1.2 GB/s 9 Bob Jenkins + * SuperFastHash 1.2 GB/s 1 Paul Hsieh + * CityHash64 1.05 GB/s 10 Pike & Alakuijala + * FNV 0.55 GB/s 5 Fowler, Noll, Vo + * CRC32 0.43 GB/s 9 + * MD5-32 0.33 GB/s 10 Ronald L. Rivest + * SHA1-32 0.28 GB/s 10 + * + * Q.Score is a measure of quality of the hash function. + * It depends on successfully passing SMHasher test set. + * 10 is a perfect score. + * + * A 64-bits version, named xxh64 offers much better speed, + * but for 64-bits applications only. + * Name Speed on 64 bits Speed on 32 bits + * xxh64 13.8 GB/s 1.9 GB/s + * xxh32 6.8 GB/s 6.0 GB/s + */ + +#ifndef XXHASH_H +#define XXHASH_H + +#include + +/*-**************************** + * Simple Hash Functions + *****************************/ + +/** + * xxh32() - calculate the 32-bit hash of the input with a given seed. + * + * @input: The data to hash. Must not be NULL. + * @length: The length of the data to hash. + * @seed: The seed can be used to alter the result predictably. + * + * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s + * + * Return: The 32-bit hash of the data. + */ +uint32_t xxh32(const void *input, size_t length, uint32_t seed); + +/** + * xxh32() - calculate the 64-bit hash of the input with a given seed. + * + * @input: The data to hash. Must not be NULL. + * @length: The length of the data to hash. + * @seed: The seed can be used to alter the result predictably. + * + * This function runs 2x faster on 64-bit systems, but slower on 32-bit systems. + * + * Return: The 64-bit hash of the data. + */ +uint64_t xxh64(const void *input, size_t length, uint64_t seed); + +/*-**************************** + * Streaming Hash Functions + *****************************/ + +/* + * These definitions are only meant to allow allocation of XXH state + * statically, on stack, or in a struct for example. + * Do not use members directly. + */ + +/** + * struct xxh32_state - private xxh32 state, do not use members directly + */ +struct xxh32_state { + uint32_t total_len_32; + uint32_t large_len; + uint32_t v1; + uint32_t v2; + uint32_t v3; + uint32_t v4; + uint32_t mem32[4]; + uint32_t memsize; +}; + +/** + * struct xxh32_state - private xxh64 state, do not use members directly + */ +struct xxh64_state { + uint64_t total_len; + uint64_t v1; + uint64_t v2; + uint64_t v3; + uint64_t v4; + uint64_t mem64[4]; + uint32_t memsize; +}; + +/** + * xxh32_reset() - reset the xxh32 state to start a new hashing operation + * + * @state: The xxh32 state to reset. + * @seed: Initialize the hash state with this seed. + * + * Call this function on any xxh32_state to prepare for a new hashing operation. + */ +void xxh32_reset(struct xxh32_state *state, uint32_t seed); + +/** + * xxh32_update() - hash the data given and update the xxh32 state + * + * @state: The xxh32 state to update. + * @input: The data to hash. Must not be NULL. + * @length: The length of the data to hash. + * + * After calling xxh32_reset() call xxh32_update() as many times as necessary. + * + * Return: Zero on success, otherwise an error code. + */ +int xxh32_update(struct xxh32_state *state, const void *input, size_t length); + +/** + * xxh32_digest() - produce the current xxh32 hash + * + * @state: Produce the current xxh32 hash of this state. + * + * A hash value can be produced at any time. It is still possible to continue + * inserting input into the hash state after a call to xxh32_digest(), and + * generate new hashes later on, by calling xxh32_digest() again. + * + * Return: The xxh32 hash stored in the state. + */ +uint32_t xxh32_digest(const struct xxh32_state *state); + +/** + * xxh64_reset() - reset the xxh64 state to start a new hashing operation + * + * @state: The xxh32 state to reset. + * @seed: Initialize the hash state with this seed. + */ +void xxh64_reset(struct xxh64_state *state, uint64_t seed); + +/** + * xxh64_update() - hash the data given and update the xxh64 state + * @state: The xxh64 state to update. + * @input: The data to hash. Must not be NULL. + * @length: The length of the data to hash. + * + * After calling xxh64_reset() call xxh64_update() as many times as necessary. + * + * Return: Zero on success, otherwise an error code. + */ +int xxh64_update(struct xxh64_state *state, const void *input, size_t length); + +/** + * xxh64_digest() - produce the current xxh64 hash + * + * @state: Produce the current xxh64 hash of this state. + * + * A hash value can be produced at any time. It is still possible to continue + * inserting input into the hash state after a call to xxh64_digest(), and + * generate new hashes later on, by calling xxh64_digest() again. + * + * Return: The xxh64 hash stored in the state. + */ +uint64_t xxh64_digest(const struct xxh64_state *state); + +/*-************************** + * Utils + ***************************/ + +/** + * xxh32_copy_state() - copy the source state into the destination state + * + * @src: The source xxh32 state. + * @dst: The destination xxh32 state. + */ +void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src); + +/** + * xxh64_copy_state() - copy the source state into the destination state + * + * @src: The source xxh64 state. + * @dst: The destination xxh64 state. + */ +void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src); + +#endif /* XXHASH_H */ diff --git a/contrib/linux-kernel/lib/Kconfig.diff b/contrib/linux-kernel/lib/Kconfig.diff deleted file mode 100644 index 07ae5398..00000000 --- a/contrib/linux-kernel/lib/Kconfig.diff +++ /dev/null @@ -1,17 +0,0 @@ -diff --git a/lib/Kconfig b/lib/Kconfig -index 260a80e..39d9347 100644 ---- a/lib/Kconfig -+++ b/lib/Kconfig -@@ -239,6 +239,12 @@ config LZ4HC_COMPRESS - config LZ4_DECOMPRESS - tristate - -+config ZSTD_COMPRESS -+ tristate -+ -+config ZSTD_DECOMPRESS -+ tristate -+ - source "lib/xz/Kconfig" - - # diff --git a/contrib/linux-kernel/lib/Makefile.diff b/contrib/linux-kernel/lib/Makefile.diff deleted file mode 100644 index be6182b3..00000000 --- a/contrib/linux-kernel/lib/Makefile.diff +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/lib/Makefile b/lib/Makefile -index 50144a3..b30a998 100644 ---- a/lib/Makefile -+++ b/lib/Makefile -@@ -106,6 +106,8 @@ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ - obj-$(CONFIG_LZ4_COMPRESS) += lz4/ - obj-$(CONFIG_LZ4HC_COMPRESS) += lz4/ - obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/ -+obj-$(CONFIG_ZSTD_COMPRESS) += zstd/ -+obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd/ - obj-$(CONFIG_XZ_DEC) += xz/ - obj-$(CONFIG_RAID6_PQ) += raid6/ - diff --git a/contrib/linux-kernel/lib/xxhash.c b/contrib/linux-kernel/lib/xxhash.c new file mode 100644 index 00000000..f367222c --- /dev/null +++ b/contrib/linux-kernel/lib/xxhash.c @@ -0,0 +1,494 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2012-2016, Yann Collet. + * + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: http://cyan4973.github.io/xxHash/ + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#include +#include +#include +#include +#include +#include +#include + +/*-************************************* + * Macros + **************************************/ +#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r))) +#define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r))) + +#ifdef __LITTLE_ENDIAN +# define XXH_CPU_LITTLE_ENDIAN 1 +#else +# define XXH_CPU_LITTLE_ENDIAN 0 +#endif + +/*-************************************* + * Constants + **************************************/ +static const uint32_t PRIME32_1 = 2654435761U; +static const uint32_t PRIME32_2 = 2246822519U; +static const uint32_t PRIME32_3 = 3266489917U; +static const uint32_t PRIME32_4 = 668265263U; +static const uint32_t PRIME32_5 = 374761393U; + +static const uint64_t PRIME64_1 = 11400714785074694791ULL; +static const uint64_t PRIME64_2 = 14029467366897019727ULL; +static const uint64_t PRIME64_3 = 1609587929392839161ULL; +static const uint64_t PRIME64_4 = 9650029242287828579ULL; +static const uint64_t PRIME64_5 = 2870177450012600261ULL; + +/*-************************** + * Utils + ***************************/ +void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src) +{ + memcpy(dst, src, sizeof(*dst)); +} +EXPORT_SYMBOL(xxh32_copy_state); + +void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src) +{ + memcpy(dst, src, sizeof(*dst)); +} +EXPORT_SYMBOL(xxh64_copy_state); + +/*-*************************** + * Simple Hash Functions + ****************************/ +static uint32_t xxh32_round(uint32_t seed, const uint32_t input) +{ + seed += input * PRIME32_2; + seed = xxh_rotl32(seed, 13); + seed *= PRIME32_1; + return seed; +} + +uint32_t xxh32(const void *input, const size_t len, const uint32_t seed) +{ + const uint8_t *p = (const uint8_t *)input; + const uint8_t *b_end = p + len; + uint32_t h32; + + if (len >= 16) { + const uint8_t *const limit = b_end - 16; + uint32_t v1 = seed + PRIME32_1 + PRIME32_2; + uint32_t v2 = seed + PRIME32_2; + uint32_t v3 = seed + 0; + uint32_t v4 = seed - PRIME32_1; + + do { + v1 = xxh32_round(v1, get_unaligned_le32(p)); + p += 4; + v2 = xxh32_round(v2, get_unaligned_le32(p)); + p += 4; + v3 = xxh32_round(v3, get_unaligned_le32(p)); + p += 4; + v4 = xxh32_round(v4, get_unaligned_le32(p)); + p += 4; + } while (p <= limit); + + h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) + + xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18); + } else { + h32 = seed + PRIME32_5; + } + + h32 += (uint32_t)len; + + while (p + 4 <= b_end) { + h32 += get_unaligned_le32(p) * PRIME32_3; + h32 = xxh_rotl32(h32, 17) * PRIME32_4; + p += 4; + } + + while (p < b_end) { + h32 += (*p) * PRIME32_5; + h32 = xxh_rotl32(h32, 11) * PRIME32_1; + p++; + } + + h32 ^= h32 >> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} +EXPORT_SYMBOL(xxh32); + +static uint64_t xxh64_round(uint64_t acc, const uint64_t input) +{ + acc += input * PRIME64_2; + acc = xxh_rotl64(acc, 31); + acc *= PRIME64_1; + return acc; +} + +static uint64_t xxh64_merge_round(uint64_t acc, uint64_t val) +{ + val = xxh64_round(0, val); + acc ^= val; + acc = acc * PRIME64_1 + PRIME64_4; + return acc; +} + +uint64_t xxh64(const void *input, const size_t len, const uint64_t seed) +{ + const uint8_t *p = (const uint8_t *)input; + const uint8_t *const b_end = p + len; + uint64_t h64; + + if (len >= 32) { + const uint8_t *const limit = b_end - 32; + uint64_t v1 = seed + PRIME64_1 + PRIME64_2; + uint64_t v2 = seed + PRIME64_2; + uint64_t v3 = seed + 0; + uint64_t v4 = seed - PRIME64_1; + + do { + v1 = xxh64_round(v1, get_unaligned_le64(p)); + p += 8; + v2 = xxh64_round(v2, get_unaligned_le64(p)); + p += 8; + v3 = xxh64_round(v3, get_unaligned_le64(p)); + p += 8; + v4 = xxh64_round(v4, get_unaligned_le64(p)); + p += 8; + } while (p <= limit); + + h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) + + xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18); + h64 = xxh64_merge_round(h64, v1); + h64 = xxh64_merge_round(h64, v2); + h64 = xxh64_merge_round(h64, v3); + h64 = xxh64_merge_round(h64, v4); + + } else { + h64 = seed + PRIME64_5; + } + + h64 += (uint64_t)len; + + while (p + 8 <= b_end) { + const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p)); + + h64 ^= k1; + h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; + p += 8; + } + + if (p + 4 <= b_end) { + h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1; + h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p += 4; + } + + while (p < b_end) { + h64 ^= (*p) * PRIME64_5; + h64 = xxh_rotl64(h64, 11) * PRIME64_1; + p++; + } + + h64 ^= h64 >> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} +EXPORT_SYMBOL(xxh64); + +/*-************************************************** + * Advanced Hash Functions + ***************************************************/ +void xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed) +{ + /* use a local state for memcpy() to avoid strict-aliasing warnings */ + struct xxh32_state state; + + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME32_1 + PRIME32_2; + state.v2 = seed + PRIME32_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME32_1; + memcpy(statePtr, &state, sizeof(state)); +} +EXPORT_SYMBOL(xxh32_reset); + +void xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed) +{ + /* use a local state for memcpy() to avoid strict-aliasing warnings */ + struct xxh64_state state; + + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME64_1 + PRIME64_2; + state.v2 = seed + PRIME64_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME64_1; + memcpy(statePtr, &state, sizeof(state)); +} +EXPORT_SYMBOL(xxh64_reset); + +int xxh32_update(struct xxh32_state *state, const void *input, const size_t len) +{ + const uint8_t *p = (const uint8_t *)input; + const uint8_t *const b_end = p + len; + + if (input == NULL) + return -EINVAL; + + state->total_len_32 += (uint32_t)len; + state->large_len |= (len >= 16) | (state->total_len_32 >= 16); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + memcpy((uint8_t *)(state->mem32) + state->memsize, input, len); + state->memsize += (uint32_t)len; + return 0; + } + + if (state->memsize) { /* some data left from previous update */ + const uint32_t *p32 = state->mem32; + + memcpy((uint8_t *)(state->mem32) + state->memsize, input, + 16 - state->memsize); + + state->v1 = xxh32_round(state->v1, get_unaligned_le32(p32)); + p32++; + state->v2 = xxh32_round(state->v2, get_unaligned_le32(p32)); + p32++; + state->v3 = xxh32_round(state->v3, get_unaligned_le32(p32)); + p32++; + state->v4 = xxh32_round(state->v4, get_unaligned_le32(p32)); + p32++; + + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= b_end - 16) { + const uint8_t *const limit = b_end - 16; + uint32_t v1 = state->v1; + uint32_t v2 = state->v2; + uint32_t v3 = state->v3; + uint32_t v4 = state->v4; + + do { + v1 = xxh32_round(v1, get_unaligned_le32(p)); + p += 4; + v2 = xxh32_round(v2, get_unaligned_le32(p)); + p += 4; + v3 = xxh32_round(v3, get_unaligned_le32(p)); + p += 4; + v4 = xxh32_round(v4, get_unaligned_le32(p)); + p += 4; + } while (p <= limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < b_end) { + memcpy(state->mem32, p, (size_t)(b_end-p)); + state->memsize = (uint32_t)(b_end-p); + } + + return 0; +} +EXPORT_SYMBOL(xxh32_update); + +uint32_t xxh32_digest(const struct xxh32_state *state) +{ + const uint8_t *p = (const uint8_t *)state->mem32; + const uint8_t *const b_end = (const uint8_t *)(state->mem32) + + state->memsize; + uint32_t h32; + + if (state->large_len) { + h32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) + + xxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18); + } else { + h32 = state->v3 /* == seed */ + PRIME32_5; + } + + h32 += state->total_len_32; + + while (p + 4 <= b_end) { + h32 += get_unaligned_le32(p) * PRIME32_3; + h32 = xxh_rotl32(h32, 17) * PRIME32_4; + p += 4; + } + + while (p < b_end) { + h32 += (*p) * PRIME32_5; + h32 = xxh_rotl32(h32, 11) * PRIME32_1; + p++; + } + + h32 ^= h32 >> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} +EXPORT_SYMBOL(xxh32_digest); + +int xxh64_update(struct xxh64_state *state, const void *input, const size_t len) +{ + const uint8_t *p = (const uint8_t *)input; + const uint8_t *const b_end = p + len; + + if (input == NULL) + return -EINVAL; + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + memcpy(((uint8_t *)state->mem64) + state->memsize, input, len); + state->memsize += (uint32_t)len; + return 0; + } + + if (state->memsize) { /* tmp buffer is full */ + const uint64_t *p64 = state->mem64; + + memcpy(((uint8_t *)p64) + state->memsize, input, + 32 - state->memsize); + + state->v1 = xxh64_round(state->v1, get_unaligned_le64(p64)); + p64++; + state->v2 = xxh64_round(state->v2, get_unaligned_le64(p64)); + p64++; + state->v3 = xxh64_round(state->v3, get_unaligned_le64(p64)); + p64++; + state->v4 = xxh64_round(state->v4, get_unaligned_le64(p64)); + + p += 32 - state->memsize; + state->memsize = 0; + } + + if (p + 32 <= b_end) { + const uint8_t *const limit = b_end - 32; + uint64_t v1 = state->v1; + uint64_t v2 = state->v2; + uint64_t v3 = state->v3; + uint64_t v4 = state->v4; + + do { + v1 = xxh64_round(v1, get_unaligned_le64(p)); + p += 8; + v2 = xxh64_round(v2, get_unaligned_le64(p)); + p += 8; + v3 = xxh64_round(v3, get_unaligned_le64(p)); + p += 8; + v4 = xxh64_round(v4, get_unaligned_le64(p)); + p += 8; + } while (p <= limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < b_end) { + memcpy(state->mem64, p, (size_t)(b_end-p)); + state->memsize = (uint32_t)(b_end - p); + } + + return 0; +} +EXPORT_SYMBOL(xxh64_update); + +uint64_t xxh64_digest(const struct xxh64_state *state) +{ + const uint8_t *p = (const uint8_t *)state->mem64; + const uint8_t *const b_end = (const uint8_t *)state->mem64 + + state->memsize; + uint64_t h64; + + if (state->total_len >= 32) { + const uint64_t v1 = state->v1; + const uint64_t v2 = state->v2; + const uint64_t v3 = state->v3; + const uint64_t v4 = state->v4; + + h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) + + xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18); + h64 = xxh64_merge_round(h64, v1); + h64 = xxh64_merge_round(h64, v2); + h64 = xxh64_merge_round(h64, v3); + h64 = xxh64_merge_round(h64, v4); + } else { + h64 = state->v3 + PRIME64_5; + } + + h64 += (uint64_t)state->total_len; + + while (p + 8 <= b_end) { + const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p)); + + h64 ^= k1; + h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; + p += 8; + } + + if (p + 4 <= b_end) { + h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1; + h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p += 4; + } + + while (p < b_end) { + h64 ^= (*p) * PRIME64_5; + h64 = xxh_rotl64(h64, 11) * PRIME64_1; + p++; + } + + h64 ^= h64 >> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} +EXPORT_SYMBOL(xxh64_digest); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("xxHash"); diff --git a/contrib/linux-kernel/lib/zstd/Makefile b/contrib/linux-kernel/lib/zstd/Makefile index 067f68d1..aa5eb4d6 100644 --- a/contrib/linux-kernel/lib/zstd/Makefile +++ b/contrib/linux-kernel/lib/zstd/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_ZSTD_DECOMPRESS) += zstd_decompress.o ccflags-y += -O3 -zstd_compress-y := entropy_common.o fse_decompress.o xxhash.o zstd_common.o \ +zstd_compress-y := entropy_common.o fse_decompress.o zstd_common.o \ fse_compress.o huf_compress.o compress.o -zstd_decompress-y := entropy_common.o fse_decompress.o xxhash.o zstd_common.o \ +zstd_decompress-y := entropy_common.o fse_decompress.o zstd_common.o \ huf_decompress.o decompress.o diff --git a/contrib/linux-kernel/lib/zstd/compress.c b/contrib/linux-kernel/lib/zstd/compress.c index 5f6d955a..79c3207f 100644 --- a/contrib/linux-kernel/lib/zstd/compress.c +++ b/contrib/linux-kernel/lib/zstd/compress.c @@ -73,7 +73,7 @@ struct ZSTD_CCtx_s { size_t workSpaceSize; size_t blockSize; U64 frameContentSize; - XXH64_state_t xxhState; + struct xxh64_state xxhState; ZSTD_customMem customMem; seqStore_t seqStore; /* sequences storage ptrs */ @@ -221,7 +221,7 @@ static size_t ZSTD_continueCCtx(ZSTD_CCtx* cctx, ZSTD_parameters params, U64 fra cctx->loadedDictEnd = 0; { int i; for (i=0; irep[i] = repStartValue[i]; } cctx->seqStore.litLengthSum = 0; /* force reset of btopt stats */ - XXH64_reset(&cctx->xxhState, 0); + xxh64_reset(&cctx->xxhState, 0); return 0; } @@ -264,7 +264,7 @@ static size_t ZSTD_resetCCtx_advanced (ZSTD_CCtx* zc, } } if (crp!=ZSTDcrp_noMemset) memset(zc->workSpace, 0, tableSpace); /* reset tables only */ - XXH64_reset(&zc->xxhState, 0); + xxh64_reset(&zc->xxhState, 0); zc->hashLog3 = hashLog3; zc->hashTable = (U32*)(zc->workSpace); zc->chainTable = zc->hashTable + hSize; @@ -2322,7 +2322,7 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx, U32 const maxDist = 1 << cctx->params.cParams.windowLog; if (cctx->params.fParams.checksumFlag && srcSize) - XXH64_update(&cctx->xxhState, src, srcSize); + xxh64_update(&cctx->xxhState, src, srcSize); while (remaining) { U32 const lastBlock = lastFrameChunk & (blockSize >= remaining); @@ -2720,7 +2720,7 @@ static size_t ZSTD_writeEpilogue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity) } if (cctx->params.fParams.checksumFlag) { - U32 const checksum = (U32) XXH64_digest(&cctx->xxhState); + U32 const checksum = (U32) xxh64_digest(&cctx->xxhState); if (dstCapacity<4) return ERROR(dstSize_tooSmall); MEM_writeLE32(op, checksum); op += 4; diff --git a/contrib/linux-kernel/lib/zstd/decompress.c b/contrib/linux-kernel/lib/zstd/decompress.c index 94f5fd56..98508b10 100644 --- a/contrib/linux-kernel/lib/zstd/decompress.c +++ b/contrib/linux-kernel/lib/zstd/decompress.c @@ -81,7 +81,7 @@ struct ZSTD_DCtx_s ZSTD_dStage stage; U32 litEntropy; U32 fseEntropy; - XXH64_state_t xxhState; + struct xxh64_state xxhState; size_t headerSize; U32 dictID; const BYTE* litPtr; @@ -366,7 +366,7 @@ static size_t ZSTD_decodeFrameHeader(ZSTD_DCtx* dctx, const void* src, size_t he if (ZSTD_isError(result)) return result; /* invalid header */ if (result>0) return ERROR(srcSize_wrong); /* headerSize too small */ if (dctx->fParams.dictID && (dctx->dictID != dctx->fParams.dictID)) return ERROR(dictionary_wrong); - if (dctx->fParams.checksumFlag) XXH64_reset(&dctx->xxhState, 0); + if (dctx->fParams.checksumFlag) xxh64_reset(&dctx->xxhState, 0); return 0; } @@ -1517,7 +1517,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, } if (ZSTD_isError(decodedSize)) return decodedSize; - if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, op, decodedSize); + if (dctx->fParams.checksumFlag) xxh64_update(&dctx->xxhState, op, decodedSize); op += decodedSize; ip += cBlockSize; remainingSize -= cBlockSize; @@ -1525,7 +1525,7 @@ static size_t ZSTD_decompressFrame(ZSTD_DCtx* dctx, } if (dctx->fParams.checksumFlag) { /* Frame content checksum verification */ - U32 const checkCalc = (U32)XXH64_digest(&dctx->xxhState); + U32 const checkCalc = (U32)xxh64_digest(&dctx->xxhState); U32 checkRead; if (remainingSize<4) return ERROR(checksum_wrong); checkRead = MEM_readLE32(ip); @@ -1731,7 +1731,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c return ERROR(corruption_detected); } if (ZSTD_isError(rSize)) return rSize; - if (dctx->fParams.checksumFlag) XXH64_update(&dctx->xxhState, dst, rSize); + if (dctx->fParams.checksumFlag) xxh64_update(&dctx->xxhState, dst, rSize); if (dctx->stage == ZSTDds_decompressLastBlock) { /* end of frame */ if (dctx->fParams.checksumFlag) { /* another round for frame checksum */ @@ -1749,7 +1749,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c return rSize; } case ZSTDds_checkChecksum: - { U32 const h32 = (U32)XXH64_digest(&dctx->xxhState); + { U32 const h32 = (U32)xxh64_digest(&dctx->xxhState); U32 const check32 = MEM_readLE32(src); /* srcSize == 4, guaranteed by dctx->expected */ if (check32 != h32) return ERROR(checksum_wrong); dctx->expected = 0; diff --git a/contrib/linux-kernel/lib/zstd/xxhash.c b/contrib/linux-kernel/lib/zstd/xxhash.c deleted file mode 100644 index 0d301ad8..00000000 --- a/contrib/linux-kernel/lib/zstd/xxhash.c +++ /dev/null @@ -1,700 +0,0 @@ -/* -* xxHash - Fast Hash algorithm -* Copyright (C) 2012-2016, Yann Collet -* -* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -* -* You can contact the author at : -* - xxHash homepage: http://www.xxhash.com -* - xxHash source repository : https://github.com/Cyan4973/xxHash -*/ - - -/* ************************************* -* Tuning parameters -***************************************/ -/*!XXH_ACCEPT_NULL_INPUT_POINTER : - * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. - * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. - * By default, this option is disabled. To enable it, uncomment below define : - */ -/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */ - -/*!XXH_FORCE_NATIVE_FORMAT : - * By default, xxHash library provides endian-independant Hash values, based on little-endian convention. - * Results are therefore identical for little-endian and big-endian CPU. - * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. - * Should endian-independance be of no importance for your application, you may set the #define below to 1, - * to improve speed for Big-endian CPU. - * This option has no impact on Little_Endian CPU. - */ -#define XXH_FORCE_NATIVE_FORMAT 0 - -/*!XXH_FORCE_ALIGN_CHECK : - * This is a minor performance trick, only useful with lots of very small keys. - * It means : check for aligned/unaligned input. - * The check costs one initial branch per hash; set to 0 when the input data - * is guaranteed to be aligned. - */ -#define XXH_FORCE_ALIGN_CHECK 0 - - -/* ************************************* -* Includes & Memory related functions -***************************************/ -/* Modify the local functions below should you wish to use some other memory routines */ -/* for memcpy() */ -#include -static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } - -#include "xxhash.h" -#include "mem.h" - - -/* ************************************* -* Compiler Specific Options -***************************************/ -#include -#define FORCE_INLINE static __always_inline - - -/* **************************************** -* Compiler-specific Functions and Macros -******************************************/ -#define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) -#define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) - -/* ************************************* -* Architecture Macros -***************************************/ -typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; - -/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ -#ifndef XXH_CPU_LITTLE_ENDIAN -# define XXH_CPU_LITTLE_ENDIAN MEM_LITTLE_ENDIAN -#endif - - -/* *************************** -* Memory reads -*****************************/ -typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; - -FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - (void)endian; - (void)align; - return MEM_readLE32(ptr); -} - -FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE32_align(ptr, endian, XXH_unaligned); -} - -static U32 XXH_readBE32(const void* ptr) -{ - return MEM_readBE32(ptr); -} - -FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) -{ - (void)endian; - (void)align; - return MEM_readLE64(ptr); -} - -FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) -{ - return XXH_readLE64_align(ptr, endian, XXH_unaligned); -} - -static U64 XXH_readBE64(const void* ptr) -{ - return MEM_readBE64(ptr); -} - - -/* ************************************* -* Macros -***************************************/ -#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */ - - -/* ************************************* -* Constants -***************************************/ -static const U32 PRIME32_1 = 2654435761U; -static const U32 PRIME32_2 = 2246822519U; -static const U32 PRIME32_3 = 3266489917U; -static const U32 PRIME32_4 = 668265263U; -static const U32 PRIME32_5 = 374761393U; - -static const U64 PRIME64_1 = 11400714785074694791ULL; -static const U64 PRIME64_2 = 14029467366897019727ULL; -static const U64 PRIME64_3 = 1609587929392839161ULL; -static const U64 PRIME64_4 = 9650029242287828579ULL; -static const U64 PRIME64_5 = 2870177450012600261ULL; - -XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } - - -/* ************************** -* Utils -****************************/ -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) -{ - memcpy(dstState, srcState, sizeof(*dstState)); -} - - -/* *************************** -* Simple Hash Functions -*****************************/ - -static U32 XXH32_round(U32 seed, U32 input) -{ - seed += input * PRIME32_2; - seed = XXH_rotl32(seed, 13); - seed *= PRIME32_1; - return seed; -} - -FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* bEnd = p + len; - U32 h32; -#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)16; - } -#endif - - if (len>=16) { - const BYTE* const limit = bEnd - 16; - U32 v1 = seed + PRIME32_1 + PRIME32_2; - U32 v2 = seed + PRIME32_2; - U32 v3 = seed + 0; - U32 v4 = seed - PRIME32_1; - - do { - v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; - v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; - v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; - v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; - } while (p<=limit); - - h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); - } else { - h32 = seed + PRIME32_5; - } - - h32 += (U32) len; - - while (p+4<=bEnd) { - h32 += XXH_get32bits(p) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; - p+=4; - } - - while (p> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - - -XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH32_CREATESTATE_STATIC(state); - XXH32_reset(state, seed); - XXH32_update(state, input, len); - return XXH32_digest(state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - - -static U64 XXH64_round(U64 acc, U64 input) -{ - acc += input * PRIME64_2; - acc = XXH_rotl64(acc, 31); - acc *= PRIME64_1; - return acc; -} - -static U64 XXH64_mergeRound(U64 acc, U64 val) -{ - val = XXH64_round(0, val); - acc ^= val; - acc = acc * PRIME64_1 + PRIME64_4; - return acc; -} - -FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - U64 h64; -#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (p==NULL) { - len=0; - bEnd=p=(const BYTE*)(size_t)32; - } -#endif - - if (len>=32) { - const BYTE* const limit = bEnd - 32; - U64 v1 = seed + PRIME64_1 + PRIME64_2; - U64 v2 = seed + PRIME64_2; - U64 v3 = seed + 0; - U64 v4 = seed - PRIME64_1; - - do { - v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; - v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; - v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; - v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; - } while (p<=limit); - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - - } else { - h64 = seed + PRIME64_5; - } - - h64 += (U64) len; - - while (p+8<=bEnd) { - U64 const k1 = XXH64_round(0, XXH_get64bits(p)); - h64 ^= k1; - h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; - p+=8; - } - - if (p+4<=bEnd) { - h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p+=4; - } - - while (p> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - - -XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) -{ -#if 0 - /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ - XXH64_CREATESTATE_STATIC(state); - XXH64_reset(state, seed); - XXH64_update(state, input, len); - return XXH64_digest(state); -#else - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if (XXH_FORCE_ALIGN_CHECK) { - if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); - } } - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); - else - return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); -#endif -} - - -/* ************************************************** -* Advanced Hash Functions -****************************************************/ - - -/*** Hash feed ***/ - -XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) -{ - XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */ - state.v1 = seed + PRIME32_1 + PRIME32_2; - state.v2 = seed + PRIME32_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME32_1; - memcpy(statePtr, &state, sizeof(state)); - return XXH_OK; -} - - -XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) -{ - XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ - memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */ - state.v1 = seed + PRIME64_1 + PRIME64_2; - state.v2 = seed + PRIME64_2; - state.v3 = seed + 0; - state.v4 = seed - PRIME64_1; - memcpy(statePtr, &state, sizeof(state)); - return XXH_OK; -} - - -FORCE_INLINE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input==NULL) return XXH_ERROR; -#endif - - state->total_len_32 += (unsigned)len; - state->large_len |= (len>=16) | (state->total_len_32>=16); - - if (state->memsize + len < 16) { /* fill in tmp buffer */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); - state->memsize += (unsigned)len; - return XXH_OK; - } - - if (state->memsize) { /* some data left from previous update */ - XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); - { const U32* p32 = state->mem32; - state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; - state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; - state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; - state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++; - } - p += 16-state->memsize; - state->memsize = 0; - } - - if (p <= bEnd-16) { - const BYTE* const limit = bEnd - 16; - U32 v1 = state->v1; - U32 v2 = state->v2; - U32 v3 = state->v3; - U32 v4 = state->v4; - - do { - v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; - v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; - v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; - v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH32_update_endian(state_in, input, len, XXH_bigEndian); -} - - - -FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) -{ - const BYTE * p = (const BYTE*)state->mem32; - const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize; - U32 h32; - - if (state->large_len) { - h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); - } else { - h32 = state->v3 /* == seed */ + PRIME32_5; - } - - h32 += state->total_len_32; - - while (p+4<=bEnd) { - h32 += XXH_readLE32(p, endian) * PRIME32_3; - h32 = XXH_rotl32(h32, 17) * PRIME32_4; - p+=4; - } - - while (p> 15; - h32 *= PRIME32_2; - h32 ^= h32 >> 13; - h32 *= PRIME32_3; - h32 ^= h32 >> 16; - - return h32; -} - - -XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH32_digest_endian(state_in, XXH_littleEndian); - else - return XXH32_digest_endian(state_in, XXH_bigEndian); -} - - - -/* **** XXH64 **** */ - -FORCE_INLINE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) -{ - const BYTE* p = (const BYTE*)input; - const BYTE* const bEnd = p + len; - -#ifdef XXH_ACCEPT_NULL_INPUT_POINTER - if (input==NULL) return XXH_ERROR; -#endif - - state->total_len += len; - - if (state->memsize + len < 32) { /* fill in tmp buffer */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); - state->memsize += (U32)len; - return XXH_OK; - } - - if (state->memsize) { /* tmp buffer is full */ - XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); - state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); - state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); - state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); - state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); - p += 32-state->memsize; - state->memsize = 0; - } - - if (p+32 <= bEnd) { - const BYTE* const limit = bEnd - 32; - U64 v1 = state->v1; - U64 v2 = state->v2; - U64 v3 = state->v3; - U64 v4 = state->v4; - - do { - v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; - v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; - v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; - v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; - } while (p<=limit); - - state->v1 = v1; - state->v2 = v2; - state->v3 = v3; - state->v4 = v4; - } - - if (p < bEnd) { - XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); - state->memsize = (unsigned)(bEnd-p); - } - - return XXH_OK; -} - -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_update_endian(state_in, input, len, XXH_littleEndian); - else - return XXH64_update_endian(state_in, input, len, XXH_bigEndian); -} - - - -FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) -{ - const BYTE * p = (const BYTE*)state->mem64; - const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize; - U64 h64; - - if (state->total_len >= 32) { - U64 const v1 = state->v1; - U64 const v2 = state->v2; - U64 const v3 = state->v3; - U64 const v4 = state->v4; - - h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); - h64 = XXH64_mergeRound(h64, v1); - h64 = XXH64_mergeRound(h64, v2); - h64 = XXH64_mergeRound(h64, v3); - h64 = XXH64_mergeRound(h64, v4); - } else { - h64 = state->v3 + PRIME64_5; - } - - h64 += (U64) state->total_len; - - while (p+8<=bEnd) { - U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian)); - h64 ^= k1; - h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; - p+=8; - } - - if (p+4<=bEnd) { - h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1; - h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; - p+=4; - } - - while (p> 33; - h64 *= PRIME64_2; - h64 ^= h64 >> 29; - h64 *= PRIME64_3; - h64 ^= h64 >> 32; - - return h64; -} - - -XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) -{ - XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; - - if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) - return XXH64_digest_endian(state_in, XXH_littleEndian); - else - return XXH64_digest_endian(state_in, XXH_bigEndian); -} - - -/* ************************** -* Canonical representation -****************************/ - -/*! Default XXH result types are basic unsigned 32 and 64 bits. -* The canonical representation follows human-readable write convention, aka big-endian (large digits first). -* These functions allow transformation of hash result into and from its canonical format. -* This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs. -*/ - -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); - MEM_writeBE32(dst, hash); -} - -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) -{ - XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); - MEM_writeBE64(dst, hash); -} - -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) -{ - return XXH_readBE32(src); -} - -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) -{ - return XXH_readBE64(src); -} diff --git a/contrib/linux-kernel/lib/zstd/xxhash.h b/contrib/linux-kernel/lib/zstd/xxhash.h deleted file mode 100644 index 974a81c4..00000000 --- a/contrib/linux-kernel/lib/zstd/xxhash.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - xxHash - Extremely Fast Hash algorithm - Header File - Copyright (C) 2012-2016, Yann Collet. - - BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - You can contact the author at : - - xxHash source repository : https://github.com/Cyan4973/xxHash -*/ - -/* Notice extracted from xxHash homepage : - -xxHash is an extremely fast Hash algorithm, running at RAM speed limits. -It also successfully passes all tests from the SMHasher suite. - -Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) - -Name Speed Q.Score Author -xxHash 5.4 GB/s 10 -CrapWow 3.2 GB/s 2 Andrew -MumurHash 3a 2.7 GB/s 10 Austin Appleby -SpookyHash 2.0 GB/s 10 Bob Jenkins -SBox 1.4 GB/s 9 Bret Mulvey -Lookup3 1.2 GB/s 9 Bob Jenkins -SuperFastHash 1.2 GB/s 1 Paul Hsieh -CityHash64 1.05 GB/s 10 Pike & Alakuijala -FNV 0.55 GB/s 5 Fowler, Noll, Vo -CRC32 0.43 GB/s 9 -MD5-32 0.33 GB/s 10 Ronald L. Rivest -SHA1-32 0.28 GB/s 10 - -Q.Score is a measure of quality of the hash function. -It depends on successfully passing SMHasher test set. -10 is a perfect score. - -A 64-bits version, named XXH64, is available since r35. -It offers much better speed, but for 64-bits applications only. -Name Speed on 64 bits Speed on 32 bits -XXH64 13.8 GB/s 1.9 GB/s -XXH32 6.8 GB/s 6.0 GB/s -*/ - -#ifndef XXHASH_H_5627135585666179 -#define XXHASH_H_5627135585666179 1 - - -/* **************************** -* Definitions -******************************/ -#include /* size_t */ -typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; - - -/* **************************** -* API modifier -******************************/ -/** XXH_PRIVATE_API -* This is useful if you want to include xxhash functions in `static` mode -* in order to inline them, and remove their symbol from the public list. -* Methodology : -* #define XXH_PRIVATE_API -* #include "xxhash.h" -* `xxhash.c` is automatically included. -* It's not useful to compile and link it as a separate module anymore. -*/ -#define XXH_PUBLIC_API /* do nothing */ - -/*!XXH_NAMESPACE, aka Namespace Emulation : - -If you want to include _and expose_ xxHash functions from within your own library, -but also want to avoid symbol collisions with another library which also includes xxHash, - -you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library -with the value of XXH_NAMESPACE (so avoid to keep it NULL and avoid numeric values). - -Note that no change is required within the calling program as long as it includes `xxhash.h` : -regular symbol name will be automatically translated by this header. -*/ - - -/* ************************************* -* Version -***************************************/ -#define XXH_VERSION_MAJOR 0 -#define XXH_VERSION_MINOR 6 -#define XXH_VERSION_RELEASE 2 -#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) -XXH_PUBLIC_API unsigned XXH_versionNumber (void); - - -/* **************************** -* Simple Hash Functions -******************************/ -typedef unsigned int XXH32_hash_t; -typedef unsigned long long XXH64_hash_t; - -XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); -XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); - -/*! -XXH32() : - Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input". - The memory between input & input+length must be valid (allocated and read-accessible). - "seed" can be used to alter the result predictably. - Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s -XXH64() : - Calculate the 64-bits hash of sequence of length "len" stored at memory address "input". - "seed" can be used to alter the result predictably. - This function runs 2x faster on 64-bits systems, but slower on 32-bits systems (see benchmark). -*/ - - -/* **************************** -* Streaming Hash Functions -******************************/ -typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ -typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ - - -/* hash streaming */ - -XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); -XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); - -XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); -XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); -XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); - -/* -These functions generate the xxHash of an input provided in multiple segments. -Note that, for small input, they are slower than single-call functions, due to state management. -For small input, prefer `XXH32()` and `XXH64()` . - -XXH state must first be allocated, using XXH*_createState() . - -Start a new hash by initializing state with a seed, using XXH*_reset(). - -Then, feed the hash state by calling XXH*_update() as many times as necessary. -Obviously, input must be allocated and read accessible. -The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. - -Finally, a hash value can be produced anytime, by using XXH*_digest(). -This function returns the nn-bits hash as an int or long long. - -It's still possible to continue inserting input into the hash state after a digest, -and generate some new hashes later on, by calling again XXH*_digest(). - -When done, free XXH state space if it was allocated dynamically. -*/ - - -/* ************************** -* Utils -****************************/ -XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); -XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); - - -/* ************************** -* Canonical representation -****************************/ -/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. -* The canonical representation uses human-readable write convention, aka big-endian (large digits first). -* These functions allow transformation of hash result into and from its canonical format. -* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. -*/ -typedef struct { unsigned char digest[4]; } XXH32_canonical_t; -typedef struct { unsigned char digest[8]; } XXH64_canonical_t; - -XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); -XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); - -XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); -XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); - - -/* ================================================================================================ - This section contains definitions which are not guaranteed to remain stable. - They may change in future versions, becoming incompatible with a different version of the library. - They shall only be used with static linking. - Never use these definitions in association with dynamic linking ! -=================================================================================================== */ -/* These definitions are only meant to allow allocation of XXH state - statically, on stack, or in a struct for example. - Do not use members directly. */ - -struct XXH32_state_s { - unsigned total_len_32; - unsigned large_len; - unsigned v1; - unsigned v2; - unsigned v3; - unsigned v4; - unsigned mem32[4]; /* buffer defined as U32 for alignment */ - unsigned memsize; - unsigned reserved; /* never read nor write, will be removed in a future version */ -}; /* typedef'd to XXH32_state_t */ - -struct XXH64_state_s { - unsigned long long total_len; - unsigned long long v1; - unsigned long long v2; - unsigned long long v3; - unsigned long long v4; - unsigned long long mem64[4]; /* buffer defined as U64 for alignment */ - unsigned memsize; - unsigned reserved[2]; /* never read nor write, will be removed in a future version */ -}; /* typedef'd to XXH64_state_t */ - -#endif /* XXHASH_H_5627135585666179 */ diff --git a/contrib/linux-kernel/lib/zstd/zstd_internal.h b/contrib/linux-kernel/lib/zstd/zstd_internal.h index 479d6827..a61bd271 100644 --- a/contrib/linux-kernel/lib/zstd/zstd_internal.h +++ b/contrib/linux-kernel/lib/zstd/zstd_internal.h @@ -22,10 +22,10 @@ ***************************************/ #include #include +#include #include #include "mem.h" #include "error_private.h" -#include "xxhash.h" /* XXH_reset, update, digest */ /*-************************************* diff --git a/contrib/linux-kernel/test/Makefile b/contrib/linux-kernel/test/Makefile index 01e877b7..0aa6d817 100644 --- a/contrib/linux-kernel/test/Makefile +++ b/contrib/linux-kernel/test/Makefile @@ -1,5 +1,5 @@ -IFLAGS := -isystem include/ -I ../include/ -I ../lib/zstd/ -isystem googletest/googletest/include +IFLAGS := -isystem include/ -I ../include/ -I ../lib/zstd/ -isystem googletest/googletest/include -isystem ../../../lib/common/ SOURCES := $(wildcard ../lib/zstd/*.c) OBJECTS := $(patsubst %.c,%.o,$(SOURCES)) @@ -15,6 +15,15 @@ CPPFLAGS += $(IFLAGS) UserlandTest: UserlandTest.cpp ../lib/zstd/libzstd.a $(CXX) $(CXXFLAGS) $(CFLAGS) $(CPPFLAGS) $^ googletest/build/googlemock/gtest/libgtest.a googletest/build/googlemock/gtest/libgtest_main.a -o $@ +../lib/zstd/xxhash.o: ../lib/zstd/xxhash.c + $(CC) $(CFLAGS) -c $^ -o $@ + +../../../lib/common/xxhash.o: ../../../lib/common/xxhash.c + $(CC) $(CFLAGS) -c $^ -o $@ + +XXHashUserlandTest: XXHashUserlandTest.cpp ../lib/xxhash.o ../../../lib/common/xxhash.o + $(CXX) $(CXXFLAGS) $(CFLAGS) $(CPPFLAGS) $^ googletest/build/googlemock/gtest/libgtest.a googletest/build/googlemock/gtest/libgtest_main.a -o $@ + # Install googletest .PHONY: googletest googletest: diff --git a/contrib/linux-kernel/test/XXHashUserlandTest.cpp b/contrib/linux-kernel/test/XXHashUserlandTest.cpp new file mode 100644 index 00000000..4ded2ae5 --- /dev/null +++ b/contrib/linux-kernel/test/XXHashUserlandTest.cpp @@ -0,0 +1,178 @@ +extern "C" { +#include +#include +} +#include +#include +#include +#include +#include +#define XXH_STATIC_LINKING_ONLY +#include + +using namespace std; + +namespace { +const std::array kTestInputs = { + "", + "0", + "01234", + "0123456789abcde", + "0123456789abcdef", + "0123456789abcdef0", + "0123456789abcdef0123", + "0123456789abcdef0123456789abcde", + "0123456789abcdef0123456789abcdef", + "0123456789abcdef0123456789abcdef0", + "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", +}; +char const kEmpty[] = ""; +char const kOne[] = "0"; +char const kFive[] = "01234"; +char const kFifteen[] = "0123456789abcde"; +char const kSixteen[] = "0123456789abcdef"; +char const kSeventeen[] = "0123456789abcdef0"; +char const kTwenty[] = "0123456789abcdef0123"; +char const kThirtyOne[] = "0123456789abcdef0123456789abcde"; +char const kThirtyTwo[] = "0123456789abcdef0123456789abcdef"; +char const kThirtyThree[] = "0123456789abcdef0123456789abcdef0"; +char const kSixtyFour[] = "0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef"; + +bool testXXH32(const void *input, const size_t length, uint32_t seed) { + return XXH32(input, length, seed) == xxh32(input, length, seed); +} + +bool testXXH64(const void *input, const size_t length, uint32_t seed) { + return XXH64(input, length, seed) == xxh64(input, length, seed); +} + +class XXH32State { + struct xxh32_state kernelState; + XXH32_state_t state; + +public: + explicit XXH32State(const uint32_t seed) { reset(seed); } + XXH32State(XXH32State const& other) noexcept { + xxh32_copy_state(&kernelState, &other.kernelState); + XXH32_copyState(&state, &other.state); + } + XXH32State& operator=(XXH32State const& other) noexcept { + xxh32_copy_state(&kernelState, &other.kernelState); + XXH32_copyState(&state, &other.state); + return *this; + } + + void reset(const uint32_t seed) { + xxh32_reset(&kernelState, seed); + EXPECT_EQ(0, XXH32_reset(&state, seed)); + } + + void update(const void *input, const size_t length) { + EXPECT_EQ(0, xxh32_update(&kernelState, input, length)); + EXPECT_EQ(0, (int)XXH32_update(&state, input, length)); + } + + bool testDigest() const { + return xxh32_digest(&kernelState) == XXH32_digest(&state); + } +}; + +class XXH64State { + struct xxh64_state kernelState; + XXH64_state_t state; + +public: + explicit XXH64State(const uint64_t seed) { reset(seed); } + XXH64State(XXH64State const& other) noexcept { + xxh64_copy_state(&kernelState, &other.kernelState); + XXH64_copyState(&state, &other.state); + } + XXH64State& operator=(XXH64State const& other) noexcept { + xxh64_copy_state(&kernelState, &other.kernelState); + XXH64_copyState(&state, &other.state); + return *this; + } + + void reset(const uint64_t seed) { + xxh64_reset(&kernelState, seed); + EXPECT_EQ(0, XXH64_reset(&state, seed)); + } + + void update(const void *input, const size_t length) { + EXPECT_EQ(0, xxh64_update(&kernelState, input, length)); + EXPECT_EQ(0, (int)XXH64_update(&state, input, length)); + } + + bool testDigest() const { + return xxh64_digest(&kernelState) == XXH64_digest(&state); + } +}; +} + +TEST(Simple, Null) { + EXPECT_TRUE(testXXH32(NULL, 0, 0)); + EXPECT_TRUE(testXXH64(NULL, 0, 0)); +} + +TEST(Stream, Null) { + struct xxh32_state state32; + xxh32_reset(&state32, 0); + EXPECT_EQ(-EINVAL, xxh32_update(&state32, NULL, 0)); + + struct xxh64_state state64; + xxh64_reset(&state64, 0); + EXPECT_EQ(-EINVAL, xxh64_update(&state64, NULL, 0)); +} + +TEST(Simple, TestInputs) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + for (auto const input : kTestInputs) { + EXPECT_TRUE(testXXH32(input.data(), input.size(), seed)); + EXPECT_TRUE(testXXH64(input.data(), input.size(), (uint64_t)seed)); + } + } +} + +TEST(Stream, TestInputs) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + for (auto const input : kTestInputs) { + XXH32State s32(seed); + XXH64State s64(seed); + s32.update(input.data(), input.size()); + s64.update(input.data(), input.size()); + EXPECT_TRUE(s32.testDigest()); + EXPECT_TRUE(s64.testDigest()); + } + } +} + +TEST(Stream, MultipleTestInputs) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + XXH32State s32(seed); + XXH64State s64(seed); + for (auto const input : kTestInputs) { + s32.update(input.data(), input.size()); + s64.update(input.data(), input.size()); + } + EXPECT_TRUE(s32.testDigest()); + EXPECT_TRUE(s64.testDigest()); + } +} + +TEST(Stream, CopyState) { + for (uint32_t seed = 0; seed < 100000; seed = (seed + 1) * 3) { + XXH32State s32(seed); + XXH64State s64(seed); + for (auto const input : kTestInputs) { + auto t32(s32); + t32.update(input.data(), input.size()); + s32 = t32; + auto t64(s64); + t64.update(input.data(), input.size()); + s64 = t64; + } + EXPECT_TRUE(s32.testDigest()); + EXPECT_TRUE(s64.testDigest()); + } +} diff --git a/contrib/linux-kernel/test/include/linux/errno.h b/contrib/linux-kernel/test/include/linux/errno.h new file mode 100644 index 00000000..b9db0852 --- /dev/null +++ b/contrib/linux-kernel/test/include/linux/errno.h @@ -0,0 +1,6 @@ +#ifndef LINUX_ERRNO_H_ +#define LINUX_ERRNO_H_ + +#define EINVAL 22 + +#endif // LINUX_ERRNO_H_ diff --git a/contrib/linux-kernel/xxhash.diff b/contrib/linux-kernel/xxhash.diff new file mode 100644 index 00000000..bbd5771b --- /dev/null +++ b/contrib/linux-kernel/xxhash.diff @@ -0,0 +1,762 @@ +diff --git a/include/linux/xxhash.h b/include/linux/xxhash.h +new file mode 100644 +index 0000000..4644337 +--- /dev/null ++++ b/include/linux/xxhash.h +@@ -0,0 +1,230 @@ ++/* ++ * xxHash - Extremely Fast Hash algorithm ++ * Copyright (C) 2012-2016, Yann Collet. ++ * ++ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are ++ * met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above ++ * copyright notice, this list of conditions and the following disclaimer ++ * in the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You can contact the author at: ++ * - xxHash homepage: http://cyan4973.github.io/xxHash/ ++ * - xxHash source repository: https://github.com/Cyan4973/xxHash ++ */ ++ ++/* ++ * Notice extracted from xxHash homepage: ++ * ++ * xxHash is an extremely fast Hash algorithm, running at RAM speed limits. ++ * It also successfully passes all tests from the SMHasher suite. ++ * ++ * Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 ++ * Duo @3GHz) ++ * ++ * Name Speed Q.Score Author ++ * xxHash 5.4 GB/s 10 ++ * CrapWow 3.2 GB/s 2 Andrew ++ * MumurHash 3a 2.7 GB/s 10 Austin Appleby ++ * SpookyHash 2.0 GB/s 10 Bob Jenkins ++ * SBox 1.4 GB/s 9 Bret Mulvey ++ * Lookup3 1.2 GB/s 9 Bob Jenkins ++ * SuperFastHash 1.2 GB/s 1 Paul Hsieh ++ * CityHash64 1.05 GB/s 10 Pike & Alakuijala ++ * FNV 0.55 GB/s 5 Fowler, Noll, Vo ++ * CRC32 0.43 GB/s 9 ++ * MD5-32 0.33 GB/s 10 Ronald L. Rivest ++ * SHA1-32 0.28 GB/s 10 ++ * ++ * Q.Score is a measure of quality of the hash function. ++ * It depends on successfully passing SMHasher test set. ++ * 10 is a perfect score. ++ * ++ * A 64-bits version, named xxh64 offers much better speed, ++ * but for 64-bits applications only. ++ * Name Speed on 64 bits Speed on 32 bits ++ * xxh64 13.8 GB/s 1.9 GB/s ++ * xxh32 6.8 GB/s 6.0 GB/s ++ */ ++ ++#ifndef XXHASH_H ++#define XXHASH_H ++ ++#include ++ ++/*-**************************** ++ * Simple Hash Functions ++ *****************************/ ++ ++/** ++ * xxh32() - calculate the 32-bit hash of the input with a given seed. ++ * ++ * @input: The data to hash. Must not be NULL. ++ * @length: The length of the data to hash. ++ * @seed: The seed can be used to alter the result predictably. ++ * ++ * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s ++ * ++ * Return: The 32-bit hash of the data. ++ */ ++uint32_t xxh32(const void *input, size_t length, uint32_t seed); ++ ++/** ++ * xxh32() - calculate the 64-bit hash of the input with a given seed. ++ * ++ * @input: The data to hash. Must not be NULL. ++ * @length: The length of the data to hash. ++ * @seed: The seed can be used to alter the result predictably. ++ * ++ * This function runs 2x faster on 64-bit systems, but slower on 32-bit systems. ++ * ++ * Return: The 64-bit hash of the data. ++ */ ++uint64_t xxh64(const void *input, size_t length, uint64_t seed); ++ ++/*-**************************** ++ * Streaming Hash Functions ++ *****************************/ ++ ++/* ++ * These definitions are only meant to allow allocation of XXH state ++ * statically, on stack, or in a struct for example. ++ * Do not use members directly. ++ */ ++ ++/** ++ * struct xxh32_state - private xxh32 state, do not use members directly ++ */ ++struct xxh32_state { ++ uint32_t total_len_32; ++ uint32_t large_len; ++ uint32_t v1; ++ uint32_t v2; ++ uint32_t v3; ++ uint32_t v4; ++ uint32_t mem32[4]; ++ uint32_t memsize; ++}; ++ ++/** ++ * struct xxh32_state - private xxh64 state, do not use members directly ++ */ ++struct xxh64_state { ++ uint64_t total_len; ++ uint64_t v1; ++ uint64_t v2; ++ uint64_t v3; ++ uint64_t v4; ++ uint64_t mem64[4]; ++ uint32_t memsize; ++}; ++ ++/** ++ * xxh32_reset() - reset the xxh32 state to start a new hashing operation ++ * ++ * @state: The xxh32 state to reset. ++ * @seed: Initialize the hash state with this seed. ++ * ++ * Call this function on any xxh32_state to prepare for a new hashing operation. ++ */ ++void xxh32_reset(struct xxh32_state *state, uint32_t seed); ++ ++/** ++ * xxh32_update() - hash the data given and update the xxh32 state ++ * ++ * @state: The xxh32 state to update. ++ * @input: The data to hash. Must not be NULL. ++ * @length: The length of the data to hash. ++ * ++ * After calling xxh32_reset() call xxh32_update() as many times as necessary. ++ * ++ * Return: Zero on success, otherwise an error code. ++ */ ++int xxh32_update(struct xxh32_state *state, const void *input, size_t length); ++ ++/** ++ * xxh32_digest() - produce the current xxh32 hash ++ * ++ * @state: Produce the current xxh32 hash of this state. ++ * ++ * A hash value can be produced at any time. It is still possible to continue ++ * inserting input into the hash state after a call to xxh32_digest(), and ++ * generate new hashes later on, by calling xxh32_digest() again. ++ * ++ * Return: The xxh32 hash stored in the state. ++ */ ++uint32_t xxh32_digest(const struct xxh32_state *state); ++ ++/** ++ * xxh64_reset() - reset the xxh64 state to start a new hashing operation ++ * ++ * @state: The xxh32 state to reset. ++ * @seed: Initialize the hash state with this seed. ++ */ ++void xxh64_reset(struct xxh64_state *state, uint64_t seed); ++ ++/** ++ * xxh64_update() - hash the data given and update the xxh64 state ++ * @state: The xxh64 state to update. ++ * @input: The data to hash. Must not be NULL. ++ * @length: The length of the data to hash. ++ * ++ * After calling xxh64_reset() call xxh64_update() as many times as necessary. ++ * ++ * Return: Zero on success, otherwise an error code. ++ */ ++int xxh64_update(struct xxh64_state *state, const void *input, size_t length); ++ ++/** ++ * xxh64_digest() - produce the current xxh64 hash ++ * ++ * @state: Produce the current xxh64 hash of this state. ++ * ++ * A hash value can be produced at any time. It is still possible to continue ++ * inserting input into the hash state after a call to xxh64_digest(), and ++ * generate new hashes later on, by calling xxh64_digest() again. ++ * ++ * Return: The xxh64 hash stored in the state. ++ */ ++uint64_t xxh64_digest(const struct xxh64_state *state); ++ ++/*-************************** ++ * Utils ++ ***************************/ ++ ++/** ++ * xxh32_copy_state() - copy the source state into the destination state ++ * ++ * @src: The source xxh32 state. ++ * @dst: The destination xxh32 state. ++ */ ++void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src); ++ ++/** ++ * xxh64_copy_state() - copy the source state into the destination state ++ * ++ * @src: The source xxh64 state. ++ * @dst: The destination xxh64 state. ++ */ ++void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src); ++ ++#endif /* XXHASH_H */ +diff --git a/lib/Kconfig b/lib/Kconfig +index 0c8b78a..b6009d7 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -184,6 +184,9 @@ config CRC8 + when they need to do cyclic redundancy check according CRC8 + algorithm. Module will be called crc8. + ++config XXHASH ++ tristate ++ + config AUDIT_GENERIC + bool + depends on AUDIT && !AUDIT_ARCH +diff --git a/lib/Makefile b/lib/Makefile +index 320ac46..e16f94a 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -101,6 +101,7 @@ obj-$(CONFIG_CRC32_SELFTEST) += crc32test.o + obj-$(CONFIG_CRC7) += crc7.o + obj-$(CONFIG_LIBCRC32C) += libcrc32c.o + obj-$(CONFIG_CRC8) += crc8.o ++obj-$(CONFIG_XXHASH) += xxhash.o + obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o + + obj-$(CONFIG_842_COMPRESS) += 842/ +diff --git a/lib/xxhash.c b/lib/xxhash.c +new file mode 100644 +index 0000000..f367222 +--- /dev/null ++++ b/lib/xxhash.c +@@ -0,0 +1,494 @@ ++/* ++ * xxHash - Extremely Fast Hash algorithm ++ * Copyright (C) 2012-2016, Yann Collet. ++ * ++ * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions are ++ * met: ++ * ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above ++ * copyright notice, this list of conditions and the following disclaimer ++ * in the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ++ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ++ * ++ * You can contact the author at: ++ * - xxHash homepage: http://cyan4973.github.io/xxHash/ ++ * - xxHash source repository: https://github.com/Cyan4973/xxHash ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/*-************************************* ++ * Macros ++ **************************************/ ++#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r))) ++#define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r))) ++ ++#ifdef __LITTLE_ENDIAN ++# define XXH_CPU_LITTLE_ENDIAN 1 ++#else ++# define XXH_CPU_LITTLE_ENDIAN 0 ++#endif ++ ++/*-************************************* ++ * Constants ++ **************************************/ ++static const uint32_t PRIME32_1 = 2654435761U; ++static const uint32_t PRIME32_2 = 2246822519U; ++static const uint32_t PRIME32_3 = 3266489917U; ++static const uint32_t PRIME32_4 = 668265263U; ++static const uint32_t PRIME32_5 = 374761393U; ++ ++static const uint64_t PRIME64_1 = 11400714785074694791ULL; ++static const uint64_t PRIME64_2 = 14029467366897019727ULL; ++static const uint64_t PRIME64_3 = 1609587929392839161ULL; ++static const uint64_t PRIME64_4 = 9650029242287828579ULL; ++static const uint64_t PRIME64_5 = 2870177450012600261ULL; ++ ++/*-************************** ++ * Utils ++ ***************************/ ++void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src) ++{ ++ memcpy(dst, src, sizeof(*dst)); ++} ++EXPORT_SYMBOL(xxh32_copy_state); ++ ++void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src) ++{ ++ memcpy(dst, src, sizeof(*dst)); ++} ++EXPORT_SYMBOL(xxh64_copy_state); ++ ++/*-*************************** ++ * Simple Hash Functions ++ ****************************/ ++static uint32_t xxh32_round(uint32_t seed, const uint32_t input) ++{ ++ seed += input * PRIME32_2; ++ seed = xxh_rotl32(seed, 13); ++ seed *= PRIME32_1; ++ return seed; ++} ++ ++uint32_t xxh32(const void *input, const size_t len, const uint32_t seed) ++{ ++ const uint8_t *p = (const uint8_t *)input; ++ const uint8_t *b_end = p + len; ++ uint32_t h32; ++ ++ if (len >= 16) { ++ const uint8_t *const limit = b_end - 16; ++ uint32_t v1 = seed + PRIME32_1 + PRIME32_2; ++ uint32_t v2 = seed + PRIME32_2; ++ uint32_t v3 = seed + 0; ++ uint32_t v4 = seed - PRIME32_1; ++ ++ do { ++ v1 = xxh32_round(v1, get_unaligned_le32(p)); ++ p += 4; ++ v2 = xxh32_round(v2, get_unaligned_le32(p)); ++ p += 4; ++ v3 = xxh32_round(v3, get_unaligned_le32(p)); ++ p += 4; ++ v4 = xxh32_round(v4, get_unaligned_le32(p)); ++ p += 4; ++ } while (p <= limit); ++ ++ h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) + ++ xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18); ++ } else { ++ h32 = seed + PRIME32_5; ++ } ++ ++ h32 += (uint32_t)len; ++ ++ while (p + 4 <= b_end) { ++ h32 += get_unaligned_le32(p) * PRIME32_3; ++ h32 = xxh_rotl32(h32, 17) * PRIME32_4; ++ p += 4; ++ } ++ ++ while (p < b_end) { ++ h32 += (*p) * PRIME32_5; ++ h32 = xxh_rotl32(h32, 11) * PRIME32_1; ++ p++; ++ } ++ ++ h32 ^= h32 >> 15; ++ h32 *= PRIME32_2; ++ h32 ^= h32 >> 13; ++ h32 *= PRIME32_3; ++ h32 ^= h32 >> 16; ++ ++ return h32; ++} ++EXPORT_SYMBOL(xxh32); ++ ++static uint64_t xxh64_round(uint64_t acc, const uint64_t input) ++{ ++ acc += input * PRIME64_2; ++ acc = xxh_rotl64(acc, 31); ++ acc *= PRIME64_1; ++ return acc; ++} ++ ++static uint64_t xxh64_merge_round(uint64_t acc, uint64_t val) ++{ ++ val = xxh64_round(0, val); ++ acc ^= val; ++ acc = acc * PRIME64_1 + PRIME64_4; ++ return acc; ++} ++ ++uint64_t xxh64(const void *input, const size_t len, const uint64_t seed) ++{ ++ const uint8_t *p = (const uint8_t *)input; ++ const uint8_t *const b_end = p + len; ++ uint64_t h64; ++ ++ if (len >= 32) { ++ const uint8_t *const limit = b_end - 32; ++ uint64_t v1 = seed + PRIME64_1 + PRIME64_2; ++ uint64_t v2 = seed + PRIME64_2; ++ uint64_t v3 = seed + 0; ++ uint64_t v4 = seed - PRIME64_1; ++ ++ do { ++ v1 = xxh64_round(v1, get_unaligned_le64(p)); ++ p += 8; ++ v2 = xxh64_round(v2, get_unaligned_le64(p)); ++ p += 8; ++ v3 = xxh64_round(v3, get_unaligned_le64(p)); ++ p += 8; ++ v4 = xxh64_round(v4, get_unaligned_le64(p)); ++ p += 8; ++ } while (p <= limit); ++ ++ h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) + ++ xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18); ++ h64 = xxh64_merge_round(h64, v1); ++ h64 = xxh64_merge_round(h64, v2); ++ h64 = xxh64_merge_round(h64, v3); ++ h64 = xxh64_merge_round(h64, v4); ++ ++ } else { ++ h64 = seed + PRIME64_5; ++ } ++ ++ h64 += (uint64_t)len; ++ ++ while (p + 8 <= b_end) { ++ const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p)); ++ ++ h64 ^= k1; ++ h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; ++ p += 8; ++ } ++ ++ if (p + 4 <= b_end) { ++ h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1; ++ h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; ++ p += 4; ++ } ++ ++ while (p < b_end) { ++ h64 ^= (*p) * PRIME64_5; ++ h64 = xxh_rotl64(h64, 11) * PRIME64_1; ++ p++; ++ } ++ ++ h64 ^= h64 >> 33; ++ h64 *= PRIME64_2; ++ h64 ^= h64 >> 29; ++ h64 *= PRIME64_3; ++ h64 ^= h64 >> 32; ++ ++ return h64; ++} ++EXPORT_SYMBOL(xxh64); ++ ++/*-************************************************** ++ * Advanced Hash Functions ++ ***************************************************/ ++void xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed) ++{ ++ /* use a local state for memcpy() to avoid strict-aliasing warnings */ ++ struct xxh32_state state; ++ ++ memset(&state, 0, sizeof(state)); ++ state.v1 = seed + PRIME32_1 + PRIME32_2; ++ state.v2 = seed + PRIME32_2; ++ state.v3 = seed + 0; ++ state.v4 = seed - PRIME32_1; ++ memcpy(statePtr, &state, sizeof(state)); ++} ++EXPORT_SYMBOL(xxh32_reset); ++ ++void xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed) ++{ ++ /* use a local state for memcpy() to avoid strict-aliasing warnings */ ++ struct xxh64_state state; ++ ++ memset(&state, 0, sizeof(state)); ++ state.v1 = seed + PRIME64_1 + PRIME64_2; ++ state.v2 = seed + PRIME64_2; ++ state.v3 = seed + 0; ++ state.v4 = seed - PRIME64_1; ++ memcpy(statePtr, &state, sizeof(state)); ++} ++EXPORT_SYMBOL(xxh64_reset); ++ ++int xxh32_update(struct xxh32_state *state, const void *input, const size_t len) ++{ ++ const uint8_t *p = (const uint8_t *)input; ++ const uint8_t *const b_end = p + len; ++ ++ if (input == NULL) ++ return -EINVAL; ++ ++ state->total_len_32 += (uint32_t)len; ++ state->large_len |= (len >= 16) | (state->total_len_32 >= 16); ++ ++ if (state->memsize + len < 16) { /* fill in tmp buffer */ ++ memcpy((uint8_t *)(state->mem32) + state->memsize, input, len); ++ state->memsize += (uint32_t)len; ++ return 0; ++ } ++ ++ if (state->memsize) { /* some data left from previous update */ ++ const uint32_t *p32 = state->mem32; ++ ++ memcpy((uint8_t *)(state->mem32) + state->memsize, input, ++ 16 - state->memsize); ++ ++ state->v1 = xxh32_round(state->v1, get_unaligned_le32(p32)); ++ p32++; ++ state->v2 = xxh32_round(state->v2, get_unaligned_le32(p32)); ++ p32++; ++ state->v3 = xxh32_round(state->v3, get_unaligned_le32(p32)); ++ p32++; ++ state->v4 = xxh32_round(state->v4, get_unaligned_le32(p32)); ++ p32++; ++ ++ p += 16-state->memsize; ++ state->memsize = 0; ++ } ++ ++ if (p <= b_end - 16) { ++ const uint8_t *const limit = b_end - 16; ++ uint32_t v1 = state->v1; ++ uint32_t v2 = state->v2; ++ uint32_t v3 = state->v3; ++ uint32_t v4 = state->v4; ++ ++ do { ++ v1 = xxh32_round(v1, get_unaligned_le32(p)); ++ p += 4; ++ v2 = xxh32_round(v2, get_unaligned_le32(p)); ++ p += 4; ++ v3 = xxh32_round(v3, get_unaligned_le32(p)); ++ p += 4; ++ v4 = xxh32_round(v4, get_unaligned_le32(p)); ++ p += 4; ++ } while (p <= limit); ++ ++ state->v1 = v1; ++ state->v2 = v2; ++ state->v3 = v3; ++ state->v4 = v4; ++ } ++ ++ if (p < b_end) { ++ memcpy(state->mem32, p, (size_t)(b_end-p)); ++ state->memsize = (uint32_t)(b_end-p); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(xxh32_update); ++ ++uint32_t xxh32_digest(const struct xxh32_state *state) ++{ ++ const uint8_t *p = (const uint8_t *)state->mem32; ++ const uint8_t *const b_end = (const uint8_t *)(state->mem32) + ++ state->memsize; ++ uint32_t h32; ++ ++ if (state->large_len) { ++ h32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) + ++ xxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18); ++ } else { ++ h32 = state->v3 /* == seed */ + PRIME32_5; ++ } ++ ++ h32 += state->total_len_32; ++ ++ while (p + 4 <= b_end) { ++ h32 += get_unaligned_le32(p) * PRIME32_3; ++ h32 = xxh_rotl32(h32, 17) * PRIME32_4; ++ p += 4; ++ } ++ ++ while (p < b_end) { ++ h32 += (*p) * PRIME32_5; ++ h32 = xxh_rotl32(h32, 11) * PRIME32_1; ++ p++; ++ } ++ ++ h32 ^= h32 >> 15; ++ h32 *= PRIME32_2; ++ h32 ^= h32 >> 13; ++ h32 *= PRIME32_3; ++ h32 ^= h32 >> 16; ++ ++ return h32; ++} ++EXPORT_SYMBOL(xxh32_digest); ++ ++int xxh64_update(struct xxh64_state *state, const void *input, const size_t len) ++{ ++ const uint8_t *p = (const uint8_t *)input; ++ const uint8_t *const b_end = p + len; ++ ++ if (input == NULL) ++ return -EINVAL; ++ ++ state->total_len += len; ++ ++ if (state->memsize + len < 32) { /* fill in tmp buffer */ ++ memcpy(((uint8_t *)state->mem64) + state->memsize, input, len); ++ state->memsize += (uint32_t)len; ++ return 0; ++ } ++ ++ if (state->memsize) { /* tmp buffer is full */ ++ const uint64_t *p64 = state->mem64; ++ ++ memcpy(((uint8_t *)p64) + state->memsize, input, ++ 32 - state->memsize); ++ ++ state->v1 = xxh64_round(state->v1, get_unaligned_le64(p64)); ++ p64++; ++ state->v2 = xxh64_round(state->v2, get_unaligned_le64(p64)); ++ p64++; ++ state->v3 = xxh64_round(state->v3, get_unaligned_le64(p64)); ++ p64++; ++ state->v4 = xxh64_round(state->v4, get_unaligned_le64(p64)); ++ ++ p += 32 - state->memsize; ++ state->memsize = 0; ++ } ++ ++ if (p + 32 <= b_end) { ++ const uint8_t *const limit = b_end - 32; ++ uint64_t v1 = state->v1; ++ uint64_t v2 = state->v2; ++ uint64_t v3 = state->v3; ++ uint64_t v4 = state->v4; ++ ++ do { ++ v1 = xxh64_round(v1, get_unaligned_le64(p)); ++ p += 8; ++ v2 = xxh64_round(v2, get_unaligned_le64(p)); ++ p += 8; ++ v3 = xxh64_round(v3, get_unaligned_le64(p)); ++ p += 8; ++ v4 = xxh64_round(v4, get_unaligned_le64(p)); ++ p += 8; ++ } while (p <= limit); ++ ++ state->v1 = v1; ++ state->v2 = v2; ++ state->v3 = v3; ++ state->v4 = v4; ++ } ++ ++ if (p < b_end) { ++ memcpy(state->mem64, p, (size_t)(b_end-p)); ++ state->memsize = (uint32_t)(b_end - p); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(xxh64_update); ++ ++uint64_t xxh64_digest(const struct xxh64_state *state) ++{ ++ const uint8_t *p = (const uint8_t *)state->mem64; ++ const uint8_t *const b_end = (const uint8_t *)state->mem64 + ++ state->memsize; ++ uint64_t h64; ++ ++ if (state->total_len >= 32) { ++ const uint64_t v1 = state->v1; ++ const uint64_t v2 = state->v2; ++ const uint64_t v3 = state->v3; ++ const uint64_t v4 = state->v4; ++ ++ h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) + ++ xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18); ++ h64 = xxh64_merge_round(h64, v1); ++ h64 = xxh64_merge_round(h64, v2); ++ h64 = xxh64_merge_round(h64, v3); ++ h64 = xxh64_merge_round(h64, v4); ++ } else { ++ h64 = state->v3 + PRIME64_5; ++ } ++ ++ h64 += (uint64_t)state->total_len; ++ ++ while (p + 8 <= b_end) { ++ const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p)); ++ ++ h64 ^= k1; ++ h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4; ++ p += 8; ++ } ++ ++ if (p + 4 <= b_end) { ++ h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1; ++ h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; ++ p += 4; ++ } ++ ++ while (p < b_end) { ++ h64 ^= (*p) * PRIME64_5; ++ h64 = xxh_rotl64(h64, 11) * PRIME64_1; ++ p++; ++ } ++ ++ h64 ^= h64 >> 33; ++ h64 *= PRIME64_2; ++ h64 ^= h64 >> 29; ++ h64 *= PRIME64_3; ++ h64 ^= h64 >> 32; ++ ++ return h64; ++} ++EXPORT_SYMBOL(xxh64_digest); ++ ++MODULE_LICENSE("Dual BSD/GPL"); ++MODULE_DESCRIPTION("xxHash");