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