xxhash.c revision 318483
1/* 2xxHash - Fast Hash algorithm 3Copyright (C) 2012-2014, Yann Collet. 4BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 5 6Redistribution and use in source and binary forms, with or without 7modification, are permitted provided that the following conditions are 8met: 9 10* Redistributions of source code must retain the above copyright 11notice, this list of conditions and the following disclaimer. 12* Redistributions in binary form must reproduce the above 13copyright notice, this list of conditions and the following disclaimer 14in the documentation and/or other materials provided with the 15distribution. 16 17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 29You can contact the author at : 30- xxHash source repository : http://code.google.com/p/xxhash/ 31*/ 32#include "archive_platform.h" 33 34#include <stdlib.h> 35#include <string.h> 36 37#include "archive_xxhash.h" 38 39#ifdef HAVE_LIBLZ4 40 41/*************************************** 42** Tuning parameters 43****************************************/ 44/* Unaligned memory access is automatically enabled for "common" CPU, such as x86. 45** For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected. 46** If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance. 47** You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32). 48*/ 49#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) 50# define XXH_USE_UNALIGNED_ACCESS 1 51#endif 52 53/* XXH_ACCEPT_NULL_INPUT_POINTER : 54** If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer. 55** When this option is enabled, xxHash output for null input pointers will be the same as a null-length input. 56** This option has a very small performance cost (only measurable on small inputs). 57** By default, this option is disabled. To enable it, uncomment below define : 58** #define XXH_ACCEPT_NULL_INPUT_POINTER 1 59 60** XXH_FORCE_NATIVE_FORMAT : 61** By default, xxHash library provides endian-independent Hash values, based on little-endian convention. 62** Results are therefore identical for little-endian and big-endian CPU. 63** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. 64** Should endian-independence be of no importance for your application, you may set the #define below to 1. 65** It will improve speed for Big-endian CPU. 66** This option has no impact on Little_Endian CPU. 67*/ 68#define XXH_FORCE_NATIVE_FORMAT 0 69 70/*************************************** 71** Compiler Specific Options 72****************************************/ 73/* Disable some Visual warning messages */ 74#ifdef _MSC_VER /* Visual Studio */ 75# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ 76#endif 77 78#ifdef _MSC_VER /* Visual Studio */ 79# define FORCE_INLINE __forceinline 80#else 81# ifdef __GNUC__ 82# define FORCE_INLINE inline __attribute__((always_inline)) 83# else 84# define FORCE_INLINE inline 85# endif 86#endif 87 88/*************************************** 89** Includes & Memory related functions 90****************************************/ 91#define XXH_malloc malloc 92#define XXH_free free 93#define XXH_memcpy memcpy 94 95 96static unsigned int XXH32 (const void*, unsigned int, unsigned int); 97static void* XXH32_init (unsigned int); 98static XXH_errorcode XXH32_update (void*, const void*, unsigned int); 99static unsigned int XXH32_digest (void*); 100/*static int XXH32_sizeofState(void);*/ 101static XXH_errorcode XXH32_resetState(void*, unsigned int); 102#define XXH32_SIZEOFSTATE 48 103typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t; 104static unsigned int XXH32_intermediateDigest (void*); 105 106/*************************************** 107** Basic Types 108****************************************/ 109#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ 110# include <stdint.h> 111 typedef uint8_t BYTE; 112 typedef uint16_t U16; 113 typedef uint32_t U32; 114 typedef int32_t S32; 115 typedef uint64_t U64; 116#else 117 typedef unsigned char BYTE; 118 typedef unsigned short U16; 119 typedef unsigned int U32; 120 typedef signed int S32; 121 typedef unsigned long long U64; 122#endif 123 124#if defined(__GNUC__) && !defined(XXH_USE_UNALIGNED_ACCESS) 125# define _PACKED __attribute__ ((packed)) 126#else 127# define _PACKED 128#endif 129 130#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) 131# ifdef __IBMC__ 132# pragma pack(1) 133# else 134# pragma pack(push, 1) 135# endif 136#endif 137 138typedef struct _U32_S { U32 v; } _PACKED U32_S; 139 140#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__) 141# pragma pack(pop) 142#endif 143 144 145/**************************************** 146** Compiler-specific Functions and Macros 147*****************************************/ 148#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0)) 149 150#if GCC_VERSION >= 409 151__attribute__((__no_sanitize_undefined__)) 152#endif 153static inline U32 A32(const void * x) 154{ 155 return (((const U32_S *)(x))->v); 156} 157 158/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ 159#if defined(_MSC_VER) 160# define XXH_rotl32(x,r) _rotl(x,r) 161#else 162# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) 163#endif 164 165#if defined(_MSC_VER) /* Visual Studio */ 166# define XXH_swap32 _byteswap_ulong 167#elif GCC_VERSION >= 403 168# define XXH_swap32 __builtin_bswap32 169#else 170static inline U32 XXH_swap32 (U32 x) { 171 return ((x << 24) & 0xff000000 ) | 172 ((x << 8) & 0x00ff0000 ) | 173 ((x >> 8) & 0x0000ff00 ) | 174 ((x >> 24) & 0x000000ff );} 175#endif 176 177 178/*************************************** 179** Constants 180****************************************/ 181#define PRIME32_1 2654435761U 182#define PRIME32_2 2246822519U 183#define PRIME32_3 3266489917U 184#define PRIME32_4 668265263U 185#define PRIME32_5 374761393U 186 187 188/*************************************** 189** Architecture Macros 190****************************************/ 191typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; 192#ifndef XXH_CPU_LITTLE_ENDIAN /* It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch */ 193 static const int one = 1; 194# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&one)) 195#endif 196 197 198/*************************************** 199** Macros 200****************************************/ 201#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(!!(c)) }; } /* use only *after* variable declarations */ 202 203 204/***************************** 205** Memory reads 206******************************/ 207typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; 208 209static 210FORCE_INLINE U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align) 211{ 212 if (align==XXH_unaligned) 213 return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr)); 214 else 215 return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr); 216} 217 218static 219FORCE_INLINE U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); } 220 221 222/***************************** 223** Simple Hash Functions 224******************************/ 225static 226FORCE_INLINE U32 XXH32_endian_align(const void* input, unsigned int len, U32 seed, XXH_endianess endian, XXH_alignment align) 227{ 228 const BYTE* p = (const BYTE*)input; 229 const BYTE* bEnd = p + len; 230 U32 h32; 231#define XXH_get32bits(p) XXH_readLE32_align((const U32*)p, endian, align) 232 233#ifdef XXH_ACCEPT_NULL_INPUT_POINTER 234 if (p==NULL) { len=0; bEnd=p=(const BYTE*)(size_t)16; } 235#endif 236 237 if (len>=16) 238 { 239 const BYTE* const limit = bEnd - 16; 240 U32 v1 = seed + PRIME32_1 + PRIME32_2; 241 U32 v2 = seed + PRIME32_2; 242 U32 v3 = seed + 0; 243 U32 v4 = seed - PRIME32_1; 244 245 do 246 { 247 v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; 248 v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; 249 v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; 250 v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; 251 } while (p<=limit); 252 253 h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); 254 } 255 else 256 { 257 h32 = seed + PRIME32_5; 258 } 259 260 h32 += (U32) len; 261 262 while (p<=bEnd-4) 263 { 264 h32 += XXH_get32bits(p) * PRIME32_3; 265 h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; 266 p+=4; 267 } 268 269 while (p<bEnd) 270 { 271 h32 += (*p) * PRIME32_5; 272 h32 = XXH_rotl32(h32, 11) * PRIME32_1 ; 273 p++; 274 } 275 276 h32 ^= h32 >> 15; 277 h32 *= PRIME32_2; 278 h32 ^= h32 >> 13; 279 h32 *= PRIME32_3; 280 h32 ^= h32 >> 16; 281 282 return h32; 283} 284 285 286U32 XXH32(const void* input, unsigned int len, U32 seed) 287{ 288#if 0 289 // Simple version, good for code maintenance, but unfortunately slow for small inputs 290 void* state = XXH32_init(seed); 291 XXH32_update(state, input, len); 292 return XXH32_digest(state); 293#else 294 XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; 295 296# if !defined(XXH_USE_UNALIGNED_ACCESS) 297 if ((((size_t)input) & 3) == 0) /* Input is aligned, let's leverage the speed advantage */ 298 { 299 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 300 return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); 301 else 302 return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); 303 } 304# endif 305 306 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 307 return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); 308 else 309 return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); 310#endif 311} 312 313/***************************** 314** Advanced Hash Functions 315******************************/ 316 317struct XXH_state32_t 318{ 319 U64 total_len; 320 U32 seed; 321 U32 v1; 322 U32 v2; 323 U32 v3; 324 U32 v4; 325 int memsize; 326 char memory[16]; 327}; 328 329#if 0 330static 331int XXH32_sizeofState(void) 332{ 333 XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t)); /* A compilation error here means XXH32_SIZEOFSTATE is not large enough */ 334 return sizeof(struct XXH_state32_t); 335} 336#endif 337 338static 339XXH_errorcode XXH32_resetState(void* state_in, U32 seed) 340{ 341 struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 342 state->seed = seed; 343 state->v1 = seed + PRIME32_1 + PRIME32_2; 344 state->v2 = seed + PRIME32_2; 345 state->v3 = seed + 0; 346 state->v4 = seed - PRIME32_1; 347 state->total_len = 0; 348 state->memsize = 0; 349 return XXH_OK; 350} 351 352static 353void* XXH32_init (U32 seed) 354{ 355 void* state = XXH_malloc (sizeof(struct XXH_state32_t)); 356 XXH32_resetState(state, seed); 357 return state; 358} 359 360static 361FORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian) 362{ 363 struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 364 const BYTE* p = (const BYTE*)input; 365 const BYTE* const bEnd = p + len; 366 367#ifdef XXH_ACCEPT_NULL_INPUT_POINTER 368 if (input==NULL) return XXH_ERROR; 369#endif 370 371 state->total_len += len; 372 373 if (state->memsize + len < 16) /* fill in tmp buffer */ 374 { 375 XXH_memcpy(state->memory + state->memsize, input, len); 376 state->memsize += len; 377 return XXH_OK; 378 } 379 380 if (state->memsize) /* some data left from previous update */ 381 { 382 XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize); 383 { 384 const U32* p32 = (const U32*)state->memory; 385 state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++; 386 state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; 387 state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++; 388 state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++; 389 } 390 p += 16-state->memsize; 391 state->memsize = 0; 392 } 393 394 if (p <= bEnd-16) 395 { 396 const BYTE* const limit = bEnd - 16; 397 U32 v1 = state->v1; 398 U32 v2 = state->v2; 399 U32 v3 = state->v3; 400 U32 v4 = state->v4; 401 402 do 403 { 404 v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; 405 v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; 406 v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; 407 v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; 408 } while (p<=limit); 409 410 state->v1 = v1; 411 state->v2 = v2; 412 state->v3 = v3; 413 state->v4 = v4; 414 } 415 416 if (p < bEnd) 417 { 418 XXH_memcpy(state->memory, p, bEnd-p); 419 state->memsize = (int)(bEnd-p); 420 } 421 422 return XXH_OK; 423} 424 425static 426XXH_errorcode XXH32_update (void* state_in, const void* input, unsigned int len) 427{ 428 XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; 429 430 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 431 return XXH32_update_endian(state_in, input, len, XXH_littleEndian); 432 else 433 return XXH32_update_endian(state_in, input, len, XXH_bigEndian); 434} 435 436 437 438static 439FORCE_INLINE U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian) 440{ 441 struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 442 const BYTE * p = (const BYTE*)state->memory; 443 BYTE* bEnd = (BYTE*)state->memory + state->memsize; 444 U32 h32; 445 446 if (state->total_len >= 16) 447 { 448 h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); 449 } 450 else 451 { 452 h32 = state->seed + PRIME32_5; 453 } 454 455 h32 += (U32) state->total_len; 456 457 while (p<=bEnd-4) 458 { 459 h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3; 460 h32 = XXH_rotl32(h32, 17) * PRIME32_4; 461 p+=4; 462 } 463 464 while (p<bEnd) 465 { 466 h32 += (*p) * PRIME32_5; 467 h32 = XXH_rotl32(h32, 11) * PRIME32_1; 468 p++; 469 } 470 471 h32 ^= h32 >> 15; 472 h32 *= PRIME32_2; 473 h32 ^= h32 >> 13; 474 h32 *= PRIME32_3; 475 h32 ^= h32 >> 16; 476 477 return h32; 478} 479 480static 481U32 XXH32_intermediateDigest (void* state_in) 482{ 483 XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; 484 485 if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) 486 return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian); 487 else 488 return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian); 489} 490 491static 492U32 XXH32_digest (void* state_in) 493{ 494 U32 h32 = XXH32_intermediateDigest(state_in); 495 496 XXH_free(state_in); 497 498 return h32; 499} 500 501const 502struct archive_xxhash __archive_xxhash = { 503 XXH32, 504 XXH32_init, 505 XXH32_update, 506 XXH32_digest 507}; 508#else 509 510/* 511 * Define an empty version of the struct if we aren't using the LZ4 library. 512 */ 513const 514struct archive_xxhash __archive_xxhash = { 515 NULL, 516 NULL, 517 NULL, 518 NULL 519}; 520 521#endif /* HAVE_LIBLZ4 */ 522