--- /dev/null
+/*
+ * 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 <linux/types.h>
+
+/*-****************************
+ * 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 */
+++ /dev/null
-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"
-
- #
+++ /dev/null
-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/
-
--- /dev/null
+/*
+ * 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 <asm/unaligned.h>
+#include <linux/errno.h>
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/xxhash.h>
+
+/*-*************************************
+ * 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");
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
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 */
cctx->loadedDictEnd = 0;
{ int i; for (i=0; i<ZSTD_REP_NUM; i++) cctx->rep[i] = repStartValue[i]; }
cctx->seqStore.litLengthSum = 0; /* force reset of btopt stats */
- XXH64_reset(&cctx->xxhState, 0);
+ xxh64_reset(&cctx->xxhState, 0);
return 0;
}
} }
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;
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);
}
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;
ZSTD_dStage stage;
U32 litEntropy;
U32 fseEntropy;
- XXH64_state_t xxhState;
+ struct xxh64_state xxhState;
size_t headerSize;
U32 dictID;
const BYTE* litPtr;
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;
}
}
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;
}
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);
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 */
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;
+++ /dev/null
-/*
-* 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 <linux/string.h>
-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 <linux/compiler.h>
-#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<bEnd) {
- 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;
-}
-
-
-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<bEnd) {
- 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;
-}
-
-
-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<bEnd) {
- 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;
-}
-
-
-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<bEnd) {
- 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;
-}
-
-
-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);
-}
+++ /dev/null
-/*
- 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 <linux/types.h> /* 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 */
***************************************/
#include <linux/compiler.h>
#include <linux/kernel.h>
+#include <linux/xxhash.h>
#include <linux/zstd.h>
#include "mem.h"
#include "error_private.h"
-#include "xxhash.h" /* XXH_reset, update, digest */
/*-*************************************
-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))
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:
--- /dev/null
+extern "C" {
+#include <linux/errno.h>
+#include <linux/xxhash.h>
+}
+#include <gtest/gtest.h>
+#include <array>
+#include <iostream>
+#include <memory>
+#include <string>
+#define XXH_STATIC_LINKING_ONLY
+#include <xxhash.h>
+
+using namespace std;
+
+namespace {
+const std::array<std::string, 11> 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());
+ }
+}
--- /dev/null
+#ifndef LINUX_ERRNO_H_
+#define LINUX_ERRNO_H_
+
+#define EINVAL 22
+
+#endif // LINUX_ERRNO_H_
--- /dev/null
+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 <linux/types.h>
++
++/*-****************************
++ * 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 <asm/unaligned.h>
++#include <linux/errno.h>
++#include <linux/compiler.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/xxhash.h>
++
++/*-*************************************
++ * 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");