Path: blob/main/sys/contrib/openzfs/module/zstd/lib/common/xxhash.c
48774 views
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only1/*2* xxHash - Fast Hash algorithm3* Copyright (c) 2012-2020, Yann Collet, Facebook, Inc.4*5* You can contact the author at :6* - xxHash homepage: http://www.xxhash.com7* - xxHash source repository : https://github.com/Cyan4973/xxHash8*9* This source code is licensed under both the BSD-style license (found in the10* LICENSE file in the root directory of this source tree) and the GPLv2 (found11* in the COPYING file in the root directory of this source tree).12* You may select, at your option, one of the above-listed licenses.13*/141516/* *************************************17* Tuning parameters18***************************************/19/*!XXH_FORCE_MEMORY_ACCESS :20* By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable.21* Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal.22* The below switch allow to select different access method for improved performance.23* Method 0 (default) : use `memcpy()`. Safe and portable.24* Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable).25* This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`.26* Method 2 : direct access. This method doesn't depend on compiler but violate C standard.27* It can generate buggy code on targets which do not support unaligned memory accesses.28* But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6)29* See http://stackoverflow.com/a/32095106/646947 for details.30* Prefer these methods in priority order (0 > 1 > 2)31*/32#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */33# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) )34# define XXH_FORCE_MEMORY_ACCESS 235# elif (defined(__INTEL_COMPILER) && !defined(WIN32)) || \36(defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) || \37defined(__ICCARM__)38# define XXH_FORCE_MEMORY_ACCESS 139# endif40#endif4142/*!XXH_ACCEPT_NULL_INPUT_POINTER :43* If the input pointer is a null pointer, xxHash default behavior is to trigger a memory access error, since it is a bad pointer.44* When this option is enabled, xxHash output for null input pointers will be the same as a null-length input.45* By default, this option is disabled. To enable it, uncomment below define :46*/47/* #define XXH_ACCEPT_NULL_INPUT_POINTER 1 */4849/*!XXH_FORCE_NATIVE_FORMAT :50* By default, xxHash library provides endian-independent Hash values, based on little-endian convention.51* Results are therefore identical for little-endian and big-endian CPU.52* This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format.53* Should endian-independence be of no importance for your application, you may set the #define below to 1,54* to improve speed for Big-endian CPU.55* This option has no impact on Little_Endian CPU.56*/57#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */58# define XXH_FORCE_NATIVE_FORMAT 059#endif6061/*!XXH_FORCE_ALIGN_CHECK :62* This is a minor performance trick, only useful with lots of very small keys.63* It means : check for aligned/unaligned input.64* The check costs one initial branch per hash; set to 0 when the input data65* is guaranteed to be aligned.66*/67#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */68# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)69# define XXH_FORCE_ALIGN_CHECK 070# else71# define XXH_FORCE_ALIGN_CHECK 172# endif73#endif747576/* *************************************77* Includes & Memory related functions78***************************************/79/* Modify the local functions below should you wish to use some other memory routines */80/* for malloc(), free() */81#include <stdlib.h>82#include <stddef.h> /* size_t */83static void* XXH_malloc(size_t s) { return malloc(s); }84static void XXH_free (void* p) { free(p); }85/* for memcpy() */86#include <string.h>87static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); }8889#ifndef XXH_STATIC_LINKING_ONLY90# define XXH_STATIC_LINKING_ONLY91#endif92#include "xxhash.h"939495/* *************************************96* Compiler Specific Options97***************************************/98#if (defined(__GNUC__) && !defined(__STRICT_ANSI__)) || defined(__cplusplus) || defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */99# define INLINE_KEYWORD inline100#else101# define INLINE_KEYWORD102#endif103104#if defined(__GNUC__) || defined(__ICCARM__)105# define FORCE_INLINE_ATTR __attribute__((always_inline))106#elif defined(_MSC_VER)107# define FORCE_INLINE_ATTR __forceinline108#else109# define FORCE_INLINE_ATTR110#endif111112#define FORCE_INLINE_TEMPLATE static INLINE_KEYWORD FORCE_INLINE_ATTR113114115#ifdef _MSC_VER116# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */117#endif118119120/* *************************************121* Basic Types122***************************************/123#ifndef MEM_MODULE124# define MEM_MODULE125# if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) )126# include <stdint.h>127typedef uint8_t BYTE;128typedef uint16_t U16;129typedef uint32_t U32;130typedef int32_t S32;131typedef uint64_t U64;132# else133typedef unsigned char BYTE;134typedef unsigned short U16;135typedef unsigned int U32;136typedef signed int S32;137typedef unsigned long long U64; /* if your compiler doesn't support unsigned long long, replace by another 64-bit type here. Note that xxhash.h will also need to be updated. */138# endif139#endif140141142#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))143144/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */145static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; }146static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; }147148#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))149150/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */151/* currently only defined for gcc and icc */152typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign;153154static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; }155static U64 XXH_read64(const void* ptr) { return ((const unalign*)ptr)->u64; }156157#else158159/* portable and safe solution. Generally efficient.160* see : http://stackoverflow.com/a/32095106/646947161*/162163static U32 XXH_read32(const void* memPtr)164{165U32 val;166memcpy(&val, memPtr, sizeof(val));167return val;168}169170static U64 XXH_read64(const void* memPtr)171{172U64 val;173memcpy(&val, memPtr, sizeof(val));174return val;175}176177#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */178179180/* ****************************************181* Compiler-specific Functions and Macros182******************************************/183#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)184185/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */186#if defined(_MSC_VER)187# define XXH_rotl32(x,r) _rotl(x,r)188# define XXH_rotl64(x,r) _rotl64(x,r)189#else190#if defined(__ICCARM__)191# include <intrinsics.h>192# define XXH_rotl32(x,r) __ROR(x,(32 - r))193#else194# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))195#endif196# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r)))197#endif198199#if defined(_MSC_VER) /* Visual Studio */200# define XXH_swap32 _byteswap_ulong201# define XXH_swap64 _byteswap_uint64202#elif GCC_VERSION >= 403203# define XXH_swap32 __builtin_bswap32204# define XXH_swap64 __builtin_bswap64205#else206static U32 XXH_swap32 (U32 x)207{208return ((x << 24) & 0xff000000 ) |209((x << 8) & 0x00ff0000 ) |210((x >> 8) & 0x0000ff00 ) |211((x >> 24) & 0x000000ff );212}213static U64 XXH_swap64 (U64 x)214{215return ((x << 56) & 0xff00000000000000ULL) |216((x << 40) & 0x00ff000000000000ULL) |217((x << 24) & 0x0000ff0000000000ULL) |218((x << 8) & 0x000000ff00000000ULL) |219((x >> 8) & 0x00000000ff000000ULL) |220((x >> 24) & 0x0000000000ff0000ULL) |221((x >> 40) & 0x000000000000ff00ULL) |222((x >> 56) & 0x00000000000000ffULL);223}224#endif225226227/* *************************************228* Architecture Macros229***************************************/230typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess;231232/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */233#ifndef XXH_CPU_LITTLE_ENDIAN234static const int g_one = 1;235# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one))236#endif237238239/* ***************************240* Memory reads241*****************************/242typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment;243244FORCE_INLINE_TEMPLATE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align)245{246if (align==XXH_unaligned)247return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr));248else249return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr);250}251252FORCE_INLINE_TEMPLATE U32 XXH_readLE32(const void* ptr, XXH_endianess endian)253{254return XXH_readLE32_align(ptr, endian, XXH_unaligned);255}256257static U32 XXH_readBE32(const void* ptr)258{259return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr);260}261262FORCE_INLINE_TEMPLATE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align)263{264if (align==XXH_unaligned)265return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr));266else267return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr);268}269270FORCE_INLINE_TEMPLATE U64 XXH_readLE64(const void* ptr, XXH_endianess endian)271{272return XXH_readLE64_align(ptr, endian, XXH_unaligned);273}274275static U64 XXH_readBE64(const void* ptr)276{277return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr);278}279280281/* *************************************282* Macros283***************************************/284#define XXH_STATIC_ASSERT(c) { enum { XXH_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */285286287/* *************************************288* Constants289***************************************/290static const U32 PRIME32_1 = 2654435761U;291static const U32 PRIME32_2 = 2246822519U;292static const U32 PRIME32_3 = 3266489917U;293static const U32 PRIME32_4 = 668265263U;294static const U32 PRIME32_5 = 374761393U;295296static const U64 PRIME64_1 = 11400714785074694791ULL;297static const U64 PRIME64_2 = 14029467366897019727ULL;298static const U64 PRIME64_3 = 1609587929392839161ULL;299static const U64 PRIME64_4 = 9650029242287828579ULL;300static const U64 PRIME64_5 = 2870177450012600261ULL;301302XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; }303304305/* **************************306* Utils307****************************/308XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dstState, const XXH32_state_t* restrict srcState)309{310memcpy(dstState, srcState, sizeof(*dstState));311}312313XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dstState, const XXH64_state_t* restrict srcState)314{315memcpy(dstState, srcState, sizeof(*dstState));316}317318319/* ***************************320* Simple Hash Functions321*****************************/322323static U32 XXH32_round(U32 seed, U32 input)324{325seed += input * PRIME32_2;326seed = XXH_rotl32(seed, 13);327seed *= PRIME32_1;328return seed;329}330331FORCE_INLINE_TEMPLATE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align)332{333const BYTE* p = (const BYTE*)input;334const BYTE* bEnd = p + len;335U32 h32;336#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align)337338#ifdef XXH_ACCEPT_NULL_INPUT_POINTER339if (p==NULL) {340len=0;341bEnd=p=(const BYTE*)(size_t)16;342}343#endif344345if (len>=16) {346const BYTE* const limit = bEnd - 16;347U32 v1 = seed + PRIME32_1 + PRIME32_2;348U32 v2 = seed + PRIME32_2;349U32 v3 = seed + 0;350U32 v4 = seed - PRIME32_1;351352do {353v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;354v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;355v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;356v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;357} while (p<=limit);358359h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);360} else {361h32 = seed + PRIME32_5;362}363364h32 += (U32) len;365366while (p+4<=bEnd) {367h32 += XXH_get32bits(p) * PRIME32_3;368h32 = XXH_rotl32(h32, 17) * PRIME32_4 ;369p+=4;370}371372while (p<bEnd) {373h32 += (*p) * PRIME32_5;374h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;375p++;376}377378h32 ^= h32 >> 15;379h32 *= PRIME32_2;380h32 ^= h32 >> 13;381h32 *= PRIME32_3;382h32 ^= h32 >> 16;383384return h32;385}386387388XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed)389{390#if 0391/* Simple version, good for code maintenance, but unfortunately slow for small inputs */392XXH32_CREATESTATE_STATIC(state);393XXH32_reset(state, seed);394XXH32_update(state, input, len);395return XXH32_digest(state);396#else397XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;398399if (XXH_FORCE_ALIGN_CHECK) {400if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */401if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)402return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);403else404return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);405} }406407if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)408return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);409else410return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);411#endif412}413414415static U64 XXH64_round(U64 acc, U64 input)416{417acc += input * PRIME64_2;418acc = XXH_rotl64(acc, 31);419acc *= PRIME64_1;420return acc;421}422423static U64 XXH64_mergeRound(U64 acc, U64 val)424{425val = XXH64_round(0, val);426acc ^= val;427acc = acc * PRIME64_1 + PRIME64_4;428return acc;429}430431FORCE_INLINE_TEMPLATE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align)432{433const BYTE* p = (const BYTE*)input;434const BYTE* const bEnd = p + len;435U64 h64;436#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align)437438#ifdef XXH_ACCEPT_NULL_INPUT_POINTER439if (p==NULL) {440len=0;441bEnd=p=(const BYTE*)(size_t)32;442}443#endif444445if (len>=32) {446const BYTE* const limit = bEnd - 32;447U64 v1 = seed + PRIME64_1 + PRIME64_2;448U64 v2 = seed + PRIME64_2;449U64 v3 = seed + 0;450U64 v4 = seed - PRIME64_1;451452do {453v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8;454v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8;455v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8;456v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8;457} while (p<=limit);458459h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);460h64 = XXH64_mergeRound(h64, v1);461h64 = XXH64_mergeRound(h64, v2);462h64 = XXH64_mergeRound(h64, v3);463h64 = XXH64_mergeRound(h64, v4);464465} else {466h64 = seed + PRIME64_5;467}468469h64 += (U64) len;470471while (p+8<=bEnd) {472U64 const k1 = XXH64_round(0, XXH_get64bits(p));473h64 ^= k1;474h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;475p+=8;476}477478if (p+4<=bEnd) {479h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1;480h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;481p+=4;482}483484while (p<bEnd) {485h64 ^= (*p) * PRIME64_5;486h64 = XXH_rotl64(h64, 11) * PRIME64_1;487p++;488}489490h64 ^= h64 >> 33;491h64 *= PRIME64_2;492h64 ^= h64 >> 29;493h64 *= PRIME64_3;494h64 ^= h64 >> 32;495496return h64;497}498499500XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed)501{502#if 0503/* Simple version, good for code maintenance, but unfortunately slow for small inputs */504XXH64_CREATESTATE_STATIC(state);505XXH64_reset(state, seed);506XXH64_update(state, input, len);507return XXH64_digest(state);508#else509XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;510511if (XXH_FORCE_ALIGN_CHECK) {512if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */513if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)514return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned);515else516return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned);517} }518519if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)520return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned);521else522return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned);523#endif524}525526527/* **************************************************528* Advanced Hash Functions529****************************************************/530531XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void)532{533return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t));534}535XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr)536{537XXH_free(statePtr);538return XXH_OK;539}540541XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)542{543return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));544}545XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr)546{547XXH_free(statePtr);548return XXH_OK;549}550551552/*** Hash feed ***/553554XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed)555{556XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */557memset(&state, 0, sizeof(state)-4); /* do not write into reserved, for future removal */558state.v1 = seed + PRIME32_1 + PRIME32_2;559state.v2 = seed + PRIME32_2;560state.v3 = seed + 0;561state.v4 = seed - PRIME32_1;562memcpy(statePtr, &state, sizeof(state));563return XXH_OK;564}565566567XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed)568{569XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */570memset(&state, 0, sizeof(state)-8); /* do not write into reserved, for future removal */571state.v1 = seed + PRIME64_1 + PRIME64_2;572state.v2 = seed + PRIME64_2;573state.v3 = seed + 0;574state.v4 = seed - PRIME64_1;575memcpy(statePtr, &state, sizeof(state));576return XXH_OK;577}578579580FORCE_INLINE_TEMPLATE XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian)581{582const BYTE* p = (const BYTE*)input;583const BYTE* const bEnd = p + len;584585#ifdef XXH_ACCEPT_NULL_INPUT_POINTER586if (input==NULL) return XXH_ERROR;587#endif588589state->total_len_32 += (unsigned)len;590state->large_len |= (len>=16) | (state->total_len_32>=16);591592if (state->memsize + len < 16) { /* fill in tmp buffer */593XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len);594state->memsize += (unsigned)len;595return XXH_OK;596}597598if (state->memsize) { /* some data left from previous update */599XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize);600{ const U32* p32 = state->mem32;601state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++;602state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++;603state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++;604state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); p32++;605}606p += 16-state->memsize;607state->memsize = 0;608}609610if (p <= bEnd-16) {611const BYTE* const limit = bEnd - 16;612U32 v1 = state->v1;613U32 v2 = state->v2;614U32 v3 = state->v3;615U32 v4 = state->v4;616617do {618v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4;619v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4;620v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4;621v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4;622} while (p<=limit);623624state->v1 = v1;625state->v2 = v2;626state->v3 = v3;627state->v4 = v4;628}629630if (p < bEnd) {631XXH_memcpy(state->mem32, p, (size_t)(bEnd-p));632state->memsize = (unsigned)(bEnd-p);633}634635return XXH_OK;636}637638XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len)639{640XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;641642if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)643return XXH32_update_endian(state_in, input, len, XXH_littleEndian);644else645return XXH32_update_endian(state_in, input, len, XXH_bigEndian);646}647648649650FORCE_INLINE_TEMPLATE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian)651{652const BYTE * p = (const BYTE*)state->mem32;653const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize;654U32 h32;655656if (state->large_len) {657h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18);658} else {659h32 = state->v3 /* == seed */ + PRIME32_5;660}661662h32 += state->total_len_32;663664while (p+4<=bEnd) {665h32 += XXH_readLE32(p, endian) * PRIME32_3;666h32 = XXH_rotl32(h32, 17) * PRIME32_4;667p+=4;668}669670while (p<bEnd) {671h32 += (*p) * PRIME32_5;672h32 = XXH_rotl32(h32, 11) * PRIME32_1;673p++;674}675676h32 ^= h32 >> 15;677h32 *= PRIME32_2;678h32 ^= h32 >> 13;679h32 *= PRIME32_3;680h32 ^= h32 >> 16;681682return h32;683}684685686XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in)687{688XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;689690if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)691return XXH32_digest_endian(state_in, XXH_littleEndian);692else693return XXH32_digest_endian(state_in, XXH_bigEndian);694}695696697698/* **** XXH64 **** */699700FORCE_INLINE_TEMPLATE XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian)701{702const BYTE* p = (const BYTE*)input;703const BYTE* const bEnd = p + len;704705#ifdef XXH_ACCEPT_NULL_INPUT_POINTER706if (input==NULL) return XXH_ERROR;707#endif708709state->total_len += len;710711if (state->memsize + len < 32) { /* fill in tmp buffer */712if (input != NULL) {713XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len);714}715state->memsize += (U32)len;716return XXH_OK;717}718719if (state->memsize) { /* tmp buffer is full */720XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize);721state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian));722state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian));723state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian));724state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian));725p += 32-state->memsize;726state->memsize = 0;727}728729if (p+32 <= bEnd) {730const BYTE* const limit = bEnd - 32;731U64 v1 = state->v1;732U64 v2 = state->v2;733U64 v3 = state->v3;734U64 v4 = state->v4;735736do {737v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8;738v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8;739v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8;740v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8;741} while (p<=limit);742743state->v1 = v1;744state->v2 = v2;745state->v3 = v3;746state->v4 = v4;747}748749if (p < bEnd) {750XXH_memcpy(state->mem64, p, (size_t)(bEnd-p));751state->memsize = (unsigned)(bEnd-p);752}753754return XXH_OK;755}756757XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len)758{759XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;760761if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)762return XXH64_update_endian(state_in, input, len, XXH_littleEndian);763else764return XXH64_update_endian(state_in, input, len, XXH_bigEndian);765}766767768769FORCE_INLINE_TEMPLATE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian)770{771const BYTE * p = (const BYTE*)state->mem64;772const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize;773U64 h64;774775if (state->total_len >= 32) {776U64 const v1 = state->v1;777U64 const v2 = state->v2;778U64 const v3 = state->v3;779U64 const v4 = state->v4;780781h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18);782h64 = XXH64_mergeRound(h64, v1);783h64 = XXH64_mergeRound(h64, v2);784h64 = XXH64_mergeRound(h64, v3);785h64 = XXH64_mergeRound(h64, v4);786} else {787h64 = state->v3 + PRIME64_5;788}789790h64 += (U64) state->total_len;791792while (p+8<=bEnd) {793U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian));794h64 ^= k1;795h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4;796p+=8;797}798799if (p+4<=bEnd) {800h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1;801h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3;802p+=4;803}804805while (p<bEnd) {806h64 ^= (*p) * PRIME64_5;807h64 = XXH_rotl64(h64, 11) * PRIME64_1;808p++;809}810811h64 ^= h64 >> 33;812h64 *= PRIME64_2;813h64 ^= h64 >> 29;814h64 *= PRIME64_3;815h64 ^= h64 >> 32;816817return h64;818}819820821XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in)822{823XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;824825if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT)826return XXH64_digest_endian(state_in, XXH_littleEndian);827else828return XXH64_digest_endian(state_in, XXH_bigEndian);829}830831832/* **************************833* Canonical representation834****************************/835836/*! Default XXH result types are basic unsigned 32 and 64 bits.837* The canonical representation follows human-readable write convention, aka big-endian (large digits first).838* These functions allow transformation of hash result into and from its canonical format.839* This way, hash values can be written into a file or buffer, and remain comparable across different systems and programs.840*/841842XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash)843{844XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t));845if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash);846memcpy(dst, &hash, sizeof(*dst));847}848849XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash)850{851XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t));852if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash);853memcpy(dst, &hash, sizeof(*dst));854}855856XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src)857{858return XXH_readBE32(src);859}860861XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src)862{863return XXH_readBE64(src);864}865866867