162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * xxHash - Extremely Fast Hash algorithm
362306a36Sopenharmony_ci * Copyright (C) 2012-2016, Yann Collet.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
862306a36Sopenharmony_ci * modification, are permitted provided that the following conditions are
962306a36Sopenharmony_ci * met:
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *   * Redistributions of source code must retain the above copyright
1262306a36Sopenharmony_ci *     notice, this list of conditions and the following disclaimer.
1362306a36Sopenharmony_ci *   * Redistributions in binary form must reproduce the above
1462306a36Sopenharmony_ci *     copyright notice, this list of conditions and the following disclaimer
1562306a36Sopenharmony_ci *     in the documentation and/or other materials provided with the
1662306a36Sopenharmony_ci *     distribution.
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1962306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2062306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2162306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2262306a36Sopenharmony_ci * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2362306a36Sopenharmony_ci * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2462306a36Sopenharmony_ci * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2562306a36Sopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2662306a36Sopenharmony_ci * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2762306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2862306a36Sopenharmony_ci * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify it under
3162306a36Sopenharmony_ci * the terms of the GNU General Public License version 2 as published by the
3262306a36Sopenharmony_ci * Free Software Foundation. This program is dual-licensed; you may select
3362306a36Sopenharmony_ci * either version 2 of the GNU General Public License ("GPL") or BSD license
3462306a36Sopenharmony_ci * ("BSD").
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * You can contact the author at:
3762306a36Sopenharmony_ci * - xxHash homepage: https://cyan4973.github.io/xxHash/
3862306a36Sopenharmony_ci * - xxHash source repository: https://github.com/Cyan4973/xxHash
3962306a36Sopenharmony_ci */
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#include <asm/unaligned.h>
4262306a36Sopenharmony_ci#include <linux/errno.h>
4362306a36Sopenharmony_ci#include <linux/compiler.h>
4462306a36Sopenharmony_ci#include <linux/kernel.h>
4562306a36Sopenharmony_ci#include <linux/module.h>
4662306a36Sopenharmony_ci#include <linux/string.h>
4762306a36Sopenharmony_ci#include <linux/xxhash.h>
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/*-*************************************
5062306a36Sopenharmony_ci * Macros
5162306a36Sopenharmony_ci **************************************/
5262306a36Sopenharmony_ci#define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r)))
5362306a36Sopenharmony_ci#define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r)))
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci#ifdef __LITTLE_ENDIAN
5662306a36Sopenharmony_ci# define XXH_CPU_LITTLE_ENDIAN 1
5762306a36Sopenharmony_ci#else
5862306a36Sopenharmony_ci# define XXH_CPU_LITTLE_ENDIAN 0
5962306a36Sopenharmony_ci#endif
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*-*************************************
6262306a36Sopenharmony_ci * Constants
6362306a36Sopenharmony_ci **************************************/
6462306a36Sopenharmony_cistatic const uint32_t PRIME32_1 = 2654435761U;
6562306a36Sopenharmony_cistatic const uint32_t PRIME32_2 = 2246822519U;
6662306a36Sopenharmony_cistatic const uint32_t PRIME32_3 = 3266489917U;
6762306a36Sopenharmony_cistatic const uint32_t PRIME32_4 =  668265263U;
6862306a36Sopenharmony_cistatic const uint32_t PRIME32_5 =  374761393U;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic const uint64_t PRIME64_1 = 11400714785074694791ULL;
7162306a36Sopenharmony_cistatic const uint64_t PRIME64_2 = 14029467366897019727ULL;
7262306a36Sopenharmony_cistatic const uint64_t PRIME64_3 =  1609587929392839161ULL;
7362306a36Sopenharmony_cistatic const uint64_t PRIME64_4 =  9650029242287828579ULL;
7462306a36Sopenharmony_cistatic const uint64_t PRIME64_5 =  2870177450012600261ULL;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci/*-**************************
7762306a36Sopenharmony_ci *  Utils
7862306a36Sopenharmony_ci ***************************/
7962306a36Sopenharmony_civoid xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	memcpy(dst, src, sizeof(*dst));
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_copy_state);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_civoid xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	memcpy(dst, src, sizeof(*dst));
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_copy_state);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/*-***************************
9262306a36Sopenharmony_ci * Simple Hash Functions
9362306a36Sopenharmony_ci ****************************/
9462306a36Sopenharmony_cistatic uint32_t xxh32_round(uint32_t seed, const uint32_t input)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	seed += input * PRIME32_2;
9762306a36Sopenharmony_ci	seed = xxh_rotl32(seed, 13);
9862306a36Sopenharmony_ci	seed *= PRIME32_1;
9962306a36Sopenharmony_ci	return seed;
10062306a36Sopenharmony_ci}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ciuint32_t xxh32(const void *input, const size_t len, const uint32_t seed)
10362306a36Sopenharmony_ci{
10462306a36Sopenharmony_ci	const uint8_t *p = (const uint8_t *)input;
10562306a36Sopenharmony_ci	const uint8_t *b_end = p + len;
10662306a36Sopenharmony_ci	uint32_t h32;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	if (len >= 16) {
10962306a36Sopenharmony_ci		const uint8_t *const limit = b_end - 16;
11062306a36Sopenharmony_ci		uint32_t v1 = seed + PRIME32_1 + PRIME32_2;
11162306a36Sopenharmony_ci		uint32_t v2 = seed + PRIME32_2;
11262306a36Sopenharmony_ci		uint32_t v3 = seed + 0;
11362306a36Sopenharmony_ci		uint32_t v4 = seed - PRIME32_1;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci		do {
11662306a36Sopenharmony_ci			v1 = xxh32_round(v1, get_unaligned_le32(p));
11762306a36Sopenharmony_ci			p += 4;
11862306a36Sopenharmony_ci			v2 = xxh32_round(v2, get_unaligned_le32(p));
11962306a36Sopenharmony_ci			p += 4;
12062306a36Sopenharmony_ci			v3 = xxh32_round(v3, get_unaligned_le32(p));
12162306a36Sopenharmony_ci			p += 4;
12262306a36Sopenharmony_ci			v4 = xxh32_round(v4, get_unaligned_le32(p));
12362306a36Sopenharmony_ci			p += 4;
12462306a36Sopenharmony_ci		} while (p <= limit);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci		h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) +
12762306a36Sopenharmony_ci			xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18);
12862306a36Sopenharmony_ci	} else {
12962306a36Sopenharmony_ci		h32 = seed + PRIME32_5;
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	h32 += (uint32_t)len;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	while (p + 4 <= b_end) {
13562306a36Sopenharmony_ci		h32 += get_unaligned_le32(p) * PRIME32_3;
13662306a36Sopenharmony_ci		h32 = xxh_rotl32(h32, 17) * PRIME32_4;
13762306a36Sopenharmony_ci		p += 4;
13862306a36Sopenharmony_ci	}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	while (p < b_end) {
14162306a36Sopenharmony_ci		h32 += (*p) * PRIME32_5;
14262306a36Sopenharmony_ci		h32 = xxh_rotl32(h32, 11) * PRIME32_1;
14362306a36Sopenharmony_ci		p++;
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	h32 ^= h32 >> 15;
14762306a36Sopenharmony_ci	h32 *= PRIME32_2;
14862306a36Sopenharmony_ci	h32 ^= h32 >> 13;
14962306a36Sopenharmony_ci	h32 *= PRIME32_3;
15062306a36Sopenharmony_ci	h32 ^= h32 >> 16;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	return h32;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistatic uint64_t xxh64_round(uint64_t acc, const uint64_t input)
15762306a36Sopenharmony_ci{
15862306a36Sopenharmony_ci	acc += input * PRIME64_2;
15962306a36Sopenharmony_ci	acc = xxh_rotl64(acc, 31);
16062306a36Sopenharmony_ci	acc *= PRIME64_1;
16162306a36Sopenharmony_ci	return acc;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic uint64_t xxh64_merge_round(uint64_t acc, uint64_t val)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	val = xxh64_round(0, val);
16762306a36Sopenharmony_ci	acc ^= val;
16862306a36Sopenharmony_ci	acc = acc * PRIME64_1 + PRIME64_4;
16962306a36Sopenharmony_ci	return acc;
17062306a36Sopenharmony_ci}
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciuint64_t xxh64(const void *input, const size_t len, const uint64_t seed)
17362306a36Sopenharmony_ci{
17462306a36Sopenharmony_ci	const uint8_t *p = (const uint8_t *)input;
17562306a36Sopenharmony_ci	const uint8_t *const b_end = p + len;
17662306a36Sopenharmony_ci	uint64_t h64;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	if (len >= 32) {
17962306a36Sopenharmony_ci		const uint8_t *const limit = b_end - 32;
18062306a36Sopenharmony_ci		uint64_t v1 = seed + PRIME64_1 + PRIME64_2;
18162306a36Sopenharmony_ci		uint64_t v2 = seed + PRIME64_2;
18262306a36Sopenharmony_ci		uint64_t v3 = seed + 0;
18362306a36Sopenharmony_ci		uint64_t v4 = seed - PRIME64_1;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci		do {
18662306a36Sopenharmony_ci			v1 = xxh64_round(v1, get_unaligned_le64(p));
18762306a36Sopenharmony_ci			p += 8;
18862306a36Sopenharmony_ci			v2 = xxh64_round(v2, get_unaligned_le64(p));
18962306a36Sopenharmony_ci			p += 8;
19062306a36Sopenharmony_ci			v3 = xxh64_round(v3, get_unaligned_le64(p));
19162306a36Sopenharmony_ci			p += 8;
19262306a36Sopenharmony_ci			v4 = xxh64_round(v4, get_unaligned_le64(p));
19362306a36Sopenharmony_ci			p += 8;
19462306a36Sopenharmony_ci		} while (p <= limit);
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci		h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
19762306a36Sopenharmony_ci			xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
19862306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v1);
19962306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v2);
20062306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v3);
20162306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v4);
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	} else {
20462306a36Sopenharmony_ci		h64  = seed + PRIME64_5;
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	h64 += (uint64_t)len;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	while (p + 8 <= b_end) {
21062306a36Sopenharmony_ci		const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci		h64 ^= k1;
21362306a36Sopenharmony_ci		h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
21462306a36Sopenharmony_ci		p += 8;
21562306a36Sopenharmony_ci	}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	if (p + 4 <= b_end) {
21862306a36Sopenharmony_ci		h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
21962306a36Sopenharmony_ci		h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
22062306a36Sopenharmony_ci		p += 4;
22162306a36Sopenharmony_ci	}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci	while (p < b_end) {
22462306a36Sopenharmony_ci		h64 ^= (*p) * PRIME64_5;
22562306a36Sopenharmony_ci		h64 = xxh_rotl64(h64, 11) * PRIME64_1;
22662306a36Sopenharmony_ci		p++;
22762306a36Sopenharmony_ci	}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	h64 ^= h64 >> 33;
23062306a36Sopenharmony_ci	h64 *= PRIME64_2;
23162306a36Sopenharmony_ci	h64 ^= h64 >> 29;
23262306a36Sopenharmony_ci	h64 *= PRIME64_3;
23362306a36Sopenharmony_ci	h64 ^= h64 >> 32;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	return h64;
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci/*-**************************************************
24062306a36Sopenharmony_ci * Advanced Hash Functions
24162306a36Sopenharmony_ci ***************************************************/
24262306a36Sopenharmony_civoid xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	/* use a local state for memcpy() to avoid strict-aliasing warnings */
24562306a36Sopenharmony_ci	struct xxh32_state state;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	memset(&state, 0, sizeof(state));
24862306a36Sopenharmony_ci	state.v1 = seed + PRIME32_1 + PRIME32_2;
24962306a36Sopenharmony_ci	state.v2 = seed + PRIME32_2;
25062306a36Sopenharmony_ci	state.v3 = seed + 0;
25162306a36Sopenharmony_ci	state.v4 = seed - PRIME32_1;
25262306a36Sopenharmony_ci	memcpy(statePtr, &state, sizeof(state));
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_reset);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_civoid xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	/* use a local state for memcpy() to avoid strict-aliasing warnings */
25962306a36Sopenharmony_ci	struct xxh64_state state;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	memset(&state, 0, sizeof(state));
26262306a36Sopenharmony_ci	state.v1 = seed + PRIME64_1 + PRIME64_2;
26362306a36Sopenharmony_ci	state.v2 = seed + PRIME64_2;
26462306a36Sopenharmony_ci	state.v3 = seed + 0;
26562306a36Sopenharmony_ci	state.v4 = seed - PRIME64_1;
26662306a36Sopenharmony_ci	memcpy(statePtr, &state, sizeof(state));
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_reset);
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ciint xxh32_update(struct xxh32_state *state, const void *input, const size_t len)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	const uint8_t *p = (const uint8_t *)input;
27362306a36Sopenharmony_ci	const uint8_t *const b_end = p + len;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	if (input == NULL)
27662306a36Sopenharmony_ci		return -EINVAL;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	state->total_len_32 += (uint32_t)len;
27962306a36Sopenharmony_ci	state->large_len |= (len >= 16) | (state->total_len_32 >= 16);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	if (state->memsize + len < 16) { /* fill in tmp buffer */
28262306a36Sopenharmony_ci		memcpy((uint8_t *)(state->mem32) + state->memsize, input, len);
28362306a36Sopenharmony_ci		state->memsize += (uint32_t)len;
28462306a36Sopenharmony_ci		return 0;
28562306a36Sopenharmony_ci	}
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	if (state->memsize) { /* some data left from previous update */
28862306a36Sopenharmony_ci		const uint32_t *p32 = state->mem32;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci		memcpy((uint8_t *)(state->mem32) + state->memsize, input,
29162306a36Sopenharmony_ci			16 - state->memsize);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci		state->v1 = xxh32_round(state->v1, get_unaligned_le32(p32));
29462306a36Sopenharmony_ci		p32++;
29562306a36Sopenharmony_ci		state->v2 = xxh32_round(state->v2, get_unaligned_le32(p32));
29662306a36Sopenharmony_ci		p32++;
29762306a36Sopenharmony_ci		state->v3 = xxh32_round(state->v3, get_unaligned_le32(p32));
29862306a36Sopenharmony_ci		p32++;
29962306a36Sopenharmony_ci		state->v4 = xxh32_round(state->v4, get_unaligned_le32(p32));
30062306a36Sopenharmony_ci		p32++;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		p += 16-state->memsize;
30362306a36Sopenharmony_ci		state->memsize = 0;
30462306a36Sopenharmony_ci	}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	if (p <= b_end - 16) {
30762306a36Sopenharmony_ci		const uint8_t *const limit = b_end - 16;
30862306a36Sopenharmony_ci		uint32_t v1 = state->v1;
30962306a36Sopenharmony_ci		uint32_t v2 = state->v2;
31062306a36Sopenharmony_ci		uint32_t v3 = state->v3;
31162306a36Sopenharmony_ci		uint32_t v4 = state->v4;
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci		do {
31462306a36Sopenharmony_ci			v1 = xxh32_round(v1, get_unaligned_le32(p));
31562306a36Sopenharmony_ci			p += 4;
31662306a36Sopenharmony_ci			v2 = xxh32_round(v2, get_unaligned_le32(p));
31762306a36Sopenharmony_ci			p += 4;
31862306a36Sopenharmony_ci			v3 = xxh32_round(v3, get_unaligned_le32(p));
31962306a36Sopenharmony_ci			p += 4;
32062306a36Sopenharmony_ci			v4 = xxh32_round(v4, get_unaligned_le32(p));
32162306a36Sopenharmony_ci			p += 4;
32262306a36Sopenharmony_ci		} while (p <= limit);
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci		state->v1 = v1;
32562306a36Sopenharmony_ci		state->v2 = v2;
32662306a36Sopenharmony_ci		state->v3 = v3;
32762306a36Sopenharmony_ci		state->v4 = v4;
32862306a36Sopenharmony_ci	}
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (p < b_end) {
33162306a36Sopenharmony_ci		memcpy(state->mem32, p, (size_t)(b_end-p));
33262306a36Sopenharmony_ci		state->memsize = (uint32_t)(b_end-p);
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	return 0;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_update);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ciuint32_t xxh32_digest(const struct xxh32_state *state)
34062306a36Sopenharmony_ci{
34162306a36Sopenharmony_ci	const uint8_t *p = (const uint8_t *)state->mem32;
34262306a36Sopenharmony_ci	const uint8_t *const b_end = (const uint8_t *)(state->mem32) +
34362306a36Sopenharmony_ci		state->memsize;
34462306a36Sopenharmony_ci	uint32_t h32;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	if (state->large_len) {
34762306a36Sopenharmony_ci		h32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) +
34862306a36Sopenharmony_ci			xxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18);
34962306a36Sopenharmony_ci	} else {
35062306a36Sopenharmony_ci		h32 = state->v3 /* == seed */ + PRIME32_5;
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	h32 += state->total_len_32;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	while (p + 4 <= b_end) {
35662306a36Sopenharmony_ci		h32 += get_unaligned_le32(p) * PRIME32_3;
35762306a36Sopenharmony_ci		h32 = xxh_rotl32(h32, 17) * PRIME32_4;
35862306a36Sopenharmony_ci		p += 4;
35962306a36Sopenharmony_ci	}
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	while (p < b_end) {
36262306a36Sopenharmony_ci		h32 += (*p) * PRIME32_5;
36362306a36Sopenharmony_ci		h32 = xxh_rotl32(h32, 11) * PRIME32_1;
36462306a36Sopenharmony_ci		p++;
36562306a36Sopenharmony_ci	}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	h32 ^= h32 >> 15;
36862306a36Sopenharmony_ci	h32 *= PRIME32_2;
36962306a36Sopenharmony_ci	h32 ^= h32 >> 13;
37062306a36Sopenharmony_ci	h32 *= PRIME32_3;
37162306a36Sopenharmony_ci	h32 ^= h32 >> 16;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	return h32;
37462306a36Sopenharmony_ci}
37562306a36Sopenharmony_ciEXPORT_SYMBOL(xxh32_digest);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ciint xxh64_update(struct xxh64_state *state, const void *input, const size_t len)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	const uint8_t *p = (const uint8_t *)input;
38062306a36Sopenharmony_ci	const uint8_t *const b_end = p + len;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	if (input == NULL)
38362306a36Sopenharmony_ci		return -EINVAL;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	state->total_len += len;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	if (state->memsize + len < 32) { /* fill in tmp buffer */
38862306a36Sopenharmony_ci		memcpy(((uint8_t *)state->mem64) + state->memsize, input, len);
38962306a36Sopenharmony_ci		state->memsize += (uint32_t)len;
39062306a36Sopenharmony_ci		return 0;
39162306a36Sopenharmony_ci	}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	if (state->memsize) { /* tmp buffer is full */
39462306a36Sopenharmony_ci		uint64_t *p64 = state->mem64;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci		memcpy(((uint8_t *)p64) + state->memsize, input,
39762306a36Sopenharmony_ci			32 - state->memsize);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci		state->v1 = xxh64_round(state->v1, get_unaligned_le64(p64));
40062306a36Sopenharmony_ci		p64++;
40162306a36Sopenharmony_ci		state->v2 = xxh64_round(state->v2, get_unaligned_le64(p64));
40262306a36Sopenharmony_ci		p64++;
40362306a36Sopenharmony_ci		state->v3 = xxh64_round(state->v3, get_unaligned_le64(p64));
40462306a36Sopenharmony_ci		p64++;
40562306a36Sopenharmony_ci		state->v4 = xxh64_round(state->v4, get_unaligned_le64(p64));
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci		p += 32 - state->memsize;
40862306a36Sopenharmony_ci		state->memsize = 0;
40962306a36Sopenharmony_ci	}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	if (p + 32 <= b_end) {
41262306a36Sopenharmony_ci		const uint8_t *const limit = b_end - 32;
41362306a36Sopenharmony_ci		uint64_t v1 = state->v1;
41462306a36Sopenharmony_ci		uint64_t v2 = state->v2;
41562306a36Sopenharmony_ci		uint64_t v3 = state->v3;
41662306a36Sopenharmony_ci		uint64_t v4 = state->v4;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		do {
41962306a36Sopenharmony_ci			v1 = xxh64_round(v1, get_unaligned_le64(p));
42062306a36Sopenharmony_ci			p += 8;
42162306a36Sopenharmony_ci			v2 = xxh64_round(v2, get_unaligned_le64(p));
42262306a36Sopenharmony_ci			p += 8;
42362306a36Sopenharmony_ci			v3 = xxh64_round(v3, get_unaligned_le64(p));
42462306a36Sopenharmony_ci			p += 8;
42562306a36Sopenharmony_ci			v4 = xxh64_round(v4, get_unaligned_le64(p));
42662306a36Sopenharmony_ci			p += 8;
42762306a36Sopenharmony_ci		} while (p <= limit);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci		state->v1 = v1;
43062306a36Sopenharmony_ci		state->v2 = v2;
43162306a36Sopenharmony_ci		state->v3 = v3;
43262306a36Sopenharmony_ci		state->v4 = v4;
43362306a36Sopenharmony_ci	}
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	if (p < b_end) {
43662306a36Sopenharmony_ci		memcpy(state->mem64, p, (size_t)(b_end-p));
43762306a36Sopenharmony_ci		state->memsize = (uint32_t)(b_end - p);
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	return 0;
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_update);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ciuint64_t xxh64_digest(const struct xxh64_state *state)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	const uint8_t *p = (const uint8_t *)state->mem64;
44762306a36Sopenharmony_ci	const uint8_t *const b_end = (const uint8_t *)state->mem64 +
44862306a36Sopenharmony_ci		state->memsize;
44962306a36Sopenharmony_ci	uint64_t h64;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	if (state->total_len >= 32) {
45262306a36Sopenharmony_ci		const uint64_t v1 = state->v1;
45362306a36Sopenharmony_ci		const uint64_t v2 = state->v2;
45462306a36Sopenharmony_ci		const uint64_t v3 = state->v3;
45562306a36Sopenharmony_ci		const uint64_t v4 = state->v4;
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci		h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
45862306a36Sopenharmony_ci			xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
45962306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v1);
46062306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v2);
46162306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v3);
46262306a36Sopenharmony_ci		h64 = xxh64_merge_round(h64, v4);
46362306a36Sopenharmony_ci	} else {
46462306a36Sopenharmony_ci		h64  = state->v3 + PRIME64_5;
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	h64 += (uint64_t)state->total_len;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	while (p + 8 <= b_end) {
47062306a36Sopenharmony_ci		const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci		h64 ^= k1;
47362306a36Sopenharmony_ci		h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
47462306a36Sopenharmony_ci		p += 8;
47562306a36Sopenharmony_ci	}
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	if (p + 4 <= b_end) {
47862306a36Sopenharmony_ci		h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
47962306a36Sopenharmony_ci		h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
48062306a36Sopenharmony_ci		p += 4;
48162306a36Sopenharmony_ci	}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	while (p < b_end) {
48462306a36Sopenharmony_ci		h64 ^= (*p) * PRIME64_5;
48562306a36Sopenharmony_ci		h64 = xxh_rotl64(h64, 11) * PRIME64_1;
48662306a36Sopenharmony_ci		p++;
48762306a36Sopenharmony_ci	}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	h64 ^= h64 >> 33;
49062306a36Sopenharmony_ci	h64 *= PRIME64_2;
49162306a36Sopenharmony_ci	h64 ^= h64 >> 29;
49262306a36Sopenharmony_ci	h64 *= PRIME64_3;
49362306a36Sopenharmony_ci	h64 ^= h64 >> 32;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	return h64;
49662306a36Sopenharmony_ci}
49762306a36Sopenharmony_ciEXPORT_SYMBOL(xxh64_digest);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
50062306a36Sopenharmony_ciMODULE_DESCRIPTION("xxHash");
501