xxhash 0.2.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ruby.yml +38 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +1 -1
- data/README.md +14 -4
- data/Rakefile +1 -0
- data/ext/xxhash/extconf.rb +2 -3
- data/ext/xxhash/libxxhash.c +683 -268
- data/ext/xxhash/libxxhash.h +208 -71
- data/ext/xxhash/xxhash.c +224 -0
- data/ext/xxhash/xxhash.h +34 -0
- data/lib/xxhash/version.rb +1 -1
- data/lib/xxhash.rb +90 -6
- data/test/xxhash_test.rb +139 -4
- data/xxhash.gemspec +2 -1
- metadata +13 -20
- data/.travis.yml +0 -4
- data/ext/xxhash/xxhash.cc +0 -56
data/ext/xxhash/libxxhash.h
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
/*
|
2
|
-
xxHash - Fast Hash algorithm
|
2
|
+
xxHash - Extremely Fast Hash algorithm
|
3
3
|
Header File
|
4
|
-
Copyright (C) 2012-
|
4
|
+
Copyright (C) 2012-2016, Yann Collet.
|
5
|
+
|
5
6
|
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
6
7
|
|
7
8
|
Redistribution and use in source and binary forms, with or without
|
@@ -28,7 +29,7 @@
|
|
28
29
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
30
|
|
30
31
|
You can contact the author at :
|
31
|
-
- xxHash source repository :
|
32
|
+
- xxHash source repository : https://github.com/Cyan4973/xxHash
|
32
33
|
*/
|
33
34
|
|
34
35
|
/* Notice extracted from xxHash homepage :
|
@@ -55,110 +56,246 @@ SHA1-32 0.28 GB/s 10
|
|
55
56
|
Q.Score is a measure of quality of the hash function.
|
56
57
|
It depends on successfully passing SMHasher test set.
|
57
58
|
10 is a perfect score.
|
59
|
+
|
60
|
+
A 64-bits version, named XXH64, is available since r35.
|
61
|
+
It offers much better speed, but for 64-bits applications only.
|
62
|
+
Name Speed on 64 bits Speed on 32 bits
|
63
|
+
XXH64 13.8 GB/s 1.9 GB/s
|
64
|
+
XXH32 6.8 GB/s 6.0 GB/s
|
58
65
|
*/
|
59
66
|
|
60
|
-
#
|
67
|
+
#ifndef XXHASH_H_5627135585666179
|
68
|
+
#define XXHASH_H_5627135585666179 1
|
61
69
|
|
62
70
|
#if defined (__cplusplus)
|
63
71
|
extern "C" {
|
64
72
|
#endif
|
65
73
|
|
66
74
|
|
67
|
-
|
68
|
-
|
69
|
-
|
75
|
+
/* ****************************
|
76
|
+
* Compiler specifics
|
77
|
+
******************************/
|
78
|
+
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* ! C99 */
|
79
|
+
# define restrict /* disable restrict */
|
80
|
+
#endif
|
81
|
+
|
82
|
+
|
83
|
+
/* ****************************
|
84
|
+
* Definitions
|
85
|
+
******************************/
|
86
|
+
#include <stddef.h> /* size_t */
|
70
87
|
typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode;
|
71
88
|
|
72
89
|
|
90
|
+
/* ****************************
|
91
|
+
* API modifier
|
92
|
+
******************************/
|
93
|
+
/** XXH_PRIVATE_API
|
94
|
+
* This is useful to include xxhash functions in `static` mode
|
95
|
+
* in order to inline them, and remove their symbol from the public list.
|
96
|
+
* Methodology :
|
97
|
+
* #define XXH_PRIVATE_API
|
98
|
+
* #include "xxhash.h"
|
99
|
+
* `xxhash.c` is automatically included.
|
100
|
+
* It's not useful to compile and link it as a separate module.
|
101
|
+
*/
|
102
|
+
#ifdef XXH_PRIVATE_API
|
103
|
+
# ifndef XXH_STATIC_LINKING_ONLY
|
104
|
+
# define XXH_STATIC_LINKING_ONLY
|
105
|
+
# endif
|
106
|
+
# if defined(__GNUC__)
|
107
|
+
# define XXH_PUBLIC_API static __inline __attribute__((unused))
|
108
|
+
# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
109
|
+
# define XXH_PUBLIC_API static inline
|
110
|
+
# elif defined(_MSC_VER)
|
111
|
+
# define XXH_PUBLIC_API static __inline
|
112
|
+
# else
|
113
|
+
# define XXH_PUBLIC_API static /* this version may generate warnings for unused static functions; disable the relevant warning */
|
114
|
+
# endif
|
115
|
+
#else
|
116
|
+
# define XXH_PUBLIC_API /* do nothing */
|
117
|
+
#endif /* XXH_PRIVATE_API */
|
118
|
+
|
119
|
+
/*!XXH_NAMESPACE, aka Namespace Emulation :
|
120
|
+
|
121
|
+
If you want to include _and expose_ xxHash functions from within your own library,
|
122
|
+
but also want to avoid symbol collisions with other libraries which may also include xxHash,
|
123
|
+
|
124
|
+
you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library
|
125
|
+
with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values).
|
126
|
+
|
127
|
+
Note that no change is required within the calling program as long as it includes `xxhash.h` :
|
128
|
+
regular symbol name will be automatically translated by this header.
|
129
|
+
*/
|
130
|
+
#ifdef XXH_NAMESPACE
|
131
|
+
# define XXH_CAT(A,B) A##B
|
132
|
+
# define XXH_NAME2(A,B) XXH_CAT(A,B)
|
133
|
+
# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber)
|
134
|
+
# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32)
|
135
|
+
# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState)
|
136
|
+
# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState)
|
137
|
+
# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset)
|
138
|
+
# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update)
|
139
|
+
# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest)
|
140
|
+
# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState)
|
141
|
+
# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash)
|
142
|
+
# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical)
|
143
|
+
# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64)
|
144
|
+
# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState)
|
145
|
+
# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState)
|
146
|
+
# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset)
|
147
|
+
# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update)
|
148
|
+
# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest)
|
149
|
+
# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState)
|
150
|
+
# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash)
|
151
|
+
# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical)
|
152
|
+
#endif
|
73
153
|
|
74
|
-
//****************************
|
75
|
-
// Simple Hash Functions
|
76
|
-
//****************************
|
77
154
|
|
78
|
-
|
155
|
+
/* *************************************
|
156
|
+
* Version
|
157
|
+
***************************************/
|
158
|
+
#define XXH_VERSION_MAJOR 0
|
159
|
+
#define XXH_VERSION_MINOR 6
|
160
|
+
#define XXH_VERSION_RELEASE 2
|
161
|
+
#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
|
162
|
+
XXH_PUBLIC_API unsigned XXH_versionNumber (void);
|
79
163
|
|
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
164
|
|
165
|
+
/*-**********************************************************************
|
166
|
+
* 32-bits hash
|
167
|
+
************************************************************************/
|
168
|
+
typedef unsigned int XXH32_hash_t;
|
91
169
|
|
170
|
+
/*! XXH32() :
|
171
|
+
Calculate the 32-bits hash of sequence "length" bytes stored at memory address "input".
|
172
|
+
The memory between input & input+length must be valid (allocated and read-accessible).
|
173
|
+
"seed" can be used to alter the result predictably.
|
174
|
+
Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */
|
175
|
+
XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed);
|
92
176
|
|
93
|
-
|
94
|
-
|
95
|
-
|
177
|
+
/*====== Streaming ======*/
|
178
|
+
typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */
|
179
|
+
XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void);
|
180
|
+
XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr);
|
181
|
+
XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* restrict dst_state, const XXH32_state_t* restrict src_state);
|
96
182
|
|
97
|
-
|
98
|
-
XXH_errorcode XXH32_update (
|
99
|
-
|
183
|
+
XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed);
|
184
|
+
XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length);
|
185
|
+
XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr);
|
100
186
|
|
101
187
|
/*
|
102
|
-
These functions
|
103
|
-
|
188
|
+
These functions generate the xxHash of an input provided in multiple segments.
|
189
|
+
Note that, for small input, they are slower than single-call functions, due to state management.
|
190
|
+
For small input, prefer `XXH32()` and `XXH64()` .
|
104
191
|
|
105
|
-
|
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
|
-
*/
|
192
|
+
XXH state must first be allocated, using XXH*_createState() .
|
122
193
|
|
194
|
+
Start a new hash by initializing state with a seed, using XXH*_reset().
|
123
195
|
|
124
|
-
|
125
|
-
|
196
|
+
Then, feed the hash state by calling XXH*_update() as many times as necessary.
|
197
|
+
Obviously, input must be allocated and read accessible.
|
198
|
+
The function returns an error code, with 0 meaning OK, and any other value meaning there is an error.
|
126
199
|
|
127
|
-
|
128
|
-
|
129
|
-
/*
|
130
|
-
These functions allow user application to make its own allocation for state.
|
200
|
+
Finally, a hash value can be produced anytime, by using XXH*_digest().
|
201
|
+
This function returns the nn-bits hash as an int or long long.
|
131
202
|
|
132
|
-
|
133
|
-
|
134
|
-
This pointer must then be provided as 'state' into XXH32_resetState(), which initializes the state.
|
203
|
+
It's still possible to continue inserting input into the hash state after a digest,
|
204
|
+
and generate some new hashes later on, by calling again XXH*_digest().
|
135
205
|
|
136
|
-
|
137
|
-
use the structure XXH32_stateSpace_t, which will ensure that memory space is large enough and correctly aligned to access 'long long' fields.
|
206
|
+
When done, free XXH state space if it was allocated dynamically.
|
138
207
|
*/
|
139
208
|
|
209
|
+
/*====== Canonical representation ======*/
|
140
210
|
|
141
|
-
unsigned
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
211
|
+
typedef struct { unsigned char digest[4]; } XXH32_canonical_t;
|
212
|
+
XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash);
|
213
|
+
XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
|
214
|
+
|
215
|
+
/* Default result type for XXH functions are primitive unsigned 32 and 64 bits.
|
216
|
+
* The canonical representation uses human-readable write convention, aka big-endian (large digits first).
|
217
|
+
* These functions allow transformation of hash result into and from its canonical format.
|
218
|
+
* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs.
|
147
219
|
*/
|
148
220
|
|
149
221
|
|
222
|
+
#ifndef XXH_NO_LONG_LONG
|
223
|
+
/*-**********************************************************************
|
224
|
+
* 64-bits hash
|
225
|
+
************************************************************************/
|
226
|
+
typedef unsigned long long XXH64_hash_t;
|
227
|
+
|
228
|
+
/*! XXH64() :
|
229
|
+
Calculate the 64-bits hash of sequence of length "len" stored at memory address "input".
|
230
|
+
"seed" can be used to alter the result predictably.
|
231
|
+
This function runs faster on 64-bits systems, but slower on 32-bits systems (see benchmark).
|
232
|
+
*/
|
233
|
+
XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed);
|
234
|
+
|
235
|
+
/*====== Streaming ======*/
|
236
|
+
typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
|
237
|
+
XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void);
|
238
|
+
XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
|
239
|
+
XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* restrict dst_state, const XXH64_state_t* restrict src_state);
|
240
|
+
|
241
|
+
XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed);
|
242
|
+
XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length);
|
243
|
+
XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr);
|
244
|
+
|
245
|
+
/*====== Canonical representation ======*/
|
246
|
+
typedef struct { unsigned char digest[8]; } XXH64_canonical_t;
|
247
|
+
XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash);
|
248
|
+
XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src);
|
249
|
+
#endif /* XXH_NO_LONG_LONG */
|
250
|
+
|
251
|
+
|
252
|
+
#ifdef XXH_STATIC_LINKING_ONLY
|
253
|
+
|
254
|
+
/* ================================================================================================
|
255
|
+
This section contains definitions which are not guaranteed to remain stable.
|
256
|
+
They may change in future versions, becoming incompatible with a different version of the library.
|
257
|
+
They shall only be used with static linking.
|
258
|
+
Never use these definitions in association with dynamic linking !
|
259
|
+
=================================================================================================== */
|
260
|
+
|
261
|
+
/* These definitions are only meant to allow allocation of XXH state
|
262
|
+
statically, on stack, or in a struct for example.
|
263
|
+
Do not use members directly. */
|
264
|
+
|
265
|
+
struct XXH32_state_s {
|
266
|
+
unsigned total_len_32;
|
267
|
+
unsigned large_len;
|
268
|
+
unsigned v1;
|
269
|
+
unsigned v2;
|
270
|
+
unsigned v3;
|
271
|
+
unsigned v4;
|
272
|
+
unsigned mem32[4]; /* buffer defined as U32 for alignment */
|
273
|
+
unsigned memsize;
|
274
|
+
unsigned reserved; /* never read nor write, will be removed in a future version */
|
275
|
+
}; /* typedef'd to XXH32_state_t */
|
276
|
+
|
277
|
+
#ifndef XXH_NO_LONG_LONG
|
278
|
+
struct XXH64_state_s {
|
279
|
+
unsigned long long total_len;
|
280
|
+
unsigned long long v1;
|
281
|
+
unsigned long long v2;
|
282
|
+
unsigned long long v3;
|
283
|
+
unsigned long long v4;
|
284
|
+
unsigned long long mem64[4]; /* buffer defined as U64 for alignment */
|
285
|
+
unsigned memsize;
|
286
|
+
unsigned reserved[2]; /* never read nor write, will be removed in a future version */
|
287
|
+
}; /* typedef'd to XXH64_state_t */
|
288
|
+
#endif
|
150
289
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
// The following translations are provided to ease code transition
|
155
|
-
// You are encouraged to no longer this function names
|
156
|
-
#define XXH32_feed XXH32_update
|
157
|
-
#define XXH32_result XXH32_digest
|
158
|
-
#define XXH32_getIntermediateResult XXH32_intermediateDigest
|
290
|
+
# ifdef XXH_PRIVATE_API
|
291
|
+
# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */
|
292
|
+
# endif
|
159
293
|
|
294
|
+
#endif /* XXH_STATIC_LINKING_ONLY */
|
160
295
|
|
161
296
|
|
162
297
|
#if defined (__cplusplus)
|
163
298
|
}
|
164
299
|
#endif
|
300
|
+
|
301
|
+
#endif /* XXHASH_H_5627135585666179 */
|
data/ext/xxhash/xxhash.c
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
#include "xxhash.h"
|
2
|
+
|
3
|
+
VALUE xxhash_xxh32_file(VALUE mod, VALUE filename, VALUE seed)
|
4
|
+
{
|
5
|
+
StringValue(filename);
|
6
|
+
|
7
|
+
XXH32_state_t* state = XXH32_createState();
|
8
|
+
if (state == NULL) {
|
9
|
+
rb_raise(rb_eRuntimeError, "%s", "Cannot create state, out of memory");
|
10
|
+
}
|
11
|
+
|
12
|
+
XXH32_reset(state, NUM2INT(seed));
|
13
|
+
|
14
|
+
char buffer[16384];
|
15
|
+
size_t count;
|
16
|
+
FILE *fp = fopen(RSTRING_PTR(filename), "rb");
|
17
|
+
if (fp == NULL) {
|
18
|
+
XXH32_freeState(state);
|
19
|
+
VALUE error = INT2FIX(errno);
|
20
|
+
rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
|
21
|
+
}
|
22
|
+
|
23
|
+
while ((count = fread(buffer, 1, sizeof(buffer), fp)) != 0) {
|
24
|
+
XXH32_update(state, buffer, count);
|
25
|
+
}
|
26
|
+
fclose(fp);
|
27
|
+
|
28
|
+
XXH32_hash_t result = XXH32_digest(state);
|
29
|
+
|
30
|
+
XXH32_freeState(state);
|
31
|
+
return ULL2NUM(result);
|
32
|
+
}
|
33
|
+
|
34
|
+
VALUE xxhash_xxh64_file(VALUE mod, VALUE filename, VALUE seed)
|
35
|
+
{
|
36
|
+
StringValue(filename);
|
37
|
+
|
38
|
+
XXH64_state_t* state = XXH64_createState();
|
39
|
+
if (state == NULL) {
|
40
|
+
rb_raise(rb_eRuntimeError, "%s", "Cannot create state, out of memory");
|
41
|
+
}
|
42
|
+
|
43
|
+
XXH64_reset(state, NUM2INT(seed));
|
44
|
+
|
45
|
+
char buffer[16384];
|
46
|
+
size_t count;
|
47
|
+
FILE *fp = fopen(RSTRING_PTR(filename), "rb");
|
48
|
+
if (fp == NULL) {
|
49
|
+
XXH64_freeState(state);
|
50
|
+
VALUE error = INT2FIX(errno);
|
51
|
+
rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
|
52
|
+
}
|
53
|
+
|
54
|
+
while ((count = fread(buffer, 1, sizeof(buffer), fp)) != 0) {
|
55
|
+
XXH64_update(state, buffer, count);
|
56
|
+
}
|
57
|
+
fclose(fp);
|
58
|
+
|
59
|
+
XXH64_hash_t result = XXH64_digest(state);
|
60
|
+
|
61
|
+
XXH64_freeState(state);
|
62
|
+
return ULL2NUM(result);
|
63
|
+
}
|
64
|
+
|
65
|
+
VALUE xxhash_xxh32(VALUE mod, VALUE input, VALUE seed)
|
66
|
+
{
|
67
|
+
return ULL2NUM(XXH32(StringValuePtr(input), (size_t)RSTRING_LEN(input), (unsigned int)NUM2ULL(seed)));
|
68
|
+
}
|
69
|
+
|
70
|
+
void xxhash32_streaming_hash_free(xxhash_xxh32_t* storage)
|
71
|
+
{
|
72
|
+
// Digest frees the memory.
|
73
|
+
XXH32_freeState(storage->state);
|
74
|
+
xfree(storage);
|
75
|
+
}
|
76
|
+
|
77
|
+
VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed)
|
78
|
+
{
|
79
|
+
XXH_errorcode code;
|
80
|
+
xxhash_xxh32_t* storage;
|
81
|
+
storage = ALLOC(xxhash_xxh32_t);
|
82
|
+
storage->state = XXH32_createState();
|
83
|
+
storage->seed = (unsigned int)NUM2ULL(seed);
|
84
|
+
code = XXH32_reset(storage->state, storage->seed);
|
85
|
+
if(code != XXH_OK) {
|
86
|
+
rb_raise(rb_eRuntimeError, "Error during reset.");
|
87
|
+
return Qnil;
|
88
|
+
}
|
89
|
+
return Data_Wrap_Struct(klass, 0, xxhash32_streaming_hash_free, storage);
|
90
|
+
}
|
91
|
+
|
92
|
+
VALUE xxhash32_streaming_hash_reset(VALUE self)
|
93
|
+
{
|
94
|
+
XXH_errorcode code;
|
95
|
+
xxhash_xxh32_t* storage;
|
96
|
+
Data_Get_Struct(self, xxhash_xxh32_t, storage);
|
97
|
+
|
98
|
+
code = XXH32_reset(storage->state, storage->seed);
|
99
|
+
if(code != XXH_OK) {
|
100
|
+
rb_raise(rb_eRuntimeError, "Error during reset.");
|
101
|
+
}
|
102
|
+
return Qnil;
|
103
|
+
}
|
104
|
+
|
105
|
+
|
106
|
+
VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data)
|
107
|
+
{
|
108
|
+
XXH_errorcode code;
|
109
|
+
xxhash_xxh32_t* storage;
|
110
|
+
Data_Get_Struct(self, xxhash_xxh32_t, storage);
|
111
|
+
|
112
|
+
code = XXH32_update(storage->state, StringValuePtr(data), (size_t)RSTRING_LEN(data));
|
113
|
+
if(code != XXH_OK) {
|
114
|
+
rb_raise(rb_eRuntimeError, "Error during update.");
|
115
|
+
}
|
116
|
+
return Qnil;
|
117
|
+
}
|
118
|
+
|
119
|
+
VALUE xxhash32_streaming_hash_digest(VALUE self)
|
120
|
+
{
|
121
|
+
xxhash_xxh32_t* storage;
|
122
|
+
Data_Get_Struct(self, xxhash_xxh32_t, storage);
|
123
|
+
|
124
|
+
// Do not free memory now.
|
125
|
+
return ULL2NUM(XXH32_digest(storage->state));
|
126
|
+
}
|
127
|
+
|
128
|
+
VALUE xxhash_xxh64(VALUE mod, VALUE input, VALUE seed)
|
129
|
+
{
|
130
|
+
return ULL2NUM(XXH64(StringValuePtr(input), (size_t)RSTRING_LEN(input), (unsigned int)NUM2ULL(seed)));
|
131
|
+
}
|
132
|
+
|
133
|
+
void xxhash64_streaming_hash_free(xxhash_xxh64_t* storage)
|
134
|
+
{
|
135
|
+
// Digest frees the memory.
|
136
|
+
XXH64_freeState(storage->state);
|
137
|
+
xfree(storage);
|
138
|
+
}
|
139
|
+
|
140
|
+
VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed)
|
141
|
+
{
|
142
|
+
XXH_errorcode code;
|
143
|
+
xxhash_xxh64_t* storage;
|
144
|
+
storage = ALLOC(xxhash_xxh64_t);
|
145
|
+
storage->state = XXH64_createState();
|
146
|
+
storage->seed = (unsigned int)NUM2ULL(seed);
|
147
|
+
|
148
|
+
code = XXH64_reset(storage->state, storage->seed);
|
149
|
+
if(code != XXH_OK) {
|
150
|
+
rb_raise(rb_eRuntimeError, "Error during reset.");
|
151
|
+
return Qnil;
|
152
|
+
}
|
153
|
+
return Data_Wrap_Struct(klass, 0, xxhash64_streaming_hash_free, storage);
|
154
|
+
}
|
155
|
+
|
156
|
+
VALUE xxhash64_streaming_hash_reset(VALUE self)
|
157
|
+
{
|
158
|
+
XXH_errorcode code;
|
159
|
+
xxhash_xxh64_t* storage;
|
160
|
+
Data_Get_Struct(self, xxhash_xxh64_t, storage);
|
161
|
+
|
162
|
+
code = XXH64_reset(storage->state, storage->seed);
|
163
|
+
if(code != XXH_OK) {
|
164
|
+
rb_raise(rb_eRuntimeError, "Error during reset.");
|
165
|
+
}
|
166
|
+
return Qnil;
|
167
|
+
}
|
168
|
+
|
169
|
+
VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data)
|
170
|
+
{
|
171
|
+
XXH_errorcode code;
|
172
|
+
xxhash_xxh64_t* storage;
|
173
|
+
Data_Get_Struct(self, xxhash_xxh64_t, storage);
|
174
|
+
|
175
|
+
code = XXH64_update(storage->state, StringValuePtr(data), (size_t)RSTRING_LEN(data));
|
176
|
+
if(code != XXH_OK) {
|
177
|
+
rb_raise(rb_eRuntimeError, "Error during update.");
|
178
|
+
}
|
179
|
+
return Qnil;
|
180
|
+
}
|
181
|
+
|
182
|
+
VALUE xxhash64_streaming_hash_digest(VALUE self)
|
183
|
+
{
|
184
|
+
xxhash_xxh64_t* storage;
|
185
|
+
Data_Get_Struct(self, xxhash_xxh64_t, storage);
|
186
|
+
|
187
|
+
// Do not free memory now.
|
188
|
+
return ULL2NUM(XXH64_digest(storage->state));
|
189
|
+
}
|
190
|
+
|
191
|
+
|
192
|
+
void Init_xxhash(void)
|
193
|
+
{
|
194
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
195
|
+
rb_ext_ractor_safe(true);
|
196
|
+
#endif
|
197
|
+
|
198
|
+
VALUE cStreamingHash;
|
199
|
+
VALUE cStreamingHash64;
|
200
|
+
VALUE mXXhash;
|
201
|
+
VALUE mInternal;
|
202
|
+
|
203
|
+
mXXhash = rb_define_module("XXhash");
|
204
|
+
mInternal = rb_define_module_under(mXXhash, "XXhashInternal");
|
205
|
+
|
206
|
+
rb_define_singleton_method(mInternal, "xxh32", (ruby_method*) &xxhash_xxh32, 2);
|
207
|
+
rb_define_singleton_method(mInternal, "xxh32_file", (ruby_method*) &xxhash_xxh32_file, 2);
|
208
|
+
rb_define_singleton_method(mInternal, "xxh64", (ruby_method*) &xxhash_xxh64, 2);
|
209
|
+
rb_define_singleton_method(mInternal, "xxh64_file", (ruby_method*) &xxhash_xxh64_file, 2);
|
210
|
+
|
211
|
+
cStreamingHash = rb_define_class_under(mInternal, "StreamingHash32", rb_cObject);
|
212
|
+
|
213
|
+
rb_define_singleton_method(cStreamingHash, "new", (ruby_method*) &xxhash32_streaming_hash_new, 1);
|
214
|
+
rb_define_method(cStreamingHash, "update", (ruby_method*) &xxhash32_streaming_hash_update, 1);
|
215
|
+
rb_define_method(cStreamingHash, "digest", (ruby_method*) &xxhash32_streaming_hash_digest, 0);
|
216
|
+
rb_define_method(cStreamingHash, "reset", (ruby_method*) &xxhash32_streaming_hash_reset, 0);
|
217
|
+
|
218
|
+
cStreamingHash64 = rb_define_class_under(mInternal, "StreamingHash64", rb_cObject);
|
219
|
+
|
220
|
+
rb_define_singleton_method(cStreamingHash64, "new", (ruby_method*) &xxhash64_streaming_hash_new, 1);
|
221
|
+
rb_define_method(cStreamingHash64, "update", (ruby_method*) &xxhash64_streaming_hash_update, 1);
|
222
|
+
rb_define_method(cStreamingHash64, "digest", (ruby_method*) &xxhash64_streaming_hash_digest, 0);
|
223
|
+
rb_define_method(cStreamingHash64, "reset", (ruby_method*) &xxhash64_streaming_hash_reset, 0);
|
224
|
+
}
|
data/ext/xxhash/xxhash.h
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#include <stdlib.h>
|
2
|
+
#include <errno.h>
|
3
|
+
#include <ruby.h>
|
4
|
+
#include "libxxhash.h"
|
5
|
+
|
6
|
+
typedef struct {
|
7
|
+
XXH32_state_t* state;
|
8
|
+
unsigned int seed;
|
9
|
+
} xxhash_xxh32_t;
|
10
|
+
|
11
|
+
typedef struct {
|
12
|
+
XXH64_state_t* state;
|
13
|
+
unsigned int seed;
|
14
|
+
} xxhash_xxh64_t;
|
15
|
+
|
16
|
+
// Use this typedef to make the compiler happy when
|
17
|
+
// calling rb_define_method()
|
18
|
+
typedef VALUE (ruby_method)();
|
19
|
+
|
20
|
+
VALUE xxhash_xxh32(VALUE mod, VALUE input, VALUE seed);
|
21
|
+
VALUE xxhash_xxh32_file(VALUE mod, VALUE filename, VALUE seed);
|
22
|
+
void xxhash32_streaming_hash_free(xxhash_xxh32_t* state);
|
23
|
+
VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed);
|
24
|
+
VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data);
|
25
|
+
VALUE xxhash32_streaming_hash_reset(VALUE self);
|
26
|
+
VALUE xxhash32_streaming_hash_digest(VALUE self);
|
27
|
+
VALUE xxhash_xxh64(VALUE mod, VALUE input, VALUE seed);
|
28
|
+
VALUE xxhash_xxh64_file(VALUE mod, VALUE filename, VALUE seed);
|
29
|
+
void xxhash64_streaming_hash_free(xxhash_xxh64_t* state);
|
30
|
+
VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed);
|
31
|
+
VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data);
|
32
|
+
VALUE xxhash64_streaming_hash_reset(VALUE self);
|
33
|
+
VALUE xxhash64_streaming_hash_digest(VALUE self);
|
34
|
+
void Init_xxhash(void);
|
data/lib/xxhash/version.rb
CHANGED