├── test └── test.lua ├── rockspecs ├── xxhash-scm-1.rockspec └── xxhash-1.0.0-1.rockspec ├── README.md ├── LICENSE └── src ├── xxhash_bind.c ├── xxhash.h └── xxhash.c /test/test.lua: -------------------------------------------------------------------------------- 1 | local xxhash = require('xxhash'); 2 | 3 | local max = 100;--0x1fffff; 4 | local seed = 0x5bd1e995; 5 | local key,idx; 6 | 7 | for i = 0, 10, 1 do 8 | key = 'test' .. i; 9 | idx = xxhash.xxh32( key, seed ); 10 | print( key, '->', idx, '->', idx % max ); 11 | end 12 | 13 | local xh = xxhash.init( seed ); 14 | print( xh ); 15 | 16 | key = 'test10'; 17 | xh:update( key ); 18 | idx = xh:digest(); 19 | print( key, '->', idx, '->', idx % max ); 20 | 21 | 22 | -------------------------------------------------------------------------------- /rockspecs/xxhash-scm-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "xxhash" 2 | version = "scm-1" 3 | source = { 4 | url = "git://github.com/mah0x211/lua-xxhash.git" 5 | } 6 | description = { 7 | summary = "xxhash binding", 8 | homepage = "https://github.com/mah0x211/lua-xxhash", 9 | license = "MIT/X11", 10 | maintainer = "Masatoshi Teruya" 11 | } 12 | dependencies = { 13 | "lua >= 5.1" 14 | } 15 | build = { 16 | type = "builtin", 17 | modules = { 18 | xxhash = { 19 | sources = { 20 | "src/xxhash_bind.c", 21 | "src/xxhash.c" 22 | } 23 | } 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /rockspecs/xxhash-1.0.0-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "xxhash" 2 | version = "1.0.0-1" 3 | source = { 4 | url = "git://github.com/mah0x211/lua-xxhash.git", 5 | tag = "v1.0.0" 6 | } 7 | description = { 8 | summary = "xxhash binding", 9 | homepage = "https://github.com/mah0x211/lua-xxhash", 10 | license = "MIT/X11", 11 | maintainer = "Masatoshi Teruya" 12 | } 13 | dependencies = { 14 | "lua >= 5.1" 15 | } 16 | build = { 17 | type = "builtin", 18 | modules = { 19 | xxhash = { 20 | sources = { 21 | "src/xxhash_bind.c", 22 | "src/xxhash.c" 23 | } 24 | } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | lua-xxhash 2 | ========= 3 | 4 | xxHash binding 5 | 6 | --- 7 | 8 | ## Installation 9 | 10 | ```sh 11 | luarocks install xxhash --from=http://mah0x211.github.io/rocks/ 12 | ``` 13 | 14 | ## Functional Interface 15 | 16 | - `val:int = xxhash.xxh32( data:string, seed:uint )` 17 | 18 | ### Usage 19 | 20 | ```lua 21 | local xxhash = require('xxhash'); 22 | local res = xxhash.xxh32( 'abc', 0x5bd1e995 ); 23 | print(res); -- 3185488385 24 | ``` 25 | 26 | ## OO Interface 27 | 28 | - `xh:table = xxhash.init( seed:uint )` 29 | - `xh:update( data:string )` 30 | - `res:uint = xh:digest()` 31 | - `xh:reset( [seed:uint] )` 32 | 33 | ### Usage 34 | 35 | ```lua 36 | local xxhash = require('xxhash'); 37 | local xh = xxhash.init( 0x5bd1e995 ); 38 | local res; 39 | 40 | print( xh ); -- 'xxhash: 0x7f95c8d003a8' 41 | 42 | xh:update('abc'); 43 | res = xh:digest(); 44 | print( res ); -- 3185488385 45 | 46 | xh:reset(); 47 | 48 | xh:update('a'); 49 | xh:update('bc'); 50 | res = xh:digest(); 51 | print( res ); -- 3185488385 52 | ``` 53 | 54 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Created by Masatoshi Teruya on 13/05/24. 2 | 3 | Copyright (C) 2013 Masatoshi Teruya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | 24 | 25 | - xxHash, located at xxhash.*. xxHash's License follows: 26 | """ 27 | Copyright (C) 2012-2013, Yann Collet. 28 | BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 29 | 30 | Redistribution and use in source and binary forms, with or without 31 | modification, are permitted provided that the following conditions are 32 | met: 33 | 34 | * Redistributions of source code must retain the above copyright notice, 35 | this list of conditions and the following disclaimer. 36 | * Redistributions in binary form must reproduce the above copyright 37 | notice, this list of conditions and the following disclaimer in the 38 | documentation and/or other materials provided with the distribution. 39 | 40 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 | 52 | You can contact the author at : 53 | - xxHash source repository : http://code.google.com/p/xxhash/ 54 | """ 55 | -------------------------------------------------------------------------------- /src/xxhash_bind.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Masatoshi Teruya 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to deal 6 | * in the Software without restriction, including without limitation the rights 7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | * copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | * THE SOFTWARE. 21 | */ 22 | /* 23 | * xxhash_bind.c 24 | * Created by Masatoshi Teruya on 13/05/24. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "xxhash.h" 32 | 33 | // helper macros 34 | #define lstate_fn2tbl(L,k,v) do{ \ 35 | lua_pushstring(L,k); \ 36 | lua_pushcfunction(L,v); \ 37 | lua_rawset(L,-3); \ 38 | }while(0) 39 | 40 | #define XXHASH_LUA "xxhash" 41 | 42 | 43 | typedef struct { 44 | void *state; 45 | unsigned int seed; 46 | } xxhash_t; 47 | 48 | 49 | static int xxh32_lua( lua_State *L ) 50 | { 51 | size_t len = 0; 52 | const char *data = luaL_checklstring( L, 1, &len ); 53 | unsigned int seed = luaL_checkinteger( L, 2 ); 54 | unsigned int hash = XXH32( data, len, seed ); 55 | 56 | lua_pushinteger( L, hash ); 57 | 58 | return 1; 59 | } 60 | 61 | static int init_lua( lua_State *L ) 62 | { 63 | unsigned int seed = luaL_checkinteger( L, 1 ); 64 | xxhash_t *xh = lua_newuserdata( L, sizeof( xxhash_t ) ); 65 | 66 | if( !xh ){ 67 | return luaL_error( L, "failed to init(): %s", lua_tostring( L, -1 ) ); 68 | } 69 | xh->seed = seed; 70 | xh->state = XXH32_init( seed ); 71 | luaL_getmetatable( L, XXHASH_LUA ); 72 | lua_setmetatable( L, -2 ); 73 | 74 | return 1; 75 | } 76 | 77 | static int update_lua( lua_State *L ) 78 | { 79 | xxhash_t *xh = luaL_checkudata( L, 1, XXHASH_LUA ); 80 | size_t len = 0; 81 | const char *data = luaL_checklstring( L, 2, &len ); 82 | 83 | XXH32_update( xh->state, data, len ); 84 | 85 | return 0; 86 | } 87 | 88 | static int digest_lua( lua_State *L ) 89 | { 90 | xxhash_t *xh = luaL_checkudata( L, 1, XXHASH_LUA ); 91 | // XXX: must not use XXH32_digest because GC will deallocate state. 92 | unsigned int hash = XXH32_intermediateDigest( xh->state ); 93 | 94 | lua_pushinteger( L, hash ); 95 | 96 | return 1; 97 | } 98 | 99 | static int reset_lua( lua_State *L ) 100 | { 101 | xxhash_t *xh = luaL_checkudata( L, 1, XXHASH_LUA ); 102 | 103 | if( lua_gettop( L ) > 1 ){ 104 | xh->seed = luaL_checkinteger( L, 2 ); 105 | } 106 | 107 | XXH32_resetState( xh->state, xh->seed ); 108 | 109 | return 0; 110 | } 111 | 112 | static int tostring_lua( lua_State *L ) 113 | { 114 | lua_pushfstring( L, XXHASH_LUA ": %p", lua_touserdata( L, 1 ) ); 115 | return 1; 116 | } 117 | 118 | static int gc_lua( lua_State *L ) 119 | { 120 | xxhash_t *xh = lua_touserdata( L, 1 ); 121 | 122 | free( xh->state ); 123 | 124 | return 0; 125 | } 126 | 127 | 128 | LUALIB_API int luaopen_xxhash( lua_State *L ) 129 | { 130 | struct luaL_Reg mmethod[] = { 131 | { "__gc", gc_lua }, 132 | { "__tostring", tostring_lua }, 133 | { NULL, NULL } 134 | }; 135 | struct luaL_Reg method[] = { 136 | { "update", update_lua }, 137 | { "digest", digest_lua }, 138 | { "reset", reset_lua }, 139 | { NULL, NULL } 140 | }; 141 | struct luaL_Reg funcs[] = { 142 | { "xxh32", xxh32_lua }, 143 | { "init", init_lua }, 144 | { NULL, NULL } 145 | }; 146 | struct luaL_Reg *ptr = NULL; 147 | 148 | // create metatable 149 | luaL_newmetatable( L, XXHASH_LUA ); 150 | // add metamethod 151 | ptr = mmethod; 152 | do { 153 | lstate_fn2tbl( L, ptr->name, ptr->func ); 154 | ptr++; 155 | } while( ptr->name ); 156 | // add method 157 | lua_pushstring( L, "__index" ); 158 | lua_newtable( L ); 159 | ptr = method; 160 | do { 161 | lstate_fn2tbl( L, ptr->name, ptr->func ); 162 | ptr++; 163 | } while( ptr->name ); 164 | lua_rawset( L, -3 ); 165 | // remove metatable 166 | lua_pop( L, 1 ); 167 | 168 | // add functions into module table 169 | lua_newtable( L ); 170 | ptr = funcs; 171 | do { 172 | lstate_fn2tbl( L, ptr->name, ptr->func ); 173 | ptr++; 174 | }while( ptr->name ); 175 | 176 | return 1; 177 | } 178 | 179 | -------------------------------------------------------------------------------- /src/xxhash.h: -------------------------------------------------------------------------------- 1 | /* 2 | xxHash - Fast Hash algorithm 3 | Header File 4 | Copyright (C) 2012-2013, Yann Collet. 5 | BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions are 9 | met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the following disclaimer 15 | in the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | You can contact the author at : 31 | - xxHash source repository : http://code.google.com/p/xxhash/ 32 | */ 33 | 34 | /* Notice extracted from xxHash homepage : 35 | 36 | xxHash is an extremely fast Hash algorithm, running at RAM speed limits. 37 | It also successfully passes all tests from the SMHasher suite. 38 | 39 | Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) 40 | 41 | Name Speed Q.Score Author 42 | xxHash 5.4 GB/s 10 43 | CrapWow 3.2 GB/s 2 Andrew 44 | MumurHash 3a 2.7 GB/s 10 Austin Appleby 45 | SpookyHash 2.0 GB/s 10 Bob Jenkins 46 | SBox 1.4 GB/s 9 Bret Mulvey 47 | Lookup3 1.2 GB/s 9 Bob Jenkins 48 | SuperFastHash 1.2 GB/s 1 Paul Hsieh 49 | CityHash64 1.05 GB/s 10 Pike & Alakuijala 50 | FNV 0.55 GB/s 5 Fowler, Noll, Vo 51 | CRC32 0.43 GB/s 9 52 | MD5-32 0.33 GB/s 10 Ronald L. Rivest 53 | SHA1-32 0.28 GB/s 10 54 | 55 | Q.Score is a measure of quality of the hash function. 56 | It depends on successfully passing SMHasher test set. 57 | 10 is a perfect score. 58 | */ 59 | 60 | #pragma once 61 | 62 | #if defined (__cplusplus) 63 | extern "C" { 64 | #endif 65 | 66 | 67 | //**************************** 68 | // Type 69 | //**************************** 70 | typedef enum { OK=0, XXH_ERROR } XXH_errorcode; 71 | 72 | 73 | 74 | //**************************** 75 | // Simple Hash Functions 76 | //**************************** 77 | 78 | unsigned int XXH32 (const void* input, int len, unsigned int seed); 79 | 80 | /* 81 | XXH32() : 82 | Calculate the 32-bits hash of sequence of length "len" stored at memory address "input". 83 | The memory between input & input+len must be valid (allocated and read-accessible). 84 | "seed" can be used to alter the result predictably. 85 | This function successfully passes all SMHasher tests. 86 | Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s 87 | Note that "len" is type "int", which means it is limited to 2^31-1. 88 | If your data is larger, use the advanced functions below. 89 | */ 90 | 91 | 92 | 93 | //**************************** 94 | // Advanced Hash Functions 95 | //**************************** 96 | 97 | void* XXH32_init (unsigned int seed); 98 | XXH_errorcode XXH32_update (void* state, const void* input, int len); 99 | unsigned int XXH32_digest (void* state); 100 | 101 | /* 102 | These functions calculate the xxhash of an input provided in several small packets, 103 | as opposed to an input provided as a single block. 104 | 105 | It must be started with : 106 | void* XXH32_init() 107 | The function returns a pointer which holds the state of calculation. 108 | 109 | This pointer must be provided as "void* state" parameter for XXH32_update(). 110 | XXH32_update() can be called as many times as necessary. 111 | The user must provide a valid (allocated) input. 112 | The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. 113 | Note that "len" is type "int", which means it is limited to 2^31-1. 114 | If your data is larger, it is recommended to chunk your data into blocks 115 | of size for example 2^30 (1GB) to avoid any "int" overflow issue. 116 | 117 | Finally, you can end the calculation anytime, by using XXH32_digest(). 118 | This function returns the final 32-bits hash. 119 | You must provide the same "void* state" parameter created by XXH32_init(). 120 | Memory will be freed by XXH32_digest(). 121 | */ 122 | 123 | 124 | int XXH32_sizeofState(); 125 | XXH_errorcode XXH32_resetState(void* state_in, unsigned int seed); 126 | /* 127 | These functions are the basic elements of XXH32_init(); 128 | The objective is to allow user application to make its own allocation. 129 | 130 | XXH32_sizeofState() is used to know how much space must be allocated by the application. 131 | This space must be referenced by a void* pointer. 132 | This pointer must be provided as 'state_in' into XXH32_resetState(), which initializes the state. 133 | */ 134 | 135 | 136 | unsigned int XXH32_intermediateDigest (void* state); 137 | /* 138 | This function does the same as XXH32_digest(), generating a 32-bit hash, 139 | but preserve memory context. 140 | This way, it becomes possible to generate intermediate hashes, and then continue feeding data with XXH32_update(). 141 | To free memory context, use XXH32_digest(). 142 | */ 143 | 144 | 145 | 146 | //**************************** 147 | // Deprecated function names 148 | //**************************** 149 | // The following translations are provided to ease code transition 150 | // You are encouraged to no longer this function names 151 | #define XXH32_feed XXH32_update 152 | #define XXH32_result XXH32_digest 153 | #define XXH32_getIntermediateResult XXH32_intermediateDigest 154 | 155 | 156 | 157 | #if defined (__cplusplus) 158 | } 159 | #endif 160 | -------------------------------------------------------------------------------- /src/xxhash.c: -------------------------------------------------------------------------------- 1 | /* 2 | xxHash - Fast Hash algorithm 3 | Copyright (C) 2012-2013, Yann Collet. 4 | BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following disclaimer 14 | in the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | You can contact the author at : 30 | - xxHash source repository : http://code.google.com/p/xxhash/ 31 | */ 32 | 33 | 34 | 35 | //************************************** 36 | // Tuning parameters 37 | //************************************** 38 | // XXH_ACCEPT_NULL_INPUT_POINTER : 39 | // If the input pointer is a null pointer, xxHash default behavior is to crash, since it is a bad input. 40 | // If this option is enabled, xxHash output for null input pointers will be the same as a null-length input. 41 | // This option has a very small performance cost (only measurable on small inputs). 42 | // By default, this option is disabled. To enable it, uncomment below define : 43 | //#define XXH_ACCEPT_NULL_INPUT_POINTER 1 44 | 45 | // XXH_FORCE_NATIVE_FORMAT : 46 | // By default, xxHash library provides endian-independant Hash values, based on little-endian convention. 47 | // Results are therefore identical for little-endian and big-endian CPU. 48 | // This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. 49 | // Should endian-independance be of no importance to your application, you may uncomment the #define below 50 | // It will improve speed for Big-endian CPU. 51 | // This option has no impact on Little_Endian CPU. 52 | //#define XXH_FORCE_NATIVE_FORMAT 1 53 | 54 | 55 | 56 | //************************************** 57 | // Includes 58 | //************************************** 59 | #include // for malloc(), free() 60 | #include // for memcpy() 61 | #include "xxhash.h" 62 | 63 | 64 | 65 | //************************************** 66 | // CPU Feature Detection 67 | //************************************** 68 | // Little Endian or Big Endian ? 69 | // You can overwrite the #define below if you know your architecture endianess 70 | #if defined(XXH_FORCE_NATIVE_FORMAT) && (XXH_FORCE_NATIVE_FORMAT==1) 71 | // Force native format. The result will be endian dependant. 72 | # define XXH_BIG_ENDIAN 0 73 | #elif defined (__GLIBC__) 74 | # include 75 | # if (__BYTE_ORDER == __BIG_ENDIAN) 76 | # define XXH_BIG_ENDIAN 1 77 | # endif 78 | #elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) 79 | # define XXH_BIG_ENDIAN 1 80 | #elif defined(__sparc) || defined(__sparc__) \ 81 | || defined(__ppc__) || defined(_POWER) || defined(__powerpc__) || defined(_ARCH_PPC) || defined(__PPC__) || defined(__PPC) || defined(PPC) || defined(__powerpc__) || defined(__powerpc) || defined(powerpc) \ 82 | || defined(__hpux) || defined(__hppa) \ 83 | || defined(_MIPSEB) || defined(__s390__) 84 | # define XXH_BIG_ENDIAN 1 85 | #endif 86 | 87 | #if !defined(XXH_BIG_ENDIAN) 88 | // Little Endian assumed. PDP Endian and other very rare endian format are unsupported. 89 | # define XXH_BIG_ENDIAN 0 90 | #endif 91 | 92 | 93 | //************************************** 94 | // Basic Types 95 | //************************************** 96 | #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L // C99 97 | # include 98 | typedef uint8_t BYTE; 99 | typedef uint16_t U16; 100 | typedef uint32_t U32; 101 | typedef int32_t S32; 102 | typedef uint64_t U64; 103 | #else 104 | typedef unsigned char BYTE; 105 | typedef unsigned short U16; 106 | typedef unsigned int U32; 107 | typedef signed int S32; 108 | typedef unsigned long long U64; 109 | #endif 110 | 111 | 112 | //************************************** 113 | // Compiler-specific Options & Functions 114 | //************************************** 115 | #define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) 116 | 117 | // Note : under GCC, it may sometimes be faster to enable the (2nd) macro definition, instead of using win32 intrinsic 118 | #if defined(_WIN32) 119 | # define XXH_rotl32(x,r) _rotl(x,r) 120 | #else 121 | # define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) 122 | #endif 123 | 124 | #if defined(_MSC_VER) // Visual Studio 125 | # define XXH_swap32 _byteswap_ulong 126 | #elif GCC_VERSION >= 403 127 | # define XXH_swap32 __builtin_bswap32 128 | #else 129 | static inline U32 XXH_swap32 (U32 x) { 130 | return ((x << 24) & 0xff000000 ) | 131 | ((x << 8) & 0x00ff0000 ) | 132 | ((x >> 8) & 0x0000ff00 ) | 133 | ((x >> 24) & 0x000000ff );} 134 | #endif 135 | 136 | 137 | //************************************** 138 | // Constants 139 | //************************************** 140 | #define PRIME32_1 2654435761U 141 | #define PRIME32_2 2246822519U 142 | #define PRIME32_3 3266489917U 143 | #define PRIME32_4 668265263U 144 | #define PRIME32_5 374761393U 145 | 146 | 147 | //************************************** 148 | // Macros 149 | //************************************** 150 | #define XXH_LE32(p) (XXH_BIG_ENDIAN ? XXH_swap32(*(U32*)(p)) : *(U32*)(p)) 151 | 152 | 153 | 154 | //**************************** 155 | // Simple Hash Functions 156 | //**************************** 157 | 158 | U32 XXH32(const void* input, int len, U32 seed) 159 | { 160 | #if 0 161 | // Simple version, good for code maintenance, but unfortunately slow for small inputs 162 | void* state = XXH32_init(seed); 163 | XXH32_update(state, input, len); 164 | return XXH32_digest(state); 165 | #else 166 | 167 | const BYTE* p = (const BYTE*)input; 168 | const BYTE* const bEnd = p + len; 169 | U32 h32; 170 | 171 | #ifdef XXH_ACCEPT_NULL_INPUT_POINTER 172 | if (p==NULL) { len=0; p=(const BYTE*)16; } 173 | #endif 174 | 175 | if (len>=16) 176 | { 177 | const BYTE* const limit = bEnd - 16; 178 | U32 v1 = seed + PRIME32_1 + PRIME32_2; 179 | U32 v2 = seed + PRIME32_2; 180 | U32 v3 = seed + 0; 181 | U32 v4 = seed - PRIME32_1; 182 | 183 | do 184 | { 185 | v1 += XXH_LE32(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; 186 | v2 += XXH_LE32(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; 187 | v3 += XXH_LE32(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; 188 | v4 += XXH_LE32(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; 189 | } while (p<=limit); 190 | 191 | h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); 192 | } 193 | else 194 | { 195 | h32 = seed + PRIME32_5; 196 | } 197 | 198 | h32 += (U32) len; 199 | 200 | while (p<=bEnd-4) 201 | { 202 | h32 += XXH_LE32(p) * PRIME32_3; 203 | h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; 204 | p+=4; 205 | } 206 | 207 | while (p> 15; 215 | h32 *= PRIME32_2; 216 | h32 ^= h32 >> 13; 217 | h32 *= PRIME32_3; 218 | h32 ^= h32 >> 16; 219 | 220 | return h32; 221 | 222 | #endif 223 | } 224 | 225 | 226 | //**************************** 227 | // Advanced Hash Functions 228 | //**************************** 229 | 230 | struct XXH_state32_t 231 | { 232 | U32 seed; 233 | U32 v1; 234 | U32 v2; 235 | U32 v3; 236 | U32 v4; 237 | U64 total_len; 238 | char memory[16]; 239 | int memsize; 240 | }; 241 | 242 | 243 | int XXH32_sizeofState() { return sizeof(struct XXH_state32_t); } 244 | 245 | 246 | XXH_errorcode XXH32_resetState(void* state_in, unsigned int seed) 247 | { 248 | struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 249 | state->seed = seed; 250 | state->v1 = seed + PRIME32_1 + PRIME32_2; 251 | state->v2 = seed + PRIME32_2; 252 | state->v3 = seed + 0; 253 | state->v4 = seed - PRIME32_1; 254 | state->total_len = 0; 255 | state->memsize = 0; 256 | return OK; 257 | } 258 | 259 | 260 | void* XXH32_init (U32 seed) 261 | { 262 | struct XXH_state32_t * state = (struct XXH_state32_t *) malloc (sizeof(struct XXH_state32_t)); 263 | XXH32_resetState(state, seed); 264 | return (void*)state; 265 | } 266 | 267 | 268 | XXH_errorcode XXH32_update (void* state_in, const void* input, int len) 269 | { 270 | struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 271 | const BYTE* p = (const BYTE*)input; 272 | const BYTE* const bEnd = p + len; 273 | 274 | #ifdef XXH_ACCEPT_NULL_INPUT_POINTER 275 | if (input==NULL) return XXH_ERROR; 276 | #endif 277 | 278 | state->total_len += len; 279 | 280 | if (state->memsize + len < 16) // fill in tmp buffer 281 | { 282 | memcpy(state->memory + state->memsize, input, len); 283 | state->memsize += len; 284 | return OK; 285 | } 286 | 287 | if (state->memsize) // some data left from previous update 288 | { 289 | memcpy(state->memory + state->memsize, input, 16-state->memsize); 290 | { 291 | const U32* p32 = (const U32*)state->memory; 292 | state->v1 += XXH_LE32(p32) * PRIME32_2; state->v1 = XXH_rotl32(state->v1, 13); state->v1 *= PRIME32_1; p32++; 293 | state->v2 += XXH_LE32(p32) * PRIME32_2; state->v2 = XXH_rotl32(state->v2, 13); state->v2 *= PRIME32_1; p32++; 294 | state->v3 += XXH_LE32(p32) * PRIME32_2; state->v3 = XXH_rotl32(state->v3, 13); state->v3 *= PRIME32_1; p32++; 295 | state->v4 += XXH_LE32(p32) * PRIME32_2; state->v4 = XXH_rotl32(state->v4, 13); state->v4 *= PRIME32_1; p32++; 296 | } 297 | p += 16-state->memsize; 298 | state->memsize = 0; 299 | } 300 | 301 | if (p <= bEnd-16) 302 | { 303 | const BYTE* const limit = bEnd - 16; 304 | U32 v1 = state->v1; 305 | U32 v2 = state->v2; 306 | U32 v3 = state->v3; 307 | U32 v4 = state->v4; 308 | 309 | do 310 | { 311 | v1 += XXH_LE32(p) * PRIME32_2; v1 = XXH_rotl32(v1, 13); v1 *= PRIME32_1; p+=4; 312 | v2 += XXH_LE32(p) * PRIME32_2; v2 = XXH_rotl32(v2, 13); v2 *= PRIME32_1; p+=4; 313 | v3 += XXH_LE32(p) * PRIME32_2; v3 = XXH_rotl32(v3, 13); v3 *= PRIME32_1; p+=4; 314 | v4 += XXH_LE32(p) * PRIME32_2; v4 = XXH_rotl32(v4, 13); v4 *= PRIME32_1; p+=4; 315 | } while (p<=limit); 316 | 317 | state->v1 = v1; 318 | state->v2 = v2; 319 | state->v3 = v3; 320 | state->v4 = v4; 321 | } 322 | 323 | if (p < bEnd) 324 | { 325 | memcpy(state->memory, p, bEnd-p); 326 | state->memsize = (int)(bEnd-p); 327 | } 328 | 329 | return OK; 330 | } 331 | 332 | 333 | U32 XXH32_intermediateDigest (void* state_in) 334 | { 335 | struct XXH_state32_t * state = (struct XXH_state32_t *) state_in; 336 | BYTE * p = (BYTE*)state->memory; 337 | BYTE* bEnd = (BYTE*)state->memory + state->memsize; 338 | U32 h32; 339 | 340 | 341 | if (state->total_len >= 16) 342 | { 343 | h32 = XXH_rotl32(state->v1, 1) + XXH_rotl32(state->v2, 7) + XXH_rotl32(state->v3, 12) + XXH_rotl32(state->v4, 18); 344 | } 345 | else 346 | { 347 | h32 = state->seed + PRIME32_5; 348 | } 349 | 350 | h32 += (U32) state->total_len; 351 | 352 | while (p<=bEnd-4) 353 | { 354 | h32 += XXH_LE32(p) * PRIME32_3; 355 | h32 = XXH_rotl32(h32, 17) * PRIME32_4; 356 | p+=4; 357 | } 358 | 359 | while (p> 15; 367 | h32 *= PRIME32_2; 368 | h32 ^= h32 >> 13; 369 | h32 *= PRIME32_3; 370 | h32 ^= h32 >> 16; 371 | 372 | return h32; 373 | } 374 | 375 | 376 | U32 XXH32_digest (void* state_in) 377 | { 378 | U32 h32 = XXH32_intermediateDigest(state_in); 379 | 380 | free(state_in); 381 | 382 | return h32; 383 | } 384 | --------------------------------------------------------------------------------