Blame libarchive/xxhash.c

Packit 08bd4c
/*
Packit 08bd4c
xxHash - Fast Hash algorithm
Packit 08bd4c
Copyright (C) 2012-2014, Yann Collet.
Packit 08bd4c
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Packit 08bd4c
Packit 08bd4c
Redistribution and use in source and binary forms, with or without
Packit 08bd4c
modification, are permitted provided that the following conditions are
Packit 08bd4c
met:
Packit 08bd4c
Packit 08bd4c
* Redistributions of source code must retain the above copyright
Packit 08bd4c
notice, this list of conditions and the following disclaimer.
Packit 08bd4c
* Redistributions in binary form must reproduce the above
Packit 08bd4c
copyright notice, this list of conditions and the following disclaimer
Packit 08bd4c
in the documentation and/or other materials provided with the
Packit 08bd4c
distribution.
Packit 08bd4c
Packit 08bd4c
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 08bd4c
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 08bd4c
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 08bd4c
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 08bd4c
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 08bd4c
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 08bd4c
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 08bd4c
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 08bd4c
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 08bd4c
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 08bd4c
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 08bd4c
Packit 08bd4c
You can contact the author at :
Packit 08bd4c
- xxHash source repository : http://code.google.com/p/xxhash/
Packit 08bd4c
*/
Packit 08bd4c
#include "archive_platform.h"
Packit 08bd4c
Packit 08bd4c
#include <stdlib.h>
Packit 08bd4c
#include <string.h>
Packit 08bd4c
Packit 08bd4c
#include "archive_xxhash.h"
Packit 08bd4c
Packit 08bd4c
#ifdef HAVE_LIBLZ4
Packit 08bd4c
Packit 08bd4c
/***************************************
Packit 08bd4c
** Tuning parameters
Packit 08bd4c
****************************************/
Packit 08bd4c
/* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
Packit 08bd4c
** For others CPU, the compiler will be more cautious, and insert extra code to ensure aligned access is respected.
Packit 08bd4c
** If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance.
Packit 08bd4c
** You can also enable this parameter if you know your input data will always be aligned (boundaries of 4, for U32).
Packit 08bd4c
*/
Packit 08bd4c
#if defined(__ARM_FEATURE_UNALIGNED) || defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
Packit 08bd4c
#  define XXH_USE_UNALIGNED_ACCESS 1
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
/* XXH_ACCEPT_NULL_INPUT_POINTER :
Packit 08bd4c
** If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.
Packit 08bd4c
** When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.
Packit 08bd4c
** This option has a very small performance cost (only measurable on small inputs).
Packit 08bd4c
** By default, this option is disabled. To enable it, uncomment below define :
Packit 08bd4c
** #define XXH_ACCEPT_NULL_INPUT_POINTER 1
Packit 08bd4c
Packit 08bd4c
** XXH_FORCE_NATIVE_FORMAT :
Packit 08bd4c
** By default, xxHash library provides endian-independent Hash values, based on little-endian convention.
Packit 08bd4c
** Results are therefore identical for little-endian and big-endian CPU.
Packit 08bd4c
** This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.
Packit 08bd4c
** Should endian-independence be of no importance for your application, you may set the #define below to 1.
Packit 08bd4c
** It will improve speed for Big-endian CPU.
Packit 08bd4c
** This option has no impact on Little_Endian CPU.
Packit 08bd4c
*/
Packit 08bd4c
#define XXH_FORCE_NATIVE_FORMAT 0
Packit 08bd4c
Packit 08bd4c
/***************************************
Packit 08bd4c
** Compiler Specific Options
Packit 08bd4c
****************************************/
Packit 08bd4c
/* Disable some Visual warning messages */
Packit 08bd4c
#ifdef _MSC_VER  /* Visual Studio */
Packit 08bd4c
#  pragma warning(disable : 4127)      /* disable: C4127: conditional expression is constant */
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
#ifdef _MSC_VER    /* Visual Studio */
Packit 08bd4c
#  define FORCE_INLINE __forceinline
Packit 08bd4c
#else
Packit 08bd4c
#  ifdef __GNUC__
Packit 08bd4c
#    define FORCE_INLINE inline __attribute__((always_inline))
Packit 08bd4c
#  else
Packit 08bd4c
#    define FORCE_INLINE inline
Packit 08bd4c
#  endif
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
/***************************************
Packit 08bd4c
** Includes & Memory related functions
Packit 08bd4c
****************************************/
Packit 08bd4c
#define XXH_malloc malloc
Packit 08bd4c
#define XXH_free free
Packit 08bd4c
#define XXH_memcpy memcpy
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
static unsigned int	  XXH32 (const void*, unsigned int, unsigned int);
Packit 08bd4c
static void*		  XXH32_init   (unsigned int);
Packit 08bd4c
static XXH_errorcode	  XXH32_update (void*, const void*, unsigned int);
Packit 08bd4c
static unsigned int	  XXH32_digest (void*);
Packit 08bd4c
/*static int		  XXH32_sizeofState(void);*/
Packit 08bd4c
static XXH_errorcode	  XXH32_resetState(void*, unsigned int);
Packit 08bd4c
#define       XXH32_SIZEOFSTATE 48
Packit 08bd4c
typedef struct { long long ll[(XXH32_SIZEOFSTATE+(sizeof(long long)-1))/sizeof(long long)]; } XXH32_stateSpace_t;
Packit 08bd4c
static unsigned int	  XXH32_intermediateDigest (void*);
Packit 08bd4c
Packit 08bd4c
/***************************************
Packit 08bd4c
** Basic Types
Packit 08bd4c
****************************************/
Packit 08bd4c
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L   /* C99 */
Packit 08bd4c
# include <stdint.h>
Packit 08bd4c
  typedef uint8_t  BYTE;
