2014-08-15 09:27:04 +00:00
/*
xxHash - Extremely Fast Hash algorithm
Header File
2016-01-04 07:32:38 +00:00
Copyright ( C ) 2012 - 2016 , Yann Collet .
2014-12-09 18:16:15 +00:00
2014-08-15 09:27:04 +00:00
BSD 2 - Clause License ( http : //www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are
met :
* Redistributions of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
* Redistributions in binary form must reproduce the above
copyright notice , this list of conditions and the following disclaimer
in the documentation and / or other materials provided with the
distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
" AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
You can contact the author at :
2015-05-04 21:56:53 +00:00
- xxHash source repository : https : //github.com/Cyan4973/xxHash
2014-08-15 09:27:04 +00:00
*/
/* Notice extracted from xxHash homepage :
xxHash is an extremely fast Hash algorithm , running at RAM speed limits .
It also successfully passes all tests from the SMHasher suite .
Comparison ( single thread , Windows Seven 32 bits , using SMHasher on a Core 2 Duo @ 3 GHz )
Name Speed Q . Score Author
xxHash 5.4 GB / s 10
CrapWow 3.2 GB / s 2 Andrew
MumurHash 3 a 2.7 GB / s 10 Austin Appleby
SpookyHash 2.0 GB / s 10 Bob Jenkins
SBox 1.4 GB / s 9 Bret Mulvey
Lookup3 1.2 GB / s 9 Bob Jenkins
SuperFastHash 1.2 GB / s 1 Paul Hsieh
CityHash64 1.05 GB / s 10 Pike & Alakuijala
FNV 0.55 GB / s 5 Fowler , Noll , Vo
2019-10-24 22:57:00 +00:00
CRC32 0.43 GB / s 9
2014-08-15 09:27:04 +00:00
MD5 - 32 0.33 GB / s 10 Ronald L . Rivest
SHA1 - 32 0.28 GB / s 10
Q . Score is a measure of quality of the hash function .
It depends on successfully passing SMHasher test set .
10 is a perfect score .
2015-05-04 21:56:53 +00:00
2019-10-24 22:57:00 +00:00
Note : SMHasher ' s CRC32 implementation is not the fastest one .
Other speed - oriented implementations can be faster ,
especially in combination with PCLMUL instruction :
http : //fastcompression.blogspot.com/2019/03/presenting-xxh3.html?showComment=1552696407071#c3490092340461170735
2017-12-26 01:57:24 +00:00
A 64 - bit version , named XXH64 , is available since r35 .
It offers much better speed , but for 64 - bit applications only .
2015-05-04 21:56:53 +00:00
Name Speed on 64 bits Speed on 32 bits
XXH64 13.8 GB / s 1.9 GB / s
XXH32 6.8 GB / s 6.0 GB / s
2014-08-15 09:27:04 +00:00
*/
# if defined (__cplusplus)
extern " C " {
# endif
2016-01-03 22:56:13 +00:00
/* ****************************
2020-02-12 22:36:11 +00:00
* INLINE mode
2018-04-18 21:27:00 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2018-03-13 22:52:21 +00:00
/** XXH_INLINE_ALL (and XXH_PRIVATE_API)
2020-02-12 19:43:33 +00:00
* Implement requested xxhash functions directly in the unit .
* Inlining offers great performance improvement on small inputs ,
2019-07-26 19:00:13 +00:00
* and dramatic ones when length is expressed as a compile - time constant .
* See https : //fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html .
2020-02-12 19:43:33 +00:00
* It also removes all symbols from the public list .
2018-04-18 21:27:00 +00:00
* Methodology :
* # define XXH_INLINE_ALL
* # include " xxhash.h "
2020-02-12 19:43:33 +00:00
* Do not compile and link xxhash . o as a separate object ( not useful )
2018-04-18 21:27:00 +00:00
*/
2020-02-12 19:43:33 +00:00
# if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \
& & ! defined ( XXH_INLINE_ALL_31684351384 )
/* this section should be traversed only once */
# define XXH_INLINE_ALL_31684351384
/* give access to advanced API, required to compile implementations */
# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */
# define XXH_STATIC_LINKING_ONLY
/* make functions private */
# undef XXH_PUBLIC_API
2016-01-04 07:32:38 +00:00
# if defined(__GNUC__)
2016-08-10 05:00:29 +00:00
# define XXH_PUBLIC_API static __inline __attribute__((unused))
2016-01-04 07:32:38 +00:00
# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ )
# define XXH_PUBLIC_API static inline
# elif defined(_MSC_VER)
# define XXH_PUBLIC_API static __inline
# else
2020-02-12 19:43:33 +00:00
/* note : this version may generate warnings for unused static functions */
2017-10-09 19:26:59 +00:00
# define XXH_PUBLIC_API static
2016-01-04 07:32:38 +00:00
# endif
2020-02-12 19:43:33 +00:00
/* prefix all names, to avoid symbol duplicates with potential library */
# ifdef XXH_NAMESPACE
# error "XXH_INLINE_ALL with XXH_NAMESPACE is not supported"
# / * Note : Alternative is to #undef all symbols (it's a pretty large list).
* If doing nothing : it compiles , but functions are actually Not inlined .
* */
# endif
# define XXH_NAMESPACE XXH_INLINE_
/* some identifiers are not symbols,
* they must nonetheless be renamed to avoid double declaration
* Alternative : do not redeclare them ,
* which requires some # ifdef , and is more dispersed in the file
* while renaming can be achieved in a single place */
# define XXH_IPREF(Id) XXH_INLINE_ ## Id
# define XXH_OK XXH_IPREF(XXH_OK)
# define XXH_ERROR XXH_IPREF(XXH_ERROR)
# define XXH_errorcode XXH_IPREF(XXH_errorcode)
# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t)
# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t)
# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t)
# define XXH32_state_s XXH_IPREF(XXH32_state_s)
# define XXH32_state_t XXH_IPREF(XXH32_state_t)
# define XXH64_state_s XXH_IPREF(XXH64_state_s)
# define XXH64_state_t XXH_IPREF(XXH64_state_t)
# define XXH3_state_s XXH_IPREF(XXH3_state_s)
# define XXH3_state_t XXH_IPREF(XXH3_state_t)
# define XXH128_hash_t XXH_IPREF(XXH128_hash_t)
/* Ensure header is parsed again, even if it was previously included */
# undef XXHASH_H_5627135585666179
# undef XXHASH_H_STATIC_13879238742
# endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */
2020-02-12 22:36:11 +00:00
/* ****************************************************************
* Stable API
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-02-12 19:43:33 +00:00
# ifndef XXHASH_H_5627135585666179
# define XXHASH_H_5627135585666179 1
/* specific declaration modes for Windows */
# if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API)
2019-03-16 16:45:49 +00:00
# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT))
2019-02-12 21:15:58 +00:00
# ifdef XXH_EXPORT
# define XXH_PUBLIC_API __declspec(dllexport)
2019-03-16 16:45:49 +00:00
# elif XXH_IMPORT
2019-02-12 21:15:58 +00:00
# define XXH_PUBLIC_API __declspec(dllimport)
# endif
# else
# define XXH_PUBLIC_API /* do nothing */
# endif
2020-02-12 19:43:33 +00:00
# endif
2015-06-28 11:20:23 +00:00
2018-04-18 21:27:00 +00:00
/*! XXH_NAMESPACE, aka Namespace Emulation :
*
* If you want to include _and expose_ xxHash functions from within your own library ,
* but also want to avoid symbol collisions with other libraries which may also include xxHash ,
*
* you can use XXH_NAMESPACE , to automatically prefix any public symbol from xxhash library
* with the value of XXH_NAMESPACE ( therefore , avoid NULL and numeric values ) .
*
* Note that no change is required within the calling program as long as it includes ` xxhash . h ` :
* regular symbol name will be automatically translated by this header .
*/
2015-06-28 11:20:23 +00:00
# ifdef XXH_NAMESPACE
# define XXH_CAT(A,B) A##B
# define XXH_NAME2(A,B) XXH_CAT(A,B)
2016-01-04 05:49:41 +00:00
# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)
2016-08-10 22:53:10 +00:00
# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
2015-06-28 11:20:23 +00:00
# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
2016-06-24 10:19:16 +00:00
# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)
2016-07-10 10:56:59 +00:00
# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)
# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)
2016-08-10 22:53:10 +00:00
# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
2016-07-10 10:56:59 +00:00
# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)
2015-06-28 11:20:23 +00:00
# endif
2014-08-15 09:27:04 +00:00
2016-01-04 05:49:41 +00:00
/* *************************************
* Version
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-01-06 00:28:36 +00:00
# define XXH_VERSION_MAJOR 0
2019-03-11 22:09:27 +00:00
# define XXH_VERSION_MINOR 7
2019-09-28 00:55:33 +00:00
# define XXH_VERSION_RELEASE 2
2016-01-04 05:49:41 +00:00
# define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
2016-01-04 07:32:38 +00:00
XXH_PUBLIC_API unsigned XXH_versionNumber ( void ) ;
2016-01-04 05:49:41 +00:00
2019-11-05 05:17:07 +00:00
/* ****************************
* Definitions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <stddef.h> /* size_t */
typedef enum { XXH_OK = 0 , XXH_ERROR } XXH_errorcode ;
2016-08-10 22:53:10 +00:00
/*-**********************************************************************
2017-12-26 01:57:24 +00:00
* 32 - bit hash
2016-08-10 22:53:10 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-05-05 03:10:52 +00:00
# if !defined (__VMS) \
& & ( defined ( __cplusplus ) \
| | ( defined ( __STDC_VERSION__ ) & & ( __STDC_VERSION__ > = 199901L ) /* C99 */ ) )
# include <stdint.h>
typedef uint32_t XXH32_hash_t ;
# else
2019-10-06 23:14:12 +00:00
# include <limits.h>
# if UINT_MAX == 0xFFFFFFFFUL
typedef unsigned int XXH32_hash_t ;
# else
2019-10-07 08:00:50 +00:00
# if ULONG_MAX == 0xFFFFFFFFUL
typedef unsigned long XXH32_hash_t ;
# else
# error "unsupported platform : need a 32-bit type"
# endif
2019-10-06 23:14:12 +00:00
# endif
2019-05-05 03:10:52 +00:00
# endif
2014-08-15 09:27:04 +00:00
2016-08-10 22:53:10 +00:00
/*! XXH32() :
2017-12-26 01:57:24 +00:00
Calculate the 32 - bit hash of sequence " length " bytes stored at memory address " input " .
2014-09-25 16:30:15 +00:00
The memory between input & input + length must be valid ( allocated and read - accessible ) .
2014-08-15 09:27:04 +00:00
" seed " can be used to alter the result predictably .
2016-08-10 22:53:10 +00:00
Speed on Core 2 Duo @ 3 GHz ( single thread , SMHasher benchmark ) : 5.4 GB / s */
2019-10-06 23:14:12 +00:00
XXH_PUBLIC_API XXH32_hash_t XXH32 ( const void * input , size_t length , XXH32_hash_t seed ) ;
2014-08-15 09:27:04 +00:00
2019-12-04 00:44:41 +00:00
/******* Streaming *******/
2014-09-25 16:30:15 +00:00
2016-06-21 06:29:40 +00:00
/*
2019-10-02 21:31:14 +00:00
* Streaming functions generate the xxHash value from an incrememtal input .
* This method is slower than single - call functions , due to state management .
2018-04-18 21:27:00 +00:00
* For small inputs , prefer ` XXH32 ( ) ` and ` XXH64 ( ) ` , which are better optimized .
*
* XXH state must first be allocated , using XXH * _createState ( ) .
*
* Start a new hash by initializing state with a seed , using XXH * _reset ( ) .
*
* Then , feed the hash state by calling XXH * _update ( ) as many times as necessary .
* The function returns an error code , with 0 meaning OK , and any other value meaning there is an error .
*
* Finally , a hash value can be produced anytime , by using XXH * _digest ( ) .
* This function returns the nn - bits hash as an int or long long .
*
* It ' s still possible to continue inserting input into the hash state after a digest ,
2019-10-02 21:31:14 +00:00
* and generate some new hash values later on , by invoking again XXH * _digest ( ) .
2018-04-18 21:27:00 +00:00
*
2019-10-02 21:31:14 +00:00
* When done , release the state , using XXH * _freeState ( ) .
2018-04-18 21:27:00 +00:00
*/
2014-08-15 09:27:04 +00:00
2019-10-02 21:31:14 +00:00
typedef struct XXH32_state_s XXH32_state_t ; /* incomplete type */
XXH_PUBLIC_API XXH32_state_t * XXH32_createState ( void ) ;
XXH_PUBLIC_API XXH_errorcode XXH32_freeState ( XXH32_state_t * statePtr ) ;
XXH_PUBLIC_API void XXH32_copyState ( XXH32_state_t * dst_state , const XXH32_state_t * src_state ) ;
2019-10-06 23:14:12 +00:00
XXH_PUBLIC_API XXH_errorcode XXH32_reset ( XXH32_state_t * statePtr , XXH32_hash_t seed ) ;
2019-10-02 21:31:14 +00:00
XXH_PUBLIC_API XXH_errorcode XXH32_update ( XXH32_state_t * statePtr , const void * input , size_t length ) ;
XXH_PUBLIC_API XXH32_hash_t XXH32_digest ( const XXH32_state_t * statePtr ) ;
2019-12-04 00:44:41 +00:00
/******* Canonical representation *******/
2014-08-15 09:27:04 +00:00
2019-10-02 21:31:14 +00:00
/* Default return values from XXH functions are basic unsigned 32 and 64 bits.
* This the simplest and fastest format for further post - processing .
* However , this leaves open the question of what is the order of bytes ,
* since little and big endian conventions will write the same number differently .
*
* The canonical representation settles this issue ,
* by mandating big - endian convention ,
* aka , the same convention as human - readable numbers ( large digits first ) .
* When writing hash values to storage , sending them over a network , or printing them ,
* it ' s highly recommended to use the canonical representation ,
* to ensure portability across a wider range of systems , present and future .
*
* The following functions allow transformation of hash values into and from canonical format .
*/
2016-01-14 02:01:39 +00:00
typedef struct { unsigned char digest [ 4 ] ; } XXH32_canonical_t ;
XXH_PUBLIC_API void XXH32_canonicalFromHash ( XXH32_canonical_t * dst , XXH32_hash_t hash ) ;
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical ( const XXH32_canonical_t * src ) ;
2016-01-11 00:31:04 +00:00
2016-08-10 22:53:10 +00:00
# ifndef XXH_NO_LONG_LONG
/*-**********************************************************************
2017-12-26 01:57:24 +00:00
* 64 - bit hash
2016-08-10 22:53:10 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-05-05 03:10:52 +00:00
# if !defined (__VMS) \
& & ( defined ( __cplusplus ) \
| | ( defined ( __STDC_VERSION__ ) & & ( __STDC_VERSION__ > = 199901L ) /* C99 */ ) )
# include <stdint.h>
typedef uint64_t XXH64_hash_t ;
# else
2019-10-07 08:00:50 +00:00
/* the following type must have a width of 64-bit */
2019-05-05 03:10:52 +00:00
typedef unsigned long long XXH64_hash_t ;
# endif
2016-08-10 22:53:10 +00:00
/*! XXH64() :
2019-10-11 14:50:06 +00:00
* Returns the 64 - bit hash of sequence of length @ length stored at memory address @ input .
* @ seed can be used to alter the result predictably .
* This function runs faster on 64 - bit systems , but slower on 32 - bit systems ( see benchmark ) .
*/
2019-10-06 23:14:12 +00:00
XXH_PUBLIC_API XXH64_hash_t XXH64 ( const void * input , size_t length , XXH64_hash_t seed ) ;
2016-08-10 22:53:10 +00:00
2019-12-04 00:44:41 +00:00
/******* Streaming *******/
2016-08-10 22:53:10 +00:00
typedef struct XXH64_state_s XXH64_state_t ; /* incomplete type */
XXH_PUBLIC_API XXH64_state_t * XXH64_createState ( void ) ;
XXH_PUBLIC_API XXH_errorcode XXH64_freeState ( XXH64_state_t * statePtr ) ;
2016-09-02 04:29:02 +00:00
XXH_PUBLIC_API void XXH64_copyState ( XXH64_state_t * dst_state , const XXH64_state_t * src_state ) ;
2016-08-10 22:53:10 +00:00
2019-10-06 23:14:12 +00:00
XXH_PUBLIC_API XXH_errorcode XXH64_reset ( XXH64_state_t * statePtr , XXH64_hash_t seed ) ;
2016-08-10 22:53:10 +00:00
XXH_PUBLIC_API XXH_errorcode XXH64_update ( XXH64_state_t * statePtr , const void * input , size_t length ) ;
XXH_PUBLIC_API XXH64_hash_t XXH64_digest ( const XXH64_state_t * statePtr ) ;
2019-12-04 00:44:41 +00:00
/******* Canonical representation *******/
2016-08-10 22:53:10 +00:00
typedef struct { unsigned char digest [ 8 ] ; } XXH64_canonical_t ;
XXH_PUBLIC_API void XXH64_canonicalFromHash ( XXH64_canonical_t * dst , XXH64_hash_t hash ) ;
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical ( const XXH64_canonical_t * src ) ;
2019-02-26 21:45:56 +00:00
2016-08-10 22:53:10 +00:00
# endif /* XXH_NO_LONG_LONG */
2019-10-11 14:50:06 +00:00
# endif /* XXHASH_H_5627135585666179 */
2016-08-10 22:53:10 +00:00
2018-03-22 01:24:19 +00:00
2016-05-28 00:14:28 +00:00
2019-10-11 14:50:06 +00:00
# if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742)
# define XXHASH_H_STATIC_13879238742
2019-12-04 00:44:41 +00:00
/* ************************************************************************************************
2017-09-23 21:46:11 +00:00
This section contains declarations which are not guaranteed to remain stable .
2016-08-06 18:35:56 +00:00
They may change in future versions , becoming incompatible with a different version of the library .
2017-09-23 21:46:11 +00:00
These declarations should only be used with static linking .
Never use them in association with dynamic linking !
2019-12-04 00:44:41 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2016-06-06 12:22:56 +00:00
2018-04-18 21:27:00 +00:00
/* These definitions are only present to allow
2018-03-22 01:24:19 +00:00
* static allocation of XXH state , on stack or in a struct for example .
* Never * * ever * * use members directly . */
2016-11-17 18:50:04 +00:00
struct XXH32_state_s {
2019-02-26 21:45:56 +00:00
XXH32_hash_t total_len_32 ;
XXH32_hash_t large_len ;
XXH32_hash_t v1 ;
XXH32_hash_t v2 ;
XXH32_hash_t v3 ;
XXH32_hash_t v4 ;
XXH32_hash_t mem32 [ 4 ] ;
XXH32_hash_t memsize ;
XXH32_hash_t reserved ; /* never read nor write, might be removed in a future version */
2016-11-17 18:50:04 +00:00
} ; /* typedef'd to XXH32_state_t */
2019-10-11 14:50:06 +00:00
# ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */
2016-11-17 18:50:04 +00:00
struct XXH64_state_s {
2019-02-26 21:45:56 +00:00
XXH64_hash_t total_len ;
XXH64_hash_t v1 ;
XXH64_hash_t v2 ;
XXH64_hash_t v3 ;
XXH64_hash_t v4 ;
XXH64_hash_t mem64 [ 4 ] ;
XXH32_hash_t memsize ;
2019-09-06 23:05:44 +00:00
XXH32_hash_t reserved32 ; /* required for padding anyway */
XXH64_hash_t reserved64 ; /* never read nor write, might be removed in a future version */
2016-11-17 18:50:04 +00:00
} ; /* typedef'd to XXH64_state_t */
2018-03-22 01:24:19 +00:00
2016-05-28 00:14:28 +00:00
2019-03-11 22:09:27 +00:00
/*-**********************************************************************
* XXH3
* New experimental hash
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-03-13 19:14:21 +00:00
2019-12-04 00:44:41 +00:00
/* *********************************************
2019-03-13 19:14:21 +00:00
* XXH3 is a new hash algorithm ,
2019-07-26 19:28:28 +00:00
* featuring improved speed performance for both small and large inputs .
2019-06-12 17:35:20 +00:00
* See full speed analysis at : http : //fastcompression.blogspot.com/2019/03/presenting-xxh3.html
2019-03-13 19:14:21 +00:00
* In general , expect XXH3 to run about ~ 2 x faster on large inputs ,
2019-07-23 22:33:58 +00:00
* and > 3 x faster on small ones , though exact differences depend on platform .
2019-03-13 19:14:21 +00:00
*
* The algorithm is portable , will generate the same hash on all platforms .
* It benefits greatly from vectorization units , but does not require it .
*
* XXH3 offers 2 variants , _64bits and _128bits .
2019-03-14 20:08:38 +00:00
* When only 64 bits are needed , prefer calling the _64bits variant :
* it reduces the amount of mixing , resulting in faster speed on small inputs .
2019-06-12 17:35:20 +00:00
* It ' s also generally simpler to manipulate a scalar return type than a struct .
2019-03-13 19:14:21 +00:00
*
* The XXH3 algorithm is still considered experimental .
2019-06-12 17:35:20 +00:00
* Produced results can still change between versions .
2019-10-02 21:31:14 +00:00
* Results produced by v0 .7 . x are not comparable with results from v0 .7 . y .
2019-07-26 19:28:28 +00:00
* It ' s nonetheless possible to use XXH3 for ephemeral data ( local sessions ) ,
2019-10-02 21:31:14 +00:00
* but avoid storing values in long - term storage for later reads .
2019-03-13 19:14:21 +00:00
*
2019-07-26 19:28:28 +00:00
* The API supports one - shot hashing , streaming mode , and custom secrets .
2019-03-13 19:14:21 +00:00
*
* There are still a number of opened questions that community can influence during the experimental period .
* I ' m trying to list a few of them below , though don ' t consider this list as complete .
*
2019-07-23 22:49:54 +00:00
* - 128 - bits output type : currently defined as a structure of two 64 - bits fields .
2019-03-13 21:44:41 +00:00
* That ' s because 128 - bit values do not exist in C standard .
2019-03-13 19:14:21 +00:00
* Note that it means that , at byte level , result is not identical depending on endianess .
* However , at field level , they are identical on all platforms .
2019-07-26 19:28:28 +00:00
* The canonical representation solves the issue of identical byte - level representation across platforms ,
2019-03-13 19:14:21 +00:00
* which is necessary for serialization .
2019-10-02 21:31:14 +00:00
* Q1 : Would there be a better representation for a 128 - bit hash result ?
* Q2 : Are the names of the inner 64 - bit fields important ? Should they be changed ?
*
* - Prototype XXH128 ( ) : XXH128 ( ) uses the same arguments as XXH64 ( ) , for consistency .
* It means it maps to XXH3_128bits_withSeed ( ) .
* This variant is slightly slower than XXH3_128bits ( ) ,
* because the seed is now part of the algorithm , and can ' t be simplified .
* Is that a good idea ?
2019-03-13 19:14:21 +00:00
*
2019-10-02 21:31:14 +00:00
* - Seed type for XXH128 ( ) : currently , it ' s a single 64 - bit value , like the 64 - bit variant .
2019-03-13 21:44:41 +00:00
* It could be argued that it ' s more logical to offer a 128 - bit seed input parameter for a 128 - bit hash .
2019-07-23 22:49:54 +00:00
* But 128 - bit seed is more difficult to use , since it requires to pass a structure instead of a scalar value .
2019-07-26 19:28:28 +00:00
* Such a variant could either replace current one , or become an additional one .
2019-03-13 19:14:21 +00:00
* Farmhash , for example , offers both variants ( the 128 - bits seed variant is called ` doubleSeed ` ) .
2019-10-02 21:31:14 +00:00
* Follow up question : if both 64 - bit and 128 - bit seeds are allowed , which variant should be called XXH128 ?
2019-03-13 19:14:21 +00:00
*
2019-10-02 21:31:14 +00:00
* - Result for len = = 0 : Currently , the result of hashing a zero - length input is always ` 0 ` .
* It seems okay as a return value when using " default " secret and seed .
2019-06-12 17:35:20 +00:00
* But is it still fine to return ` 0 ` when secret or seed are non - default ?
2019-07-26 19:28:28 +00:00
* Are there use cases which could depend on generating a different hash result for zero - length input when the secret is different ?
2019-10-02 21:47:59 +00:00
*
* - Consistency ( 1 ) : Streaming XXH128 uses an XXH3 state , which is the same state as XXH3_64bits ( ) .
* It means a 128 bit streaming loop must invoke the following symbols :
* XXH3_createState ( ) , XXH3_128bits_reset ( ) , XXH3_128bits_update ( ) ( loop ) , XXH3_128bits_digest ( ) , XXH3_freeState ( ) .
* Is that consistent enough ?
*
* - Consistency ( 2 ) : The canonical representation of ` XXH3_64bits ` is provided by existing functions
* XXH64_canonicalFromHash ( ) , and reverse operation XXH64_hashFromCanonical ( ) .
* As a mirror , canonical functions for XXH128_hash_t results generated by ` XXH3_128bits `
* are XXH128_canonicalFromHash ( ) and XXH128_hashFromCanonical ( ) .
* Which means , ` XXH3 ` doesn ' t appear in the names , because canonical functions operate on a type ,
* independently of which algorithm was used to generate that type .
* Is that consistent enough ?
2019-03-13 19:14:21 +00:00
*/
2019-03-11 22:09:27 +00:00
# ifdef XXH_NAMESPACE
# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits)
2019-06-11 18:13:44 +00:00
# define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret)
2019-03-11 22:09:27 +00:00
# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed)
2019-06-13 22:56:41 +00:00
2019-07-20 00:28:09 +00:00
# define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState)
# define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState)
# define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState)
2019-06-13 23:19:51 +00:00
# define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset)
2019-06-14 01:22:46 +00:00
# define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed)
# define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret)
2019-06-13 23:19:51 +00:00
# define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update)
# define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest)
2019-03-11 22:09:27 +00:00
# endif
2019-03-14 20:08:38 +00:00
2019-06-11 23:40:56 +00:00
/* XXH3_64bits() :
2019-06-12 17:35:20 +00:00
* default 64 - bit variant , using default secret and default seed of 0.
2019-07-26 19:28:28 +00:00
* It ' s the fastest variant . */
2019-06-12 00:26:30 +00:00
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits ( const void * data , size_t len ) ;
2019-03-13 22:08:04 +00:00
2019-06-11 23:40:56 +00:00
/* XXH3_64bits_withSecret() :
* It ' s possible to provide any blob of bytes as a " secret " to generate the hash .
2019-06-12 00:26:30 +00:00
* This makes it more difficult for an external actor to prepare an intentional collision .
2019-06-17 21:16:52 +00:00
* The secret * must * be large enough ( > = XXH3_SECRET_SIZE_MIN ) .
2019-06-14 18:34:24 +00:00
* It should consist of random bytes .
2019-07-26 19:28:28 +00:00
* Avoid repeating same character , or sequences of bytes ,
* and especially avoid swathes of \ 0.
* Failure to respect these conditions will result in a poor quality hash .
2019-06-11 23:40:56 +00:00
*/
2019-06-17 21:16:52 +00:00
# define XXH3_SECRET_SIZE_MIN 136
2019-06-12 00:26:30 +00:00
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret ( const void * data , size_t len , const void * secret , size_t secretSize ) ;
2019-03-11 22:09:27 +00:00
2019-06-11 23:40:56 +00:00
/* XXH3_64bits_withSeed() :
* This variant generates on the fly a custom secret ,
* based on the default secret , altered using the ` seed ` value .
* While this operation is decently fast , note that it ' s not completely free .
* note : seed = = 0 produces same results as XXH3_64bits ( ) */
2019-06-12 00:26:30 +00:00
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed ( const void * data , size_t len , XXH64_hash_t seed ) ;
2019-03-11 22:09:27 +00:00
2019-05-05 03:10:52 +00:00
2019-06-13 22:56:41 +00:00
/* streaming 64-bit */
2019-05-05 03:10:52 +00:00
# if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11+ */
# include <stdalign.h>
2019-06-13 22:56:41 +00:00
# define XXH_ALIGN(n) alignas(n)
2019-05-05 03:10:52 +00:00
# elif defined(__GNUC__)
2019-06-13 22:56:41 +00:00
# define XXH_ALIGN(n) __attribute__ ((aligned(n)))
2019-05-05 03:10:52 +00:00
# elif defined(_MSC_VER)
2019-06-13 22:56:41 +00:00
# define XXH_ALIGN(n) __declspec(align(n))
2019-05-05 03:10:52 +00:00
# else
2019-06-13 22:56:41 +00:00
# define XXH_ALIGN(n) /* disabled */
2019-05-05 03:10:52 +00:00
# endif
typedef struct XXH3_state_s XXH3_state_t ;
2019-06-17 21:16:52 +00:00
# define XXH3_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */
# define XXH3_INTERNALBUFFER_SIZE 256
2019-05-05 03:10:52 +00:00
struct XXH3_state_s {
2019-06-13 22:56:41 +00:00
XXH_ALIGN ( 64 ) XXH64_hash_t acc [ 8 ] ;
2019-10-01 22:52:21 +00:00
XXH_ALIGN ( 64 ) unsigned char customSecret [ XXH3_SECRET_DEFAULT_SIZE ] ; /* used to store a custom secret generated from the seed. Makes state larger. Design might change */
XXH_ALIGN ( 64 ) unsigned char buffer [ XXH3_INTERNALBUFFER_SIZE ] ;
2019-05-05 03:10:52 +00:00
XXH32_hash_t bufferedSize ;
2019-06-14 01:22:46 +00:00
XXH32_hash_t nbStripesPerBlock ;
XXH32_hash_t nbStripesSoFar ;
2019-09-06 23:05:44 +00:00
XXH32_hash_t secretLimit ;
2019-05-05 03:10:52 +00:00
XXH32_hash_t reserved32 ;
2019-06-14 01:22:46 +00:00
XXH32_hash_t reserved32_2 ;
XXH64_hash_t totalLen ;
2019-05-05 03:10:52 +00:00
XXH64_hash_t seed ;
2019-06-14 01:22:46 +00:00
XXH64_hash_t reserved64 ;
2019-10-01 22:52:21 +00:00
const unsigned char * secret ; /* note : there is some padding after, due to alignment on 64 bytes */
2019-05-05 03:10:52 +00:00
} ; /* typedef'd to XXH3_state_t */
2019-06-14 18:34:24 +00:00
/* Streaming requires state maintenance.
* This operation costs memory and cpu .
* As a consequence , streaming is slower than one - shot hashing .
2019-07-23 22:33:58 +00:00
* For better performance , prefer using one - shot functions whenever possible . */
2019-06-14 18:34:24 +00:00
2019-07-23 23:12:13 +00:00
XXH_PUBLIC_API XXH3_state_t * XXH3_createState ( void ) ;
XXH_PUBLIC_API XXH_errorcode XXH3_freeState ( XXH3_state_t * statePtr ) ;
XXH_PUBLIC_API void XXH3_copyState ( XXH3_state_t * dst_state , const XXH3_state_t * src_state ) ;
2019-05-05 03:10:52 +00:00
2019-06-14 01:22:46 +00:00
/* XXH3_64bits_reset() :
* initialize with default parameters .
2019-07-23 22:33:58 +00:00
* result will be equivalent to ` XXH3_64bits ( ) ` . */
2019-06-14 01:22:46 +00:00
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset ( XXH3_state_t * statePtr ) ;
2019-06-14 18:34:24 +00:00
/* XXH3_64bits_reset_withSeed() :
* generate a custom secret from ` seed ` , and store it into state .
2019-07-23 22:33:58 +00:00
* digest will be equivalent to ` XXH3_64bits_withSeed ( ) ` . */
2019-06-14 01:22:46 +00:00
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed ( XXH3_state_t * statePtr , XXH64_hash_t seed ) ;
/* XXH3_64bits_reset_withSecret() :
* ` secret ` is referenced , and must outlive the hash streaming session .
2019-06-17 21:16:52 +00:00
* secretSize must be > = XXH3_SECRET_SIZE_MIN .
2019-06-14 01:22:46 +00:00
*/
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret ( XXH3_state_t * statePtr , const void * secret , size_t secretSize ) ;
2019-06-13 23:19:51 +00:00
XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update ( XXH3_state_t * statePtr , const void * input , size_t length ) ;
XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest ( const XXH3_state_t * statePtr ) ;
2019-05-05 03:10:52 +00:00
2019-06-13 22:56:41 +00:00
/* 128-bit */
2019-07-23 22:33:58 +00:00
# ifdef XXH_NAMESPACE
# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128)
# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits)
# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed)
# define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret)
# define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset)
# define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed)
# define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret)
# define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update)
# define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest)
2019-07-23 23:12:13 +00:00
# define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual)
# define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp)
# define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash)
# define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical)
2019-07-23 22:33:58 +00:00
# endif
2019-03-14 20:08:38 +00:00
typedef struct {
XXH64_hash_t low64 ;
XXH64_hash_t high64 ;
} XXH128_hash_t ;
2019-07-18 22:29:22 +00:00
XXH_PUBLIC_API XXH128_hash_t XXH128 ( const void * data , size_t len , XXH64_hash_t seed ) ;
2019-03-13 01:13:46 +00:00
XXH_PUBLIC_API XXH128_hash_t XXH3_128bits ( const void * data , size_t len ) ;
2019-06-11 18:13:44 +00:00
XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed ( const void * data , size_t len , XXH64_hash_t seed ) ; /* == XXH128() */
2019-07-18 22:29:22 +00:00
XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret ( const void * data , size_t len , const void * secret , size_t secretSize ) ;
2019-03-11 22:09:27 +00:00
2019-07-03 16:09:57 +00:00
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset ( XXH3_state_t * statePtr ) ;
2019-07-20 00:28:09 +00:00
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed ( XXH3_state_t * statePtr , XXH64_hash_t seed ) ;
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret ( XXH3_state_t * statePtr , const void * secret , size_t secretSize ) ;
XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update ( XXH3_state_t * statePtr , const void * input , size_t length ) ;
2019-07-03 16:09:57 +00:00
XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest ( const XXH3_state_t * statePtr ) ;
2019-03-11 22:09:27 +00:00
2019-05-05 03:10:52 +00:00
2019-10-02 21:31:14 +00:00
/* Note : for better performance, following functions can be inlined,
2019-07-26 19:00:13 +00:00
* using XXH_INLINE_ALL */
2019-07-23 01:39:47 +00:00
/* return : 1 is equal, 0 if different */
2019-07-23 22:33:58 +00:00
XXH_PUBLIC_API int XXH128_isEqual ( XXH128_hash_t h1 , XXH128_hash_t h2 ) ;
2019-07-23 01:39:47 +00:00
2019-07-23 23:12:13 +00:00
/* This comparator is compatible with stdlib's qsort().
2019-07-23 01:39:47 +00:00
* return : > 0 if * h128_1 > * h128_2
* < 0 if * h128_1 < * h128_2
* = 0 if * h128_1 = = * h128_2 */
2019-07-23 22:33:58 +00:00
XXH_PUBLIC_API int XXH128_cmp ( const void * h128_1 , const void * h128_2 ) ;
2019-07-23 01:39:47 +00:00
2019-12-04 00:44:41 +00:00
/******* Canonical representation *******/
2019-07-23 22:49:54 +00:00
typedef struct { unsigned char digest [ 16 ] ; } XXH128_canonical_t ;
XXH_PUBLIC_API void XXH128_canonicalFromHash ( XXH128_canonical_t * dst , XXH128_hash_t hash ) ;
XXH_PUBLIC_API XXH128_hash_t XXH128_hashFromCanonical ( const XXH128_canonical_t * src ) ;
2019-03-13 01:13:46 +00:00
# endif /* XXH_NO_LONG_LONG */
2019-03-11 22:09:27 +00:00
2019-11-04 23:53:35 +00:00
# if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)
# define XXH_IMPLEMENTATION
# endif
# endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */
2020-02-12 19:43:33 +00:00
/* ======================================================================== */
/* ======================================================================== */
/* ======================================================================== */
2019-03-11 22:09:27 +00:00
/*-**********************************************************************
2019-11-04 23:53:35 +00:00
* xxHash implementation
2020-02-12 19:43:33 +00:00
* - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2019-11-04 23:53:35 +00:00
* Functions implementation used to be hosted within xxhash . c .
* However , code inlining requires to place implementation in the header file .
* As a consequence , xxhash . c used to be included within xxhash . h .
* But some build systems don ' t like * . c inclusions .
* So the implementation is now directly integrated within xxhash . h .
* Another small advantage is that xxhash . c is no longer required in / includes .
2019-03-11 22:09:27 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-11-04 23:53:35 +00:00
# if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \
| | defined ( XXH_IMPLEMENTATION ) ) & & ! defined ( XXH_IMPLEM_13a8737387 )
# define XXH_IMPLEM_13a8737387
/* *************************************
* Tuning parameters
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!XXH_FORCE_MEMORY_ACCESS :
* By default , access to unaligned memory is controlled by ` memcpy ( ) ` , which is safe and portable .
* Unfortunately , on some target / compiler combinations , the generated assembly is sub - optimal .
* The below switch allow to select different access method for improved performance .
* Method 0 ( default ) : use ` memcpy ( ) ` . Safe and portable .
* Method 1 : ` __packed ` statement . It depends on compiler extension ( ie , not portable ) .
* This method is safe if your compiler supports it , and * generally * as fast or faster than ` memcpy ` .
* Method 2 : direct access . This method doesn ' t depend on compiler but violate C standard .
* It can generate buggy code on targets which do not support unaligned memory accesses .
* But in some circumstances , it ' s the only known way to get the most performance ( ie GCC + ARMv6 )
* See http : //stackoverflow.com/a/32095106/646947 for details.
* Prefer these methods in priority order ( 0 > 1 > 2 )
*/
# ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */
# if !defined(__clang__) && defined(__GNUC__) && defined(__ARM_FEATURE_UNALIGNED) && defined(__ARM_ARCH) && (__ARM_ARCH == 6)
# define XXH_FORCE_MEMORY_ACCESS 2
# elif !defined(__clang__) && ((defined(__INTEL_COMPILER) && !defined(_WIN32)) || \
( defined ( __GNUC__ ) & & ( defined ( __ARM_ARCH ) & & __ARM_ARCH > = 7 ) ) )
# define XXH_FORCE_MEMORY_ACCESS 1
# endif
2016-11-17 18:50:04 +00:00
# endif
2016-06-06 12:12:27 +00:00
2019-11-04 23:53:35 +00:00
/*!XXH_ACCEPT_NULL_INPUT_POINTER :
* If input pointer is NULL , xxHash default behavior is to dereference it , triggering a segfault .
* When this macro is enabled , xxHash actively checks input for null pointer .
* It it is , result for null input pointers is the same as a null - length input .
*/
# ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */
# define XXH_ACCEPT_NULL_INPUT_POINTER 0
# endif
/*!XXH_FORCE_ALIGN_CHECK :
* This is a minor performance trick , only useful with lots of very small keys .
* It means : check for aligned / unaligned input .
* The check costs one initial branch per hash ;
* set it to 0 when the input is guaranteed to be aligned ,
* or when alignment doesn ' t matter for performance .
*/
# ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */
# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)
# define XXH_FORCE_ALIGN_CHECK 0
# else
# define XXH_FORCE_ALIGN_CHECK 1
# endif
# endif
2020-02-11 16:52:09 +00:00
/*!XXH_NO_INLINE_HINTS :
* By default , xxHash tries to force the compiler to inline
* almost all internal functions .
* This can usually improve performance due to reduced jumping
* and improved constant folding , but significantly increases
* the size of the binary which might not be favorable .
*
* Additionally , sometimes the forced inlining can be detrimental
* to performance , depending on the architecture .
*
* XXH_NO_INLINE_HINTS marks all internal functions as static ,
* giving the compiler full control on whether to inline or not .
*
* When not optimizing ( - O0 ) , optimizing for size ( - Os , - Oz ) , or using
* - fno - inline with GCC or Clang , this will automatically be
* defined . */
# ifndef XXH_NO_INLINE_HINTS
# if defined(__OPTIMIZE_SIZE__) /* -Os, -Oz */ \
| | defined ( __NO_INLINE__ ) /* -O0, -fno-inline */
# define XXH_NO_INLINE_HINTS 1
# else
# define XXH_NO_INLINE_HINTS 0
# endif
# endif
2019-11-04 23:53:35 +00:00
/*!XXH_REROLL:
* Whether to reroll XXH32_finalize , and XXH64_finalize ,
* instead of using an unrolled jump table / if statement loop .
*
* This is automatically defined on - Os / - Oz on GCC and Clang . */
# ifndef XXH_REROLL
# if defined(__OPTIMIZE_SIZE__)
# define XXH_REROLL 1
# else
# define XXH_REROLL 0
# endif
# endif
/* *************************************
* Includes & Memory related functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*! Modify the local functions below should you wish to use some other memory routines
* for malloc ( ) , free ( ) */
# include <stdlib.h>
static void * XXH_malloc ( size_t s ) { return malloc ( s ) ; }
static void XXH_free ( void * p ) { free ( p ) ; }
/*! and for memcpy() */
# include <string.h>
static void * XXH_memcpy ( void * dest , const void * src , size_t size ) { return memcpy ( dest , src , size ) ; }
# include <limits.h> /* ULLONG_MAX */
/* *************************************
* Compiler Specific Options
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020-02-11 16:52:09 +00:00
# ifdef _MSC_VER /* Visual Studio warning fix */
2019-11-04 23:53:35 +00:00
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
2020-02-11 16:52:09 +00:00
# endif
# if XXH_NO_INLINE_HINTS /* disable inlining hints */
# define XXH_FORCE_INLINE static
# define XXH_NO_INLINE static
# elif defined(_MSC_VER) /* Visual Studio */
2019-11-04 23:53:35 +00:00
# define XXH_FORCE_INLINE static __forceinline
# define XXH_NO_INLINE static __declspec(noinline)
# else
# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */
# ifdef __GNUC__
# define XXH_FORCE_INLINE static inline __attribute__((always_inline))
# define XXH_NO_INLINE static __attribute__((noinline))
# else
# define XXH_FORCE_INLINE static inline
# define XXH_NO_INLINE static
# endif
# else
# define XXH_FORCE_INLINE static
# define XXH_NO_INLINE static
# endif /* __STDC_VERSION__ */
# endif
/* *************************************
* Debug
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* DEBUGLEVEL is expected to be defined externally,
* typically through compiler command line .
* Value must be a number . */
# ifndef DEBUGLEVEL
# define DEBUGLEVEL 0
# endif
# if (DEBUGLEVEL>=1)
# include <assert.h> /* note : can still be disabled with NDEBUG */
# define XXH_ASSERT(c) assert(c)
# else
# define XXH_ASSERT(c) ((void)0)
# endif
/* note : use after variable declarations */
# define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1 / (int)(!!(c)) }; }
/* *************************************
* Basic Types
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if !defined (__VMS) \
& & ( defined ( __cplusplus ) \
| | ( defined ( __STDC_VERSION__ ) & & ( __STDC_VERSION__ > = 199901L ) /* C99 */ ) )
# include <stdint.h>
typedef uint8_t xxh_u8 ;
# else
typedef unsigned char xxh_u8 ;
# endif
typedef XXH32_hash_t xxh_u32 ;
2019-12-04 00:44:41 +00:00
/* *** Memory access *** */
2019-11-04 23:53:35 +00:00
# if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
static xxh_u32 XXH_read32 ( const void * memPtr ) { return * ( const xxh_u32 * ) memPtr ; }
# elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
/* currently only defined for gcc and icc */
typedef union { xxh_u32 u32 ; } __attribute__ ( ( packed ) ) unalign ;
static xxh_u32 XXH_read32 ( const void * ptr ) { return ( ( const unalign * ) ptr ) - > u32 ; }
# else
/* portable and safe solution. Generally efficient.
* see : http : //stackoverflow.com/a/32095106/646947
*/
static xxh_u32 XXH_read32 ( const void * memPtr )
{
xxh_u32 val ;
memcpy ( & val , memPtr , sizeof ( val ) ) ;
return val ;
}
# endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
2019-12-04 00:44:41 +00:00
/* *** Endianess *** */
2019-11-04 23:53:35 +00:00
typedef enum { XXH_bigEndian = 0 , XXH_littleEndian = 1 } XXH_endianess ;
/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */
# ifndef XXH_CPU_LITTLE_ENDIAN
# if defined(_WIN32) /* Windows is always little endian */ \
| | defined ( __LITTLE_ENDIAN__ ) \
| | ( defined ( __BYTE_ORDER__ ) & & __BYTE_ORDER__ = = __ORDER_LITTLE_ENDIAN__ )
# define XXH_CPU_LITTLE_ENDIAN 1
# elif defined(__BIG_ENDIAN__) \
| | ( defined ( __BYTE_ORDER__ ) & & __BYTE_ORDER__ = = __ORDER_BIG_ENDIAN__ )
# define XXH_CPU_LITTLE_ENDIAN 0
# else
static int XXH_isLittleEndian ( void )
{
const union { xxh_u32 u ; xxh_u8 c [ 4 ] ; } one = { 1 } ; /* don't use static : performance detrimental */
return one . c [ 0 ] ;
}
# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
# endif
# endif
/* ****************************************
* Compiler - specific Functions and Macros
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
# ifndef __has_builtin
# define __has_builtin(x) 0
# endif
# if !defined(NO_CLANG_BUILTIN) && __has_builtin(__builtin_rotateleft32) && __has_builtin(__builtin_rotateleft64)
# define XXH_rotl32 __builtin_rotateleft32
# define XXH_rotl64 __builtin_rotateleft64
/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */
# elif defined(_MSC_VER)
# define XXH_rotl32(x,r) _rotl(x,r)
# define XXH_rotl64(x,r) _rotl64(x,r)
# else
# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r))))
# endif
# if defined(_MSC_VER) /* Visual Studio */
# define XXH_swap32 _byteswap_ulong
# elif XXH_GCC_VERSION >= 403
# define XXH_swap32 __builtin_bswap32
# else
static xxh_u32 XXH_swap32 ( xxh_u32 x )
{
return ( ( x < < 24 ) & 0xff000000 ) |
( ( x < < 8 ) & 0x00ff0000 ) |
( ( x > > 8 ) & 0x0000ff00 ) |
( ( x > > 24 ) & 0x000000ff ) ;
}
# endif
/* ***************************
* Memory reads
* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
typedef enum { XXH_aligned , XXH_unaligned } XXH_alignment ;
XXH_FORCE_INLINE xxh_u32 XXH_readLE32 ( const void * ptr )
{
return XXH_CPU_LITTLE_ENDIAN ? XXH_read32 ( ptr ) : XXH_swap32 ( XXH_read32 ( ptr ) ) ;
}
static xxh_u32 XXH_readBE32 ( const void * ptr )
{
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32 ( XXH_read32 ( ptr ) ) : XXH_read32 ( ptr ) ;
}
XXH_FORCE_INLINE xxh_u32
XXH_readLE32_align ( const void * ptr , XXH_alignment align )
{
if ( align = = XXH_unaligned ) {
return XXH_readLE32 ( ptr ) ;
} else {
return XXH_CPU_LITTLE_ENDIAN ? * ( const xxh_u32 * ) ptr : XXH_swap32 ( * ( const xxh_u32 * ) ptr ) ;
}
}
/* *************************************
* Misc
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
XXH_PUBLIC_API unsigned XXH_versionNumber ( void ) { return XXH_VERSION_NUMBER ; }
/* *******************************************************************
* 32 - bit hash functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const xxh_u32 PRIME32_1 = 0x9E3779B1U ; /* 0b10011110001101110111100110110001 */
static const xxh_u32 PRIME32_2 = 0x85EBCA77U ; /* 0b10000101111010111100101001110111 */
static const xxh_u32 PRIME32_3 = 0xC2B2AE3DU ; /* 0b11000010101100101010111000111101 */
static const xxh_u32 PRIME32_4 = 0x27D4EB2FU ; /* 0b00100111110101001110101100101111 */
static const xxh_u32 PRIME32_5 = 0x165667B1U ; /* 0b00010110010101100110011110110001 */
static xxh_u32 XXH32_round ( xxh_u32 acc , xxh_u32 input )
{
acc + = input * PRIME32_2 ;
acc = XXH_rotl32 ( acc , 13 ) ;
acc * = PRIME32_1 ;
# if defined(__GNUC__) && defined(__SSE4_1__) && !defined(XXH_ENABLE_AUTOVECTORIZE)
/* UGLY HACK:
* This inline assembly hack forces acc into a normal register . This is the
* only thing that prevents GCC and Clang from autovectorizing the XXH32 loop
* ( pragmas and attributes don ' t work for some resason ) without globally
* disabling SSE4 .1 .
*
* The reason we want to avoid vectorization is because despite working on
* 4 integers at a time , there are multiple factors slowing XXH32 down on
* SSE4 :
* - There ' s a ridiculous amount of lag from pmulld ( 10 cycles of latency on newer chips ! )
* making it slightly slower to multiply four integers at once compared to four
* integers independently . Even when pmulld was fastest , Sandy / Ivy Bridge , it is
* still not worth it to go into SSE just to multiply unless doing a long operation .
*
* - Four instructions are required to rotate ,
* movqda tmp , v // not required with VEX encoding
* pslld tmp , 13 // tmp <<= 13
* psrld v , 19 // x >>= 19
* por v , tmp // x |= tmp
* compared to one for scalar :
* roll v , 13 // reliably fast across the board
* shldl v , v , 13 // Sandy Bridge and later prefer this for some reason
*
* - Instruction level parallelism is actually more beneficial here because the
* SIMD actually serializes this operation : While v1 is rotating , v2 can load data ,
* while v3 can multiply . SSE forces them to operate together .
*
* How this hack works :
* __asm__ ( " " // Declare an assembly block but don't declare any instructions
* : // However, as an Input/Output Operand,
* " +r " // constrain a read/write operand (+) as a general purpose register (r).
* ( acc ) // and set acc as the operand
* ) ;
*
* Because of the ' r ' , the compiler has promised that seed will be in a
* general purpose register and the ' + ' says that it will be ' read / write ' ,
* so it has to assume it has changed . It is like volatile without all the
* loads and stores .
*
* Since the argument has to be in a normal register ( not an SSE register ) ,
* each time XXH32_round is called , it is impossible to vectorize . */
__asm__ ( " " : " +r " ( acc ) ) ;
# endif
return acc ;
}
/* mix all bits */
static xxh_u32 XXH32_avalanche ( xxh_u32 h32 )
{
h32 ^ = h32 > > 15 ;
h32 * = PRIME32_2 ;
h32 ^ = h32 > > 13 ;
h32 * = PRIME32_3 ;
h32 ^ = h32 > > 16 ;
return ( h32 ) ;
}
# define XXH_get32bits(p) XXH_readLE32_align(p, align)
static xxh_u32
XXH32_finalize ( xxh_u32 h32 , const xxh_u8 * ptr , size_t len , XXH_alignment align )
{
# define PROCESS1 \
h32 + = ( * ptr + + ) * PRIME32_5 ; \
h32 = XXH_rotl32 ( h32 , 11 ) * PRIME32_1 ;
# define PROCESS4 \
h32 + = XXH_get32bits ( ptr ) * PRIME32_3 ; \
ptr + = 4 ; \
h32 = XXH_rotl32 ( h32 , 17 ) * PRIME32_4 ;
/* Compact rerolled version */
if ( XXH_REROLL ) {
len & = 15 ;
while ( len > = 4 ) {
PROCESS4 ;
len - = 4 ;
}
while ( len > 0 ) {
PROCESS1 ;
- - len ;
}
return XXH32_avalanche ( h32 ) ;
} else {
switch ( len & 15 ) /* or switch(bEnd - p) */ {
case 12 : PROCESS4 ;
/* fallthrough */
case 8 : PROCESS4 ;
/* fallthrough */
case 4 : PROCESS4 ;
return XXH32_avalanche ( h32 ) ;
case 13 : PROCESS4 ;
/* fallthrough */
case 9 : PROCESS4 ;
/* fallthrough */
case 5 : PROCESS4 ;
PROCESS1 ;
return XXH32_avalanche ( h32 ) ;
case 14 : PROCESS4 ;
/* fallthrough */
case 10 : PROCESS4 ;
/* fallthrough */
case 6 : PROCESS4 ;
PROCESS1 ;
PROCESS1 ;
return XXH32_avalanche ( h32 ) ;
case 15 : PROCESS4 ;
/* fallthrough */
case 11 : PROCESS4 ;
/* fallthrough */
case 7 : PROCESS4 ;
/* fallthrough */
case 3 : PROCESS1 ;
/* fallthrough */
case 2 : PROCESS1 ;
/* fallthrough */
case 1 : PROCESS1 ;
/* fallthrough */
case 0 : return XXH32_avalanche ( h32 ) ;
}
XXH_ASSERT ( 0 ) ;
return h32 ; /* reaching this point is deemed impossible */
}
}
XXH_FORCE_INLINE xxh_u32
XXH32_endian_align ( const xxh_u8 * input , size_t len , xxh_u32 seed , XXH_alignment align )
{
const xxh_u8 * bEnd = input + len ;
xxh_u32 h32 ;
# if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
if ( input = = NULL ) {
len = 0 ;
bEnd = input = ( const xxh_u8 * ) ( size_t ) 16 ;
}
# endif
if ( len > = 16 ) {
const xxh_u8 * const limit = bEnd - 15 ;
xxh_u32 v1 = seed + PRIME32_1 + PRIME32_2 ;
xxh_u32 v2 = seed + PRIME32_2 ;
xxh_u32 v3 = seed + 0 ;
xxh_u32 v4 = seed - PRIME32_1 ;
do {
v1 = XXH32_round ( v1 , XXH_get32bits ( input ) ) ; input + = 4 ;
v2 = XXH32_round ( v2 , XXH_get32bits ( input ) ) ; input + = 4 ;
v3 = XXH32_round ( v3 , XXH_get32bits ( input ) ) ; input + = 4 ;
v4 = XXH32_round ( v4 , XXH_get32bits ( input ) ) ; input + = 4 ;
} while ( input < limit ) ;
h32 = XXH_rotl32 ( v1 , 1 ) + XXH_rotl32 ( v2 , 7 )
+ XXH_rotl32 ( v3 , 12 ) + XXH_rotl32 ( v4 , 18 ) ;
} else {
h32 = seed + PRIME32_5 ;
}
h32 + = ( xxh_u32 ) len ;
return XXH32_finalize ( h32 , input , len & 15 , align ) ;
}
XXH_PUBLIC_API XXH32_hash_t XXH32 ( const void * input , size_t len , XXH32_hash_t seed )
{
#if 0
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
XXH32_state_t state ;
XXH32_reset ( & state , seed ) ;
XXH32_update ( & state , ( const xxh_u8 * ) input , len ) ;
return XXH32_digest ( & state ) ;
# else
if ( XXH_FORCE_ALIGN_CHECK ) {
if ( ( ( ( size_t ) input ) & 3 ) = = 0 ) { /* Input is 4-bytes aligned, leverage the speed benefit */
return XXH32_endian_align ( ( const xxh_u8 * ) input , len , seed , XXH_aligned ) ;
} }
return XXH32_endian_align ( ( const xxh_u8 * ) input , len , seed , XXH_unaligned ) ;
# endif
}
2019-12-04 00:44:41 +00:00
/******* Hash streaming *******/
2019-11-04 23:53:35 +00:00
XXH_PUBLIC_API XXH32_state_t * XXH32_createState ( void )
{
return ( XXH32_state_t * ) XXH_malloc ( sizeof ( XXH32_state_t ) ) ;
}
XXH_PUBLIC_API XXH_errorcode XXH32_freeState ( XXH32_state_t * statePtr )
{
XXH_free ( statePtr ) ;
return XXH_OK ;
}
XXH_PUBLIC_API void XXH32_copyState ( XXH32_state_t * dstState , const XXH32_state_t * srcState )
{
memcpy ( dstState , srcState , sizeof ( * dstState ) ) ;
}
XXH_PUBLIC_API XXH_errorcode XXH32_reset ( XXH32_state_t * statePtr , XXH32_hash_t seed )
{
XXH32_state_t state ; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
memset ( & state , 0 , sizeof ( state ) ) ;
state . v1 = seed + PRIME32_1 + PRIME32_2 ;
state . v2 = seed + PRIME32_2 ;
state . v3 = seed + 0 ;
state . v4 = seed - PRIME32_1 ;
/* do not write into reserved, planned to be removed in a future version */
memcpy ( statePtr , & state , sizeof ( state ) - sizeof ( state . reserved ) ) ;
return XXH_OK ;
2014-08-15 09:27:04 +00:00
}
2019-11-04 23:53:35 +00:00
XXH_PUBLIC_API XXH_errorcode
XXH32_update ( XXH32_state_t * state , const void * input , size_t len )
{
if ( input = = NULL )
# if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
return XXH_OK ;
# else
return XXH_ERROR ;
2014-08-15 09:27:04 +00:00
# endif
2016-01-07 22:24:04 +00:00
2019-11-04 23:53:35 +00:00
{ const xxh_u8 * p = ( const xxh_u8 * ) input ;
const xxh_u8 * const bEnd = p + len ;
state - > total_len_32 + = ( XXH32_hash_t ) len ;
state - > large_len | = ( XXH32_hash_t ) ( ( len > = 16 ) | ( state - > total_len_32 > = 16 ) ) ;
if ( state - > memsize + len < 16 ) { /* fill in tmp buffer */
XXH_memcpy ( ( xxh_u8 * ) ( state - > mem32 ) + state - > memsize , input , len ) ;
state - > memsize + = ( XXH32_hash_t ) len ;
return XXH_OK ;
}
if ( state - > memsize ) { /* some data left from previous update */
XXH_memcpy ( ( xxh_u8 * ) ( state - > mem32 ) + state - > memsize , input , 16 - state - > memsize ) ;
{ const xxh_u32 * p32 = state - > mem32 ;
state - > v1 = XXH32_round ( state - > v1 , XXH_readLE32 ( p32 ) ) ; p32 + + ;
state - > v2 = XXH32_round ( state - > v2 , XXH_readLE32 ( p32 ) ) ; p32 + + ;
state - > v3 = XXH32_round ( state - > v3 , XXH_readLE32 ( p32 ) ) ; p32 + + ;
state - > v4 = XXH32_round ( state - > v4 , XXH_readLE32 ( p32 ) ) ;
}
p + = 16 - state - > memsize ;
state - > memsize = 0 ;
}
if ( p < = bEnd - 16 ) {
const xxh_u8 * const limit = bEnd - 16 ;
xxh_u32 v1 = state - > v1 ;
xxh_u32 v2 = state - > v2 ;
xxh_u32 v3 = state - > v3 ;
xxh_u32 v4 = state - > v4 ;
do {
v1 = XXH32_round ( v1 , XXH_readLE32 ( p ) ) ; p + = 4 ;
v2 = XXH32_round ( v2 , XXH_readLE32 ( p ) ) ; p + = 4 ;
v3 = XXH32_round ( v3 , XXH_readLE32 ( p ) ) ; p + = 4 ;
v4 = XXH32_round ( v4 , XXH_readLE32 ( p ) ) ; p + = 4 ;
} while ( p < = limit ) ;
state - > v1 = v1 ;
state - > v2 = v2 ;
state - > v3 = v3 ;
state - > v4 = v4 ;
}
if ( p < bEnd ) {
XXH_memcpy ( state - > mem32 , p , ( size_t ) ( bEnd - p ) ) ;
state - > memsize = ( unsigned ) ( bEnd - p ) ;
}
}
return XXH_OK ;
}
XXH_PUBLIC_API XXH32_hash_t XXH32_digest ( const XXH32_state_t * state )
{
xxh_u32 h32 ;
if ( state - > large_len ) {
h32 = XXH_rotl32 ( state - > v1 , 1 )
+ XXH_rotl32 ( state - > v2 , 7 )
+ XXH_rotl32 ( state - > v3 , 12 )
+ XXH_rotl32 ( state - > v4 , 18 ) ;
} else {
h32 = state - > v3 /* == seed */ + PRIME32_5 ;
}
h32 + = state - > total_len_32 ;
return XXH32_finalize ( h32 , ( const xxh_u8 * ) state - > mem32 , state - > memsize , XXH_aligned ) ;
}
2019-12-04 00:44:41 +00:00
/******* Canonical representation *******/
2019-11-04 23:53:35 +00:00
/*! Default XXH result types are basic unsigned 32 and 64 bits.
* The canonical representation follows human - readable write convention , aka big - endian ( large digits first ) .
* These functions allow transformation of hash result into and from its canonical format .
* This way , hash values can be written into a file or buffer , remaining comparable across different systems .
*/
XXH_PUBLIC_API void XXH32_canonicalFromHash ( XXH32_canonical_t * dst , XXH32_hash_t hash )
{
XXH_STATIC_ASSERT ( sizeof ( XXH32_canonical_t ) = = sizeof ( XXH32_hash_t ) ) ;
if ( XXH_CPU_LITTLE_ENDIAN ) hash = XXH_swap32 ( hash ) ;
memcpy ( dst , & hash , sizeof ( * dst ) ) ;
}
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical ( const XXH32_canonical_t * src )
{
return XXH_readBE32 ( src ) ;
}
# ifndef XXH_NO_LONG_LONG
/* *******************************************************************
* 64 - bit hash functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2019-12-04 00:44:41 +00:00
/******* Memory access *******/
2019-11-04 23:53:35 +00:00
typedef XXH64_hash_t xxh_u64 ;
/*! XXH_REROLL_XXH64:
* Whether to reroll the XXH64_finalize ( ) loop .
*
* Just like XXH32 , we can unroll the XXH64_finalize ( ) loop . This can be a performance gain
* on 64 - bit hosts , as only one jump is required .
*
* However , on 32 - bit hosts , because arithmetic needs to be done with two 32 - bit registers ,
* and 64 - bit arithmetic needs to be simulated , it isn ' t beneficial to unroll . The code becomes
* ridiculously large ( the largest function in the binary on i386 ! ) , and rerolling it saves
* anywhere from 3 kB to 20 kB . It is also slightly faster because it fits into cache better
* and is more likely to be inlined by the compiler .
*
* If XXH_REROLL is defined , this is ignored and the loop is always rerolled . */
# ifndef XXH_REROLL_XXH64
# if (defined(__ILP32__) || defined(_ILP32)) /* ILP32 is often defined on 32-bit GCC family */ \
| | ! ( defined ( __x86_64__ ) | | defined ( _M_X64 ) | | defined ( _M_AMD64 ) /* x86-64 */ \
| | defined ( _M_ARM64 ) | | defined ( __aarch64__ ) | | defined ( __arm64__ ) /* aarch64 */ \
| | defined ( __PPC64__ ) | | defined ( __PPC64LE__ ) | | defined ( __ppc64__ ) | | defined ( __powerpc64__ ) /* ppc64 */ \
| | defined ( __mips64__ ) | | defined ( __mips64 ) ) /* mips64 */ \
| | ( ! defined ( SIZE_MAX ) | | SIZE_MAX < ULLONG_MAX ) /* check limits */
# define XXH_REROLL_XXH64 1
# else
# define XXH_REROLL_XXH64 0
# endif
# endif /* !defined(XXH_REROLL_XXH64) */
# if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2))
/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */
static xxh_u64 XXH_read64 ( const void * memPtr ) { return * ( const xxh_u64 * ) memPtr ; }
# elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1))
/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */
/* currently only defined for gcc and icc */
typedef union { xxh_u32 u32 ; xxh_u64 u64 ; } __attribute__ ( ( packed ) ) unalign64 ;
static xxh_u64 XXH_read64 ( const void * ptr ) { return ( ( const unalign64 * ) ptr ) - > u64 ; }
# else
/* portable and safe solution. Generally efficient.
* see : http : //stackoverflow.com/a/32095106/646947
*/
static xxh_u64 XXH_read64 ( const void * memPtr )
{
xxh_u64 val ;
memcpy ( & val , memPtr , sizeof ( val ) ) ;
return val ;
}
# endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */
# if defined(_MSC_VER) /* Visual Studio */
# define XXH_swap64 _byteswap_uint64
# elif XXH_GCC_VERSION >= 403
# define XXH_swap64 __builtin_bswap64
# else
static xxh_u64 XXH_swap64 ( xxh_u64 x )
{
return ( ( x < < 56 ) & 0xff00000000000000ULL ) |
( ( x < < 40 ) & 0x00ff000000000000ULL ) |
( ( x < < 24 ) & 0x0000ff0000000000ULL ) |
( ( x < < 8 ) & 0x000000ff00000000ULL ) |
( ( x > > 8 ) & 0x00000000ff000000ULL ) |
( ( x > > 24 ) & 0x0000000000ff0000ULL ) |
( ( x > > 40 ) & 0x000000000000ff00ULL ) |
( ( x > > 56 ) & 0x00000000000000ffULL ) ;
}
# endif
XXH_FORCE_INLINE xxh_u64 XXH_readLE64 ( const void * ptr )
{
return XXH_CPU_LITTLE_ENDIAN ? XXH_read64 ( ptr ) : XXH_swap64 ( XXH_read64 ( ptr ) ) ;
}
static xxh_u64 XXH_readBE64 ( const void * ptr )
{
return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64 ( XXH_read64 ( ptr ) ) : XXH_read64 ( ptr ) ;
}
XXH_FORCE_INLINE xxh_u64
XXH_readLE64_align ( const void * ptr , XXH_alignment align )
{
if ( align = = XXH_unaligned )
return XXH_readLE64 ( ptr ) ;
else
return XXH_CPU_LITTLE_ENDIAN ? * ( const xxh_u64 * ) ptr : XXH_swap64 ( * ( const xxh_u64 * ) ptr ) ;
}
2019-12-04 00:44:41 +00:00
/******* xxh64 *******/
2019-11-04 23:53:35 +00:00
static const xxh_u64 PRIME64_1 = 0x9E3779B185EBCA87ULL ; /* 0b1001111000110111011110011011000110000101111010111100101010000111 */
static const xxh_u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL ; /* 0b1100001010110010101011100011110100100111110101001110101101001111 */
static const xxh_u64 PRIME64_3 = 0x165667B19E3779F9ULL ; /* 0b0001011001010110011001111011000110011110001101110111100111111001 */
static const xxh_u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL ; /* 0b1000010111101011110010100111011111000010101100101010111001100011 */
static const xxh_u64 PRIME64_5 = 0x27D4EB2F165667C5ULL ; /* 0b0010011111010100111010110010111100010110010101100110011111000101 */
static xxh_u64 XXH64_round ( xxh_u64 acc , xxh_u64 input )
{
acc + = input * PRIME64_2 ;
acc = XXH_rotl64 ( acc , 31 ) ;
acc * = PRIME64_1 ;
return acc ;
}
static xxh_u64 XXH64_mergeRound ( xxh_u64 acc , xxh_u64 val )
{
val = XXH64_round ( 0 , val ) ;
acc ^ = val ;
acc = acc * PRIME64_1 + PRIME64_4 ;
return acc ;
}
static xxh_u64 XXH64_avalanche ( xxh_u64 h64 )
{
h64 ^ = h64 > > 33 ;
h64 * = PRIME64_2 ;
h64 ^ = h64 > > 29 ;
h64 * = PRIME64_3 ;
h64 ^ = h64 > > 32 ;
return h64 ;
}
# define XXH_get64bits(p) XXH_readLE64_align(p, align)
static xxh_u64
XXH64_finalize ( xxh_u64 h64 , const xxh_u8 * ptr , size_t len , XXH_alignment align )
{
# define PROCESS1_64 \
h64 ^ = ( * ptr + + ) * PRIME64_5 ; \
h64 = XXH_rotl64 ( h64 , 11 ) * PRIME64_1 ;
# define PROCESS4_64 \
h64 ^ = ( xxh_u64 ) ( XXH_get32bits ( ptr ) ) * PRIME64_1 ; \
ptr + = 4 ; \
h64 = XXH_rotl64 ( h64 , 23 ) * PRIME64_2 + PRIME64_3 ;
# define PROCESS8_64 { \
xxh_u64 const k1 = XXH64_round ( 0 , XXH_get64bits ( ptr ) ) ; \
ptr + = 8 ; \
h64 ^ = k1 ; \
h64 = XXH_rotl64 ( h64 , 27 ) * PRIME64_1 + PRIME64_4 ; \
}
/* Rerolled version for 32-bit targets is faster and much smaller. */
if ( XXH_REROLL | | XXH_REROLL_XXH64 ) {
len & = 31 ;
while ( len > = 8 ) {
PROCESS8_64 ;
len - = 8 ;
}
if ( len > = 4 ) {
PROCESS4_64 ;
len - = 4 ;
}
while ( len > 0 ) {
PROCESS1_64 ;
- - len ;
}
return XXH64_avalanche ( h64 ) ;
} else {
switch ( len & 31 ) {
case 24 : PROCESS8_64 ;
/* fallthrough */
case 16 : PROCESS8_64 ;
/* fallthrough */
case 8 : PROCESS8_64 ;
return XXH64_avalanche ( h64 ) ;
case 28 : PROCESS8_64 ;
/* fallthrough */
case 20 : PROCESS8_64 ;
/* fallthrough */
case 12 : PROCESS8_64 ;
/* fallthrough */
case 4 : PROCESS4_64 ;
return XXH64_avalanche ( h64 ) ;
case 25 : PROCESS8_64 ;
/* fallthrough */
case 17 : PROCESS8_64 ;
/* fallthrough */
case 9 : PROCESS8_64 ;
PROCESS1_64 ;
return XXH64_avalanche ( h64 ) ;
case 29 : PROCESS8_64 ;
/* fallthrough */
case 21 : PROCESS8_64 ;
/* fallthrough */
case 13 : PROCESS8_64 ;
/* fallthrough */
case 5 : PROCESS4_64 ;
PROCESS1_64 ;
return XXH64_avalanche ( h64 ) ;
case 26 : PROCESS8_64 ;
/* fallthrough */
case 18 : PROCESS8_64 ;
/* fallthrough */
case 10 : PROCESS8_64 ;
PROCESS1_64 ;
PROCESS1_64 ;
return XXH64_avalanche ( h64 ) ;
case 30 : PROCESS8_64 ;
/* fallthrough */
case 22 : PROCESS8_64 ;
/* fallthrough */
case 14 : PROCESS8_64 ;
/* fallthrough */
case 6 : PROCESS4_64 ;
PROCESS1_64 ;
PROCESS1_64 ;
return XXH64_avalanche ( h64 ) ;
case 27 : PROCESS8_64 ;
/* fallthrough */
case 19 : PROCESS8_64 ;
/* fallthrough */
case 11 : PROCESS8_64 ;
PROCESS1_64 ;
PROCESS1_64 ;
PROCESS1_64 ;
return XXH64_avalanche ( h64 ) ;
case 31 : PROCESS8_64 ;
/* fallthrough */
case 23 : PROCESS8_64 ;
/* fallthrough */
case 15 : PROCESS8_64 ;
/* fallthrough */
case 7 : PROCESS4_64 ;
/* fallthrough */
case 3 : PROCESS1_64 ;
/* fallthrough */
case 2 : PROCESS1_64 ;
/* fallthrough */
case 1 : PROCESS1_64 ;
/* fallthrough */
case 0 : return XXH64_avalanche ( h64 ) ;
}
}
/* impossible to reach */
XXH_ASSERT ( 0 ) ;
return 0 ; /* unreachable, but some compilers complain without it */
}
XXH_FORCE_INLINE xxh_u64
XXH64_endian_align ( const xxh_u8 * input , size_t len , xxh_u64 seed , XXH_alignment align )
{
const xxh_u8 * bEnd = input + len ;
xxh_u64 h64 ;
# if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
if ( input = = NULL ) {
len = 0 ;
bEnd = input = ( const xxh_u8 * ) ( size_t ) 32 ;
}
# endif
if ( len > = 32 ) {
const xxh_u8 * const limit = bEnd - 32 ;
xxh_u64 v1 = seed + PRIME64_1 + PRIME64_2 ;
xxh_u64 v2 = seed + PRIME64_2 ;
xxh_u64 v3 = seed + 0 ;
xxh_u64 v4 = seed - PRIME64_1 ;
do {
v1 = XXH64_round ( v1 , XXH_get64bits ( input ) ) ; input + = 8 ;
v2 = XXH64_round ( v2 , XXH_get64bits ( input ) ) ; input + = 8 ;
v3 = XXH64_round ( v3 , XXH_get64bits ( input ) ) ; input + = 8 ;
v4 = XXH64_round ( v4 , XXH_get64bits ( input ) ) ; input + = 8 ;
} while ( input < = limit ) ;
h64 = XXH_rotl64 ( v1 , 1 ) + XXH_rotl64 ( v2 , 7 ) + XXH_rotl64 ( v3 , 12 ) + XXH_rotl64 ( v4 , 18 ) ;
h64 = XXH64_mergeRound ( h64 , v1 ) ;
h64 = XXH64_mergeRound ( h64 , v2 ) ;
h64 = XXH64_mergeRound ( h64 , v3 ) ;
h64 = XXH64_mergeRound ( h64 , v4 ) ;
} else {
h64 = seed + PRIME64_5 ;
}
h64 + = ( xxh_u64 ) len ;
return XXH64_finalize ( h64 , input , len , align ) ;
}
XXH_PUBLIC_API XXH64_hash_t XXH64 ( const void * input , size_t len , XXH64_hash_t seed )
{
#if 0
/* Simple version, good for code maintenance, but unfortunately slow for small inputs */
XXH64_state_t state ;
XXH64_reset ( & state , seed ) ;
XXH64_update ( & state , ( const xxh_u8 * ) input , len ) ;
return XXH64_digest ( & state ) ;
# else
if ( XXH_FORCE_ALIGN_CHECK ) {
if ( ( ( ( size_t ) input ) & 7 ) = = 0 ) { /* Input is aligned, let's leverage the speed advantage */
return XXH64_endian_align ( ( const xxh_u8 * ) input , len , seed , XXH_aligned ) ;
} }
return XXH64_endian_align ( ( const xxh_u8 * ) input , len , seed , XXH_unaligned ) ;
# endif
}
2019-12-04 00:44:41 +00:00
/******* Hash Streaming *******/
2019-11-04 23:53:35 +00:00
XXH_PUBLIC_API XXH64_state_t * XXH64_createState ( void )
{
return ( XXH64_state_t * ) XXH_malloc ( sizeof ( XXH64_state_t ) ) ;
}
XXH_PUBLIC_API XXH_errorcode XXH64_freeState ( XXH64_state_t * statePtr )
{
XXH_free ( statePtr ) ;
return XXH_OK ;
}
XXH_PUBLIC_API void XXH64_copyState ( XXH64_state_t * dstState , const XXH64_state_t * srcState )
{
memcpy ( dstState , srcState , sizeof ( * dstState ) ) ;
}
XXH_PUBLIC_API XXH_errorcode XXH64_reset ( XXH64_state_t * statePtr , XXH64_hash_t seed )
{
XXH64_state_t state ; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */
memset ( & state , 0 , sizeof ( state ) ) ;
state . v1 = seed + PRIME64_1 + PRIME64_2 ;
state . v2 = seed + PRIME64_2 ;
state . v3 = seed + 0 ;
state . v4 = seed - PRIME64_1 ;
/* do not write into reserved64, might be removed in a future version */
memcpy ( statePtr , & state , sizeof ( state ) - sizeof ( state . reserved64 ) ) ;
return XXH_OK ;
}
XXH_PUBLIC_API XXH_errorcode
XXH64_update ( XXH64_state_t * state , const void * input , size_t len )
{
if ( input = = NULL )
# if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1)
return XXH_OK ;
# else
return XXH_ERROR ;
# endif
{ const xxh_u8 * p = ( const xxh_u8 * ) input ;
const xxh_u8 * const bEnd = p + len ;
state - > total_len + = len ;
if ( state - > memsize + len < 32 ) { /* fill in tmp buffer */
XXH_memcpy ( ( ( xxh_u8 * ) state - > mem64 ) + state - > memsize , input , len ) ;
state - > memsize + = ( xxh_u32 ) len ;
return XXH_OK ;
}
if ( state - > memsize ) { /* tmp buffer is full */
XXH_memcpy ( ( ( xxh_u8 * ) state - > mem64 ) + state - > memsize , input , 32 - state - > memsize ) ;
state - > v1 = XXH64_round ( state - > v1 , XXH_readLE64 ( state - > mem64 + 0 ) ) ;
state - > v2 = XXH64_round ( state - > v2 , XXH_readLE64 ( state - > mem64 + 1 ) ) ;
state - > v3 = XXH64_round ( state - > v3 , XXH_readLE64 ( state - > mem64 + 2 ) ) ;
state - > v4 = XXH64_round ( state - > v4 , XXH_readLE64 ( state - > mem64 + 3 ) ) ;
p + = 32 - state - > memsize ;
state - > memsize = 0 ;
}
if ( p + 32 < = bEnd ) {
const xxh_u8 * const limit = bEnd - 32 ;
xxh_u64 v1 = state - > v1 ;
xxh_u64 v2 = state - > v2 ;
xxh_u64 v3 = state - > v3 ;
xxh_u64 v4 = state - > v4 ;
do {
v1 = XXH64_round ( v1 , XXH_readLE64 ( p ) ) ; p + = 8 ;
v2 = XXH64_round ( v2 , XXH_readLE64 ( p ) ) ; p + = 8 ;
v3 = XXH64_round ( v3 , XXH_readLE64 ( p ) ) ; p + = 8 ;
v4 = XXH64_round ( v4 , XXH_readLE64 ( p ) ) ; p + = 8 ;
} while ( p < = limit ) ;
state - > v1 = v1 ;
state - > v2 = v2 ;
state - > v3 = v3 ;
state - > v4 = v4 ;
}
if ( p < bEnd ) {
XXH_memcpy ( state - > mem64 , p , ( size_t ) ( bEnd - p ) ) ;
state - > memsize = ( unsigned ) ( bEnd - p ) ;
}
}
return XXH_OK ;
}
XXH_PUBLIC_API XXH64_hash_t XXH64_digest ( const XXH64_state_t * state )
{
xxh_u64 h64 ;
if ( state - > total_len > = 32 ) {
xxh_u64 const v1 = state - > v1 ;
xxh_u64 const v2 = state - > v2 ;
xxh_u64 const v3 = state - > v3 ;
xxh_u64 const v4 = state - > v4 ;
h64 = XXH_rotl64 ( v1 , 1 ) + XXH_rotl64 ( v2 , 7 ) + XXH_rotl64 ( v3 , 12 ) + XXH_rotl64 ( v4 , 18 ) ;
h64 = XXH64_mergeRound ( h64 , v1 ) ;
h64 = XXH64_mergeRound ( h64 , v2 ) ;
h64 = XXH64_mergeRound ( h64 , v3 ) ;
h64 = XXH64_mergeRound ( h64 , v4 ) ;
} else {
h64 = state - > v3 /*seed*/ + PRIME64_5 ;
}
h64 + = ( xxh_u64 ) state - > total_len ;
return XXH64_finalize ( h64 , ( const xxh_u8 * ) state - > mem64 , ( size_t ) state - > total_len , XXH_aligned ) ;
}
2019-12-04 00:44:41 +00:00
/******* Canonical representation *******/
2019-11-04 23:53:35 +00:00
XXH_PUBLIC_API void XXH64_canonicalFromHash ( XXH64_canonical_t * dst , XXH64_hash_t hash )
{
XXH_STATIC_ASSERT ( sizeof ( XXH64_canonical_t ) = = sizeof ( XXH64_hash_t ) ) ;
if ( XXH_CPU_LITTLE_ENDIAN ) hash = XXH_swap64 ( hash ) ;
memcpy ( dst , & hash , sizeof ( * dst ) ) ;
}
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical ( const XXH64_canonical_t * src )
{
return XXH_readBE64 ( src ) ;
}
/* *********************************************************************
* XXH3
* New generation hash designed for speed on small keys and vectorization
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "xxh3.h"
# endif /* XXH_NO_LONG_LONG */
# endif /* XXH_IMPLEMENTATION */
# if defined (__cplusplus)
}
# endif