1 // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
2 // This source code is licensed under both the GPLv2 (found in the
3 // COPYING file in the root directory) and Apache 2.0 License
4 // (found in the LICENSE.Apache file in the root directory).
5 /*
6 * xxHash - Fast Hash algorithm
7 * Copyright (C) 2012-2016, Yann Collet
8 *
9 * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions are
13 * met:
14 *
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following disclaimer
19 * in the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * You can contact the author at :
35 * - xxHash homepage: http://www.xxhash.com
36 * - xxHash source repository : https://github.com/Cyan4973/xxHash
37 */
38
39
40 /* since xxhash.c can be included (via XXH_INLINE_ALL),
41 * it's good practice to protect it with guard
42 * in case of multiples inclusions */
43 #ifndef XXHASH_C_01393879
44 #define XXHASH_C_01393879
45
46 /* *************************************
47 * Tuning parameters
48 ***************************************/
49 /*!XXH_FORCE_MEMORY_ACCESS :
50 * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
51 * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
52 * The below switch allow to select different access method for improved performance.
53 * Method 0 (default) : use `memcpy()`. Safe and portable.
54 * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
55 * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
56 * Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
57 * It can generate buggy code on targets which do not support unaligned memory accesses.
58 * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
59 * See http://stackoverflow.com/a/32095106/646947 for details.
60 * Prefer these methods in priority order (0 > 1 > 2)
61 */
62 #ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
63 # if !defined(__clang__) && defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED) && defined(__ARM_ARCH) && (__ARM_ARCH == 6)
64 # define XXH_FORCE_MEMORY_ACCESS 2
65 # elif !defined(__clang__) && ((defined(__INTEL_COMPILER) && !defined(_WIN32)) || \
66 (defined(__GNUC__) && (defined(__ARM_ARCH) && __ARM_ARCH >= 7)))
67 # define XXH_FORCE_MEMORY_ACCESS 1
68 # endif
69 #endif
70
71 /*!XXH_ACCEPT_NULL_INPUT_POINTER :
72 * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault.
73 * When this macro is enabled, xxHash actively checks input for null pointer.
74 * It it is, result for null input pointers is the same as a null-length input.
75 */
76 #ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */
77 # define XXH_ACCEPT_NULL_INPUT_POINTER 0
78 #endif
79
80 /*!XXH_FORCE_ALIGN_CHECK :
81 * This is a minor performance trick, only useful with lots of very small keys.
82 * It means : check for aligned/unaligned input.
83 * The check costs one initial branch per hash;
84 * set it to 0 when the input is guaranteed to be aligned,
85 * or when alignment doesn't matter for performance.
86 */
87 #ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
88 # if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
89 # define XXH_FORCE_ALIGN_CHECK 0
90 # else
91 # define XXH_FORCE_ALIGN_CHECK 1
92 # endif
93 #endif
94
95 /*!XXH_REROLL:
96 * Whether to reroll XXH32_finalize, and XXH64_finalize,
97 * instead of using an unrolled jump table/if statement loop.
98 *
99 * This is automatically defined on -Os/-Oz on GCC and Clang. */
100 #ifndef XXH_REROLL
101 # if defined(__OPTIMIZE_SIZE__)
102 # define XXH_REROLL 1
103 # else
104 # define XXH_REROLL 0
105 # endif
106 #endif
107
108 /* *************************************
109 * Includes & Memory related functions
110 ***************************************/
111 /*! Modify the local functions below should you wish to use some other memory routines
112 * for malloc(), free() */
113 #include <stdlib.h>
XXH_malloc(size_t s)114 static void* XXH_malloc(size_t s) { return malloc(s); }
XXH_free(void * p)115 static void XXH_free (void* p) { free(p); }
116 /*! and for memcpy() */
117 #include <string.h>
XXH_memcpy(void * dest,const void * src,size_t size)118 static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
119
120 #include <limits.h> /* ULLONG_MAX */
121
122 #ifndef XXH_STATIC_LINKING_ONLY
123 #define XXH_STATIC_LINKING_ONLY
124 #endif
125
126 #include "xxhash.h"
127
128 /* BEGIN RocksDB customizations */
129 #include "util/util.h" /* for FALLTHROUGH_INTENDED, inserted as appropriate */
130 /* END RocksDB customizations */
131
132 /* *************************************
133 * Compiler Specific Options
134 ***************************************/
135 #ifdef _MSC_VER /* Visual Studio */
136 # pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
137 # define XXH_FORCE_INLINE static __forceinline
138 # define XXH_NO_INLINE static __declspec(noinline)
139 #else
140 # if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
141 # ifdef __GNUC__
142 # define XXH_FORCE_INLINE static inline __attribute__((always_inline))
143 # define XXH_NO_INLINE static __attribute__((noinline))
144 # else
145 # define XXH_FORCE_INLINE static inline
146 # define XXH_NO_INLINE static
147 # endif
148 # else
149 # define XXH_FORCE_INLINE static
150 # define XXH_NO_INLINE static
151 # endif /* __STDC_VERSION__ */
152 #endif
153
154
155
156 /* *************************************
157 * Debug
158 ***************************************/
159 /* DEBUGLEVEL is expected to be defined externally,
160 * typically through compiler command line.
161 * Value must be a number. */
162 #ifndef DEBUGLEVEL
163 # define DEBUGLEVEL 0
164 #endif
165
166 #if (DEBUGLEVEL>=1)
167 # include <assert.h> /* note : can still be disabled with NDEBUG */
168 # define XXH_ASSERT(c) assert(c)
169 #else
170 # define XXH_ASSERT(c) ((void)0)
171 #endif
172
173 /* note : use after variable declarations */
174 #define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; }
175
176
177 /* *************************************
178 * Basic Types
179 ***************************************/
180 #if !defined (__VMS) \
181 && (defined (__cplusplus) \
182 || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
183 # include <stdint.h>
184 typedef uint8_t xxh_u8;
185 #else
186 typedef unsigned char xxh_u8;
187 #endif
188 typedef XXH32_hash_t xxh_u32;
189
190
191 /* === Memory access === */
192
193 #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
194
195 /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
XXH_read32(const void * memPtr)196 static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; }
197
198 #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
199
200 /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
201 /* currently only defined for gcc and icc */
202 typedef union { xxh_u32 u32; } __attribute__((packed)) unalign;
XXH_read32(const void * ptr)203 static xxh_u32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
204
205 #else
206
207 /* portable and safe solution. Generally efficient.
208 * see : http://stackoverflow.com/a/32095106/646947
209 */
XXH_read32(const void * memPtr)210 static xxh_u32 XXH_read32(const void* memPtr)
211 {
212 xxh_u32 val;
213 memcpy(&val, memPtr, sizeof(val));
214 return val;
215 }
216
217 #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
218
219
220 /* === Endianess === */
221 typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
222
223 /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
224 #ifndef XXH_CPU_LITTLE_ENDIAN
225 # if defined(_WIN32) /* Windows is always little endian */ \
226 || defined(__LITTLE_ENDIAN__) \
227 || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
228 # define XXH_CPU_LITTLE_ENDIAN 1
229 # elif defined(__BIG_ENDIAN__) \
230 || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
231 # define XXH_CPU_LITTLE_ENDIAN 0
232 # else
XXH_isLittleEndian(void)233 static int XXH_isLittleEndian(void)
234 {
235 const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; /* don't use static : performance detrimental */
236 return one.c[0];
237 }
238 # define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
239 # endif
240 #endif
241
242
243
244
245 /* ****************************************
246 * Compiler-specific Functions and Macros
247 ******************************************/
248 #define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
249
250 #ifndef __has_builtin
251 # define __has_builtin(x) 0
252 #endif
253
254 #if !defined(NO_CLANG_BUILTIN) && __has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateleft64)
255 # define XXH_rotl32 __builtin_rotateleft32
256 # define XXH_rotl64 __builtin_rotateleft64
257 /* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
258 #elif defined(_MSC_VER)
259 # define XXH_rotl32(x,r) _rotl(x,r)
260 # define XXH_rotl64(x,r) _rotl64(x,r)
261 #else
262 # define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
263 # define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))
264 #endif
265
266 #if defined(_MSC_VER) /* Visual Studio */
267 # define XXH_swap32 _byteswap_ulong
268 #elif XXH_GCC_VERSION >= 403
269 # define XXH_swap32 __builtin_bswap32
270 #else
XXH_swap32(xxh_u32 x)271 static xxh_u32 XXH_swap32 (xxh_u32 x)
272 {
273 return ((x << 24) & 0xff000000 ) |
274 ((x << 8) & 0x00ff0000 ) |
275 ((x >> 8) & 0x0000ff00 ) |
276 ((x >> 24) & 0x000000ff );
277 }
278 #endif
279
280
281 /* ***************************
282 * Memory reads
283 *****************************/
284 typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
285
XXH_readLE32(const void * ptr)286 XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr)
287 {
288 return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
289 }
290
XXH_readBE32(const void * ptr)291 static xxh_u32 XXH_readBE32(const void* ptr)
292 {
293 return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
294 }
295
296 XXH_FORCE_INLINE xxh_u32
XXH_readLE32_align(const void * ptr,XXH_alignment align)297 XXH_readLE32_align(const void* ptr, XXH_alignment align)
298 {
299 if (align==XXH_unaligned) {
300 return XXH_readLE32(ptr);
301 } else {
302 return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr);
303 }
304 }
305
306
307 /* *************************************
308 * Misc
309 ***************************************/
XXH_versionNumber(void)310 XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
311
312
313 /* *******************************************************************
314 * 32-bit hash functions
315 *********************************************************************/
316 static const xxh_u32 PRIME32_1 = 0x9E3779B1U; /* 0b10011110001101110111100110110001 */
317 static const xxh_u32 PRIME32_2 = 0x85EBCA77U; /* 0b10000101111010111100101001110111 */
318 static const xxh_u32 PRIME32_3 = 0xC2B2AE3DU; /* 0b11000010101100101010111000111101 */
319 static const xxh_u32 PRIME32_4 = 0x27D4EB2FU; /* 0b00100111110101001110101100101111 */
320 static const xxh_u32 PRIME32_5 = 0x165667B1U; /* 0b00010110010101100110011110110001 */
321
XXH32_round(xxh_u32 acc,xxh_u32 input)322 static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input)
323 {
324 acc += input * PRIME32_2;
325 acc = XXH_rotl32(acc, 13);
326 acc *= PRIME32_1;
327 #if defined(__GNUC__) && defined(__SSE4_1__) && !defined(XXH_ENABLE_AUTOVECTORIZE)
328 /* UGLY HACK:
329 * This inline assembly hack forces acc into a normal register. This is the
330 * only thing that prevents GCC and Clang from autovectorizing the XXH32 loop
331 * (pragmas and attributes don't work for some resason) without globally
332 * disabling SSE4.1.
333 *
334 * The reason we want to avoid vectorization is because despite working on
335 * 4 integers at a time, there are multiple factors slowing XXH32 down on
336 * SSE4:
337 * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on newer chips!)
338 * making it slightly slower to multiply four integers at once compared to four
339 * integers independently. Even when pmulld was fastest, Sandy/Ivy Bridge, it is
340 * still not worth it to go into SSE just to multiply unless doing a long operation.
341 *
342 * - Four instructions are required to rotate,
343 * movqda tmp, v // not required with VEX encoding
344 * pslld tmp, 13 // tmp <<= 13
345 * psrld v, 19 // x >>= 19
346 * por v, tmp // x |= tmp
347 * compared to one for scalar:
348 * roll v, 13 // reliably fast across the board
349 * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason
350 *
351 * - Instruction level parallelism is actually more beneficial here because the
352 * SIMD actually serializes this operation: While v1 is rotating, v2 can load data,
353 * while v3 can multiply. SSE forces them to operate together.
354 *
355 * How this hack works:
356 * __asm__("" // Declare an assembly block but don't declare any instructions
357 * : // However, as an Input/Output Operand,
358 * "+r" // constrain a read/write operand (+) as a general purpose register (r).
359 * (acc) // and set acc as the operand
360 * );
361 *
362 * Because of the 'r', the compiler has promised that seed will be in a
363 * general purpose register and the '+' says that it will be 'read/write',
364 * so it has to assume it has changed. It is like volatile without all the
365 * loads and stores.
366 *
367 * Since the argument has to be in a normal register (not an SSE register),
368 * each time XXH32_round is called, it is impossible to vectorize. */
369 __asm__("" : "+r" (acc));
370 #endif
371 return acc;
372 }
373
374 /* mix all bits */
XXH32_avalanche(xxh_u32 h32)375 static xxh_u32 XXH32_avalanche(xxh_u32 h32)
376 {
377 h32 ^= h32 >> 15;
378 h32 *= PRIME32_2;
379 h32 ^= h32 >> 13;
380 h32 *= PRIME32_3;
381 h32 ^= h32 >> 16;
382 return(h32);
383 }
384
385 #define XXH_get32bits(p) XXH_readLE32_align(p, align)
386
387 static xxh_u32
XXH32_finalize(xxh_u32 h32,const xxh_u8 * ptr,size_t len,XXH_alignment align)388 XXH32_finalize(xxh_u32 h32, const xxh_u8* ptr, size_t len, XXH_alignment align)
389 {
390 #define PROCESS1 \
391 h32 += (*ptr++) * PRIME32_5; \
392 h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
393
394 #define PROCESS4 \
395 h32 += XXH_get32bits(ptr) * PRIME32_3; \
396 ptr+=4; \
397 h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;
398
399 /* Compact rerolled version */
400 if (XXH_REROLL) {
401 len &= 15;
402 while (len >= 4) {
403 PROCESS4;
404 len -= 4;
405 }
406 while (len > 0) {
407 PROCESS1;
408 --len;
409 }
410 return XXH32_avalanche(h32);
411 } else {
412 switch(len&15) /* or switch(bEnd - p) */ {
413 case 12: PROCESS4;
414 FALLTHROUGH_INTENDED;
415 /* fallthrough */
416 case 8: PROCESS4;
417 FALLTHROUGH_INTENDED;
418 /* fallthrough */
419 case 4: PROCESS4;
420 return XXH32_avalanche(h32);
421
422 case 13: PROCESS4;
423 FALLTHROUGH_INTENDED;
424 /* fallthrough */
425 case 9: PROCESS4;
426 FALLTHROUGH_INTENDED;
427 /* fallthrough */
428 case 5: PROCESS4;
429 PROCESS1;
430 return XXH32_avalanche(h32);
431
432 case 14: PROCESS4;
433 FALLTHROUGH_INTENDED;
434 /* fallthrough */
435 case 10: PROCESS4;
436 FALLTHROUGH_INTENDED;
437 /* fallthrough */
438 case 6: PROCESS4;
439 PROCESS1;
440 PROCESS1;
441 return XXH32_avalanche(h32);
442
443 case 15: PROCESS4;
444 FALLTHROUGH_INTENDED;
445 /* fallthrough */
446 case 11: PROCESS4;
447 FALLTHROUGH_INTENDED;
448 /* fallthrough */
449 case 7: PROCESS4;
450 FALLTHROUGH_INTENDED;
451 /* fallthrough */
452 case 3: PROCESS1;
453 FALLTHROUGH_INTENDED;
454 /* fallthrough */
455 case 2: PROCESS1;
456 FALLTHROUGH_INTENDED;
457 /* fallthrough */
458 case 1: PROCESS1;
459 FALLTHROUGH_INTENDED;
460 /* fallthrough */
461 case 0: return XXH32_avalanche(h32);
462 }
463 XXH_ASSERT(0);
464 return h32; /* reaching this point is deemed impossible */
465 }
466 }
467
468 XXH_FORCE_INLINE xxh_u32
XXH32_endian_align(const xxh_u8 * input,size_t len,xxh_u32 seed,XXH_alignment align)469 XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align)
470 {
471 const xxh_u8* bEnd = input + len;
472 xxh_u32 h32;
473
474 #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
475 if (input==NULL) {
476 len=0;
477 bEnd=input=(const xxh_u8*)(size_t)16;
478 }
479 #endif
480
481 if (len>=16) {
482 const xxh_u8* const limit = bEnd - 15;
483 xxh_u32 v1 = seed + PRIME32_1 + PRIME32_2;
484 xxh_u32 v2 = seed + PRIME32_2;
485 xxh_u32 v3 = seed + 0;
486 xxh_u32 v4 = seed - PRIME32_1;
487
488 do {
489 v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4;
490 v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4;
491 v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4;
492 v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4;
493 } while (input < limit);
494
495 h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7)
496 + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
497 } else {
498 h32 = seed + PRIME32_5;
499 }
500
501 h32 += (xxh_u32)len;
502
503 return XXH32_finalize(h32, input, len&15, align);
504 }
505
506
XXH32(const void * input,size_t len,XXH32_hash_t seed)507 XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed)
508 {
509 #if 0
510 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
511 XXH32_state_t state;
512 XXH32_reset(&state, seed);
513 XXH32_update(&state, (const xxh_u8*)input, len);
514 return XXH32_digest(&state);
515
516 #else
517
518 if (XXH_FORCE_ALIGN_CHECK) {
519 if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */
520 return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);
521 } }
522
523 return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);
524 #endif
525 }
526
527
528
529 /*====== Hash streaming ======*/
530
XXH32_createState(void)531 XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
532 {
533 return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
534 }
XXH32_freeState(XXH32_state_t * statePtr)535 XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
536 {
537 XXH_free(statePtr);
538 return XXH_OK;
539 }
540
XXH32_copyState(XXH32_state_t * dstState,const XXH32_state_t * srcState)541 XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState)
542 {
543 memcpy(dstState, srcState, sizeof(*dstState));
544 }
545
XXH32_reset(XXH32_state_t * statePtr,XXH32_hash_t seed)546 XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed)
547 {
548 XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
549 memset(&state, 0, sizeof(state));
550 state.v1 = seed + PRIME32_1 + PRIME32_2;
551 state.v2 = seed + PRIME32_2;
552 state.v3 = seed + 0;
553 state.v4 = seed - PRIME32_1;
554 /* do not write into reserved, planned to be removed in a future version */
555 memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved));
556 return XXH_OK;
557 }
558
559
560 XXH_PUBLIC_API XXH_errorcode
XXH32_update(XXH32_state_t * state,const void * input,size_t len)561 XXH32_update(XXH32_state_t* state, const void* input, size_t len)
562 {
563 if (input==NULL)
564 #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
565 return XXH_OK;
566 #else
567 return XXH_ERROR;
568 #endif
569
570 { const xxh_u8* p = (const xxh_u8*)input;
571 const xxh_u8* const bEnd = p + len;
572
573 state->total_len_32 += (XXH32_hash_t)len;
574 state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16));
575
576 if (state->memsize + len < 16) { /* fill in tmp buffer */
577 XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len);
578 state->memsize += (XXH32_hash_t)len;
579 return XXH_OK;
580 }
581
582 if (state->memsize) { /* some data left from previous update */
583 XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize);
584 { const xxh_u32* p32 = state->mem32;
585 state->v1 = XXH32_round(state->v1, XXH_readLE32(p32)); p32++;
586 state->v2 = XXH32_round(state->v2, XXH_readLE32(p32)); p32++;
587 state->v3 = XXH32_round(state->v3, XXH_readLE32(p32)); p32++;
588 state->v4 = XXH32_round(state->v4, XXH_readLE32(p32));
589 }
590 p += 16-state->memsize;
591 state->memsize = 0;
592 }
593
594 // uintptr_t casts added to avoid array-bounds error on
595 // some inlined calls
596 if ((uintptr_t)p <= (uintptr_t)bEnd - 16) {
597 const uintptr_t limit = (uintptr_t)bEnd - 16;
598 xxh_u32 v1 = state->v1;
599 xxh_u32 v2 = state->v2;
600 xxh_u32 v3 = state->v3;
601 xxh_u32 v4 = state->v4;
602
603 do {
604 v1 = XXH32_round(v1, XXH_readLE32(p)); p+=4;
605 v2 = XXH32_round(v2, XXH_readLE32(p)); p+=4;
606 v3 = XXH32_round(v3, XXH_readLE32(p)); p+=4;
607 v4 = XXH32_round(v4, XXH_readLE32(p)); p+=4;
608 } while ((uintptr_t)p <= limit);
609
610 state->v1 = v1;
611 state->v2 = v2;
612 state->v3 = v3;
613 state->v4 = v4;
614 }
615
616 if (p < bEnd) {
617 XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
618 state->memsize = (unsigned)(bEnd-p);
619 }
620 }
621
622 return XXH_OK;
623 }
624
625
XXH32_digest(const XXH32_state_t * state)626 XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* state)
627 {
628 xxh_u32 h32;
629
630 if (state->large_len) {
631 h32 = XXH_rotl32(state->v1, 1)
632 + XXH_rotl32(state->v2, 7)
633 + XXH_rotl32(state->v3, 12)
634 + XXH_rotl32(state->v4, 18);
635 } else {
636 h32 = state->v3 /* == seed */ + PRIME32_5;
637 }
638
639 h32 += state->total_len_32;
640
641 return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned);
642 }
643
644
645 /*====== Canonical representation ======*/
646
647 /*! Default XXH result types are basic unsigned 32 and 64 bits.
648 * The canonical representation follows human-readable write convention, aka big-endian (large digits first).
649 * These functions allow transformation of hash result into and from its canonical format.
650 * This way, hash values can be written into a file or buffer, remaining comparable across different systems.
651 */
652
XXH32_canonicalFromHash(XXH32_canonical_t * dst,XXH32_hash_t hash)653 XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
654 {
655 XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
656 if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
657 memcpy(dst, &hash, sizeof(*dst));
658 }
659
XXH32_hashFromCanonical(const XXH32_canonical_t * src)660 XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
661 {
662 return XXH_readBE32(src);
663 }
664
665
666 #ifndef XXH_NO_LONG_LONG
667
668 /* *******************************************************************
669 * 64-bit hash functions
670 *********************************************************************/
671
672 /*====== Memory access ======*/
673
674 typedef XXH64_hash_t xxh_u64;
675
676
677 /*! XXH_REROLL_XXH64:
678 * Whether to reroll the XXH64_finalize() loop.
679 *
680 * Just like XXH32, we can unroll the XXH64_finalize() loop. This can be a performance gain
681 * on 64-bit hosts, as only one jump is required.
682 *
683 * However, on 32-bit hosts, because arithmetic needs to be done with two 32-bit registers,
684 * and 64-bit arithmetic needs to be simulated, it isn't beneficial to unroll. The code becomes
685 * ridiculously large (the largest function in the binary on i386!), and rerolling it saves
686 * anywhere from 3kB to 20kB. It is also slightly faster because it fits into cache better
687 * and is more likely to be inlined by the compiler.
688 *
689 * If XXH_REROLL is defined, this is ignored and the loop is always rerolled. */
690 #ifndef XXH_REROLL_XXH64
691 # if (defined(__ILP32__) || defined(_ILP32)) /* ILP32 is often defined on 32-bit GCC family */ \
692 || !(defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) /* x86-64 */ \
693 || defined(_M_ARM64) || defined(__aarch64__) || defined(__arm64__) /* aarch64 */ \
694 || defined(__PPC64__) || defined(__PPC64LE__) || defined(__ppc64__) || defined(__powerpc64__) /* ppc64 */ \
695 || defined(__mips64__) || defined(__mips64)) /* mips64 */ \
696 || (!defined(SIZE_MAX) || SIZE_MAX < ULLONG_MAX) /* check limits */
697 # define XXH_REROLL_XXH64 1
698 # else
699 # define XXH_REROLL_XXH64 0
700 # endif
701 #endif /* !defined(XXH_REROLL_XXH64) */
702
703 #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
704
705 /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
XXH_read64(const void * memPtr)706 static xxh_u64 XXH_read64(const void* memPtr) { return *(const xxh_u64*) memPtr; }
707
708 #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
709
710 /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
711 /* currently only defined for gcc and icc */
712 typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64;
XXH_read64(const void * ptr)713 static xxh_u64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; }
714
715 #else
716
717 /* portable and safe solution. Generally efficient.
718 * see : http://stackoverflow.com/a/32095106/646947
719 */
720
XXH_read64(const void * memPtr)721 static xxh_u64 XXH_read64(const void* memPtr)
722 {
723 xxh_u64 val;
724 memcpy(&val, memPtr, sizeof(val));
725 return val;
726 }
727
728 #endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
729
730 #if defined(_MSC_VER) /* Visual Studio */
731 # define XXH_swap64 _byteswap_uint64
732 #elif XXH_GCC_VERSION >= 403
733 # define XXH_swap64 __builtin_bswap64
734 #else
XXH_swap64(xxh_u64 x)735 static xxh_u64 XXH_swap64 (xxh_u64 x)
736 {
737 return ((x << 56) & 0xff00000000000000ULL) |
738 ((x << 40) & 0x00ff000000000000ULL) |
739 ((x << 24) & 0x0000ff0000000000ULL) |
740 ((x << 8) & 0x000000ff00000000ULL) |
741 ((x >> 8) & 0x00000000ff000000ULL) |
742 ((x >> 24) & 0x0000000000ff0000ULL) |
743 ((x >> 40) & 0x000000000000ff00ULL) |
744 ((x >> 56) & 0x00000000000000ffULL);
745 }
746 #endif
747
XXH_readLE64(const void * ptr)748 XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr)
749 {
750 return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
751 }
752
XXH_readBE64(const void * ptr)753 static xxh_u64 XXH_readBE64(const void* ptr)
754 {
755 return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
756 }
757
758 XXH_FORCE_INLINE xxh_u64
XXH_readLE64_align(const void * ptr,XXH_alignment align)759 XXH_readLE64_align(const void* ptr, XXH_alignment align)
760 {
761 if (align==XXH_unaligned)
762 return XXH_readLE64(ptr);
763 else
764 return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr);
765 }
766
767
768 /*====== xxh64 ======*/
769
770 static const xxh_u64 PRIME64_1 = 0x9E3779B185EBCA87ULL; /* 0b1001111000110111011110011011000110000101111010111100101010000111 */
771 static const xxh_u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; /* 0b1100001010110010101011100011110100100111110101001110101101001111 */
772 static const xxh_u64 PRIME64_3 = 0x165667B19E3779F9ULL; /* 0b0001011001010110011001111011000110011110001101110111100111111001 */
773 static const xxh_u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL; /* 0b1000010111101011110010100111011111000010101100101010111001100011 */
774 static const xxh_u64 PRIME64_5 = 0x27D4EB2F165667C5ULL; /* 0b0010011111010100111010110010111100010110010101100110011111000101 */
775
XXH64_round(xxh_u64 acc,xxh_u64 input)776 static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input)
777 {
778 acc += input * PRIME64_2;
779 acc = XXH_rotl64(acc, 31);
780 acc *= PRIME64_1;
781 return acc;
782 }
783
XXH64_mergeRound(xxh_u64 acc,xxh_u64 val)784 static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val)
785 {
786 val = XXH64_round(0, val);
787 acc ^= val;
788 acc = acc * PRIME64_1 + PRIME64_4;
789 return acc;
790 }
791
XXH64_avalanche(xxh_u64 h64)792 static xxh_u64 XXH64_avalanche(xxh_u64 h64)
793 {
794 h64 ^= h64 >> 33;
795 h64 *= PRIME64_2;
796 h64 ^= h64 >> 29;
797 h64 *= PRIME64_3;
798 h64 ^= h64 >> 32;
799 return h64;
800 }
801
802
803 #define XXH_get64bits(p) XXH_readLE64_align(p, align)
804
805 static xxh_u64
XXH64_finalize(xxh_u64 h64,const xxh_u8 * ptr,size_t len,XXH_alignment align)806 XXH64_finalize(xxh_u64 h64, const xxh_u8* ptr, size_t len, XXH_alignment align)
807 {
808 #define PROCESS1_64 \
809 h64 ^= (*ptr++) * PRIME64_5; \
810 h64 = XXH_rotl64(h64, 11) * PRIME64_1;
811
812 #define PROCESS4_64 \
813 h64 ^= (xxh_u64)(XXH_get32bits(ptr)) * PRIME64_1; \
814 ptr+=4; \
815 h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
816
817 #define PROCESS8_64 { \
818 xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); \
819 ptr+=8; \
820 h64 ^= k1; \
821 h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; \
822 }
823
824 /* Rerolled version for 32-bit targets is faster and much smaller. */
825 if (XXH_REROLL || XXH_REROLL_XXH64) {
826 len &= 31;
827 while (len >= 8) {
828 PROCESS8_64;
829 len -= 8;
830 }
831 if (len >= 4) {
832 PROCESS4_64;
833 len -= 4;
834 }
835 while (len > 0) {
836 PROCESS1_64;
837 --len;
838 }
839 return XXH64_avalanche(h64);
840 } else {
841 switch(len & 31) {
842 case 24: PROCESS8_64;
843 FALLTHROUGH_INTENDED;
844 /* fallthrough */
845 case 16: PROCESS8_64;
846 FALLTHROUGH_INTENDED;
847 /* fallthrough */
848 case 8: PROCESS8_64;
849 return XXH64_avalanche(h64);
850
851 case 28: PROCESS8_64;
852 FALLTHROUGH_INTENDED;
853 /* fallthrough */
854 case 20: PROCESS8_64;
855 FALLTHROUGH_INTENDED;
856 /* fallthrough */
857 case 12: PROCESS8_64;
858 FALLTHROUGH_INTENDED;
859 /* fallthrough */
860 case 4: PROCESS4_64;
861 return XXH64_avalanche(h64);
862
863 case 25: PROCESS8_64;
864 FALLTHROUGH_INTENDED;
865 /* fallthrough */
866 case 17: PROCESS8_64;
867 FALLTHROUGH_INTENDED;
868 /* fallthrough */
869 case 9: PROCESS8_64;
870 PROCESS1_64;
871 return XXH64_avalanche(h64);
872
873 case 29: PROCESS8_64;
874 FALLTHROUGH_INTENDED;
875 /* fallthrough */
876 case 21: PROCESS8_64;
877 FALLTHROUGH_INTENDED;
878 /* fallthrough */
879 case 13: PROCESS8_64;
880 FALLTHROUGH_INTENDED;
881 /* fallthrough */
882 case 5: PROCESS4_64;
883 PROCESS1_64;
884 return XXH64_avalanche(h64);
885
886 case 26: PROCESS8_64;
887 FALLTHROUGH_INTENDED;
888 /* fallthrough */
889 case 18: PROCESS8_64;
890 FALLTHROUGH_INTENDED;
891 /* fallthrough */
892 case 10: PROCESS8_64;
893 PROCESS1_64;
894 PROCESS1_64;
895 return XXH64_avalanche(h64);
896
897 case 30: PROCESS8_64;
898 FALLTHROUGH_INTENDED;
899 /* fallthrough */
900 case 22: PROCESS8_64;
901 FALLTHROUGH_INTENDED;
902 /* fallthrough */
903 case 14: PROCESS8_64;
904 FALLTHROUGH_INTENDED;
905 /* fallthrough */
906 case 6: PROCESS4_64;
907 PROCESS1_64;
908 PROCESS1_64;
909 return XXH64_avalanche(h64);
910
911 case 27: PROCESS8_64;
912 FALLTHROUGH_INTENDED;
913 /* fallthrough */
914 case 19: PROCESS8_64;
915 FALLTHROUGH_INTENDED;
916 /* fallthrough */
917 case 11: PROCESS8_64;
918 PROCESS1_64;
919 PROCESS1_64;
920 PROCESS1_64;
921 return XXH64_avalanche(h64);
922
923 case 31: PROCESS8_64;
924 FALLTHROUGH_INTENDED;
925 /* fallthrough */
926 case 23: PROCESS8_64;
927 FALLTHROUGH_INTENDED;
928 /* fallthrough */
929 case 15: PROCESS8_64;
930 FALLTHROUGH_INTENDED;
931 /* fallthrough */
932 case 7: PROCESS4_64;
933 FALLTHROUGH_INTENDED;
934 /* fallthrough */
935 case 3: PROCESS1_64;
936 FALLTHROUGH_INTENDED;
937 /* fallthrough */
938 case 2: PROCESS1_64;
939 FALLTHROUGH_INTENDED;
940 /* fallthrough */
941 case 1: PROCESS1_64;
942 FALLTHROUGH_INTENDED;
943 /* fallthrough */
944 case 0: return XXH64_avalanche(h64);
945 }
946 }
947 /* impossible to reach */
948 XXH_ASSERT(0);
949 return 0; /* unreachable, but some compilers complain without it */
950 }
951
952 XXH_FORCE_INLINE xxh_u64
XXH64_endian_align(const xxh_u8 * input,size_t len,xxh_u64 seed,XXH_alignment align)953 XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align)
954 {
955 const xxh_u8* bEnd = input + len;
956 xxh_u64 h64;
957
958 #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
959 if (input==NULL) {
960 len=0;
961 bEnd=input=(const xxh_u8*)(size_t)32;
962 }
963 #endif
964
965 if (len>=32) {
966 const xxh_u8* const limit = bEnd - 32;
967 xxh_u64 v1 = seed + PRIME64_1 + PRIME64_2;
968 xxh_u64 v2 = seed + PRIME64_2;
969 xxh_u64 v3 = seed + 0;
970 xxh_u64 v4 = seed - PRIME64_1;
971
972 do {
973 v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8;
974 v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8;
975 v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8;
976 v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8;
977 } while (input<=limit);
978
979 h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
980 h64 = XXH64_mergeRound(h64, v1);
981 h64 = XXH64_mergeRound(h64, v2);
982 h64 = XXH64_mergeRound(h64, v3);
983 h64 = XXH64_mergeRound(h64, v4);
984
985 } else {
986 h64 = seed + PRIME64_5;
987 }
988
989 h64 += (xxh_u64) len;
990
991 return XXH64_finalize(h64, input, len, align);
992 }
993
994
XXH64(const void * input,size_t len,XXH64_hash_t seed)995 XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t len, XXH64_hash_t seed)
996 {
997 #if 0
998 /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
999 XXH64_state_t state;
1000 XXH64_reset(&state, seed);
1001 XXH64_update(&state, (const xxh_u8*)input, len);
1002 return XXH64_digest(&state);
1003
1004 #else
1005
1006 if (XXH_FORCE_ALIGN_CHECK) {
1007 if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */
1008 return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned);
1009 } }
1010
1011 return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned);
1012
1013 #endif
1014 }
1015
1016 /*====== Hash Streaming ======*/
1017
XXH64_createState(void)1018 XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
1019 {
1020 return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
1021 }
XXH64_freeState(XXH64_state_t * statePtr)1022 XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
1023 {
1024 XXH_free(statePtr);
1025 return XXH_OK;
1026 }
1027
XXH64_copyState(XXH64_state_t * dstState,const XXH64_state_t * srcState)1028 XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState)
1029 {
1030 memcpy(dstState, srcState, sizeof(*dstState));
1031 }
1032
XXH64_reset(XXH64_state_t * statePtr,XXH64_hash_t seed)1033 XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, XXH64_hash_t seed)
1034 {
1035 XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
1036 memset(&state, 0, sizeof(state));
1037 state.v1 = seed + PRIME64_1 + PRIME64_2;
1038 state.v2 = seed + PRIME64_2;
1039 state.v3 = seed + 0;
1040 state.v4 = seed - PRIME64_1;
1041 /* do not write into reserved64, might be removed in a future version */
1042 memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved64));
1043 return XXH_OK;
1044 }
1045
1046 XXH_PUBLIC_API XXH_errorcode
XXH64_update(XXH64_state_t * state,const void * input,size_t len)1047 XXH64_update (XXH64_state_t* state, const void* input, size_t len)
1048 {
1049 if (input==NULL)
1050 #if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
1051 return XXH_OK;
1052 #else
1053 return XXH_ERROR;
1054 #endif
1055
1056 { const xxh_u8* p = (const xxh_u8*)input;
1057 const xxh_u8* const bEnd = p + len;
1058
1059 state->total_len += len;
1060
1061 if (state->memsize + len < 32) { /* fill in tmp buffer */
1062 XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len);
1063 state->memsize += (xxh_u32)len;
1064 return XXH_OK;
1065 }
1066
1067 if (state->memsize) { /* tmp buffer is full */
1068 XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize);
1069 state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0));
1070 state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1));
1071 state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2));
1072 state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3));
1073 p += 32-state->memsize;
1074 state->memsize = 0;
1075 }
1076
1077 // uintptr_t casts added to avoid array-bounds error on
1078 // some inlined calls
1079 if ((uintptr_t)p + 32 <= (uintptr_t)bEnd) {
1080 const uintptr_t limit = (uintptr_t)bEnd - 32;
1081 xxh_u64 v1 = state->v1;
1082 xxh_u64 v2 = state->v2;
1083 xxh_u64 v3 = state->v3;
1084 xxh_u64 v4 = state->v4;
1085
1086 do {
1087 v1 = XXH64_round(v1, XXH_readLE64(p)); p+=8;
1088 v2 = XXH64_round(v2, XXH_readLE64(p)); p+=8;
1089 v3 = XXH64_round(v3, XXH_readLE64(p)); p+=8;
1090 v4 = XXH64_round(v4, XXH_readLE64(p)); p+=8;
1091 } while ((uintptr_t)p <= limit);
1092
1093 state->v1 = v1;
1094 state->v2 = v2;
1095 state->v3 = v3;
1096 state->v4 = v4;
1097 }
1098
1099 if (p < bEnd) {
1100 XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
1101 state->memsize = (unsigned)(bEnd-p);
1102 }
1103 }
1104
1105 return XXH_OK;
1106 }
1107
1108
XXH64_digest(const XXH64_state_t * state)1109 XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* state)
1110 {
1111 xxh_u64 h64;
1112
1113 if (state->total_len >= 32) {
1114 xxh_u64 const v1 = state->v1;
1115 xxh_u64 const v2 = state->v2;
1116 xxh_u64 const v3 = state->v3;
1117 xxh_u64 const v4 = state->v4;
1118
1119 h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
1120 h64 = XXH64_mergeRound(h64, v1);
1121 h64 = XXH64_mergeRound(h64, v2);
1122 h64 = XXH64_mergeRound(h64, v3);
1123 h64 = XXH64_mergeRound(h64, v4);
1124 } else {
1125 h64 = state->v3 /*seed*/ + PRIME64_5;
1126 }
1127
1128 h64 += (xxh_u64) state->total_len;
1129
1130 return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned);
1131 }
1132
1133
1134 /*====== Canonical representation ======*/
1135
XXH64_canonicalFromHash(XXH64_canonical_t * dst,XXH64_hash_t hash)1136 XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
1137 {
1138 XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
1139 if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
1140 memcpy(dst, &hash, sizeof(*dst));
1141 }
1142
XXH64_hashFromCanonical(const XXH64_canonical_t * src)1143 XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
1144 {
1145 return XXH_readBE64(src);
1146 }
1147
1148
1149
1150 /* *********************************************************************
1151 * XXH3
1152 * New generation hash designed for speed on small keys and vectorization
1153 ************************************************************************ */
1154
1155 #include "xxh3p.h" /* XXH3 preview for RocksDB */
1156
1157
1158 #endif /* XXH_NO_LONG_LONG */
1159
1160 #endif /* XXHASH_C_01393879 */
1161