Packit 08bd4c
  typedef uint16_t U16;
Packit 08bd4c
  typedef uint32_t U32;
Packit 08bd4c
  typedef  int32_t S32;
Packit 08bd4c
  typedef uint64_t U64;
Packit 08bd4c
#else
Packit 08bd4c
  typedef unsigned char      BYTE;
Packit 08bd4c
  typedef unsigned short     U16;
Packit 08bd4c
  typedef unsigned int       U32;
Packit 08bd4c
  typedef   signed int       S32;
Packit 08bd4c
  typedef unsigned long long U64;
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
#if defined(__GNUC__)  && !defined(XXH_USE_UNALIGNED_ACCESS)
Packit 08bd4c
#  define _PACKED __attribute__ ((packed))
Packit 08bd4c
#else
Packit 08bd4c
#  define _PACKED
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
Packit 08bd4c
#  ifdef __IBMC__
Packit 08bd4c
#    pragma pack(1)
Packit 08bd4c
#  else
Packit 08bd4c
#    pragma pack(push, 1)
Packit 08bd4c
#  endif
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
typedef struct _U32_S { U32 v; } _PACKED U32_S;
Packit 08bd4c
Packit 08bd4c
#if !defined(XXH_USE_UNALIGNED_ACCESS) && !defined(__GNUC__)
Packit 08bd4c
#  pragma pack(pop)
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
/****************************************
Packit 08bd4c
** Compiler-specific Functions and Macros
Packit 08bd4c
*****************************************/
Packit 08bd4c
#define GCC_VERSION ((__GNUC__-0) * 100 + (__GNUC_MINOR__ - 0))
Packit 08bd4c
Packit 08bd4c
#if GCC_VERSION >= 409
Packit 08bd4c
__attribute__((__no_sanitize_undefined__))
Packit 08bd4c
#endif
Packit 08bd4c
static inline U32 A32(const void * x)
Packit 08bd4c
{
Packit 08bd4c
    return (((const U32_S *)(x))->v);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
Packit 08bd4c
#if defined(_MSC_VER)
Packit 08bd4c
#  define XXH_rotl32(x,r) _rotl(x,r)
Packit 08bd4c
#else
Packit 08bd4c
#  define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
#if defined(_MSC_VER)     /* Visual Studio */
Packit 08bd4c
#  define XXH_swap32 _byteswap_ulong
Packit 08bd4c
#elif GCC_VERSION >= 403
Packit 08bd4c
#  define XXH_swap32 __builtin_bswap32
Packit 08bd4c
#else
Packit 08bd4c
static inline U32 XXH_swap32 (U32 x) {
Packit 08bd4c
    return  ((x << 24) & 0xff000000 ) |
Packit 08bd4c
			((x <<  8) & 0x00ff0000 ) |
Packit 08bd4c
			((x >>  8) & 0x0000ff00 ) |
Packit 08bd4c
			((x >> 24) & 0x000000ff );}
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
/***************************************
Packit 08bd4c
** Constants
Packit 08bd4c
****************************************/
Packit 08bd4c
#define PRIME32_1   2654435761U
Packit 08bd4c
#define PRIME32_2   2246822519U
Packit 08bd4c
#define PRIME32_3   3266489917U
Packit 08bd4c
#define PRIME32_4    668265263U
Packit 08bd4c
#define PRIME32_5    374761393U
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
/***************************************
Packit 08bd4c
** Architecture Macros
Packit 08bd4c
****************************************/
Packit 08bd4c
typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;
Packit 08bd4c
#ifndef XXH_CPU_LITTLE_ENDIAN   /* It is possible to define XXH_CPU_LITTLE_ENDIAN externally, for example using a compiler switch */
Packit 08bd4c
    static const int one = 1;
Packit 08bd4c
#   define XXH_CPU_LITTLE_ENDIAN   (*(const char*)(&one))
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
/***************************************
Packit 08bd4c
** Macros
Packit 08bd4c
****************************************/
Packit 08bd4c
#define XXH_STATIC_ASSERT(c)   { enum { XXH_static_assert = 1/(!!(c)) }; }    /* use only *after* variable declarations */
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
/*****************************
Packit 08bd4c
** Memory reads
Packit 08bd4c
******************************/
Packit 08bd4c
typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
FORCE_INLINE U32 XXH_readLE32_align(const U32* ptr, XXH_endianess endian, XXH_alignment align)
Packit 08bd4c
{
Packit 08bd4c
    if (align==XXH_unaligned)
Packit 08bd4c
        return endian==XXH_littleEndian ? A32(ptr) : XXH_swap32(A32(ptr));
Packit 08bd4c
    else
Packit 08bd4c
        return endian==XXH_littleEndian ? *ptr : XXH_swap32(*ptr);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
FORCE_INLINE U32 XXH_readLE32(const U32* ptr, XXH_endianess endian) { return XXH_readLE32_align(ptr, endian, XXH_unaligned); }
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
/*****************************
Packit 08bd4c
** Simple Hash Functions
Packit 08bd4c
******************************/
Packit 08bd4c
static
Packit 08bd4c
FORCE_INLINE U32 XXH32_endian_align(const void* input, unsigned int len, U32 seed, XXH_endianess endian, XXH_alignment align)
Packit 08bd4c
{
Packit 08bd4c
    const BYTE* p = (const BYTE*)input;
Packit 08bd4c
    const BYTE* bEnd = p + len;
Packit 08bd4c
    U32 h32;
Packit 08bd4c
#define XXH_get32bits(p) XXH_readLE32_align((const U32*)p, endian, align)
Packit 08bd4c
Packit 08bd4c
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
Packit 08bd4c
    if (p==NULL) { len=0; bEnd=p=(const BYTE*)(size_t)16; }
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
    if (len>=16)
Packit 08bd4c
    {
Packit 08bd4c
        const BYTE* const limit = bEnd - 16;
Packit 08bd4c
        U32 v1 = seed + PRIME32_1 + PRIME32_2;
Packit 08bd4c
        U32 v2 = seed + PRIME32_2;
Packit 08bd4c
        U32 v3 = seed + 0;
Packit 08bd4c
        U32 v4 = seed - PRIME32_1;
Packit 08bd4c
Packit 08bd4c
        do
Packit 08bd4c
        {
Packit 08bd4c
            v1 += XXH_get32bits(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
Packit 08bd4c
            v2 += XXH_get32bits(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
Packit 08bd4c
            v3 += XXH_get32bits(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
Packit 08bd4c
            v4 += XXH_get32bits(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
Packit 08bd4c
        } while (p<=limit);
Packit 08bd4c
Packit 08bd4c
        h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
Packit 08bd4c
    }
Packit 08bd4c
    else
Packit 08bd4c
    {
Packit 08bd4c
        h32  = seed + PRIME32_5;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    h32 += (U32) len;
Packit 08bd4c
Packit 08bd4c
    while (p<=bEnd-4)
Packit 08bd4c
    {
Packit 08bd4c
        h32 += XXH_get32bits(p) * PRIME32_3;
Packit 08bd4c
        h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
Packit 08bd4c
        p+=4;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    while (p
Packit 08bd4c
    {
Packit 08bd4c
        h32 += (*p) * PRIME32_5;
Packit 08bd4c
        h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
Packit 08bd4c
        p++;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    h32 ^= h32 >> 15;
Packit 08bd4c
    h32 *= PRIME32_2;
Packit 08bd4c
    h32 ^= h32 >> 13;
Packit 08bd4c
    h32 *= PRIME32_3;
Packit 08bd4c
    h32 ^= h32 >> 16;
Packit 08bd4c
Packit 08bd4c
    return h32;
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
U32 XXH32(const void* input, unsigned int len, U32 seed)
Packit 08bd4c
{
Packit 08bd4c
#if 0
Packit 08bd4c
    // Simple version, good for code maintenance, but unfortunately slow for small inputs
Packit 08bd4c
    void* state = XXH32_init(seed);
Packit 08bd4c
    XXH32_update(state, input, len);
Packit 08bd4c
    return XXH32_digest(state);
Packit 08bd4c
#else
Packit 08bd4c
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
Packit 08bd4c
Packit 08bd4c
#  if !defined(XXH_USE_UNALIGNED_ACCESS)
Packit 08bd4c
    if ((((size_t)input) & 3) == 0)   /* Input is aligned, let's leverage the speed advantage */
Packit 08bd4c
    {
Packit 08bd4c
        if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
Packit 08bd4c
            return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);
Packit 08bd4c
        else
Packit 08bd4c
            return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);
Packit 08bd4c
    }
Packit 08bd4c
#  endif
Packit 08bd4c
Packit 08bd4c
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
Packit 08bd4c
        return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);
Packit 08bd4c
    else
Packit 08bd4c
        return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);
Packit 08bd4c
#endif
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
/*****************************
Packit 08bd4c
** Advanced Hash Functions
Packit 08bd4c
******************************/
Packit 08bd4c
Packit 08bd4c
struct XXH_state32_t
Packit 08bd4c
{
Packit 08bd4c
    U64 total_len;
Packit 08bd4c
    U32 seed;
Packit 08bd4c
    U32 v1;
Packit 08bd4c
    U32 v2;
Packit 08bd4c
    U32 v3;
Packit 08bd4c
    U32 v4;
Packit 08bd4c
    int memsize;
Packit 08bd4c
    char memory[16];
Packit 08bd4c
};
Packit 08bd4c
Packit 08bd4c
#if 0
Packit 08bd4c
static
Packit 08bd4c
int XXH32_sizeofState(void)
Packit 08bd4c
{
Packit 08bd4c
    XXH_STATIC_ASSERT(XXH32_SIZEOFSTATE >= sizeof(struct XXH_state32_t));   /* A compilation error here means XXH32_SIZEOFSTATE is not large enough */
Packit 08bd4c
    return sizeof(struct XXH_state32_t);
Packit 08bd4c
}
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
XXH_errorcode XXH32_resetState(void* state_in, U32 seed)
Packit 08bd4c
{
Packit 08bd4c
    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
Packit 08bd4c
    state->seed = seed;
Packit 08bd4c
    state->v1 = seed + PRIME32_1 + PRIME32_2;
Packit 08bd4c
    state->v2 = seed + PRIME32_2;
Packit 08bd4c
    state->v3 = seed + 0;
Packit 08bd4c
    state->v4 = seed - PRIME32_1;
Packit 08bd4c
    state->total_len = 0;
Packit 08bd4c
    state->memsize = 0;
Packit 08bd4c
    return XXH_OK;
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
void* XXH32_init (U32 seed)
Packit 08bd4c
{
Packit 08bd4c
    void* state = XXH_malloc (sizeof(struct XXH_state32_t));
Packit 08bd4c
    XXH32_resetState(state, seed);
Packit 08bd4c
    return state;
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
FORCE_INLINE XXH_errorcode XXH32_update_endian (void* state_in, const void* input, int len, XXH_endianess endian)
Packit 08bd4c
{
Packit 08bd4c
    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
Packit 08bd4c
    const BYTE* p = (const BYTE*)input;
Packit 08bd4c
    const BYTE* const bEnd = p + len;
Packit 08bd4c
Packit 08bd4c
#ifdef XXH_ACCEPT_NULL_INPUT_POINTER
Packit 08bd4c
    if (input==NULL) return XXH_ERROR;
Packit 08bd4c
#endif
Packit 08bd4c
Packit 08bd4c
    state->total_len += len;
Packit 08bd4c
Packit 08bd4c
    if (state->memsize + len < 16)   /* fill in tmp buffer */
Packit 08bd4c
    {
Packit 08bd4c
        XXH_memcpy(state->memory + state->memsize, input, len);
Packit 08bd4c
        state->memsize +=  len;
Packit 08bd4c
        return XXH_OK;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    if (state->memsize)   /* some data left from previous update */
Packit 08bd4c
    {
Packit 08bd4c
        XXH_memcpy(state->memory + state->memsize, input, 16-state->memsize);
Packit 08bd4c
        {
Packit 08bd4c
            const U32* p32 = (const U32*)state->memory;
Packit 08bd4c
            state->v1 += XXH_readLE32(p32, endian) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++;
Packit 08bd4c
            state->v2 += XXH_readLE32(p32, endian) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++;
Packit 08bd4c
            state->v3 += XXH_readLE32(p32, endian) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++;
Packit 08bd4c
            state->v4 += XXH_readLE32(p32, endian) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++;
Packit 08bd4c
        }
Packit 08bd4c
        p += 16-state->memsize;
Packit 08bd4c
        state->memsize = 0;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    if (p <= bEnd-16)
Packit 08bd4c
    {
Packit 08bd4c
        const BYTE* const limit = bEnd - 16;
Packit 08bd4c
        U32 v1 = state->v1;
Packit 08bd4c
        U32 v2 = state->v2;
Packit 08bd4c
        U32 v3 = state->v3;
Packit 08bd4c
        U32 v4 = state->v4;
Packit 08bd4c
Packit 08bd4c
        do
Packit 08bd4c
        {
Packit 08bd4c
            v1 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4;
Packit 08bd4c
            v2 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4;
Packit 08bd4c
            v3 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4;
Packit 08bd4c
            v4 += XXH_readLE32((const U32*)p, endian) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4;
Packit 08bd4c
        } while (p<=limit);
Packit 08bd4c
Packit 08bd4c
        state->v1 = v1;
Packit 08bd4c
        state->v2 = v2;
Packit 08bd4c
        state->v3 = v3;
Packit 08bd4c
        state->v4 = v4;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    if (p < bEnd)
Packit 08bd4c
    {
Packit 08bd4c
        XXH_memcpy(state->memory, p, bEnd-p);
Packit 08bd4c
        state->memsize = (int)(bEnd-p);
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    return XXH_OK;
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
XXH_errorcode XXH32_update (void* state_in, const void* input, unsigned int len)
Packit 08bd4c
{
Packit 08bd4c
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
Packit 08bd4c
Packit 08bd4c
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
Packit 08bd4c
        return XXH32_update_endian(state_in, input, len, XXH_littleEndian);
Packit 08bd4c
    else
Packit 08bd4c
        return XXH32_update_endian(state_in, input, len, XXH_bigEndian);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
FORCE_INLINE U32 XXH32_intermediateDigest_endian (void* state_in, XXH_endianess endian)
Packit 08bd4c
{
Packit 08bd4c
    struct XXH_state32_t * state = (struct XXH_state32_t *) state_in;
Packit 08bd4c
    const BYTE * p = (const BYTE*)state->memory;
Packit 08bd4c
    BYTE* bEnd = (BYTE*)state->memory + state->memsize;
Packit 08bd4c
    U32 h32;
Packit 08bd4c
Packit 08bd4c
    if (state->total_len >= 16)
Packit 08bd4c
    {
Packit 08bd4c
        h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);
Packit 08bd4c
    }
Packit 08bd4c
    else
Packit 08bd4c
    {
Packit 08bd4c
        h32  = state->seed + PRIME32_5;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    h32 += (U32) state->total_len;
Packit 08bd4c
Packit 08bd4c
    while (p<=bEnd-4)
Packit 08bd4c
    {
Packit 08bd4c
        h32 += XXH_readLE32((const U32*)p, endian) * PRIME32_3;
Packit 08bd4c
        h32  = XXH_rotl32(h32, 17) * PRIME32_4;
Packit 08bd4c
        p+=4;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    while (p
Packit 08bd4c
    {
Packit 08bd4c
        h32 += (*p) * PRIME32_5;
Packit 08bd4c
        h32 = XXH_rotl32(h32, 11) * PRIME32_1;
Packit 08bd4c
        p++;
Packit 08bd4c
    }
Packit 08bd4c
Packit 08bd4c
    h32 ^= h32 >> 15;
Packit 08bd4c
    h32 *= PRIME32_2;
Packit 08bd4c
    h32 ^= h32 >> 13;
Packit 08bd4c
    h32 *= PRIME32_3;
Packit 08bd4c
    h32 ^= h32 >> 16;
Packit 08bd4c
Packit 08bd4c
    return h32;
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
U32 XXH32_intermediateDigest (void* state_in)
Packit 08bd4c
{
Packit 08bd4c
    XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
Packit 08bd4c
Packit 08bd4c
    if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)
Packit 08bd4c
        return XXH32_intermediateDigest_endian(state_in, XXH_littleEndian);
Packit 08bd4c
    else
Packit 08bd4c
        return XXH32_intermediateDigest_endian(state_in, XXH_bigEndian);
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
static
Packit 08bd4c
U32 XXH32_digest (void* state_in)
Packit 08bd4c
{
Packit 08bd4c
    U32 h32 = XXH32_intermediateDigest(state_in);
Packit 08bd4c
Packit 08bd4c
    XXH_free(state_in);
Packit 08bd4c
Packit 08bd4c
    return h32;
Packit 08bd4c
}
Packit 08bd4c
Packit 08bd4c
const
Packit 08bd4c
struct archive_xxhash __archive_xxhash = {
Packit 08bd4c
	XXH32,
Packit 08bd4c
	XXH32_init,
Packit 08bd4c
	XXH32_update,
Packit 08bd4c
	XXH32_digest
Packit 08bd4c
};
Packit 08bd4c
#else
Packit 08bd4c
Packit 08bd4c
/*
Packit 08bd4c
 * Define an empty version of the struct if we aren't using the LZ4 library.
Packit 08bd4c
 */
Packit 08bd4c
const
Packit 08bd4c
struct archive_xxhash __archive_xxhash = {
Packit 08bd4c
	NULL,
Packit 08bd4c
	NULL,
Packit 08bd4c
	NULL,
Packit 08bd4c
	NULL
Packit 08bd4c
};
Packit 08bd4c
Packit 08bd4c
#endif /* HAVE_LIBLZ4 */