xref: /OK3568_Linux_fs/kernel/lib/xxhash.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * xxHash - Extremely Fast Hash algorithm
3*4882a593Smuzhiyun  * Copyright (C) 2012-2016, Yann Collet.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
8*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions are
9*4882a593Smuzhiyun  * met:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  *   * Redistributions of source code must retain the above copyright
12*4882a593Smuzhiyun  *     notice, this list of conditions and the following disclaimer.
13*4882a593Smuzhiyun  *   * Redistributions in binary form must reproduce the above
14*4882a593Smuzhiyun  *     copyright notice, this list of conditions and the following disclaimer
15*4882a593Smuzhiyun  *     in the documentation and/or other materials provided with the
16*4882a593Smuzhiyun  *     distribution.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19*4882a593Smuzhiyun  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20*4882a593Smuzhiyun  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21*4882a593Smuzhiyun  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22*4882a593Smuzhiyun  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23*4882a593Smuzhiyun  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24*4882a593Smuzhiyun  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25*4882a593Smuzhiyun  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26*4882a593Smuzhiyun  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27*4882a593Smuzhiyun  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28*4882a593Smuzhiyun  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*4882a593Smuzhiyun  *
30*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or modify it under
31*4882a593Smuzhiyun  * the terms of the GNU General Public License version 2 as published by the
32*4882a593Smuzhiyun  * Free Software Foundation. This program is dual-licensed; you may select
33*4882a593Smuzhiyun  * either version 2 of the GNU General Public License ("GPL") or BSD license
34*4882a593Smuzhiyun  * ("BSD").
35*4882a593Smuzhiyun  *
36*4882a593Smuzhiyun  * You can contact the author at:
37*4882a593Smuzhiyun  * - xxHash homepage: https://cyan4973.github.io/xxHash/
38*4882a593Smuzhiyun  * - xxHash source repository: https://github.com/Cyan4973/xxHash
39*4882a593Smuzhiyun  */
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #include <asm/unaligned.h>
42*4882a593Smuzhiyun #include <linux/errno.h>
43*4882a593Smuzhiyun #include <linux/compiler.h>
44*4882a593Smuzhiyun #include <linux/kernel.h>
45*4882a593Smuzhiyun #include <linux/module.h>
46*4882a593Smuzhiyun #include <linux/string.h>
47*4882a593Smuzhiyun #include <linux/xxhash.h>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun /*-*************************************
50*4882a593Smuzhiyun  * Macros
51*4882a593Smuzhiyun  **************************************/
52*4882a593Smuzhiyun #define xxh_rotl32(x, r) ((x << r) | (x >> (32 - r)))
53*4882a593Smuzhiyun #define xxh_rotl64(x, r) ((x << r) | (x >> (64 - r)))
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN
56*4882a593Smuzhiyun # define XXH_CPU_LITTLE_ENDIAN 1
57*4882a593Smuzhiyun #else
58*4882a593Smuzhiyun # define XXH_CPU_LITTLE_ENDIAN 0
59*4882a593Smuzhiyun #endif
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun /*-*************************************
62*4882a593Smuzhiyun  * Constants
63*4882a593Smuzhiyun  **************************************/
64*4882a593Smuzhiyun static const uint32_t PRIME32_1 = 2654435761U;
65*4882a593Smuzhiyun static const uint32_t PRIME32_2 = 2246822519U;
66*4882a593Smuzhiyun static const uint32_t PRIME32_3 = 3266489917U;
67*4882a593Smuzhiyun static const uint32_t PRIME32_4 =  668265263U;
68*4882a593Smuzhiyun static const uint32_t PRIME32_5 =  374761393U;
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static const uint64_t PRIME64_1 = 11400714785074694791ULL;
71*4882a593Smuzhiyun static const uint64_t PRIME64_2 = 14029467366897019727ULL;
72*4882a593Smuzhiyun static const uint64_t PRIME64_3 =  1609587929392839161ULL;
73*4882a593Smuzhiyun static const uint64_t PRIME64_4 =  9650029242287828579ULL;
74*4882a593Smuzhiyun static const uint64_t PRIME64_5 =  2870177450012600261ULL;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /*-**************************
77*4882a593Smuzhiyun  *  Utils
78*4882a593Smuzhiyun  ***************************/
xxh32_copy_state(struct xxh32_state * dst,const struct xxh32_state * src)79*4882a593Smuzhiyun void xxh32_copy_state(struct xxh32_state *dst, const struct xxh32_state *src)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun 	memcpy(dst, src, sizeof(*dst));
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun EXPORT_SYMBOL(xxh32_copy_state);
84*4882a593Smuzhiyun 
xxh64_copy_state(struct xxh64_state * dst,const struct xxh64_state * src)85*4882a593Smuzhiyun void xxh64_copy_state(struct xxh64_state *dst, const struct xxh64_state *src)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun 	memcpy(dst, src, sizeof(*dst));
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun EXPORT_SYMBOL(xxh64_copy_state);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun /*-***************************
92*4882a593Smuzhiyun  * Simple Hash Functions
93*4882a593Smuzhiyun  ****************************/
xxh32_round(uint32_t seed,const uint32_t input)94*4882a593Smuzhiyun static uint32_t xxh32_round(uint32_t seed, const uint32_t input)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	seed += input * PRIME32_2;
97*4882a593Smuzhiyun 	seed = xxh_rotl32(seed, 13);
98*4882a593Smuzhiyun 	seed *= PRIME32_1;
99*4882a593Smuzhiyun 	return seed;
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
xxh32(const void * input,const size_t len,const uint32_t seed)102*4882a593Smuzhiyun uint32_t xxh32(const void *input, const size_t len, const uint32_t seed)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	const uint8_t *p = (const uint8_t *)input;
105*4882a593Smuzhiyun 	const uint8_t *b_end = p + len;
106*4882a593Smuzhiyun 	uint32_t h32;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	if (len >= 16) {
109*4882a593Smuzhiyun 		const uint8_t *const limit = b_end - 16;
110*4882a593Smuzhiyun 		uint32_t v1 = seed + PRIME32_1 + PRIME32_2;
111*4882a593Smuzhiyun 		uint32_t v2 = seed + PRIME32_2;
112*4882a593Smuzhiyun 		uint32_t v3 = seed + 0;
113*4882a593Smuzhiyun 		uint32_t v4 = seed - PRIME32_1;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 		do {
116*4882a593Smuzhiyun 			v1 = xxh32_round(v1, get_unaligned_le32(p));
117*4882a593Smuzhiyun 			p += 4;
118*4882a593Smuzhiyun 			v2 = xxh32_round(v2, get_unaligned_le32(p));
119*4882a593Smuzhiyun 			p += 4;
120*4882a593Smuzhiyun 			v3 = xxh32_round(v3, get_unaligned_le32(p));
121*4882a593Smuzhiyun 			p += 4;
122*4882a593Smuzhiyun 			v4 = xxh32_round(v4, get_unaligned_le32(p));
123*4882a593Smuzhiyun 			p += 4;
124*4882a593Smuzhiyun 		} while (p <= limit);
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 		h32 = xxh_rotl32(v1, 1) + xxh_rotl32(v2, 7) +
127*4882a593Smuzhiyun 			xxh_rotl32(v3, 12) + xxh_rotl32(v4, 18);
128*4882a593Smuzhiyun 	} else {
129*4882a593Smuzhiyun 		h32 = seed + PRIME32_5;
130*4882a593Smuzhiyun 	}
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	h32 += (uint32_t)len;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	while (p + 4 <= b_end) {
135*4882a593Smuzhiyun 		h32 += get_unaligned_le32(p) * PRIME32_3;
136*4882a593Smuzhiyun 		h32 = xxh_rotl32(h32, 17) * PRIME32_4;
137*4882a593Smuzhiyun 		p += 4;
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	while (p < b_end) {
141*4882a593Smuzhiyun 		h32 += (*p) * PRIME32_5;
142*4882a593Smuzhiyun 		h32 = xxh_rotl32(h32, 11) * PRIME32_1;
143*4882a593Smuzhiyun 		p++;
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	h32 ^= h32 >> 15;
147*4882a593Smuzhiyun 	h32 *= PRIME32_2;
148*4882a593Smuzhiyun 	h32 ^= h32 >> 13;
149*4882a593Smuzhiyun 	h32 *= PRIME32_3;
150*4882a593Smuzhiyun 	h32 ^= h32 >> 16;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	return h32;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun EXPORT_SYMBOL(xxh32);
155*4882a593Smuzhiyun 
xxh64_round(uint64_t acc,const uint64_t input)156*4882a593Smuzhiyun static uint64_t xxh64_round(uint64_t acc, const uint64_t input)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	acc += input * PRIME64_2;
159*4882a593Smuzhiyun 	acc = xxh_rotl64(acc, 31);
160*4882a593Smuzhiyun 	acc *= PRIME64_1;
161*4882a593Smuzhiyun 	return acc;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
xxh64_merge_round(uint64_t acc,uint64_t val)164*4882a593Smuzhiyun static uint64_t xxh64_merge_round(uint64_t acc, uint64_t val)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	val = xxh64_round(0, val);
167*4882a593Smuzhiyun 	acc ^= val;
168*4882a593Smuzhiyun 	acc = acc * PRIME64_1 + PRIME64_4;
169*4882a593Smuzhiyun 	return acc;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
xxh64(const void * input,const size_t len,const uint64_t seed)172*4882a593Smuzhiyun uint64_t xxh64(const void *input, const size_t len, const uint64_t seed)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	const uint8_t *p = (const uint8_t *)input;
175*4882a593Smuzhiyun 	const uint8_t *const b_end = p + len;
176*4882a593Smuzhiyun 	uint64_t h64;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	if (len >= 32) {
179*4882a593Smuzhiyun 		const uint8_t *const limit = b_end - 32;
180*4882a593Smuzhiyun 		uint64_t v1 = seed + PRIME64_1 + PRIME64_2;
181*4882a593Smuzhiyun 		uint64_t v2 = seed + PRIME64_2;
182*4882a593Smuzhiyun 		uint64_t v3 = seed + 0;
183*4882a593Smuzhiyun 		uint64_t v4 = seed - PRIME64_1;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 		do {
186*4882a593Smuzhiyun 			v1 = xxh64_round(v1, get_unaligned_le64(p));
187*4882a593Smuzhiyun 			p += 8;
188*4882a593Smuzhiyun 			v2 = xxh64_round(v2, get_unaligned_le64(p));
189*4882a593Smuzhiyun 			p += 8;
190*4882a593Smuzhiyun 			v3 = xxh64_round(v3, get_unaligned_le64(p));
191*4882a593Smuzhiyun 			p += 8;
192*4882a593Smuzhiyun 			v4 = xxh64_round(v4, get_unaligned_le64(p));
193*4882a593Smuzhiyun 			p += 8;
194*4882a593Smuzhiyun 		} while (p <= limit);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 		h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
197*4882a593Smuzhiyun 			xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
198*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v1);
199*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v2);
200*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v3);
201*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v4);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	} else {
204*4882a593Smuzhiyun 		h64  = seed + PRIME64_5;
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	h64 += (uint64_t)len;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	while (p + 8 <= b_end) {
210*4882a593Smuzhiyun 		const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		h64 ^= k1;
213*4882a593Smuzhiyun 		h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
214*4882a593Smuzhiyun 		p += 8;
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	if (p + 4 <= b_end) {
218*4882a593Smuzhiyun 		h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
219*4882a593Smuzhiyun 		h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
220*4882a593Smuzhiyun 		p += 4;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	while (p < b_end) {
224*4882a593Smuzhiyun 		h64 ^= (*p) * PRIME64_5;
225*4882a593Smuzhiyun 		h64 = xxh_rotl64(h64, 11) * PRIME64_1;
226*4882a593Smuzhiyun 		p++;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	h64 ^= h64 >> 33;
230*4882a593Smuzhiyun 	h64 *= PRIME64_2;
231*4882a593Smuzhiyun 	h64 ^= h64 >> 29;
232*4882a593Smuzhiyun 	h64 *= PRIME64_3;
233*4882a593Smuzhiyun 	h64 ^= h64 >> 32;
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	return h64;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun EXPORT_SYMBOL(xxh64);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun /*-**************************************************
240*4882a593Smuzhiyun  * Advanced Hash Functions
241*4882a593Smuzhiyun  ***************************************************/
xxh32_reset(struct xxh32_state * statePtr,const uint32_t seed)242*4882a593Smuzhiyun void xxh32_reset(struct xxh32_state *statePtr, const uint32_t seed)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	/* use a local state for memcpy() to avoid strict-aliasing warnings */
245*4882a593Smuzhiyun 	struct xxh32_state state;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	memset(&state, 0, sizeof(state));
248*4882a593Smuzhiyun 	state.v1 = seed + PRIME32_1 + PRIME32_2;
249*4882a593Smuzhiyun 	state.v2 = seed + PRIME32_2;
250*4882a593Smuzhiyun 	state.v3 = seed + 0;
251*4882a593Smuzhiyun 	state.v4 = seed - PRIME32_1;
252*4882a593Smuzhiyun 	memcpy(statePtr, &state, sizeof(state));
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun EXPORT_SYMBOL(xxh32_reset);
255*4882a593Smuzhiyun 
xxh64_reset(struct xxh64_state * statePtr,const uint64_t seed)256*4882a593Smuzhiyun void xxh64_reset(struct xxh64_state *statePtr, const uint64_t seed)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun 	/* use a local state for memcpy() to avoid strict-aliasing warnings */
259*4882a593Smuzhiyun 	struct xxh64_state state;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	memset(&state, 0, sizeof(state));
262*4882a593Smuzhiyun 	state.v1 = seed + PRIME64_1 + PRIME64_2;
263*4882a593Smuzhiyun 	state.v2 = seed + PRIME64_2;
264*4882a593Smuzhiyun 	state.v3 = seed + 0;
265*4882a593Smuzhiyun 	state.v4 = seed - PRIME64_1;
266*4882a593Smuzhiyun 	memcpy(statePtr, &state, sizeof(state));
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun EXPORT_SYMBOL(xxh64_reset);
269*4882a593Smuzhiyun 
xxh32_update(struct xxh32_state * state,const void * input,const size_t len)270*4882a593Smuzhiyun int xxh32_update(struct xxh32_state *state, const void *input, const size_t len)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	const uint8_t *p = (const uint8_t *)input;
273*4882a593Smuzhiyun 	const uint8_t *const b_end = p + len;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	if (input == NULL)
276*4882a593Smuzhiyun 		return -EINVAL;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	state->total_len_32 += (uint32_t)len;
279*4882a593Smuzhiyun 	state->large_len |= (len >= 16) | (state->total_len_32 >= 16);
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	if (state->memsize + len < 16) { /* fill in tmp buffer */
282*4882a593Smuzhiyun 		memcpy((uint8_t *)(state->mem32) + state->memsize, input, len);
283*4882a593Smuzhiyun 		state->memsize += (uint32_t)len;
284*4882a593Smuzhiyun 		return 0;
285*4882a593Smuzhiyun 	}
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	if (state->memsize) { /* some data left from previous update */
288*4882a593Smuzhiyun 		const uint32_t *p32 = state->mem32;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 		memcpy((uint8_t *)(state->mem32) + state->memsize, input,
291*4882a593Smuzhiyun 			16 - state->memsize);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 		state->v1 = xxh32_round(state->v1, get_unaligned_le32(p32));
294*4882a593Smuzhiyun 		p32++;
295*4882a593Smuzhiyun 		state->v2 = xxh32_round(state->v2, get_unaligned_le32(p32));
296*4882a593Smuzhiyun 		p32++;
297*4882a593Smuzhiyun 		state->v3 = xxh32_round(state->v3, get_unaligned_le32(p32));
298*4882a593Smuzhiyun 		p32++;
299*4882a593Smuzhiyun 		state->v4 = xxh32_round(state->v4, get_unaligned_le32(p32));
300*4882a593Smuzhiyun 		p32++;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 		p += 16-state->memsize;
303*4882a593Smuzhiyun 		state->memsize = 0;
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	if (p <= b_end - 16) {
307*4882a593Smuzhiyun 		const uint8_t *const limit = b_end - 16;
308*4882a593Smuzhiyun 		uint32_t v1 = state->v1;
309*4882a593Smuzhiyun 		uint32_t v2 = state->v2;
310*4882a593Smuzhiyun 		uint32_t v3 = state->v3;
311*4882a593Smuzhiyun 		uint32_t v4 = state->v4;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 		do {
314*4882a593Smuzhiyun 			v1 = xxh32_round(v1, get_unaligned_le32(p));
315*4882a593Smuzhiyun 			p += 4;
316*4882a593Smuzhiyun 			v2 = xxh32_round(v2, get_unaligned_le32(p));
317*4882a593Smuzhiyun 			p += 4;
318*4882a593Smuzhiyun 			v3 = xxh32_round(v3, get_unaligned_le32(p));
319*4882a593Smuzhiyun 			p += 4;
320*4882a593Smuzhiyun 			v4 = xxh32_round(v4, get_unaligned_le32(p));
321*4882a593Smuzhiyun 			p += 4;
322*4882a593Smuzhiyun 		} while (p <= limit);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 		state->v1 = v1;
325*4882a593Smuzhiyun 		state->v2 = v2;
326*4882a593Smuzhiyun 		state->v3 = v3;
327*4882a593Smuzhiyun 		state->v4 = v4;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	if (p < b_end) {
331*4882a593Smuzhiyun 		memcpy(state->mem32, p, (size_t)(b_end-p));
332*4882a593Smuzhiyun 		state->memsize = (uint32_t)(b_end-p);
333*4882a593Smuzhiyun 	}
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	return 0;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun EXPORT_SYMBOL(xxh32_update);
338*4882a593Smuzhiyun 
xxh32_digest(const struct xxh32_state * state)339*4882a593Smuzhiyun uint32_t xxh32_digest(const struct xxh32_state *state)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun 	const uint8_t *p = (const uint8_t *)state->mem32;
342*4882a593Smuzhiyun 	const uint8_t *const b_end = (const uint8_t *)(state->mem32) +
343*4882a593Smuzhiyun 		state->memsize;
344*4882a593Smuzhiyun 	uint32_t h32;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	if (state->large_len) {
347*4882a593Smuzhiyun 		h32 = xxh_rotl32(state->v1, 1) + xxh_rotl32(state->v2, 7) +
348*4882a593Smuzhiyun 			xxh_rotl32(state->v3, 12) + xxh_rotl32(state->v4, 18);
349*4882a593Smuzhiyun 	} else {
350*4882a593Smuzhiyun 		h32 = state->v3 /* == seed */ + PRIME32_5;
351*4882a593Smuzhiyun 	}
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun 	h32 += state->total_len_32;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	while (p + 4 <= b_end) {
356*4882a593Smuzhiyun 		h32 += get_unaligned_le32(p) * PRIME32_3;
357*4882a593Smuzhiyun 		h32 = xxh_rotl32(h32, 17) * PRIME32_4;
358*4882a593Smuzhiyun 		p += 4;
359*4882a593Smuzhiyun 	}
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	while (p < b_end) {
362*4882a593Smuzhiyun 		h32 += (*p) * PRIME32_5;
363*4882a593Smuzhiyun 		h32 = xxh_rotl32(h32, 11) * PRIME32_1;
364*4882a593Smuzhiyun 		p++;
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	h32 ^= h32 >> 15;
368*4882a593Smuzhiyun 	h32 *= PRIME32_2;
369*4882a593Smuzhiyun 	h32 ^= h32 >> 13;
370*4882a593Smuzhiyun 	h32 *= PRIME32_3;
371*4882a593Smuzhiyun 	h32 ^= h32 >> 16;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	return h32;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun EXPORT_SYMBOL(xxh32_digest);
376*4882a593Smuzhiyun 
xxh64_update(struct xxh64_state * state,const void * input,const size_t len)377*4882a593Smuzhiyun int xxh64_update(struct xxh64_state *state, const void *input, const size_t len)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	const uint8_t *p = (const uint8_t *)input;
380*4882a593Smuzhiyun 	const uint8_t *const b_end = p + len;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	if (input == NULL)
383*4882a593Smuzhiyun 		return -EINVAL;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	state->total_len += len;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	if (state->memsize + len < 32) { /* fill in tmp buffer */
388*4882a593Smuzhiyun 		memcpy(((uint8_t *)state->mem64) + state->memsize, input, len);
389*4882a593Smuzhiyun 		state->memsize += (uint32_t)len;
390*4882a593Smuzhiyun 		return 0;
391*4882a593Smuzhiyun 	}
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	if (state->memsize) { /* tmp buffer is full */
394*4882a593Smuzhiyun 		uint64_t *p64 = state->mem64;
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 		memcpy(((uint8_t *)p64) + state->memsize, input,
397*4882a593Smuzhiyun 			32 - state->memsize);
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 		state->v1 = xxh64_round(state->v1, get_unaligned_le64(p64));
400*4882a593Smuzhiyun 		p64++;
401*4882a593Smuzhiyun 		state->v2 = xxh64_round(state->v2, get_unaligned_le64(p64));
402*4882a593Smuzhiyun 		p64++;
403*4882a593Smuzhiyun 		state->v3 = xxh64_round(state->v3, get_unaligned_le64(p64));
404*4882a593Smuzhiyun 		p64++;
405*4882a593Smuzhiyun 		state->v4 = xxh64_round(state->v4, get_unaligned_le64(p64));
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 		p += 32 - state->memsize;
408*4882a593Smuzhiyun 		state->memsize = 0;
409*4882a593Smuzhiyun 	}
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	if (p + 32 <= b_end) {
412*4882a593Smuzhiyun 		const uint8_t *const limit = b_end - 32;
413*4882a593Smuzhiyun 		uint64_t v1 = state->v1;
414*4882a593Smuzhiyun 		uint64_t v2 = state->v2;
415*4882a593Smuzhiyun 		uint64_t v3 = state->v3;
416*4882a593Smuzhiyun 		uint64_t v4 = state->v4;
417*4882a593Smuzhiyun 
418*4882a593Smuzhiyun 		do {
419*4882a593Smuzhiyun 			v1 = xxh64_round(v1, get_unaligned_le64(p));
420*4882a593Smuzhiyun 			p += 8;
421*4882a593Smuzhiyun 			v2 = xxh64_round(v2, get_unaligned_le64(p));
422*4882a593Smuzhiyun 			p += 8;
423*4882a593Smuzhiyun 			v3 = xxh64_round(v3, get_unaligned_le64(p));
424*4882a593Smuzhiyun 			p += 8;
425*4882a593Smuzhiyun 			v4 = xxh64_round(v4, get_unaligned_le64(p));
426*4882a593Smuzhiyun 			p += 8;
427*4882a593Smuzhiyun 		} while (p <= limit);
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 		state->v1 = v1;
430*4882a593Smuzhiyun 		state->v2 = v2;
431*4882a593Smuzhiyun 		state->v3 = v3;
432*4882a593Smuzhiyun 		state->v4 = v4;
433*4882a593Smuzhiyun 	}
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	if (p < b_end) {
436*4882a593Smuzhiyun 		memcpy(state->mem64, p, (size_t)(b_end-p));
437*4882a593Smuzhiyun 		state->memsize = (uint32_t)(b_end - p);
438*4882a593Smuzhiyun 	}
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	return 0;
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun EXPORT_SYMBOL(xxh64_update);
443*4882a593Smuzhiyun 
xxh64_digest(const struct xxh64_state * state)444*4882a593Smuzhiyun uint64_t xxh64_digest(const struct xxh64_state *state)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun 	const uint8_t *p = (const uint8_t *)state->mem64;
447*4882a593Smuzhiyun 	const uint8_t *const b_end = (const uint8_t *)state->mem64 +
448*4882a593Smuzhiyun 		state->memsize;
449*4882a593Smuzhiyun 	uint64_t h64;
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun 	if (state->total_len >= 32) {
452*4882a593Smuzhiyun 		const uint64_t v1 = state->v1;
453*4882a593Smuzhiyun 		const uint64_t v2 = state->v2;
454*4882a593Smuzhiyun 		const uint64_t v3 = state->v3;
455*4882a593Smuzhiyun 		const uint64_t v4 = state->v4;
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 		h64 = xxh_rotl64(v1, 1) + xxh_rotl64(v2, 7) +
458*4882a593Smuzhiyun 			xxh_rotl64(v3, 12) + xxh_rotl64(v4, 18);
459*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v1);
460*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v2);
461*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v3);
462*4882a593Smuzhiyun 		h64 = xxh64_merge_round(h64, v4);
463*4882a593Smuzhiyun 	} else {
464*4882a593Smuzhiyun 		h64  = state->v3 + PRIME64_5;
465*4882a593Smuzhiyun 	}
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	h64 += (uint64_t)state->total_len;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	while (p + 8 <= b_end) {
470*4882a593Smuzhiyun 		const uint64_t k1 = xxh64_round(0, get_unaligned_le64(p));
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 		h64 ^= k1;
473*4882a593Smuzhiyun 		h64 = xxh_rotl64(h64, 27) * PRIME64_1 + PRIME64_4;
474*4882a593Smuzhiyun 		p += 8;
475*4882a593Smuzhiyun 	}
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	if (p + 4 <= b_end) {
478*4882a593Smuzhiyun 		h64 ^= (uint64_t)(get_unaligned_le32(p)) * PRIME64_1;
479*4882a593Smuzhiyun 		h64 = xxh_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
480*4882a593Smuzhiyun 		p += 4;
481*4882a593Smuzhiyun 	}
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	while (p < b_end) {
484*4882a593Smuzhiyun 		h64 ^= (*p) * PRIME64_5;
485*4882a593Smuzhiyun 		h64 = xxh_rotl64(h64, 11) * PRIME64_1;
486*4882a593Smuzhiyun 		p++;
487*4882a593Smuzhiyun 	}
488*4882a593Smuzhiyun 
489*4882a593Smuzhiyun 	h64 ^= h64 >> 33;
490*4882a593Smuzhiyun 	h64 *= PRIME64_2;
491*4882a593Smuzhiyun 	h64 ^= h64 >> 29;
492*4882a593Smuzhiyun 	h64 *= PRIME64_3;
493*4882a593Smuzhiyun 	h64 ^= h64 >> 32;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	return h64;
496*4882a593Smuzhiyun }
497*4882a593Smuzhiyun EXPORT_SYMBOL(xxh64_digest);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun MODULE_LICENSE("Dual BSD/GPL");
500*4882a593Smuzhiyun MODULE_DESCRIPTION("xxHash");
501