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