xref: /freebsd-src/sys/contrib/openzfs/module/zstd/lib/common/xxhash.c (revision c03c5b1c80914ec656fbee84539355d1fad68bf9)
1*c03c5b1cSMartin Matuska /*
2*c03c5b1cSMartin Matuska  *  xxHash - Fast Hash algorithm
3*c03c5b1cSMartin Matuska  *  Copyright (c) 2012-2020, Yann Collet, Facebook, Inc.
4*c03c5b1cSMartin Matuska  *
5*c03c5b1cSMartin Matuska  *  You can contact the author at :
6*c03c5b1cSMartin Matuska  *  - xxHash homepage: http://www.xxhash.com
7*c03c5b1cSMartin Matuska  *  - xxHash source repository : https://github.com/Cyan4973/xxHash
8*c03c5b1cSMartin Matuska  *
9*c03c5b1cSMartin Matuska  * This source code is licensed under both the BSD-style license (found in the
10*c03c5b1cSMartin Matuska  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
11*c03c5b1cSMartin Matuska  * in the COPYING file in the root directory of this source tree).
12*c03c5b1cSMartin Matuska  * You may select, at your option, one of the above-listed licenses.
13*c03c5b1cSMartin Matuska */
14*c03c5b1cSMartin Matuska 
15*c03c5b1cSMartin Matuska 
16*c03c5b1cSMartin Matuska /* *************************************
17*c03c5b1cSMartin Matuska *  Tuning parameters
18*c03c5b1cSMartin Matuska ***************************************/
19*c03c5b1cSMartin Matuska /*!XXH_FORCE_MEMORY_ACCESS :
20*c03c5b1cSMartin Matuska  * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.
21*c03c5b1cSMartin Matuska  * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.
22*c03c5b1cSMartin Matuska  * The below switch allow to select different access method for improved performance.
23*c03c5b1cSMartin Matuska  * Method 0 (default) : use `memcpy()`. Safe and portable.
24*c03c5b1cSMartin Matuska  * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).
25*c03c5b1cSMartin Matuska  *            This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.
26*c03c5b1cSMartin Matuska  * Method 2 : direct access. This method doesn't depend on compiler but violate C standard.
27*c03c5b1cSMartin Matuska  *            It can generate buggy code on targets which do not support unaligned memory accesses.
28*c03c5b1cSMartin Matuska  *            But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)
29*c03c5b1cSMartin Matuska  * See http://stackoverflow.com/a/32095106/646947 for details.
30*c03c5b1cSMartin Matuska  * Prefer these methods in priority order (0 > 1 > 2)
31*c03c5b1cSMartin Matuska  */
32*c03c5b1cSMartin Matuska #ifndef XXH_FORCE_MEMORY_ACCESS   /* can be defined externally, on command line for example */
33*c03c5b1cSMartin Matuska #  if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )
34*c03c5b1cSMartin Matuska #    define XXH_FORCE_MEMORY_ACCESS 2
35*c03c5b1cSMartin Matuska #  elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \
36*c03c5b1cSMartin Matuska   (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \
37*c03c5b1cSMartin Matuska   defined(__ICCARM__)
38*c03c5b1cSMartin Matuska #    define XXH_FORCE_MEMORY_ACCESS 1
39*c03c5b1cSMartin Matuska #  endif
40*c03c5b1cSMartin Matuska #endif
41*c03c5b1cSMartin Matuska 
42*c03c5b1cSMartin Matuska /*!XXH_ACCEPT_NULL_INPUT_POINTER :
43*c03c5b1cSMartin Matuska  * If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
44*c03c5b1cSMartin Matuska  * When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
45*c03c5b1cSMartin Matuska  * By default, this option is disabled. To enable it, uncomment below define :
46*c03c5b1cSMartin Matuska  */
47*c03c5b1cSMartin Matuska /* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */
48*c03c5b1cSMartin Matuska 
49*c03c5b1cSMartin Matuska /*!XXH_FORCE_NATIVE_FORMAT :
50*c03c5b1cSMartin Matuska  * By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
51*c03c5b1cSMartin Matuska  * Results are therefore identical for little-endian and big-endian CPU.
52*c03c5b1cSMartin Matuska  * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
53*c03c5b1cSMartin Matuska  * Should endian-independence be of no importance for your application, you may set the #define below to 1,
54*c03c5b1cSMartin Matuska  * to improve speed for Big-endian CPU.
55*c03c5b1cSMartin Matuska  * This option has no impact on Little_Endian CPU.
56*c03c5b1cSMartin Matuska  */
57*c03c5b1cSMartin Matuska #ifndef XXH_FORCE_NATIVE_FORMAT   /* can be defined externally */
58*c03c5b1cSMartin Matuska #  define XXH_FORCE_NATIVE_FORMAT 0
59*c03c5b1cSMartin Matuska #endif
60*c03c5b1cSMartin Matuska 
61*c03c5b1cSMartin Matuska /*!XXH_FORCE_ALIGN_CHECK :
62*c03c5b1cSMartin Matuska  * This is a minor performance trick, only useful with lots of very small keys.
63*c03c5b1cSMartin Matuska  * It means : check for aligned/unaligned input.
64*c03c5b1cSMartin Matuska  * The check costs one initial branch per hash; set to 0 when the input data
65*c03c5b1cSMartin Matuska  * is guaranteed to be aligned.
66*c03c5b1cSMartin Matuska  */
67*c03c5b1cSMartin Matuska #ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
68*c03c5b1cSMartin Matuska #  if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
69*c03c5b1cSMartin Matuska #    define XXH_FORCE_ALIGN_CHECK 0
70*c03c5b1cSMartin Matuska #  else
71*c03c5b1cSMartin Matuska #    define XXH_FORCE_ALIGN_CHECK 1
72*c03c5b1cSMartin Matuska #  endif
73*c03c5b1cSMartin Matuska #endif
74*c03c5b1cSMartin Matuska 
75*c03c5b1cSMartin Matuska 
76*c03c5b1cSMartin Matuska /* *************************************
77*c03c5b1cSMartin Matuska *  Includes & Memory related functions
78*c03c5b1cSMartin Matuska ***************************************/
79*c03c5b1cSMartin Matuska /* Modify the local functions below should you wish to use some other memory routines */
80*c03c5b1cSMartin Matuska /* for malloc(), free() */
81*c03c5b1cSMartin Matuska #include <stdlib.h>
82*c03c5b1cSMartin Matuska #include <stddef.h>     /* size_t */
XXH_malloc(size_t s)83*c03c5b1cSMartin Matuska static void* XXH_malloc(size_t s) { return malloc(s); }
XXH_free(void * p)84*c03c5b1cSMartin Matuska static void  XXH_free  (void* p)  { free(p); }
85*c03c5b1cSMartin Matuska /* for memcpy() */
86*c03c5b1cSMartin Matuska #include <string.h>
XXH_memcpy(void * dest,const void * src,size_t size)87*c03c5b1cSMartin Matuska static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }
88*c03c5b1cSMartin Matuska 
89*c03c5b1cSMartin Matuska #ifndef XXH_STATIC_LINKING_ONLY
90*c03c5b1cSMartin Matuska #  define XXH_STATIC_LINKING_ONLY
91*c03c5b1cSMartin Matuska #endif
92*c03c5b1cSMartin Matuska #include "xxhash.h"
93*c03c5b1cSMartin Matuska 
94*c03c5b1cSMartin Matuska 
95*c03c5b1cSMartin Matuska /* *************************************
96*c03c5b1cSMartin Matuska *  Compiler Specific Options
97*c03c5b1cSMartin Matuska ***************************************/
98*c03c5b1cSMartin Matuska #if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
99*c03c5b1cSMartin Matuska #  define INLINE_KEYWORD inline
100*c03c5b1cSMartin Matuska #else
101*c03c5b1cSMartin Matuska #  define INLINE_KEYWORD
102*c03c5b1cSMartin Matuska #endif
103*c03c5b1cSMartin Matuska 
104*c03c5b1cSMartin Matuska #if defined(__GNUC__) || defined(__ICCARM__)
105*c03c5b1cSMartin Matuska #  define FORCE_INLINE_ATTR __attribute__((always_inline))
106*c03c5b1cSMartin Matuska #elif defined(_MSC_VER)
107*c03c5b1cSMartin Matuska #  define FORCE_INLINE_ATTR __forceinline
108*c03c5b1cSMartin Matuska #else
109*c03c5b1cSMartin Matuska #  define FORCE_INLINE_ATTR
110*c03c5b1cSMartin Matuska #endif
111*c03c5b1cSMartin Matuska 
112*c03c5b1cSMartin Matuska #define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR
113*c03c5b1cSMartin Matuska 
114*c03c5b1cSMartin Matuska 
115*c03c5b1cSMartin Matuska #ifdef _MSC_VER
116*c03c5b1cSMartin Matuska #  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
117*c03c5b1cSMartin Matuska #endif
118*c03c5b1cSMartin Matuska 
119*c03c5b1cSMartin Matuska 
120*c03c5b1cSMartin Matuska /* *************************************
121*c03c5b1cSMartin Matuska *  Basic Types
122*c03c5b1cSMartin Matuska ***************************************/
123*c03c5b1cSMartin Matuska #ifndef MEM_MODULE
124*c03c5b1cSMartin Matuska # define MEM_MODULE
125*c03c5b1cSMartin Matuska # if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )
126*c03c5b1cSMartin Matuska #   include <stdint.h>
127*c03c5b1cSMartin Matuska     typedef uint8_t  BYTE;
128*c03c5b1cSMartin Matuska     typedef uint16_t U16;
129*c03c5b1cSMartin Matuska     typedef uint32_t U32;
130*c03c5b1cSMartin Matuska     typedef  int32_t S32;
131*c03c5b1cSMartin Matuska     typedef uint64_t U64;
132*c03c5b1cSMartin Matuska #  else
133*c03c5b1cSMartin Matuska     typedef unsigned char      BYTE;
134*c03c5b1cSMartin Matuska     typedef unsigned short     U16;
135*c03c5b1cSMartin Matuska     typedef unsigned int       U32;
136*c03c5b1cSMartin Matuska     typedef   signed int       S32;
137*c03c5b1cSMartin Matuska     typedef unsigned long long U64;   /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */
138*c03c5b1cSMartin Matuska #  endif
139*c03c5b1cSMartin Matuska #endif
140*c03c5b1cSMartin Matuska 
141*c03c5b1cSMartin Matuska 
142*c03c5b1cSMartin Matuska #if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
143*c03c5b1cSMartin Matuska 
144*c03c5b1cSMartin Matuska /* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
XXH_read32(const void * memPtr)145*c03c5b1cSMartin Matuska static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }
XXH_read64(const void * memPtr)146*c03c5b1cSMartin Matuska static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }
147*c03c5b1cSMartin Matuska 
148*c03c5b1cSMartin Matuska #elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
149*c03c5b1cSMartin Matuska 
150*c03c5b1cSMartin Matuska /* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
151*c03c5b1cSMartin Matuska /* currently only defined for gcc and icc */
152*c03c5b1cSMartin Matuska typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign;
153*c03c5b1cSMartin Matuska 
XXH_read32(const void * ptr)154*c03c5b1cSMartin Matuska static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }
XXH_read64(const void * ptr)155*c03c5b1cSMartin Matuska static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }
156*c03c5b1cSMartin Matuska 
157*c03c5b1cSMartin Matuska #else
158*c03c5b1cSMartin Matuska 
159*c03c5b1cSMartin Matuska /* portable and safe solution. Generally efficient.
160*c03c5b1cSMartin Matuska  * see : http://stackoverflow.com/a/32095106/646947
161*c03c5b1cSMartin Matuska  */
162*c03c5b1cSMartin Matuska 
XXH_read32(const void * memPtr)163*c03c5b1cSMartin Matuska static U32 XXH_read32(const void* memPtr)
164*c03c5b1cSMartin Matuska {
165*c03c5b1cSMartin Matuska     U32 val;
166*c03c5b1cSMartin Matuska     memcpy(&val, memPtr, sizeof(val));
167*c03c5b1cSMartin Matuska     return val;
168*c03c5b1cSMartin Matuska }
169*c03c5b1cSMartin Matuska 
XXH_read64(const void * memPtr)170*c03c5b1cSMartin Matuska static U64 XXH_read64(const void* memPtr)
171*c03c5b1cSMartin Matuska {
172*c03c5b1cSMartin Matuska     U64 val;
173*c03c5b1cSMartin Matuska     memcpy(&val, memPtr, sizeof(val));
174*c03c5b1cSMartin Matuska     return val;
175*c03c5b1cSMartin Matuska }
176*c03c5b1cSMartin Matuska 
177*c03c5b1cSMartin Matuska #endif   /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
178*c03c5b1cSMartin Matuska 
179*c03c5b1cSMartin Matuska 
180*c03c5b1cSMartin Matuska /* ****************************************
181*c03c5b1cSMartin Matuska *  Compiler-specific Functions and Macros
182*c03c5b1cSMartin Matuska ******************************************/
183*c03c5b1cSMartin Matuska #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
184*c03c5b1cSMartin Matuska 
185*c03c5b1cSMartin Matuska /* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
186*c03c5b1cSMartin Matuska #if defined(_MSC_VER)
187*c03c5b1cSMartin Matuska #  define XXH_rotl32(x,r) _rotl(x,r)
188*c03c5b1cSMartin Matuska #  define XXH_rotl64(x,r) _rotl64(x,r)
189*c03c5b1cSMartin Matuska #else
190*c03c5b1cSMartin Matuska #if defined(__ICCARM__)
191*c03c5b1cSMartin Matuska #  include <intrinsics.h>
192*c03c5b1cSMartin Matuska #  define XXH_rotl32(x,r) __ROR(x,(32 - r))
193*c03c5b1cSMartin Matuska #else
194*c03c5b1cSMartin Matuska #  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
195*c03c5b1cSMartin Matuska #endif
196*c03c5b1cSMartin Matuska #  define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))
197*c03c5b1cSMartin Matuska #endif
198*c03c5b1cSMartin Matuska 
199*c03c5b1cSMartin Matuska #if defined(_MSC_VER)     /* Visual Studio */
200*c03c5b1cSMartin Matuska #  define XXH_swap32 _byteswap_ulong
201*c03c5b1cSMartin Matuska #  define XXH_swap64 _byteswap_uint64
202*c03c5b1cSMartin Matuska #elif GCC_VERSION >= 403
203*c03c5b1cSMartin Matuska #  define XXH_swap32 __builtin_bswap32
204*c03c5b1cSMartin Matuska #  define XXH_swap64 __builtin_bswap64
205*c03c5b1cSMartin Matuska #else
XXH_swap32(U32 x)206*c03c5b1cSMartin Matuska static U32 XXH_swap32 (U32 x)
207*c03c5b1cSMartin Matuska {
208*c03c5b1cSMartin Matuska     return  ((x << 24) & 0xff000000 ) |
209*c03c5b1cSMartin Matuska             ((x <<  8) & 0x00ff0000 ) |
210*c03c5b1cSMartin Matuska             ((x >>  8) & 0x0000ff00 ) |
211*c03c5b1cSMartin Matuska             ((x >> 24) & 0x000000ff );
212*c03c5b1cSMartin Matuska }
XXH_swap64(U64 x)213*c03c5b1cSMartin Matuska static U64 XXH_swap64 (U64 x)
214*c03c5b1cSMartin Matuska {
215*c03c5b1cSMartin Matuska     return  ((x << 56) & 0xff00000000000000ULL) |
216*c03c5b1cSMartin Matuska             ((x << 40) & 0x00ff000000000000ULL) |
217*c03c5b1cSMartin Matuska             ((x << 24) & 0x0000ff0000000000ULL) |
218*c03c5b1cSMartin Matuska             ((x << 8)  & 0x000000ff00000000ULL) |
219*c03c5b1cSMartin Matuska             ((x >> 8)  & 0x00000000ff000000ULL) |
220*c03c5b1cSMartin Matuska             ((x >> 24) & 0x0000000000ff0000ULL) |
221*c03c5b1cSMartin Matuska             ((x >> 40) & 0x000000000000ff00ULL) |
222*c03c5b1cSMartin Matuska             ((x >> 56) & 0x00000000000000ffULL);
223*c03c5b1cSMartin Matuska }
224*c03c5b1cSMartin Matuska #endif
225*c03c5b1cSMartin Matuska 
226*c03c5b1cSMartin Matuska 
227*c03c5b1cSMartin Matuska /* *************************************
228*c03c5b1cSMartin Matuska *  Architecture Macros
229*c03c5b1cSMartin Matuska ***************************************/
230*c03c5b1cSMartin Matuska typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
231*c03c5b1cSMartin Matuska 
232*c03c5b1cSMartin Matuska /* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
233*c03c5b1cSMartin Matuska #ifndef XXH_CPU_LITTLE_ENDIAN
234*c03c5b1cSMartin Matuska     static const int g_one = 1;
235*c03c5b1cSMartin Matuska #   define XXH_CPU_LITTLE_ENDIAN   (*(const char*)(&g_one))
236*c03c5b1cSMartin Matuska #endif
237*c03c5b1cSMartin Matuska 
238*c03c5b1cSMartin Matuska 
239*c03c5b1cSMartin Matuska /* ***************************
240*c03c5b1cSMartin Matuska *  Memory reads
241*c03c5b1cSMartin Matuska *****************************/
242*c03c5b1cSMartin Matuska typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
243*c03c5b1cSMartin Matuska 
XXH_readLE32_align(const void * ptr,XXH_endianess endian,XXH_alignment align)244*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
245*c03c5b1cSMartin Matuska {
246*c03c5b1cSMartin Matuska     if (align==XXH_unaligned)
247*c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));
248*c03c5b1cSMartin Matuska     else
249*c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);
250*c03c5b1cSMartin Matuska }
251*c03c5b1cSMartin Matuska 
XXH_readLE32(const void * ptr,XXH_endianess endian)252*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)
253*c03c5b1cSMartin Matuska {
254*c03c5b1cSMartin Matuska     return XXH_readLE32_align(ptr, endian, XXH_unaligned);
255*c03c5b1cSMartin Matuska }
256*c03c5b1cSMartin Matuska 
XXH_readBE32(const void * ptr)257*c03c5b1cSMartin Matuska static U32 XXH_readBE32(const void* ptr)
258*c03c5b1cSMartin Matuska {
259*c03c5b1cSMartin Matuska     return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);
260*c03c5b1cSMartin Matuska }
261*c03c5b1cSMartin Matuska 
XXH_readLE64_align(const void * ptr,XXH_endianess endian,XXH_alignment align)262*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)
263*c03c5b1cSMartin Matuska {
264*c03c5b1cSMartin Matuska     if (align==XXH_unaligned)
265*c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));
266*c03c5b1cSMartin Matuska     else
267*c03c5b1cSMartin Matuska         return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);
268*c03c5b1cSMartin Matuska }
269*c03c5b1cSMartin Matuska 
XXH_readLE64(const void * ptr,XXH_endianess endian)270*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)
271*c03c5b1cSMartin Matuska {
272*c03c5b1cSMartin Matuska     return XXH_readLE64_align(ptr, endian, XXH_unaligned);
273*c03c5b1cSMartin Matuska }
274*c03c5b1cSMartin Matuska 
XXH_readBE64(const void * ptr)275*c03c5b1cSMartin Matuska static U64 XXH_readBE64(const void* ptr)
276*c03c5b1cSMartin Matuska {
277*c03c5b1cSMartin Matuska     return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);
278*c03c5b1cSMartin Matuska }
279*c03c5b1cSMartin Matuska 
280*c03c5b1cSMartin Matuska 
281*c03c5b1cSMartin Matuska /* *************************************
282*c03c5b1cSMartin Matuska *  Macros
283*c03c5b1cSMartin Matuska ***************************************/
284*c03c5b1cSMartin Matuska #define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(int)(!!(c)) }; }    /* use only *after* variable declarations */
285*c03c5b1cSMartin Matuska 
286*c03c5b1cSMartin Matuska 
287*c03c5b1cSMartin Matuska /* *************************************
288*c03c5b1cSMartin Matuska *  Constants
289*c03c5b1cSMartin Matuska ***************************************/
290*c03c5b1cSMartin Matuska static const U32 PRIME32_1 = 2654435761U;
291*c03c5b1cSMartin Matuska static const U32 PRIME32_2 = 2246822519U;
292*c03c5b1cSMartin Matuska static const U32 PRIME32_3 = 3266489917U;
293*c03c5b1cSMartin Matuska static const U32 PRIME32_4 =  668265263U;
294*c03c5b1cSMartin Matuska static const U32 PRIME32_5 =  374761393U;
295*c03c5b1cSMartin Matuska 
296*c03c5b1cSMartin Matuska static const U64 PRIME64_1 = 11400714785074694791ULL;
297*c03c5b1cSMartin Matuska static const U64 PRIME64_2 = 14029467366897019727ULL;
298*c03c5b1cSMartin Matuska static const U64 PRIME64_3 =  1609587929392839161ULL;
299*c03c5b1cSMartin Matuska static const U64 PRIME64_4 =  9650029242287828579ULL;
300*c03c5b1cSMartin Matuska static const U64 PRIME64_5 =  2870177450012600261ULL;
301*c03c5b1cSMartin Matuska 
XXH_versionNumber(void)302*c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }
303*c03c5b1cSMartin Matuska 
304*c03c5b1cSMartin Matuska 
305*c03c5b1cSMartin Matuska /* **************************
306*c03c5b1cSMartin Matuska *  Utils
307*c03c5b1cSMartin Matuska ****************************/
XXH32_copyState(XXH32_state_t * restrict dstState,const XXH32_state_t * restrict srcState)308*c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState)
309*c03c5b1cSMartin Matuska {
310*c03c5b1cSMartin Matuska     memcpy(dstState, srcState, sizeof(*dstState));
311*c03c5b1cSMartin Matuska }
312*c03c5b1cSMartin Matuska 
XXH64_copyState(XXH64_state_t * restrict dstState,const XXH64_state_t * restrict srcState)313*c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState)
314*c03c5b1cSMartin Matuska {
315*c03c5b1cSMartin Matuska     memcpy(dstState, srcState, sizeof(*dstState));
316*c03c5b1cSMartin Matuska }
317*c03c5b1cSMartin Matuska 
318*c03c5b1cSMartin Matuska 
319*c03c5b1cSMartin Matuska /* ***************************
320*c03c5b1cSMartin Matuska *  Simple Hash Functions
321*c03c5b1cSMartin Matuska *****************************/
322*c03c5b1cSMartin Matuska 
XXH32_round(U32 seed,U32 input)323*c03c5b1cSMartin Matuska static U32 XXH32_round(U32 seed, U32 input)
324*c03c5b1cSMartin Matuska {
325*c03c5b1cSMartin Matuska     seed += input * PRIME32_2;
326*c03c5b1cSMartin Matuska     seed  = XXH_rotl32(seed, 13);
327*c03c5b1cSMartin Matuska     seed *= PRIME32_1;
328*c03c5b1cSMartin Matuska     return seed;
329*c03c5b1cSMartin Matuska }
330*c03c5b1cSMartin Matuska 
XXH32_endian_align(const void * input,size_t len,U32 seed,XXH_endianess endian,XXH_alignment align)331*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)
332*c03c5b1cSMartin Matuska {
333*c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
334*c03c5b1cSMartin Matuska     const BYTE* bEnd = p + len;
335*c03c5b1cSMartin Matuska     U32 h32;
336*c03c5b1cSMartin Matuska #define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)
337*c03c5b1cSMartin Matuska 
338*c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
339*c03c5b1cSMartin Matuska     if (p==NULL) {
340*c03c5b1cSMartin Matuska         len=0;
341*c03c5b1cSMartin Matuska         bEnd=p=(const BYTE*)(size_t)16;
342*c03c5b1cSMartin Matuska     }
343*c03c5b1cSMartin Matuska #endif
344*c03c5b1cSMartin Matuska 
345*c03c5b1cSMartin Matuska     if (len>=16) {
346*c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 16;
347*c03c5b1cSMartin Matuska         U32 v1 = seed + PRIME32_1 + PRIME32_2;
348*c03c5b1cSMartin Matuska         U32 v2 = seed + PRIME32_2;
349*c03c5b1cSMartin Matuska         U32 v3 = seed + 0;
350*c03c5b1cSMartin Matuska         U32 v4 = seed - PRIME32_1;
351*c03c5b1cSMartin Matuska 
352*c03c5b1cSMartin Matuska         do {
353*c03c5b1cSMartin Matuska             v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
354*c03c5b1cSMartin Matuska             v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
355*c03c5b1cSMartin Matuska             v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
356*c03c5b1cSMartin Matuska             v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
357*c03c5b1cSMartin Matuska         } while (p<=limit);
358*c03c5b1cSMartin Matuska 
359*c03c5b1cSMartin Matuska         h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
360*c03c5b1cSMartin Matuska     } else {
361*c03c5b1cSMartin Matuska         h32  = seed + PRIME32_5;
362*c03c5b1cSMartin Matuska     }
363*c03c5b1cSMartin Matuska 
364*c03c5b1cSMartin Matuska     h32 += (U32) len;
365*c03c5b1cSMartin Matuska 
366*c03c5b1cSMartin Matuska     while (p+4<=bEnd) {
367*c03c5b1cSMartin Matuska         h32 += XXH_get32bits(p) * PRIME32_3;
368*c03c5b1cSMartin Matuska         h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
369*c03c5b1cSMartin Matuska         p+=4;
370*c03c5b1cSMartin Matuska     }
371*c03c5b1cSMartin Matuska 
372*c03c5b1cSMartin Matuska     while (p<bEnd) {
373*c03c5b1cSMartin Matuska         h32 += (*p) * PRIME32_5;
374*c03c5b1cSMartin Matuska         h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
375*c03c5b1cSMartin Matuska         p++;
376*c03c5b1cSMartin Matuska     }
377*c03c5b1cSMartin Matuska 
378*c03c5b1cSMartin Matuska     h32 ^= h32 >> 15;
379*c03c5b1cSMartin Matuska     h32 *= PRIME32_2;
380*c03c5b1cSMartin Matuska     h32 ^= h32 >> 13;
381*c03c5b1cSMartin Matuska     h32 *= PRIME32_3;
382*c03c5b1cSMartin Matuska     h32 ^= h32 >> 16;
383*c03c5b1cSMartin Matuska 
384*c03c5b1cSMartin Matuska     return h32;
385*c03c5b1cSMartin Matuska }
386*c03c5b1cSMartin Matuska 
387*c03c5b1cSMartin Matuska 
XXH32(const void * input,size_t len,unsigned int seed)388*c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)
389*c03c5b1cSMartin Matuska {
390*c03c5b1cSMartin Matuska #if 0
391*c03c5b1cSMartin Matuska     /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
392*c03c5b1cSMartin Matuska     XXH32_CREATESTATE_STATIC(state);
393*c03c5b1cSMartin Matuska     XXH32_reset(state, seed);
394*c03c5b1cSMartin Matuska     XXH32_update(state, input, len);
395*c03c5b1cSMartin Matuska     return XXH32_digest(state);
396*c03c5b1cSMartin Matuska #else
397*c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
398*c03c5b1cSMartin Matuska 
399*c03c5b1cSMartin Matuska     if (XXH_FORCE_ALIGN_CHECK) {
400*c03c5b1cSMartin Matuska         if ((((size_t)input) & 3) == 0) {   /* Input is 4-bytes aligned, leverage the speed benefit */
401*c03c5b1cSMartin Matuska             if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
402*c03c5b1cSMartin Matuska                 return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
403*c03c5b1cSMartin Matuska             else
404*c03c5b1cSMartin Matuska                 return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
405*c03c5b1cSMartin Matuska     }   }
406*c03c5b1cSMartin Matuska 
407*c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
408*c03c5b1cSMartin Matuska         return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
409*c03c5b1cSMartin Matuska     else
410*c03c5b1cSMartin Matuska         return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
411*c03c5b1cSMartin Matuska #endif
412*c03c5b1cSMartin Matuska }
413*c03c5b1cSMartin Matuska 
414*c03c5b1cSMartin Matuska 
XXH64_round(U64 acc,U64 input)415*c03c5b1cSMartin Matuska static U64 XXH64_round(U64 acc, U64 input)
416*c03c5b1cSMartin Matuska {
417*c03c5b1cSMartin Matuska     acc += input * PRIME64_2;
418*c03c5b1cSMartin Matuska     acc  = XXH_rotl64(acc, 31);
419*c03c5b1cSMartin Matuska     acc *= PRIME64_1;
420*c03c5b1cSMartin Matuska     return acc;
421*c03c5b1cSMartin Matuska }
422*c03c5b1cSMartin Matuska 
XXH64_mergeRound(U64 acc,U64 val)423*c03c5b1cSMartin Matuska static U64 XXH64_mergeRound(U64 acc, U64 val)
424*c03c5b1cSMartin Matuska {
425*c03c5b1cSMartin Matuska     val  = XXH64_round(0, val);
426*c03c5b1cSMartin Matuska     acc ^= val;
427*c03c5b1cSMartin Matuska     acc  = acc * PRIME64_1 + PRIME64_4;
428*c03c5b1cSMartin Matuska     return acc;
429*c03c5b1cSMartin Matuska }
430*c03c5b1cSMartin Matuska 
XXH64_endian_align(const void * input,size_t len,U64 seed,XXH_endianess endian,XXH_alignment align)431*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)
432*c03c5b1cSMartin Matuska {
433*c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
434*c03c5b1cSMartin Matuska     const BYTE* const bEnd = p + len;
435*c03c5b1cSMartin Matuska     U64 h64;
436*c03c5b1cSMartin Matuska #define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)
437*c03c5b1cSMartin Matuska 
438*c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
439*c03c5b1cSMartin Matuska     if (p==NULL) {
440*c03c5b1cSMartin Matuska         len=0;
441*c03c5b1cSMartin Matuska         bEnd=p=(const BYTE*)(size_t)32;
442*c03c5b1cSMartin Matuska     }
443*c03c5b1cSMartin Matuska #endif
444*c03c5b1cSMartin Matuska 
445*c03c5b1cSMartin Matuska     if (len>=32) {
446*c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 32;
447*c03c5b1cSMartin Matuska         U64 v1 = seed + PRIME64_1 + PRIME64_2;
448*c03c5b1cSMartin Matuska         U64 v2 = seed + PRIME64_2;
449*c03c5b1cSMartin Matuska         U64 v3 = seed + 0;
450*c03c5b1cSMartin Matuska         U64 v4 = seed - PRIME64_1;
451*c03c5b1cSMartin Matuska 
452*c03c5b1cSMartin Matuska         do {
453*c03c5b1cSMartin Matuska             v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;
454*c03c5b1cSMartin Matuska             v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;
455*c03c5b1cSMartin Matuska             v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;
456*c03c5b1cSMartin Matuska             v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;
457*c03c5b1cSMartin Matuska         } while (p<=limit);
458*c03c5b1cSMartin Matuska 
459*c03c5b1cSMartin Matuska         h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
460*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v1);
461*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v2);
462*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v3);
463*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v4);
464*c03c5b1cSMartin Matuska 
465*c03c5b1cSMartin Matuska     } else {
466*c03c5b1cSMartin Matuska         h64  = seed + PRIME64_5;
467*c03c5b1cSMartin Matuska     }
468*c03c5b1cSMartin Matuska 
469*c03c5b1cSMartin Matuska     h64 += (U64) len;
470*c03c5b1cSMartin Matuska 
471*c03c5b1cSMartin Matuska     while (p+8<=bEnd) {
472*c03c5b1cSMartin Matuska         U64 const k1 = XXH64_round(0, XXH_get64bits(p));
473*c03c5b1cSMartin Matuska         h64 ^= k1;
474*c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
475*c03c5b1cSMartin Matuska         p+=8;
476*c03c5b1cSMartin Matuska     }
477*c03c5b1cSMartin Matuska 
478*c03c5b1cSMartin Matuska     if (p+4<=bEnd) {
479*c03c5b1cSMartin Matuska         h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;
480*c03c5b1cSMartin Matuska         h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
481*c03c5b1cSMartin Matuska         p+=4;
482*c03c5b1cSMartin Matuska     }
483*c03c5b1cSMartin Matuska 
484*c03c5b1cSMartin Matuska     while (p<bEnd) {
485*c03c5b1cSMartin Matuska         h64 ^= (*p) * PRIME64_5;
486*c03c5b1cSMartin Matuska         h64 = XXH_rotl64(h64, 11) * PRIME64_1;
487*c03c5b1cSMartin Matuska         p++;
488*c03c5b1cSMartin Matuska     }
489*c03c5b1cSMartin Matuska 
490*c03c5b1cSMartin Matuska     h64 ^= h64 >> 33;
491*c03c5b1cSMartin Matuska     h64 *= PRIME64_2;
492*c03c5b1cSMartin Matuska     h64 ^= h64 >> 29;
493*c03c5b1cSMartin Matuska     h64 *= PRIME64_3;
494*c03c5b1cSMartin Matuska     h64 ^= h64 >> 32;
495*c03c5b1cSMartin Matuska 
496*c03c5b1cSMartin Matuska     return h64;
497*c03c5b1cSMartin Matuska }
498*c03c5b1cSMartin Matuska 
499*c03c5b1cSMartin Matuska 
XXH64(const void * input,size_t len,unsigned long long seed)500*c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)
501*c03c5b1cSMartin Matuska {
502*c03c5b1cSMartin Matuska #if 0
503*c03c5b1cSMartin Matuska     /* Simple version, good for code maintenance, but unfortunately slow for small inputs */
504*c03c5b1cSMartin Matuska     XXH64_CREATESTATE_STATIC(state);
505*c03c5b1cSMartin Matuska     XXH64_reset(state, seed);
506*c03c5b1cSMartin Matuska     XXH64_update(state, input, len);
507*c03c5b1cSMartin Matuska     return XXH64_digest(state);
508*c03c5b1cSMartin Matuska #else
509*c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
510*c03c5b1cSMartin Matuska 
511*c03c5b1cSMartin Matuska     if (XXH_FORCE_ALIGN_CHECK) {
512*c03c5b1cSMartin Matuska         if ((((size_t)input) & 7)==0) {  /* Input is aligned, let's leverage the speed advantage */
513*c03c5b1cSMartin Matuska             if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
514*c03c5b1cSMartin Matuska                 return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
515*c03c5b1cSMartin Matuska             else
516*c03c5b1cSMartin Matuska                 return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
517*c03c5b1cSMartin Matuska     }   }
518*c03c5b1cSMartin Matuska 
519*c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
520*c03c5b1cSMartin Matuska         return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
521*c03c5b1cSMartin Matuska     else
522*c03c5b1cSMartin Matuska         return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
523*c03c5b1cSMartin Matuska #endif
524*c03c5b1cSMartin Matuska }
525*c03c5b1cSMartin Matuska 
526*c03c5b1cSMartin Matuska 
527*c03c5b1cSMartin Matuska /* **************************************************
528*c03c5b1cSMartin Matuska *  Advanced Hash Functions
529*c03c5b1cSMartin Matuska ****************************************************/
530*c03c5b1cSMartin Matuska 
XXH32_createState(void)531*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)
532*c03c5b1cSMartin Matuska {
533*c03c5b1cSMartin Matuska     return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));
534*c03c5b1cSMartin Matuska }
XXH32_freeState(XXH32_state_t * statePtr)535*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)
536*c03c5b1cSMartin Matuska {
537*c03c5b1cSMartin Matuska     XXH_free(statePtr);
538*c03c5b1cSMartin Matuska     return XXH_OK;
539*c03c5b1cSMartin Matuska }
540*c03c5b1cSMartin Matuska 
XXH64_createState(void)541*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
542*c03c5b1cSMartin Matuska {
543*c03c5b1cSMartin Matuska     return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
544*c03c5b1cSMartin Matuska }
XXH64_freeState(XXH64_state_t * statePtr)545*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)
546*c03c5b1cSMartin Matuska {
547*c03c5b1cSMartin Matuska     XXH_free(statePtr);
548*c03c5b1cSMartin Matuska     return XXH_OK;
549*c03c5b1cSMartin Matuska }
550*c03c5b1cSMartin Matuska 
551*c03c5b1cSMartin Matuska 
552*c03c5b1cSMartin Matuska /*** Hash feed ***/
553*c03c5b1cSMartin Matuska 
XXH32_reset(XXH32_state_t * statePtr,unsigned int seed)554*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)
555*c03c5b1cSMartin Matuska {
556*c03c5b1cSMartin Matuska     XXH32_state_t state;   /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
557*c03c5b1cSMartin Matuska     memset(&state, 0, sizeof(state)-4);   /* do not write into reserved, for future removal */
558*c03c5b1cSMartin Matuska     state.v1 = seed + PRIME32_1 + PRIME32_2;
559*c03c5b1cSMartin Matuska     state.v2 = seed + PRIME32_2;
560*c03c5b1cSMartin Matuska     state.v3 = seed + 0;
561*c03c5b1cSMartin Matuska     state.v4 = seed - PRIME32_1;
562*c03c5b1cSMartin Matuska     memcpy(statePtr, &state, sizeof(state));
563*c03c5b1cSMartin Matuska     return XXH_OK;
564*c03c5b1cSMartin Matuska }
565*c03c5b1cSMartin Matuska 
566*c03c5b1cSMartin Matuska 
XXH64_reset(XXH64_state_t * statePtr,unsigned long long seed)567*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)
568*c03c5b1cSMartin Matuska {
569*c03c5b1cSMartin Matuska     XXH64_state_t state;   /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
570*c03c5b1cSMartin Matuska     memset(&state, 0, sizeof(state)-8);   /* do not write into reserved, for future removal */
571*c03c5b1cSMartin Matuska     state.v1 = seed + PRIME64_1 + PRIME64_2;
572*c03c5b1cSMartin Matuska     state.v2 = seed + PRIME64_2;
573*c03c5b1cSMartin Matuska     state.v3 = seed + 0;
574*c03c5b1cSMartin Matuska     state.v4 = seed - PRIME64_1;
575*c03c5b1cSMartin Matuska     memcpy(statePtr, &state, sizeof(state));
576*c03c5b1cSMartin Matuska     return XXH_OK;
577*c03c5b1cSMartin Matuska }
578*c03c5b1cSMartin Matuska 
579*c03c5b1cSMartin Matuska 
XXH32_update_endian(XXH32_state_t * state,const void * input,size_t len,XXH_endianess endian)580*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)
581*c03c5b1cSMartin Matuska {
582*c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
583*c03c5b1cSMartin Matuska     const BYTE* const bEnd = p + len;
584*c03c5b1cSMartin Matuska 
585*c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
586*c03c5b1cSMartin Matuska     if (input==NULL) return XXH_ERROR;
587*c03c5b1cSMartin Matuska #endif
588*c03c5b1cSMartin Matuska 
589*c03c5b1cSMartin Matuska     state->total_len_32 += (unsigned)len;
590*c03c5b1cSMartin Matuska     state->large_len |= (len>=16) | (state->total_len_32>=16);
591*c03c5b1cSMartin Matuska 
592*c03c5b1cSMartin Matuska     if (state->memsize + len < 16)  {   /* fill in tmp buffer */
593*c03c5b1cSMartin Matuska         XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);
594*c03c5b1cSMartin Matuska         state->memsize += (unsigned)len;
595*c03c5b1cSMartin Matuska         return XXH_OK;
596*c03c5b1cSMartin Matuska     }
597*c03c5b1cSMartin Matuska 
598*c03c5b1cSMartin Matuska     if (state->memsize) {   /* some data left from previous update */
599*c03c5b1cSMartin Matuska         XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);
600*c03c5b1cSMartin Matuska         {   const U32* p32 = state->mem32;
601*c03c5b1cSMartin Matuska             state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++;
602*c03c5b1cSMartin Matuska             state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++;
603*c03c5b1cSMartin Matuska             state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++;
604*c03c5b1cSMartin Matuska             state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++;
605*c03c5b1cSMartin Matuska         }
606*c03c5b1cSMartin Matuska         p += 16-state->memsize;
607*c03c5b1cSMartin Matuska         state->memsize = 0;
608*c03c5b1cSMartin Matuska     }
609*c03c5b1cSMartin Matuska 
610*c03c5b1cSMartin Matuska     if (p <= bEnd-16) {
611*c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 16;
612*c03c5b1cSMartin Matuska         U32 v1 = state->v1;
613*c03c5b1cSMartin Matuska         U32 v2 = state->v2;
614*c03c5b1cSMartin Matuska         U32 v3 = state->v3;
615*c03c5b1cSMartin Matuska         U32 v4 = state->v4;
616*c03c5b1cSMartin Matuska 
617*c03c5b1cSMartin Matuska         do {
618*c03c5b1cSMartin Matuska             v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4;
619*c03c5b1cSMartin Matuska             v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4;
620*c03c5b1cSMartin Matuska             v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4;
621*c03c5b1cSMartin Matuska             v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4;
622*c03c5b1cSMartin Matuska         } while (p<=limit);
623*c03c5b1cSMartin Matuska 
624*c03c5b1cSMartin Matuska         state->v1 = v1;
625*c03c5b1cSMartin Matuska         state->v2 = v2;
626*c03c5b1cSMartin Matuska         state->v3 = v3;
627*c03c5b1cSMartin Matuska         state->v4 = v4;
628*c03c5b1cSMartin Matuska     }
629*c03c5b1cSMartin Matuska 
630*c03c5b1cSMartin Matuska     if (p < bEnd) {
631*c03c5b1cSMartin Matuska         XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));
632*c03c5b1cSMartin Matuska         state->memsize = (unsigned)(bEnd-p);
633*c03c5b1cSMartin Matuska     }
634*c03c5b1cSMartin Matuska 
635*c03c5b1cSMartin Matuska     return XXH_OK;
636*c03c5b1cSMartin Matuska }
637*c03c5b1cSMartin Matuska 
XXH32_update(XXH32_state_t * state_in,const void * input,size_t len)638*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)
639*c03c5b1cSMartin Matuska {
640*c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
641*c03c5b1cSMartin Matuska 
642*c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
643*c03c5b1cSMartin Matuska         return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
644*c03c5b1cSMartin Matuska     else
645*c03c5b1cSMartin Matuska         return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
646*c03c5b1cSMartin Matuska }
647*c03c5b1cSMartin Matuska 
648*c03c5b1cSMartin Matuska 
649*c03c5b1cSMartin Matuska 
XXH32_digest_endian(const XXH32_state_t * state,XXH_endianess endian)650*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)
651*c03c5b1cSMartin Matuska {
652*c03c5b1cSMartin Matuska     const BYTE * p = (const BYTE*)state->mem32;
653*c03c5b1cSMartin Matuska     const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;
654*c03c5b1cSMartin Matuska     U32 h32;
655*c03c5b1cSMartin Matuska 
656*c03c5b1cSMartin Matuska     if (state->large_len) {
657*c03c5b1cSMartin Matuska         h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
658*c03c5b1cSMartin Matuska     } else {
659*c03c5b1cSMartin Matuska         h32 = state->v3 /* == seed */ + PRIME32_5;
660*c03c5b1cSMartin Matuska     }
661*c03c5b1cSMartin Matuska 
662*c03c5b1cSMartin Matuska     h32 += state->total_len_32;
663*c03c5b1cSMartin Matuska 
664*c03c5b1cSMartin Matuska     while (p+4<=bEnd) {
665*c03c5b1cSMartin Matuska         h32 += XXH_readLE32(p, endian) * PRIME32_3;
666*c03c5b1cSMartin Matuska         h32  = XXH_rotl32(h32, 17) * PRIME32_4;
667*c03c5b1cSMartin Matuska         p+=4;
668*c03c5b1cSMartin Matuska     }
669*c03c5b1cSMartin Matuska 
670*c03c5b1cSMartin Matuska     while (p<bEnd) {
671*c03c5b1cSMartin Matuska         h32 += (*p) * PRIME32_5;
672*c03c5b1cSMartin Matuska         h32  = XXH_rotl32(h32, 11) * PRIME32_1;
673*c03c5b1cSMartin Matuska         p++;
674*c03c5b1cSMartin Matuska     }
675*c03c5b1cSMartin Matuska 
676*c03c5b1cSMartin Matuska     h32 ^= h32 >> 15;
677*c03c5b1cSMartin Matuska     h32 *= PRIME32_2;
678*c03c5b1cSMartin Matuska     h32 ^= h32 >> 13;
679*c03c5b1cSMartin Matuska     h32 *= PRIME32_3;
680*c03c5b1cSMartin Matuska     h32 ^= h32 >> 16;
681*c03c5b1cSMartin Matuska 
682*c03c5b1cSMartin Matuska     return h32;
683*c03c5b1cSMartin Matuska }
684*c03c5b1cSMartin Matuska 
685*c03c5b1cSMartin Matuska 
XXH32_digest(const XXH32_state_t * state_in)686*c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)
687*c03c5b1cSMartin Matuska {
688*c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
689*c03c5b1cSMartin Matuska 
690*c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
691*c03c5b1cSMartin Matuska         return XXH32_digest_endian(state_in, XXH_littleEndian);
692*c03c5b1cSMartin Matuska     else
693*c03c5b1cSMartin Matuska         return XXH32_digest_endian(state_in, XXH_bigEndian);
694*c03c5b1cSMartin Matuska }
695*c03c5b1cSMartin Matuska 
696*c03c5b1cSMartin Matuska 
697*c03c5b1cSMartin Matuska 
698*c03c5b1cSMartin Matuska /* **** XXH64 **** */
699*c03c5b1cSMartin Matuska 
XXH64_update_endian(XXH64_state_t * state,const void * input,size_t len,XXH_endianess endian)700*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)
701*c03c5b1cSMartin Matuska {
702*c03c5b1cSMartin Matuska     const BYTE* p = (const BYTE*)input;
703*c03c5b1cSMartin Matuska     const BYTE* const bEnd = p + len;
704*c03c5b1cSMartin Matuska 
705*c03c5b1cSMartin Matuska #ifdef XXH_ACCEPT_NULL_INPUT_POINTER
706*c03c5b1cSMartin Matuska     if (input==NULL) return XXH_ERROR;
707*c03c5b1cSMartin Matuska #endif
708*c03c5b1cSMartin Matuska 
709*c03c5b1cSMartin Matuska     state->total_len += len;
710*c03c5b1cSMartin Matuska 
711*c03c5b1cSMartin Matuska     if (state->memsize + len < 32) {  /* fill in tmp buffer */
712*c03c5b1cSMartin Matuska         if (input != NULL) {
713*c03c5b1cSMartin Matuska             XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);
714*c03c5b1cSMartin Matuska         }
715*c03c5b1cSMartin Matuska         state->memsize += (U32)len;
716*c03c5b1cSMartin Matuska         return XXH_OK;
717*c03c5b1cSMartin Matuska     }
718*c03c5b1cSMartin Matuska 
719*c03c5b1cSMartin Matuska     if (state->memsize) {   /* tmp buffer is full */
720*c03c5b1cSMartin Matuska         XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);
721*c03c5b1cSMartin Matuska         state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian));
722*c03c5b1cSMartin Matuska         state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian));
723*c03c5b1cSMartin Matuska         state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian));
724*c03c5b1cSMartin Matuska         state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian));
725*c03c5b1cSMartin Matuska         p += 32-state->memsize;
726*c03c5b1cSMartin Matuska         state->memsize = 0;
727*c03c5b1cSMartin Matuska     }
728*c03c5b1cSMartin Matuska 
729*c03c5b1cSMartin Matuska     if (p+32 <= bEnd) {
730*c03c5b1cSMartin Matuska         const BYTE* const limit = bEnd - 32;
731*c03c5b1cSMartin Matuska         U64 v1 = state->v1;
732*c03c5b1cSMartin Matuska         U64 v2 = state->v2;
733*c03c5b1cSMartin Matuska         U64 v3 = state->v3;
734*c03c5b1cSMartin Matuska         U64 v4 = state->v4;
735*c03c5b1cSMartin Matuska 
736*c03c5b1cSMartin Matuska         do {
737*c03c5b1cSMartin Matuska             v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8;
738*c03c5b1cSMartin Matuska             v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8;
739*c03c5b1cSMartin Matuska             v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8;
740*c03c5b1cSMartin Matuska             v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8;
741*c03c5b1cSMartin Matuska         } while (p<=limit);
742*c03c5b1cSMartin Matuska 
743*c03c5b1cSMartin Matuska         state->v1 = v1;
744*c03c5b1cSMartin Matuska         state->v2 = v2;
745*c03c5b1cSMartin Matuska         state->v3 = v3;
746*c03c5b1cSMartin Matuska         state->v4 = v4;
747*c03c5b1cSMartin Matuska     }
748*c03c5b1cSMartin Matuska 
749*c03c5b1cSMartin Matuska     if (p < bEnd) {
750*c03c5b1cSMartin Matuska         XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));
751*c03c5b1cSMartin Matuska         state->memsize = (unsigned)(bEnd-p);
752*c03c5b1cSMartin Matuska     }
753*c03c5b1cSMartin Matuska 
754*c03c5b1cSMartin Matuska     return XXH_OK;
755*c03c5b1cSMartin Matuska }
756*c03c5b1cSMartin Matuska 
XXH64_update(XXH64_state_t * state_in,const void * input,size_t len)757*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)
758*c03c5b1cSMartin Matuska {
759*c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
760*c03c5b1cSMartin Matuska 
761*c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
762*c03c5b1cSMartin Matuska         return XXH64_update_endian(state_in, input, len, XXH_littleEndian);
763*c03c5b1cSMartin Matuska     else
764*c03c5b1cSMartin Matuska         return XXH64_update_endian(state_in, input, len, XXH_bigEndian);
765*c03c5b1cSMartin Matuska }
766*c03c5b1cSMartin Matuska 
767*c03c5b1cSMartin Matuska 
768*c03c5b1cSMartin Matuska 
XXH64_digest_endian(const XXH64_state_t * state,XXH_endianess endian)769*c03c5b1cSMartin Matuska FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)
770*c03c5b1cSMartin Matuska {
771*c03c5b1cSMartin Matuska     const BYTE * p = (const BYTE*)state->mem64;
772*c03c5b1cSMartin Matuska     const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;
773*c03c5b1cSMartin Matuska     U64 h64;
774*c03c5b1cSMartin Matuska 
775*c03c5b1cSMartin Matuska     if (state->total_len >= 32) {
776*c03c5b1cSMartin Matuska         U64 const v1 = state->v1;
777*c03c5b1cSMartin Matuska         U64 const v2 = state->v2;
778*c03c5b1cSMartin Matuska         U64 const v3 = state->v3;
779*c03c5b1cSMartin Matuska         U64 const v4 = state->v4;
780*c03c5b1cSMartin Matuska 
781*c03c5b1cSMartin Matuska         h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);
782*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v1);
783*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v2);
784*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v3);
785*c03c5b1cSMartin Matuska         h64 = XXH64_mergeRound(h64, v4);
786*c03c5b1cSMartin Matuska     } else {
787*c03c5b1cSMartin Matuska         h64  = state->v3 + PRIME64_5;
788*c03c5b1cSMartin Matuska     }
789*c03c5b1cSMartin Matuska 
790*c03c5b1cSMartin Matuska     h64 += (U64) state->total_len;
791*c03c5b1cSMartin Matuska 
792*c03c5b1cSMartin Matuska     while (p+8<=bEnd) {
793*c03c5b1cSMartin Matuska         U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian));
794*c03c5b1cSMartin Matuska         h64 ^= k1;
795*c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;
796*c03c5b1cSMartin Matuska         p+=8;
797*c03c5b1cSMartin Matuska     }
798*c03c5b1cSMartin Matuska 
799*c03c5b1cSMartin Matuska     if (p+4<=bEnd) {
800*c03c5b1cSMartin Matuska         h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;
801*c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;
802*c03c5b1cSMartin Matuska         p+=4;
803*c03c5b1cSMartin Matuska     }
804*c03c5b1cSMartin Matuska 
805*c03c5b1cSMartin Matuska     while (p<bEnd) {
806*c03c5b1cSMartin Matuska         h64 ^= (*p) * PRIME64_5;
807*c03c5b1cSMartin Matuska         h64  = XXH_rotl64(h64, 11) * PRIME64_1;
808*c03c5b1cSMartin Matuska         p++;
809*c03c5b1cSMartin Matuska     }
810*c03c5b1cSMartin Matuska 
811*c03c5b1cSMartin Matuska     h64 ^= h64 >> 33;
812*c03c5b1cSMartin Matuska     h64 *= PRIME64_2;
813*c03c5b1cSMartin Matuska     h64 ^= h64 >> 29;
814*c03c5b1cSMartin Matuska     h64 *= PRIME64_3;
815*c03c5b1cSMartin Matuska     h64 ^= h64 >> 32;
816*c03c5b1cSMartin Matuska 
817*c03c5b1cSMartin Matuska     return h64;
818*c03c5b1cSMartin Matuska }
819*c03c5b1cSMartin Matuska 
820*c03c5b1cSMartin Matuska 
XXH64_digest(const XXH64_state_t * state_in)821*c03c5b1cSMartin Matuska XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in)
822*c03c5b1cSMartin Matuska {
823*c03c5b1cSMartin Matuska     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
824*c03c5b1cSMartin Matuska 
825*c03c5b1cSMartin Matuska     if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
826*c03c5b1cSMartin Matuska         return XXH64_digest_endian(state_in, XXH_littleEndian);
827*c03c5b1cSMartin Matuska     else
828*c03c5b1cSMartin Matuska         return XXH64_digest_endian(state_in, XXH_bigEndian);
829*c03c5b1cSMartin Matuska }
830*c03c5b1cSMartin Matuska 
831*c03c5b1cSMartin Matuska 
832*c03c5b1cSMartin Matuska /* **************************
833*c03c5b1cSMartin Matuska *  Canonical representation
834*c03c5b1cSMartin Matuska ****************************/
835*c03c5b1cSMartin Matuska 
836*c03c5b1cSMartin Matuska /*! Default XXH result types are basic unsigned 32 and 64 bits.
837*c03c5b1cSMartin Matuska *   The canonical representation follows human-readable write convention, aka big-endian (large digits first).
838*c03c5b1cSMartin Matuska *   These functions allow transformation of hash result into and from its canonical format.
839*c03c5b1cSMartin Matuska *   This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs.
840*c03c5b1cSMartin Matuska */
841*c03c5b1cSMartin Matuska 
XXH32_canonicalFromHash(XXH32_canonical_t * dst,XXH32_hash_t hash)842*c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)
843*c03c5b1cSMartin Matuska {
844*c03c5b1cSMartin Matuska     XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));
845*c03c5b1cSMartin Matuska     if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);
846*c03c5b1cSMartin Matuska     memcpy(dst, &hash, sizeof(*dst));
847*c03c5b1cSMartin Matuska }
848*c03c5b1cSMartin Matuska 
XXH64_canonicalFromHash(XXH64_canonical_t * dst,XXH64_hash_t hash)849*c03c5b1cSMartin Matuska XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)
850*c03c5b1cSMartin Matuska {
851*c03c5b1cSMartin Matuska     XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));
852*c03c5b1cSMartin Matuska     if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);
853*c03c5b1cSMartin Matuska     memcpy(dst, &hash, sizeof(*dst));
854*c03c5b1cSMartin Matuska }
855*c03c5b1cSMartin Matuska 
XXH32_hashFromCanonical(const XXH32_canonical_t * src)856*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)
857*c03c5b1cSMartin Matuska {
858*c03c5b1cSMartin Matuska     return XXH_readBE32(src);
859*c03c5b1cSMartin Matuska }
860*c03c5b1cSMartin Matuska 
XXH64_hashFromCanonical(const XXH64_canonical_t * src)861*c03c5b1cSMartin Matuska XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)
862*c03c5b1cSMartin Matuska {
863*c03c5b1cSMartin Matuska     return XXH_readBE64(src);
864*c03c5b1cSMartin Matuska }
865