1299425Smm/*
2299425SmmxxHash - Fast Hash algorithm
3299425SmmCopyright (C) 2012-2014, Yann Collet.
4299425SmmBSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
5299425Smm
6299425SmmRedistribution and use in source and binary forms, with or without
7299425Smmmodification, are permitted provided that the following conditions are
8299425Smmmet:
9299425Smm
10299425Smm* Redistributions of source code must retain the above copyright
11299425Smmnotice, this list of conditions and the following disclaimer.
12299425Smm* Redistributions in binary form must reproduce the above
13299425Smmcopyright notice, this list of conditions and the following disclaimer
14299425Smmin the documentation and/or other materials provided with the
15299425Smmdistribution.
16299425Smm
17299425SmmTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18299425Smm"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19299425SmmLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20299425SmmA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21299425SmmOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22299425SmmSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23299425SmmLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24299425SmmDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25299425SmmTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26299425Smm(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27299425SmmOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28299425Smm
29299425SmmYou can contact the author at :
30299425Smm- xxHash source repository : http://code.google.com/p/xxhash/
31299425Smm*/
32313570Smm#include "archive_platform.h"
33313570Smm
34299425Smm#include <stdlib.h>
35299425Smm#include <string.h>
36299425Smm
37299425Smm#include "archive_xxhash.h"
38299425Smm
39299425Smm#ifdef HAVE_LIBLZ4
40299425Smm
41299425Smm/***************************************
42299425Smm** Tuning parameters
43299425Smm****************************************/
44299425Smm/* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
45299425Smm** For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
46299425Smm** If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
47299425Smm** You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
48299425Smm*/
49299425Smm#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
50299425Smm#  define XXH_USE_UNALIGNED_ACCESS 1
51299425Smm#endif
52299425Smm
53299425Smm/* XXH_ACCEPT_NULL_INPUT_POINTER :
54299425Smm** If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
55299425Smm** When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
56299425Smm** This option has a very small performance cost (only measurable on small inputs).
57299425Smm** By default, this option is disabled. To enable it, uncomment below define :
58299425Smm** #define XXH_ACCEPT_NULL_INPUT_POINTER 1
59299425Smm
60299425Smm** XXH_FORCE_NATIVE_FORMAT :
61299425Smm** By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
62299425Smm** Results are therefore identical for little-endian and big-endian CPU.
63299425Smm** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
64313570Smm** Should endian-independence be of no importance for your application, you may set the #define below to 1.
65299425Smm** It will improve speed for Big-endian CPU.
66299425Smm** This option has no impact on Little_Endian CPU.
67299425Smm*/
68299425Smm#define XXH_FORCE_NATIVE_FORMAT 0
69299425Smm
70299425Smm/***************************************
71299425Smm** Compiler Specific Options
72299425Smm****************************************/
73299425Smm/* Disable some Visual warning messages */
74299425Smm#ifdef _MSC_VER  /* Visual Studio */
75299425Smm#  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
76299425Smm#endif
77299425Smm
78299425Smm#ifdef _MSC_VER    /* Visual Studio */
79299425Smm#  define FORCE_INLINE __forceinline
80299425Smm#else
81299425Smm#  ifdef __GNUC__
82299425Smm#    define FORCE_INLINE inline __attribute__((always_inline))
83299425Smm#  else
84299425Smm#    define FORCE_INLINE inline
85299425Smm#  endif
86299425Smm#endif
87299425Smm
88299425Smm/***************************************
89299425Smm** Includes & Memory related functions
90299425Smm****************************************/
91299425Smm#define XXH_malloc malloc
92299425Smm#define XXH_free free
93299425Smm#define XXH_memcpy memcpy
94299425Smm
95299425Smm
96299425Smmstatic unsigned int	  XXH32 (const void*, unsigned int, unsigned int);
97299425Smmstatic void*		  XXH32_init   (unsigned int);
98299425Smmstatic XXH_errorcode	  XXH32_update (void*, const void*, unsigned int);
99299425Smmstatic unsigned int	  XXH32_digest (void*);
100299425Smm/*static int		  XXH32_sizeofState(void);*/
101299425Smmstatic XXH_errorcode	  XXH32_resetState(void*, unsigned int);
102299425Smm#define       XXH32_SIZEOFSTATE 48
103299425Smmtypedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t;
104299425Smmstatic unsigned int	  XXH32_intermediateDigest (void*);
105299425Smm
106299425Smm/***************************************
107299425Smm** Basic Types
108299425Smm****************************************/
109299425Smm#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
110299425Smm# include <stdint.h>
111299425Smm  typedef uint8_t  BYTE;
112299425Smm  typedef uint16_t U16;
113299425Smm  typedef uint32_t U32;
114299425Smm  typedef  int32_t S32;
115299425Smm  typedef uint64_t U64;
116299425Smm#else
117299425Smm  typedef unsigned char      BYTE;
118299425Smm  typedef unsigned short     U16;
119299425Smm  typedef unsigned int       U32;
120299425Smm  typedef   signed int       S32;
121299425Smm  typedef unsigned long long U64;
122299425Smm#endif
123299425Smm
124299425Smm#if defined(__GNUC__)  && !defined(XXH_USE_UNALIGNED_ACCESS)
125299425Smm#  define _PACKED __attribute__ ((packed))
126299425Smm#else
127299425Smm#  define _PACKED
128299425Smm#endif
129299425Smm
130299425Smm#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
131299425Smm#  ifdef __IBMC__
132299425Smm#    pragma pack(1)
133299425Smm#  else
134299425Smm#    pragma pack(push, 1)
135299425Smm#  endif
136299425Smm#endif
137299425Smm
138299425Smmtypedef struct _U32_S { U32 v; } _PACKED U32_S;
139299425Smm
140299425Smm#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
141299425Smm#  pragma pack(pop)
142299425Smm#endif
143299425Smm
144299425Smm
145299425Smm/****************************************
146299425Smm** Compiler-specific Functions and Macros
147299425Smm*****************************************/
148318482Smm#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0))
149299425Smm
150318482Smm#if GCC_VERSION >= 409
151318482Smm__attribute__((__no_sanitize_undefined__))
152318482Smm#endif
153370535Sgit2svn#if defined(_MSC_VER)
154370535Sgit2svnstatic __inline U32 A32(const void * x)
155370535Sgit2svn#else
156370535Sgit2svnstatic inline U32 A32(const void* x)
157370535Sgit2svn#endif
158318482Smm{
159318482Smm    return (((const U32_S *)(x))->v);
160318482Smm}
161318482Smm
162299425Smm/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
163299425Smm#if defined(_MSC_VER)
164299425Smm#  define XXH_rotl32(x,r) _rotl(x,r)
165299425Smm#else
166299425Smm#  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
167299425Smm#endif
168299425Smm
169299425Smm#if defined(_MSC_VER)     /* Visual Studio */
170299425Smm#  define XXH_swap32 _byteswap_ulong
171299425Smm#elif GCC_VERSION >= 403
172299425Smm#  define XXH_swap32 __builtin_bswap32
173299425Smm#else
174299425Smmstatic inline U32 XXH_swap32 (U32 x) {
175299425Smm    return  ((x << 24) & 0xff000000 ) |
176299425Smm			((x <<  8) & 0x00ff0000 ) |
177299425Smm			((x >>  8) & 0x0000ff00 ) |
178299425Smm			((x >> 24) & 0x000000ff );}
179299425Smm#endif
180299425Smm
181299425Smm
182299425Smm/***************************************
183299425Smm** Constants
184299425Smm****************************************/
185299425Smm#define PRIME32_1   2654435761U
186299425Smm#define PRIME32_2   2246822519U
187299425Smm#define PRIME32_3   3266489917U
188299425Smm#define PRIME32_4    668265263U
189299425Smm#define PRIME32_5    374761393U
190299425Smm
191299425Smm
192299425Smm/***************************************
193299425Smm** Architecture Macros
194299425Smm****************************************/
195299425Smmtypedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
196299425Smm#ifndef XXH_CPU_LITTLE_ENDIAN   /* It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch */
197299425Smm    static const int one = 1;
198299425Smm#   define XXH_CPU_LITTLE_ENDIAN   (*(const char*)(&one))
199299425Smm#endif
200299425Smm
201299425Smm
202299425Smm/***************************************
203299425Smm** Macros
204299425Smm****************************************/
205299425Smm#define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(!!(c)) }; }    /* use only *after* variable declarations */
206299425Smm
207299425Smm
208299425Smm/*****************************
209299425Smm** Memory reads
210299425Smm******************************/
211299425Smmtypedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
212299425Smm
213299425Smmstatic
214299425SmmFORCE_INLINE U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align)
215299425Smm{
216299425Smm    if (align==XXH_unaligned)
217299425Smm        return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
218299425Smm    else
219299425Smm        return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr);
220299425Smm}
221299425Smm
222299425Smmstatic
223299425SmmFORCE_INLINE U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); }
224299425Smm
225299425Smm
226299425Smm/*****************************
227299425Smm** Simple Hash Functions
228299425Smm******************************/
229299425Smmstatic
230299425SmmFORCE_INLINE U32 XXH32_endian_align(const void* input, unsigned int len, U32 seed, XXH_endianess endian, XXH_alignment align)
231299425Smm{
232299425Smm    const BYTE* p = (const BYTE*)input;
233299425Smm    const BYTE* bEnd = p + len;
234299425Smm    U32 h32;
235299425Smm#define XXH_get32bits(p) XXH_readLE32_align((const U32*)p, endian, align)
236299425Smm
237299425Smm#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
238299425Smm    if (p==NULL) { len=0; bEnd=p=(const BYTE*)(size_t)16; }
239299425Smm#endif
240299425Smm
241299425Smm    if (len>=16)
242299425Smm    {
243299425Smm        const BYTE* const limit = bEnd - 16;
244299425Smm        U32 v1 = seed + PRIME32_1 + PRIME32_2;
245299425Smm        U32 v2 = seed + PRIME32_2;
246299425Smm        U32 v3 = seed + 0;
247299425Smm        U32 v4 = seed - PRIME32_1;
248299425Smm
249299425Smm        do
250299425Smm        {
251299425Smm            v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
252299425Smm            v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
253299425Smm            v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
254299425Smm            v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
255299425Smm        } while (p<=limit);
256299425Smm
257299425Smm        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
258299425Smm    }
259299425Smm    else
260299425Smm    {
261299425Smm        h32  = seed + PRIME32_5;
262299425Smm    }
263299425Smm
264299425Smm    h32 += (U32) len;
265299425Smm
266299425Smm    while (p<=bEnd-4)
267299425Smm    {
268299425Smm        h32 += XXH_get32bits(p) * PRIME32_3;
269299425Smm        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
270299425Smm        p+=4;
271299425Smm    }
272299425Smm
273299425Smm    while (p<bEnd)
274299425Smm    {
275299425Smm        h32 += (*p) * PRIME32_5;
276299425Smm        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
277299425Smm        p++;
278299425Smm    }
279299425Smm
280299425Smm    h32 ^= h32 >> 15;
281299425Smm    h32 *= PRIME32_2;
282299425Smm    h32 ^= h32 >> 13;
283299425Smm    h32 *= PRIME32_3;
284299425Smm    h32 ^= h32 >> 16;
285299425Smm
286299425Smm    return h32;
287299425Smm}
288299425Smm
289299425Smm
290299425SmmU32 XXH32(const void* input, unsigned int len, U32 seed)
291299425Smm{
292299425Smm#if 0
293299425Smm    // Simple version, good for code maintenance, but unfortunately slow for small inputs
294299425Smm    void* state = XXH32_init(seed);
295299425Smm    XXH32_update(state, input, len);
296299425Smm    return XXH32_digest(state);
297299425Smm#else
298299425Smm    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
299299425Smm
300299425Smm#  if !defined(XXH_USE_UNALIGNED_ACCESS)
301299425Smm    if ((((size_t)input) & 3) == 0)   /* Input is aligned, let's leverage the speed advantage */
302299425Smm    {
303299425Smm        if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
304299425Smm            return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
305299425Smm        else
306299425Smm            return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
307299425Smm    }
308299425Smm#  endif
309299425Smm
310299425Smm    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
311299425Smm        return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
312299425Smm    else
313299425Smm        return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
314299425Smm#endif
315299425Smm}
316299425Smm
317299425Smm/*****************************
318299425Smm** Advanced Hash Functions
319299425Smm******************************/
320299425Smm
321299425Smmstruct XXH_state32_t
322299425Smm{
323299425Smm    U64 total_len;
324299425Smm    U32 seed;
325299425Smm    U32 v1;
326299425Smm    U32 v2;
327299425Smm    U32 v3;
328299425Smm    U32 v4;
329299425Smm    int memsize;
330299425Smm    char memory[16];
331299425Smm};
332299425Smm
333299425Smm#if 0
334299425Smmstatic
335299425Smmint XXH32_sizeofState(void)
336299425Smm{
337299425Smm    XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t));   /* A compilation error here means XXH32_SIZEOFSTATE is not large enough */
338299425Smm    return sizeof(struct XXH_state32_t);
339299425Smm}
340299425Smm#endif
341299425Smm
342299425Smmstatic
343299425SmmXXH_errorcode XXH32_resetState(void* state_in, U32 seed)
344299425Smm{
345299425Smm    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
346299425Smm    state->seed = seed;
347299425Smm    state->v1 = seed + PRIME32_1 + PRIME32_2;
348299425Smm    state->v2 = seed + PRIME32_2;
349299425Smm    state->v3 = seed + 0;
350299425Smm    state->v4 = seed - PRIME32_1;
351299425Smm    state->total_len = 0;
352299425Smm    state->memsize = 0;
353299425Smm    return XXH_OK;
354299425Smm}
355299425Smm
356299425Smmstatic
357299425Smmvoid* XXH32_init (U32 seed)
358299425Smm{
359299425Smm    void* state = XXH_malloc (sizeof(struct XXH_state32_t));
360299425Smm    XXH32_resetState(state, seed);
361299425Smm    return state;
362299425Smm}
363299425Smm
364299425Smmstatic
365299425SmmFORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian)
366299425Smm{
367299425Smm    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
368299425Smm    const BYTE* p = (const BYTE*)input;
369299425Smm    const BYTE* const bEnd = p + len;
370299425Smm
371299425Smm#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
372299425Smm    if (input==NULL) return XXH_ERROR;
373299425Smm#endif
374299425Smm
375299425Smm    state->total_len += len;
376299425Smm
377299425Smm    if (state->memsize + len < 16)   /* fill in tmp buffer */
378299425Smm    {
379299425Smm        XXH_memcpy(state->memory + state->memsize, input, len);
380299425Smm        state->memsize +=  len;
381299425Smm        return XXH_OK;
382299425Smm    }
383299425Smm
384299425Smm    if (state->memsize)   /* some data left from previous update */
385299425Smm    {
386299425Smm        XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize);
387299425Smm        {
388299425Smm            const U32* p32 = (const U32*)state->memory;
389299425Smm            state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;
390299425Smm            state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++;
391299425Smm            state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;
392299425Smm            state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;
393299425Smm        }
394299425Smm        p += 16-state->memsize;
395299425Smm        state->memsize = 0;
396299425Smm    }
397299425Smm
398299425Smm    if (p <= bEnd-16)
399299425Smm    {
400299425Smm        const BYTE* const limit = bEnd - 16;
401299425Smm        U32 v1 = state->v1;
402299425Smm        U32 v2 = state->v2;
403299425Smm        U32 v3 = state->v3;
404299425Smm        U32 v4 = state->v4;
405299425Smm
406299425Smm        do
407299425Smm        {
408299425Smm            v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
409299425Smm            v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
410299425Smm            v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
411299425Smm            v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
412299425Smm        } while (p<=limit);
413299425Smm
414299425Smm        state->v1 = v1;
415299425Smm        state->v2 = v2;
416299425Smm        state->v3 = v3;
417299425Smm        state->v4 = v4;
418299425Smm    }
419299425Smm
420299425Smm    if (p < bEnd)
421299425Smm    {
422299425Smm        XXH_memcpy(state->memory, p, bEnd-p);
423299425Smm        state->memsize = (int)(bEnd-p);
424299425Smm    }
425299425Smm
426299425Smm    return XXH_OK;
427299425Smm}
428299425Smm
429299425Smmstatic
430299425SmmXXH_errorcode XXH32_update (void* state_in, const void* input, unsigned int len)
431299425Smm{
432299425Smm    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
433299425Smm
434299425Smm    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
435299425Smm        return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
436299425Smm    else
437299425Smm        return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
438299425Smm}
439299425Smm
440299425Smm
441299425Smm
442299425Smmstatic
443299425SmmFORCE_INLINE U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian)
444299425Smm{
445299425Smm    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
446299425Smm    const BYTE * p = (const BYTE*)state->memory;
447299425Smm    BYTE* bEnd = (BYTE*)state->memory + state->memsize;
448299425Smm    U32 h32;
449299425Smm
450299425Smm    if (state->total_len >= 16)
451299425Smm    {
452299425Smm        h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
453299425Smm    }
454299425Smm    else
455299425Smm    {
456299425Smm        h32  = state->seed + PRIME32_5;
457299425Smm    }
458299425Smm
459299425Smm    h32 += (U32) state->total_len;
460299425Smm
461299425Smm    while (p<=bEnd-4)
462299425Smm    {
463299425Smm        h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3;
464299425Smm        h32  = XXH_rotl32(h32, 17) * PRIME32_4;
465299425Smm        p+=4;
466299425Smm    }
467299425Smm
468299425Smm    while (p<bEnd)
469299425Smm    {
470299425Smm        h32 += (*p) * PRIME32_5;
471299425Smm        h32 = XXH_rotl32(h32, 11) * PRIME32_1;
472299425Smm        p++;
473299425Smm    }
474299425Smm
475299425Smm    h32 ^= h32 >> 15;
476299425Smm    h32 *= PRIME32_2;
477299425Smm    h32 ^= h32 >> 13;
478299425Smm    h32 *= PRIME32_3;
479299425Smm    h32 ^= h32 >> 16;
480299425Smm
481299425Smm    return h32;
482299425Smm}
483299425Smm
484299425Smmstatic
485299425SmmU32 XXH32_intermediateDigest (void* state_in)
486299425Smm{
487299425Smm    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
488299425Smm
489299425Smm    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
490299425Smm        return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian);
491299425Smm    else
492299425Smm        return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian);
493299425Smm}
494299425Smm
495299425Smmstatic
496299425SmmU32 XXH32_digest (void* state_in)
497299425Smm{
498299425Smm    U32 h32 = XXH32_intermediateDigest(state_in);
499299425Smm
500299425Smm    XXH_free(state_in);
501299425Smm
502299425Smm    return h32;
503299425Smm}
504299425Smm
505299425Smmconst
506299425Smmstruct archive_xxhash __archive_xxhash = {
507299425Smm	XXH32,
508299425Smm	XXH32_init,
509299425Smm	XXH32_update,
510299425Smm	XXH32_digest
511299425Smm};
512299425Smm#else
513299425Smm
514299425Smm/*
515299425Smm * Define an empty version of the struct if we aren't using the LZ4 library.
516299425Smm */
517299425Smmconst
518299425Smmstruct archive_xxhash __archive_xxhash = {
519299425Smm	NULL,
520299425Smm	NULL,
521299425Smm	NULL,
522299425Smm	NULL
523299425Smm};
524299425Smm
525299425Smm#endif /* HAVE_LIBLZ4 */
526