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