1262395Sbapt/* 2262395SbaptxxHash - Fast Hash algorithm 3262395SbaptCopyright (C) 2012-2013, Yann Collet. 4262395SbaptBSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 5262395Sbapt 6262395SbaptRedistribution and use in source and binary forms, with or without 7262395Sbaptmodification, are permitted provided that the following conditions are 8262395Sbaptmet: 9262395Sbapt 10262395Sbapt* Redistributions of source code must retain the above copyright 11262395Sbaptnotice, this list of conditions and the following disclaimer. 12262395Sbapt* Redistributions in binary form must reproduce the above 13262395Sbaptcopyright notice, this list of conditions and the following disclaimer 14262395Sbaptin the documentation and/or other materials provided with the 15262395Sbaptdistribution. 16262395Sbapt 17262395SbaptTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18262395Sbapt"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19262395SbaptLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20262395SbaptA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21262395SbaptOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22262395SbaptSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23262395SbaptLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24262395SbaptDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25262395SbaptTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26262395Sbapt(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27262395SbaptOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28262395Sbapt 29262395SbaptYou can contact the author at : 30262395Sbapt- xxHash source repository : http://code.google.com/p/xxhash/ 31262395Sbapt*/ 32262395Sbapt 33262395Sbapt 34262395Sbapt//************************************** 35262395Sbapt// Tuning parameters 36262395Sbapt//************************************** 37262395Sbapt// Unaligned memory access is automatically enabled for "common" CPU, such as x86. 38262395Sbapt// For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected. 39262395Sbapt// If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance. 40262395Sbapt// You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32). 41262395Sbapt#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) 42262395Sbapt# define XXH_USE_UNALIGNED_ACCESS 1 43262395Sbapt#endif 44262395Sbapt 45262395Sbapt// XXH_ACCEPT_NULL_INPUT_POINTER : 46262395Sbapt// If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. 47262395Sbapt// When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. 48262395Sbapt// This option has a very small performance cost (only measurable on small inputs). 49262395Sbapt// By default, this option is disabled. To enable it, uncomment below define : 50262395Sbapt//#define XXH_ACCEPT_NULL_INPUT_POINTER 1 51262395Sbapt 52262395Sbapt// XXH_FORCE_NATIVE_FORMAT : 53262395Sbapt// By default, xxHash library provides endian-independant Hash values, based on little-endian convention. 54262395Sbapt// Results are therefore identical for little-endian and big-endian CPU. 55262395Sbapt// This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. 56262395Sbapt// Should endian-independance be of no importance for your application, you may set the #define below to 1. 57262395Sbapt// It will improve speed for Big-endian CPU. 58262395Sbapt// This option has no impact on Little_Endian CPU. 59262395Sbapt#define XXH_FORCE_NATIVE_FORMAT 0 60262395Sbapt 61262395Sbapt 62262395Sbapt//************************************** 63262395Sbapt// Compiler Specific Options 64262395Sbapt//************************************** 65262395Sbapt// Disable some Visual warning messages 66262395Sbapt#ifdef _MSC_VER // Visual Studio 67262395Sbapt# pragma warning(disable : 4127) // disable: C4127: conditional expression is constant 68262395Sbapt#endif 69262395Sbapt 70262395Sbapt#ifdef _MSC_VER // Visual Studio 71262395Sbapt# define forceinline static __forceinline 72262395Sbapt#else 73262395Sbapt# ifdef __GNUC__ 74262395Sbapt# define forceinline static inline __attribute__((always_inline)) 75262395Sbapt# else 76262395Sbapt# define forceinline static inline 77262395Sbapt# endif 78262395Sbapt#endif 79262395Sbapt 80262395Sbapt 81262395Sbapt//************************************** 82262395Sbapt// Includes & Memory related functions 83262395Sbapt//************************************** 84262395Sbapt#include "xxhash.h" 85262395Sbapt// Modify the local functions below should you wish to use some other memory related routines 86262395Sbapt// for malloc(), free() 87262395Sbapt#include <stdlib.h> 88262395Sbaptforceinline void* XXH_malloc(size_t s) { return malloc(s); } 89262395Sbaptforceinline void XXH_free (void* p) { free(p); } 90262395Sbapt// for memcpy() 91262395Sbapt#include <string.h> 92262395Sbaptforceinline void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } 93262395Sbapt 94262395Sbapt 95262395Sbapt//************************************** 96262395Sbapt// Basic Types 97262395Sbapt//************************************** 98262395Sbapt#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99 99262395Sbapt# include <stdint.h> 100262395Sbapt typedef uint8_t BYTE; 101262395Sbapt typedef uint16_t U16; 102262395Sbapt typedef uint32_t U32; 103262395Sbapt typedef int32_t S32; 104262395Sbapt typedef uint64_t U64; 105262395Sbapt#else 106262395Sbapt typedef unsigned char BYTE; 107262395Sbapt typedef unsigned short U16; 108262395Sbapt typedef unsigned int U32; 109262395Sbapt typedef signed int S32; 110262395Sbapt typedef unsigned long long U64; 111262395Sbapt#endif 112262395Sbapt 113262395Sbapt#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS) 114262395Sbapt# define _PACKED __attribute__ ((packed)) 115262395Sbapt#else 116262395Sbapt# define _PACKED 117262395Sbapt#endif 118262395Sbapt 119262395Sbapt#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) 120262395Sbapt# ifdef __IBMC__ 121262395Sbapt# pragma pack(1) 122262395Sbapt# else 123262395Sbapt# pragma pack(push, 1) 124262395Sbapt# endif 125262395Sbapt#endif 126262395Sbapt 127262395Sbapttypedef struct _U32_S { U32 v; } _PACKED U32_S; 128262395Sbapt 129262395Sbapt#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) 130262395Sbapt# pragma pack(pop) 131262395Sbapt#endif 132262395Sbapt 133262395Sbapt#define A32(x) (((U32_S *)(x))->v) 134262395Sbapt 135262395Sbapt 136262395Sbapt//*************************************** 137262395Sbapt// Compiler-specific Functions and Macros 138262395Sbapt//*************************************** 139262395Sbapt#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) 140262395Sbapt 141262395Sbapt// Note : although _rotl exists for minGW (GCC under windows), performance seems poor 142262395Sbapt#if defined(_MSC_VER) 143262395Sbapt# define XXH_rotl32(x,r) _rotl(x,r) 144262395Sbapt#else 145262395Sbapt# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) 146262395Sbapt#endif 147262395Sbapt 148262395Sbapt#if defined(_MSC_VER) // Visual Studio 149262395Sbapt# define XXH_swap32 _byteswap_ulong 150262395Sbapt#elif GCC_VERSION >= 403 151262395Sbapt# define XXH_swap32 __builtin_bswap32 152262395Sbapt#else 153262395Sbaptstatic inline U32 XXH_swap32 (U32 x) { 154262395Sbapt return ((x << 24) & 0xff000000 ) | 155262395Sbapt ((x << 8) & 0x00ff0000 ) | 156262395Sbapt ((x >> 8) & 0x0000ff00 ) | 157262395Sbapt ((x >> 24) & 0x000000ff );} 158262395Sbapt#endif 159262395Sbapt 160262395Sbapt 161262395Sbapt//************************************** 162262395Sbapt// Constants 163262395Sbapt//************************************** 164262395Sbapt#define PRIME32_1 2654435761U 165262395Sbapt#define PRIME32_2 2246822519U 166262395Sbapt#define PRIME32_3 3266489917U 167262395Sbapt#define PRIME32_4 668265263U 168262395Sbapt#define PRIME32_5 374761393U 169262395Sbapt 170262395Sbapt 171262395Sbapt//************************************** 172262395Sbapt// Architecture Macros 173262395Sbapt//************************************** 174262395Sbapttypedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; 175262395Sbapt#ifndef XXH_CPU_LITTLE_ENDIAN // It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch 176262395Sbapt static const int one = 1; 177262395Sbapt# define XXH_CPU_LITTLE_ENDIAN (*(char*)(&one)) 178262395Sbapt#endif 179262395Sbapt 180262395Sbapt 181262395Sbapt//************************************** 182262395Sbapt// Macros 183262395Sbapt//************************************** 184262395Sbapt#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } // use only *after* variable declarations 185262395Sbapt 186262395Sbapt 187262395Sbapt//**************************** 188262395Sbapt// Memory reads 189262395Sbapt//**************************** 190262395Sbapttypedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; 191262395Sbapt 192262395Sbaptforceinline U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align) 193262395Sbapt{ 194262395Sbapt if (align==XXH_unaligned) 195262395Sbapt return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr)); 196262395Sbapt else 197262395Sbapt return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr); 198262395Sbapt} 199262395Sbapt 200262395Sbaptforceinline U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); } 201262395Sbapt 202262395Sbapt 203262395Sbapt//**************************** 204262395Sbapt// Simple Hash Functions 205262395Sbapt//**************************** 206262395Sbaptforceinline U32 XXH32_endian_align(const void* input, int len, U32 seed, XXH_endianess endian, XXH_alignment align) 207262395Sbapt{ 208262395Sbapt const BYTE* p = (const BYTE*)input; 209262395Sbapt const BYTE* const bEnd = p + len; 210262395Sbapt U32 h32; 211262395Sbapt 212262395Sbapt#ifdef XXH_ACCEPT_NULL_INPUT_POINTER 213262395Sbapt if (p==NULL) { len=0; p=(const BYTE*)(size_t)16; } 214262395Sbapt#endif 215262395Sbapt 216262395Sbapt if (len>=16) 217262395Sbapt { 218262395Sbapt const BYTE* const limit = bEnd - 16; 219262395Sbapt U32 v1 = seed + PRIME32_1 + PRIME32_2; 220262395Sbapt U32 v2 = seed + PRIME32_2; 221262395Sbapt U32 v3 = seed + 0; 222262395Sbapt U32 v4 = seed - PRIME32_1; 223262395Sbapt 224262395Sbapt do 225262395Sbapt { 226262395Sbapt v1 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; 227262395Sbapt v2 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; 228262395Sbapt v3 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; 229262395Sbapt v4 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; 230262395Sbapt } while (p<=limit); 231262395Sbapt 232262395Sbapt h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); 233262395Sbapt } 234262395Sbapt else 235262395Sbapt { 236262395Sbapt h32 = seed + PRIME32_5; 237262395Sbapt } 238262395Sbapt 239262395Sbapt h32 += (U32) len; 240262395Sbapt 241262395Sbapt while (p<=bEnd-4) 242262395Sbapt { 243262395Sbapt h32 += XXH_readLE32_align((const U32*)p, endian, align) * PRIME32_3; 244262395Sbapt h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; 245262395Sbapt p+=4; 246262395Sbapt } 247262395Sbapt 248262395Sbapt while (p<bEnd) 249262395Sbapt { 250262395Sbapt h32 += (*p) * PRIME32_5; 251262395Sbapt h32 = XXH_rotl32(h32, 11) * PRIME32_1 ; 252262395Sbapt p++; 253262395Sbapt } 254262395Sbapt 255262395Sbapt h32 ^= h32 >> 15; 256262395Sbapt h32 *= PRIME32_2; 257262395Sbapt h32 ^= h32 >> 13; 258262395Sbapt h32 *= PRIME32_3; 259262395Sbapt h32 ^= h32 >> 16; 260262395Sbapt 261262395Sbapt return h32; 262262395Sbapt} 263262395Sbapt 264262395Sbapt 265262395SbaptU32 XXH32(const void* input, int len, U32 seed) 266262395Sbapt{ 267262395Sbapt#if 0 268262395Sbapt // Simple version, good for code maintenance, but unfortunately slow for small inputs 269262395Sbapt void* state = XXH32_init(seed); 270262395Sbapt XXH32_update(state, input, len); 271262395Sbapt return XXH32_digest(state); 272262395Sbapt#else 273262395Sbapt XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; 274262395Sbapt 275262395Sbapt# if !defined(XXH_USE_UNALIGNED_ACCESS) 276262395Sbapt if (!(((size_t)input) & 3)) // Input is aligned, let's leverage the speed advantage 277262395Sbapt { 278262395Sbapt if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 279262395Sbapt return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); 280262395Sbapt else 281262395Sbapt return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); 282262395Sbapt } 283262395Sbapt# endif 284262395Sbapt 285262395Sbapt if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 286262395Sbapt return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); 287262395Sbapt else 288262395Sbapt return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); 289262395Sbapt#endif 290262395Sbapt} 291262395Sbapt 292262395Sbapt 293262395Sbapt//**************************** 294262395Sbapt// Advanced Hash Functions 295262395Sbapt//**************************** 296262395Sbapt 297262395Sbaptstruct XXH_state32_t 298262395Sbapt{ 299262395Sbapt U64 total_len; 300262395Sbapt U32 seed; 301262395Sbapt U32 v1; 302262395Sbapt U32 v2; 303262395Sbapt U32 v3; 304262395Sbapt U32 v4; 305262395Sbapt int memsize; 306262395Sbapt char memory[16]; 307262395Sbapt}; 308262395Sbapt 309262395Sbapt 310262395Sbaptint XXH32_sizeofState(void) 311262395Sbapt{ 312262395Sbapt XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); // A compilation error here means XXH32_SIZEOFSTATE is not large enough 313262395Sbapt return sizeof(struct XXH_state32_t); 314262395Sbapt} 315262395Sbapt 316262395Sbapt 317262395SbaptXXH_errorcode XXH32_resetState(void* state_in, U32 seed) 318262395Sbapt{ 319262395Sbapt struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 320262395Sbapt state->seed = seed; 321262395Sbapt state->v1 = seed + PRIME32_1 + PRIME32_2; 322262395Sbapt state->v2 = seed + PRIME32_2; 323262395Sbapt state->v3 = seed + 0; 324262395Sbapt state->v4 = seed - PRIME32_1; 325262395Sbapt state->total_len = 0; 326262395Sbapt state->memsize = 0; 327262395Sbapt return XXH_OK; 328262395Sbapt} 329262395Sbapt 330262395Sbapt 331262395Sbaptvoid* XXH32_init (U32 seed) 332262395Sbapt{ 333262395Sbapt void* state = XXH_malloc (sizeof(struct XXH_state32_t)); 334262395Sbapt XXH32_resetState(state, seed); 335262395Sbapt return state; 336262395Sbapt} 337262395Sbapt 338262395Sbapt 339262395Sbaptforceinline XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian) 340262395Sbapt{ 341262395Sbapt struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 342262395Sbapt const BYTE* p = (const BYTE*)input; 343262395Sbapt const BYTE* const bEnd = p + len; 344262395Sbapt 345262395Sbapt#ifdef XXH_ACCEPT_NULL_INPUT_POINTER 346262395Sbapt if (input==NULL) return XXH_ERROR; 347262395Sbapt#endif 348262395Sbapt 349262395Sbapt state->total_len += len; 350262395Sbapt 351262395Sbapt if (state->memsize + len < 16) // fill in tmp buffer 352262395Sbapt { 353262395Sbapt XXH_memcpy(state->memory + state->memsize, input, len); 354262395Sbapt state->memsize += len; 355262395Sbapt return XXH_OK; 356262395Sbapt } 357262395Sbapt 358262395Sbapt if (state->memsize) // some data left from previous update 359262395Sbapt { 360262395Sbapt XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize); 361262395Sbapt { 362262395Sbapt const U32* p32 = (const U32*)state->memory; 363262395Sbapt state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++; 364262395Sbapt state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; 365262395Sbapt state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++; 366262395Sbapt state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++; 367262395Sbapt } 368262395Sbapt p += 16-state->memsize; 369262395Sbapt state->memsize = 0; 370262395Sbapt } 371262395Sbapt 372262395Sbapt if (p <= bEnd-16) 373262395Sbapt { 374262395Sbapt const BYTE* const limit = bEnd - 16; 375262395Sbapt U32 v1 = state->v1; 376262395Sbapt U32 v2 = state->v2; 377262395Sbapt U32 v3 = state->v3; 378262395Sbapt U32 v4 = state->v4; 379262395Sbapt 380262395Sbapt do 381262395Sbapt { 382262395Sbapt v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; 383262395Sbapt v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; 384262395Sbapt v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; 385262395Sbapt v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; 386262395Sbapt } while (p<=limit); 387262395Sbapt 388262395Sbapt state->v1 = v1; 389262395Sbapt state->v2 = v2; 390262395Sbapt state->v3 = v3; 391262395Sbapt state->v4 = v4; 392262395Sbapt } 393262395Sbapt 394262395Sbapt if (p < bEnd) 395262395Sbapt { 396262395Sbapt XXH_memcpy(state->memory, p, bEnd-p); 397262395Sbapt state->memsize = (int)(bEnd-p); 398262395Sbapt } 399262395Sbapt 400262395Sbapt return XXH_OK; 401262395Sbapt} 402262395Sbapt 403262395SbaptXXH_errorcode XXH32_update (void* state_in, const void* input, int len) 404262395Sbapt{ 405262395Sbapt XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; 406262395Sbapt 407262395Sbapt if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 408262395Sbapt return XXH32_update_endian(state_in, input, len, XXH_littleEndian); 409262395Sbapt else 410262395Sbapt return XXH32_update_endian(state_in, input, len, XXH_bigEndian); 411262395Sbapt} 412262395Sbapt 413262395Sbapt 414262395Sbapt 415262395Sbaptforceinline U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian) 416262395Sbapt{ 417262395Sbapt struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 418262395Sbapt const BYTE * p = (const BYTE*)state->memory; 419262395Sbapt BYTE* bEnd = (BYTE*)state->memory + state->memsize; 420262395Sbapt U32 h32; 421262395Sbapt 422262395Sbapt if (state->total_len >= 16) 423262395Sbapt { 424262395Sbapt h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); 425262395Sbapt } 426262395Sbapt else 427262395Sbapt { 428262395Sbapt h32 = state->seed + PRIME32_5; 429262395Sbapt } 430262395Sbapt 431262395Sbapt h32 += (U32) state->total_len; 432262395Sbapt 433262395Sbapt while (p<=bEnd-4) 434262395Sbapt { 435262395Sbapt h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3; 436262395Sbapt h32 = XXH_rotl32(h32, 17) * PRIME32_4; 437262395Sbapt p+=4; 438262395Sbapt } 439262395Sbapt 440262395Sbapt while (p<bEnd) 441262395Sbapt { 442262395Sbapt h32 += (*p) * PRIME32_5; 443262395Sbapt h32 = XXH_rotl32(h32, 11) * PRIME32_1; 444262395Sbapt p++; 445262395Sbapt } 446262395Sbapt 447262395Sbapt h32 ^= h32 >> 15; 448262395Sbapt h32 *= PRIME32_2; 449262395Sbapt h32 ^= h32 >> 13; 450262395Sbapt h32 *= PRIME32_3; 451262395Sbapt h32 ^= h32 >> 16; 452262395Sbapt 453262395Sbapt return h32; 454262395Sbapt} 455262395Sbapt 456262395Sbapt 457262395SbaptU32 XXH32_intermediateDigest (void* state_in) 458262395Sbapt{ 459262395Sbapt XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; 460262395Sbapt 461262395Sbapt if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 462262395Sbapt return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian); 463262395Sbapt else 464262395Sbapt return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian); 465262395Sbapt} 466262395Sbapt 467262395Sbapt 468262395SbaptU32 XXH32_digest (void* state_in) 469262395Sbapt{ 470262395Sbapt U32 h32 = XXH32_intermediateDigest(state_in); 471262395Sbapt 472262395Sbapt XXH_free(state_in); 473262395Sbapt 474262395Sbapt return h32; 475262395Sbapt} 476