]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[linux-kernel] Separate xxhash into its own module
authorNick Terrell <terrelln@fb.com>
Tue, 16 May 2017 19:56:38 +0000 (12:56 -0700)
committerNick Terrell <terrelln@fb.com>
Tue, 16 May 2017 22:52:35 +0000 (15:52 -0700)
14 files changed:
contrib/linux-kernel/include/linux/xxhash.h [new file with mode: 0644]
contrib/linux-kernel/lib/Kconfig.diff [deleted file]
contrib/linux-kernel/lib/Makefile.diff [deleted file]
contrib/linux-kernel/lib/xxhash.c [new file with mode: 0644]
contrib/linux-kernel/lib/zstd/Makefile
contrib/linux-kernel/lib/zstd/compress.c
contrib/linux-kernel/lib/zstd/decompress.c
contrib/linux-kernel/lib/zstd/xxhash.c [deleted file]
contrib/linux-kernel/lib/zstd/xxhash.h [deleted file]
contrib/linux-kernel/lib/zstd/zstd_internal.h
contrib/linux-kernel/test/Makefile
contrib/linux-kernel/test/XXHashUserlandTest.cpp [new file with mode: 0644]
contrib/linux-kernel/test/include/linux/errno.h [new file with mode: 0644]
contrib/linux-kernel/xxhash.diff [new file with mode: 0644]

diff --git a/contrib/linux-kernel/include/linux/xxhash.h b/contrib/linux-kernel/include/linux/xxhash.h
new file mode 100644 (file)
index 0000000..4644337
--- /dev/null
@@ -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/contrib/linux-kernel/lib/Kconfig.diff b/contrib/linux-kernel/lib/Kconfig.diff
deleted file mode 100644 (file)
index 07ae539..0000000
+++ /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 (file)
index be6182b..0000000
+++ /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 (file)
index 0000000..f367222
--- /dev/null
@@ -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");
index 067f68d19898ed40b570bea84ff7eaaec10d3113..aa5eb4d68a2df375e3b20a1dfd4e7e5097bee71c 100644 (file)
@@ -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
index 5f6d955a497008d34160321fe5b3717efa7d996b..79c3207fe063edb371c05e4747a9a49a9182b01f 100644 (file)
@@ -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; 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;
 }
 
@@ -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;
index 94f5fd560e8af66d06dc6f892787bff78953005e..98508b10d2d8696366ce4bac957947663a6cba77 100644 (file)
@@ -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 (file)
index 0d301ad..0000000
+++ /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 <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);
-}
diff --git a/contrib/linux-kernel/lib/zstd/xxhash.h b/contrib/linux-kernel/lib/zstd/xxhash.h
deleted file mode 100644 (file)
index 974a81c..0000000
+++ /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 <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 */
index 479d6827db086aa8dc3cf55e276e0ab56701e483..a61bd2713985170092d481c7ed78360a323ae103 100644 (file)
 ***************************************/
 #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 */
 
 
 /*-*************************************
index 01e877b7e9950ec17590dc30edc6a9b5902ff1ac..0aa6d81734ea3e62e9b37ea30f2300d77c3fe1b7 100644 (file)
@@ -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 (file)
index 0000000..4ded2ae
--- /dev/null
@@ -0,0 +1,178 @@
+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());
+  }
+}
diff --git a/contrib/linux-kernel/test/include/linux/errno.h b/contrib/linux-kernel/test/include/linux/errno.h
new file mode 100644 (file)
index 0000000..b9db085
--- /dev/null
@@ -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 (file)
index 0000000..bbd5771
--- /dev/null
@@ -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 <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");