digest-xxhash 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.md +61 -0
- data/Rakefile +20 -0
- data/digest-xxhash.gemspec +29 -0
- data/ext/digest/xxhash/debug-funcs.h +46 -0
- data/ext/digest/xxhash/ext.c +771 -0
- data/ext/digest/xxhash/extconf.rb +2 -0
- data/ext/digest/xxhash/utils.h +151 -0
- data/ext/digest/xxhash/xxhash.c +888 -0
- data/ext/digest/xxhash/xxhash.h +293 -0
- data/lib/digest/xxhash/version.rb +5 -0
- data/test/produce-vectors-with-ruby-xxhash.rb +73 -0
- data/test/test.rb +85 -0
- data/test/test.vectors +462 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 89f6bcb49f857af24e726b360ba1f0f4ce8de03c
|
4
|
+
data.tar.gz: 00341374c8aa7499599a41fd9d3f17e0ad522573
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b6d3e2afd0fcc4bfc4fa01bfe3315600b5d0939be148f90a97a90121993dcace0e49555c26b91a49278f429679ee81eebde22e08c786aa186f635fbe84c15d98
|
7
|
+
data.tar.gz: 17f501e8a8a864004532684ddebe011f52bf26d802827934595fbc2daf961477942260701ab48b544d92d69078c09e822a6222a91d9f768b3d01c98e595913b7
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2017 konsolebox
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# digest-xxhash-ruby
|
2
|
+
|
3
|
+
This gem 'digest-xxhash' provides XXH32 and XXH64 functions for Ruby. It works
|
4
|
+
on top of Digest::Class and complies with the functional design of
|
5
|
+
Digest::Instance.
|
6
|
+
|
7
|
+
Its core implementation was taken from the official source, which is
|
8
|
+
in https://github.com/Cyan4973/xxHash.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'digest-xxhash'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install digest-xxhash
|
23
|
+
|
24
|
+
## Example Usage
|
25
|
+
|
26
|
+
require 'digest/xxhash'
|
27
|
+
|
28
|
+
Digest::XXH32.digest("ABXY")
|
29
|
+
=> "\x0E\xA4\xB6\xCA"
|
30
|
+
|
31
|
+
Digest::XXH32.hexdigest("ABXY")
|
32
|
+
=> "0ea4b6ca"
|
33
|
+
|
34
|
+
Digest::XXH32.idigest("ABXY")
|
35
|
+
=> 245675722
|
36
|
+
|
37
|
+
Digest::XXH32.hexdigest("1234", "\xab\xcd\xef\x00")
|
38
|
+
=> "2af3be26"
|
39
|
+
|
40
|
+
Digest::XXH32.hexdigest("1234", "abcdef00")
|
41
|
+
=> "2af3be26"
|
42
|
+
|
43
|
+
Digest::XXH32.hexdigest("1234", 2882400000)
|
44
|
+
=> "2af3be26"
|
45
|
+
|
46
|
+
Digest::XXH64.hexdigest("1234", "0123456789abcdef")
|
47
|
+
=> "d7544504de216507"
|
48
|
+
|
49
|
+
Digest::XXH64.new("0123456789abcdef").update("1234").hexdigest
|
50
|
+
=> "d7544504de216507"
|
51
|
+
|
52
|
+
Digest::XXH64.new.reset("0123456789abcdef").update("12").update("34").hexdigest
|
53
|
+
=> "d7544504de216507"
|
54
|
+
|
55
|
+
## Contributing
|
56
|
+
|
57
|
+
1. Fork it ( https://github.com/konsolebox/digest-xxhash-ruby/fork ).
|
58
|
+
2. Create your feature branch (`git checkout -b my-new-feature`).
|
59
|
+
3. Commit your changes (`git commit -am 'Add some feature'`).
|
60
|
+
4. Push to the branch (`git push origin my-new-feature`).
|
61
|
+
5. Create a new Pull Request.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
# clean, clobber, compile, and compile:digest/xxhash
|
5
|
+
require 'rake/extensiontask'
|
6
|
+
Rake::ExtensionTask.new('digest/xxhash', Bundler::GemHelper.gemspec)
|
7
|
+
|
8
|
+
# test
|
9
|
+
Rake::TestTask.new(:test => :compile) do |t|
|
10
|
+
t.test_files = FileList['test/test.rb']
|
11
|
+
t.verbose = true
|
12
|
+
end
|
13
|
+
|
14
|
+
# clean
|
15
|
+
task :clean do
|
16
|
+
list = FileList.new('test/*.tmp', 'test/*.temp')
|
17
|
+
rm_f list unless list.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
# Run `rake --tasks` for a list of tasks.
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'digest/xxhash/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "digest-xxhash"
|
9
|
+
spec.version = Digest::XXHash::VERSION
|
10
|
+
spec.authors = ["konsolebox"]
|
11
|
+
spec.email = ["konsolebox@gmail.com"]
|
12
|
+
spec.summary = "XXHash for Ruby"
|
13
|
+
spec.description = "An XXHash library that complies with Digest::Instance's functional design."
|
14
|
+
spec.homepage = "https://github.com/konsolebox/digest-xxhash-ruby"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.required_ruby_version = '>= 2.2'
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency "rake-compiler", "~> 1.0"
|
26
|
+
spec.add_development_dependency "minitest", "~> 5.8"
|
27
|
+
|
28
|
+
spec.extensions = %w[ext/digest/xxhash/extconf.rb]
|
29
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#ifndef DEBUG_FUNCS_H
|
2
|
+
#define DEBUG_FUNCS_H
|
3
|
+
|
4
|
+
#include "utils.h"
|
5
|
+
|
6
|
+
static void print_in_hex(const char *format, const unsigned char *str, size_t len)
|
7
|
+
{
|
8
|
+
unsigned char buffer[len * 2 + 1];
|
9
|
+
hex_encode_str_implied(str, len, buffer);
|
10
|
+
buffer[len * 2] = '\0';
|
11
|
+
_DEBUG(format, buffer);
|
12
|
+
}
|
13
|
+
|
14
|
+
static void dump_state_32(XXH32_state_t *state)
|
15
|
+
{
|
16
|
+
_DEBUG("state->total_len: %u\n", state->total_len_32);
|
17
|
+
_DEBUG("state->large_len: %u\n", state->large_len);
|
18
|
+
_DEBUG("state->v1: %u\n", state->v1);
|
19
|
+
_DEBUG("state->v2: %u\n", state->v2);
|
20
|
+
_DEBUG("state->v3: %u\n", state->v3);
|
21
|
+
_DEBUG("state->v4: %u\n", state->v4);
|
22
|
+
_DEBUG("state->mem32[0]: %u\n", state->mem32[0]);
|
23
|
+
_DEBUG("state->mem32[1]: %u\n", state->mem32[1]);
|
24
|
+
_DEBUG("state->mem32[2]: %u\n", state->mem32[2]);
|
25
|
+
_DEBUG("state->mem32[3]: %u\n", state->mem32[3]);
|
26
|
+
_DEBUG("state->memsize: %u\n", state->memsize);
|
27
|
+
_DEBUG("state->reserved: %u\n", state->reserved);
|
28
|
+
}
|
29
|
+
|
30
|
+
static void dump_state_64(XXH64_state_t *state)
|
31
|
+
{
|
32
|
+
_DEBUG("state->total_len: %llu\n", state->total_len);
|
33
|
+
_DEBUG("state->v1: %llu\n", state->v1);
|
34
|
+
_DEBUG("state->v2: %llu\n", state->v2);
|
35
|
+
_DEBUG("state->v3: %llu\n", state->v3);
|
36
|
+
_DEBUG("state->v4: %llu\n", state->v4);
|
37
|
+
_DEBUG("state->mem64[0]: %llu\n", state->mem64[0]);
|
38
|
+
_DEBUG("state->mem64[1]: %llu\n", state->mem64[1]);
|
39
|
+
_DEBUG("state->mem64[2]: %llu\n", state->mem64[2]);
|
40
|
+
_DEBUG("state->mem64[3]: %llu\n", state->mem64[3]);
|
41
|
+
_DEBUG("state->memsize: %u\n", state->memsize);
|
42
|
+
_DEBUG("state->reserved[0]: %u\n", state->reserved[0]);
|
43
|
+
_DEBUG("state->reserved[1]: %u\n", state->reserved[1]);
|
44
|
+
}
|
45
|
+
|
46
|
+
#endif
|
@@ -0,0 +1,771 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 2017 konsolebox
|
3
|
+
*
|
4
|
+
* MIT License
|
5
|
+
*
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
* a copy of this software and associated documentation files (the
|
8
|
+
* "Software"), to deal in the Software without restriction, including
|
9
|
+
* without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
* distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
* permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
* the following conditions:
|
13
|
+
*
|
14
|
+
* The above copyright notice and this permission notice shall be
|
15
|
+
* included in all copies or substantial portions of the Software.
|
16
|
+
*
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
*/
|
25
|
+
|
26
|
+
|
27
|
+
#include <ruby.h>
|
28
|
+
#include <ruby/digest.h>
|
29
|
+
#include <stdint.h>
|
30
|
+
|
31
|
+
#define XXH_STATIC_LINKING_ONLY
|
32
|
+
#include "xxhash.h"
|
33
|
+
#include "utils.h"
|
34
|
+
|
35
|
+
#define _DIGEST_API_VERSION_IS_SUPPORTED(version) (version == 3)
|
36
|
+
|
37
|
+
#if !_DIGEST_API_VERSION_IS_SUPPORTED(RUBY_DIGEST_API_VERSION)
|
38
|
+
# error Digest API version is not supported.
|
39
|
+
#endif
|
40
|
+
|
41
|
+
#define _XXH32_DIGEST_SIZE 4
|
42
|
+
#define _XXH64_DIGEST_SIZE 8
|
43
|
+
|
44
|
+
#define _XXH32_BLOCK_SIZE 4
|
45
|
+
#define _XXH64_BLOCK_SIZE 8
|
46
|
+
|
47
|
+
#define _XXH32_DEFAULT_SEED 0
|
48
|
+
#define _XXH64_DEFAULT_SEED 0
|
49
|
+
|
50
|
+
#if 0
|
51
|
+
# define _DEBUG(...) fprintf(stderr, __VA_ARGS__)
|
52
|
+
#else
|
53
|
+
# define _DEBUG(...) (void)0;
|
54
|
+
#endif
|
55
|
+
|
56
|
+
static ID _id_digest;
|
57
|
+
static ID _id_finish;
|
58
|
+
static ID _id_hexdigest;
|
59
|
+
static ID _id_idigest;
|
60
|
+
static ID _id_ifinish;
|
61
|
+
static ID _id_new;
|
62
|
+
static ID _id_reset;
|
63
|
+
static ID _id_update;
|
64
|
+
|
65
|
+
static VALUE _Digest;
|
66
|
+
static VALUE _Digest_XXHash;
|
67
|
+
static VALUE _Digest_XXH32;
|
68
|
+
static VALUE _Digest_XXH64;
|
69
|
+
|
70
|
+
/*
|
71
|
+
* Data types
|
72
|
+
*/
|
73
|
+
|
74
|
+
static const rb_data_type_t _xxh32_state_data_type = {
|
75
|
+
"xxh32_state_data",
|
76
|
+
{ 0, RUBY_TYPED_DEFAULT_FREE, 0, }, 0, 0,
|
77
|
+
RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
|
78
|
+
};
|
79
|
+
|
80
|
+
static const rb_data_type_t _xxh64_state_data_type = {
|
81
|
+
"xxh64_state_data",
|
82
|
+
{ 0, RUBY_TYPED_DEFAULT_FREE, 0, }, 0, 0,
|
83
|
+
RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
|
84
|
+
};
|
85
|
+
|
86
|
+
/*
|
87
|
+
* Common functions
|
88
|
+
*/
|
89
|
+
|
90
|
+
static XXH32_state_t *_get_state_32(VALUE self)
|
91
|
+
{
|
92
|
+
XXH32_state_t *state_p;
|
93
|
+
TypedData_Get_Struct(self, XXH32_state_t, &_xxh32_state_data_type, state_p);
|
94
|
+
return state_p;
|
95
|
+
}
|
96
|
+
|
97
|
+
static XXH64_state_t *_get_state_64(VALUE self)
|
98
|
+
{
|
99
|
+
XXH64_state_t *state_p;
|
100
|
+
TypedData_Get_Struct(self, XXH64_state_t, &_xxh64_state_data_type, state_p);
|
101
|
+
return state_p;
|
102
|
+
}
|
103
|
+
|
104
|
+
static void _xxh32_reset(XXH32_state_t *state_p, uint32_t seed)
|
105
|
+
{
|
106
|
+
if (XXH32_reset(state_p, seed) != XXH_OK)
|
107
|
+
rb_raise(rb_eRuntimeError, "Failed to reset state.");
|
108
|
+
}
|
109
|
+
|
110
|
+
static void _xxh64_reset(XXH64_state_t *state_p, uint64_t seed)
|
111
|
+
{
|
112
|
+
if (XXH64_reset(state_p, seed) != XXH_OK)
|
113
|
+
rb_raise(rb_eRuntimeError, "Failed to reset state.");
|
114
|
+
}
|
115
|
+
|
116
|
+
static VALUE _encode_big_endian_32(uint32_t num)
|
117
|
+
{
|
118
|
+
uint32_t temp;
|
119
|
+
|
120
|
+
if (is_little_endian()) {
|
121
|
+
temp = swap_uint32(num);
|
122
|
+
} else {
|
123
|
+
temp = num;
|
124
|
+
}
|
125
|
+
|
126
|
+
return rb_usascii_str_new((unsigned char *) &temp, sizeof(uint32_t));
|
127
|
+
}
|
128
|
+
|
129
|
+
static uint32_t _decode_big_endian_32_cstr(unsigned char *str)
|
130
|
+
{
|
131
|
+
uint32_t temp = read32(str);
|
132
|
+
|
133
|
+
if (is_little_endian()) {
|
134
|
+
return swap_uint32(temp);
|
135
|
+
} else {
|
136
|
+
return temp;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
static uint32_t _decode_big_endian_32(VALUE str)
|
141
|
+
{
|
142
|
+
return _decode_big_endian_32_cstr(RSTRING_PTR(str));
|
143
|
+
}
|
144
|
+
|
145
|
+
static VALUE _encode_big_endian_64(uint64_t num)
|
146
|
+
{
|
147
|
+
uint64_t temp;
|
148
|
+
|
149
|
+
if (is_little_endian()) {
|
150
|
+
temp = swap_uint64(num);
|
151
|
+
} else {
|
152
|
+
temp = num;
|
153
|
+
}
|
154
|
+
|
155
|
+
return rb_usascii_str_new((unsigned char *) &temp, sizeof(uint64_t));
|
156
|
+
}
|
157
|
+
|
158
|
+
static uint64_t _decode_big_endian_64_cstr(unsigned char *str)
|
159
|
+
{
|
160
|
+
uint64_t temp = read64(str);
|
161
|
+
|
162
|
+
if (is_little_endian()) {
|
163
|
+
return swap_uint64(temp);
|
164
|
+
} else {
|
165
|
+
return temp;
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
static uint64_t _decode_big_endian_64(VALUE str)
|
170
|
+
{
|
171
|
+
return _decode_big_endian_64_cstr(RSTRING_PTR(str));
|
172
|
+
}
|
173
|
+
|
174
|
+
static VALUE _hex_encode_str(VALUE str)
|
175
|
+
{
|
176
|
+
int len = RSTRING_LEN(str);
|
177
|
+
VALUE hex = rb_str_new(0, len * 2);
|
178
|
+
hex_encode_str_implied(RSTRING_PTR(str), len, RSTRING_PTR(hex));
|
179
|
+
return hex;
|
180
|
+
}
|
181
|
+
|
182
|
+
/*
|
183
|
+
* Document-class: Digest::XXHash
|
184
|
+
*
|
185
|
+
* This is the base class of Digest::XXH32 and Digest::XXH64.
|
186
|
+
*/
|
187
|
+
|
188
|
+
static VALUE _Digest_XXHash_internal_allocate(VALUE klass)
|
189
|
+
{
|
190
|
+
if (klass == _Digest_XXHash)
|
191
|
+
rb_raise(rb_eRuntimeError, "Digest::XXHash is an incomplete class and cannot be instantiated.");
|
192
|
+
|
193
|
+
rb_raise(rb_eNotImpError, "Allocator function not implemented.");
|
194
|
+
}
|
195
|
+
|
196
|
+
/*
|
197
|
+
* call-seq:
|
198
|
+
* new -> instance
|
199
|
+
* new(seed) -> instance
|
200
|
+
*
|
201
|
+
* Returns a new hash instance.
|
202
|
+
*
|
203
|
+
* If seed is provided, the state is reset with its value, otherwise the default
|
204
|
+
* seed (0) is used.
|
205
|
+
*
|
206
|
+
* +seed+ can be in the form of a string, a hex string, or a number.
|
207
|
+
*/
|
208
|
+
static VALUE _Digest_XXHash_initialize(int argc, VALUE* argv, VALUE self)
|
209
|
+
{
|
210
|
+
if (argc > 0)
|
211
|
+
rb_funcallv(self, _id_reset, argc, argv);
|
212
|
+
|
213
|
+
return self;
|
214
|
+
}
|
215
|
+
|
216
|
+
/* :nodoc: */
|
217
|
+
static VALUE _Digest_XXHash_ifinish(VALUE self)
|
218
|
+
{
|
219
|
+
rb_raise(rb_eNotImpError, "Method not implemented.");
|
220
|
+
}
|
221
|
+
|
222
|
+
static VALUE _do_digest(int argc, VALUE* argv, VALUE self, ID finish_method_id)
|
223
|
+
{
|
224
|
+
VALUE str, seed;
|
225
|
+
int argc2 = argc > 0 ? rb_scan_args(argc, argv, "02", &str, &seed) : 0;
|
226
|
+
|
227
|
+
if (argc2 > 0) {
|
228
|
+
if (TYPE(str) != T_STRING)
|
229
|
+
rb_raise(rb_eTypeError, "Argument type not string.");
|
230
|
+
|
231
|
+
if (argc2 > 1)
|
232
|
+
rb_funcall(self, _id_reset, 1, seed);
|
233
|
+
else
|
234
|
+
rb_funcall(self, _id_reset, 0);
|
235
|
+
|
236
|
+
rb_funcall(self, _id_update, 1, str);
|
237
|
+
}
|
238
|
+
|
239
|
+
VALUE result = rb_funcall(self, finish_method_id, 0);
|
240
|
+
|
241
|
+
if (argc2 > 0)
|
242
|
+
rb_funcall(self, _id_reset, 0);
|
243
|
+
|
244
|
+
return result;
|
245
|
+
}
|
246
|
+
|
247
|
+
/*
|
248
|
+
* call-seq:
|
249
|
+
* digest -> str
|
250
|
+
* digest(str, seed = 0) -> str
|
251
|
+
*
|
252
|
+
* Returns digest value in string form.
|
253
|
+
*
|
254
|
+
* If no argument is provided, the current digest value is returned, and no
|
255
|
+
* reset happens.
|
256
|
+
*
|
257
|
+
* If a string argument is provided, the string's digest value is calculated
|
258
|
+
* with +seed+, and is used as the return value. The instance's state is reset
|
259
|
+
* to default afterwards.
|
260
|
+
*
|
261
|
+
* Providing an argument means that previous calculations done with #update
|
262
|
+
* would be discarded, so be careful with its use.
|
263
|
+
*
|
264
|
+
* +seed+ can be in the form of a string, a hex string, or a number.
|
265
|
+
*/
|
266
|
+
static VALUE _Digest_XXHash_digest(int argc, VALUE* argv, VALUE self)
|
267
|
+
{
|
268
|
+
return _do_digest(argc, argv, self, _id_finish);
|
269
|
+
}
|
270
|
+
|
271
|
+
/*
|
272
|
+
* call-seq:
|
273
|
+
* hexdigest -> hex_str
|
274
|
+
* hexdigest(str) -> hex_str
|
275
|
+
* hexdigest(str, seed) -> hex_str
|
276
|
+
*
|
277
|
+
* Same as #digest but returns the digest value in hex form.
|
278
|
+
*/
|
279
|
+
static VALUE _Digest_XXHash_hexdigest(int argc, VALUE* argv, VALUE self)
|
280
|
+
{
|
281
|
+
VALUE result = _do_digest(argc, argv, self, _id_finish);
|
282
|
+
return _hex_encode_str(result);
|
283
|
+
}
|
284
|
+
|
285
|
+
/*
|
286
|
+
* call-seq:
|
287
|
+
* idigest -> num
|
288
|
+
* idigest(str) -> num
|
289
|
+
* idigest(str, seed) -> num
|
290
|
+
*
|
291
|
+
* Same as #digest but returns the digest value in numerical form.
|
292
|
+
*/
|
293
|
+
static VALUE _Digest_XXHash_idigest(int argc, VALUE* argv, VALUE self)
|
294
|
+
{
|
295
|
+
return _do_digest(argc, argv, self, _id_ifinish);
|
296
|
+
}
|
297
|
+
|
298
|
+
/*
|
299
|
+
* call-seq: idigest!
|
300
|
+
*
|
301
|
+
* Returns current digest value and resets state to default form.
|
302
|
+
*/
|
303
|
+
static VALUE _Digest_XXHash_idigest_bang(VALUE self)
|
304
|
+
{
|
305
|
+
VALUE result = rb_funcall(self, _id_ifinish, 0);
|
306
|
+
rb_funcall(self, _id_reset, 0);
|
307
|
+
return result;
|
308
|
+
}
|
309
|
+
|
310
|
+
/*
|
311
|
+
* call-seq: initialize_copy(orig) -> self
|
312
|
+
*
|
313
|
+
* This method is called when instances are cloned. It is responsible for
|
314
|
+
* replicating internal data.
|
315
|
+
*/
|
316
|
+
static VALUE _Digest_XXHash_initialize_copy(VALUE orig)
|
317
|
+
{
|
318
|
+
rb_raise(rb_eNotImpError, "initialize_copy method not implemented.");
|
319
|
+
}
|
320
|
+
|
321
|
+
/*
|
322
|
+
* call-seq: inspect -> str
|
323
|
+
*
|
324
|
+
* Returns a string in the form of <tt>#<class_name|hex_digest></tt>.
|
325
|
+
*/
|
326
|
+
static VALUE _Digest_XXHash_inspect(VALUE self)
|
327
|
+
{
|
328
|
+
VALUE klass = rb_obj_class(self);
|
329
|
+
VALUE klass_name = rb_class_name(klass);
|
330
|
+
|
331
|
+
if (klass_name == Qnil)
|
332
|
+
klass_name = rb_inspect(klass);
|
333
|
+
|
334
|
+
VALUE hexdigest = rb_funcall(self, _id_hexdigest, 0);
|
335
|
+
|
336
|
+
VALUE args[] = { klass_name, hexdigest };
|
337
|
+
return rb_str_format(sizeof(args), args, rb_str_new_literal("#<%s|%s>"));
|
338
|
+
}
|
339
|
+
|
340
|
+
static VALUE _instantiate_and_digest(int argc, VALUE* argv, VALUE klass, ID digest_method_id)
|
341
|
+
{
|
342
|
+
VALUE str, seed;
|
343
|
+
int argc2 = rb_scan_args(argc, argv, "11", &str, &seed);
|
344
|
+
|
345
|
+
if (TYPE(str) != T_STRING)
|
346
|
+
rb_raise(rb_eTypeError, "Argument type not string.");
|
347
|
+
|
348
|
+
VALUE instance = rb_funcall(klass, _id_new, 0);
|
349
|
+
|
350
|
+
if (argc2 > 1)
|
351
|
+
return rb_funcall(instance, digest_method_id, 2, str, seed);
|
352
|
+
else
|
353
|
+
return rb_funcall(instance, digest_method_id, 1, str);
|
354
|
+
}
|
355
|
+
|
356
|
+
/*
|
357
|
+
* call-seq: Digest::XXHash::digest(str, seed = 0) -> str
|
358
|
+
*
|
359
|
+
* Returns the digest value of +str+ in string form with +seed+ as its seed.
|
360
|
+
*
|
361
|
+
* +seed+ can be in the form of a string, a hex string, or a number.
|
362
|
+
*
|
363
|
+
* If +seed+ is not provided, the default value would be 0.
|
364
|
+
*/
|
365
|
+
static VALUE _Digest_XXHash_singleton_digest(int argc, VALUE* argv, VALUE self)
|
366
|
+
{
|
367
|
+
return _instantiate_and_digest(argc, argv, self, _id_digest);
|
368
|
+
}
|
369
|
+
|
370
|
+
/*
|
371
|
+
* call-seq: Digest::XXHash::hexdigest -> hex_str
|
372
|
+
*
|
373
|
+
* Same as ::digest but returns the digest value in hex form.
|
374
|
+
*/
|
375
|
+
static VALUE _Digest_XXHash_singleton_hexdigest(int argc, VALUE* argv, VALUE self)
|
376
|
+
{
|
377
|
+
return _instantiate_and_digest(argc, argv, self, _id_hexdigest);
|
378
|
+
}
|
379
|
+
|
380
|
+
/*
|
381
|
+
* call-seq: Digest::XXHash::idigest -> num
|
382
|
+
*
|
383
|
+
* Same as ::digest but returns the digest value in numerical form.
|
384
|
+
*/
|
385
|
+
static VALUE _Digest_XXHash_singleton_idigest(int argc, VALUE* argv, VALUE self)
|
386
|
+
{
|
387
|
+
return _instantiate_and_digest(argc, argv, self, _id_idigest);
|
388
|
+
}
|
389
|
+
|
390
|
+
/*
|
391
|
+
* Document-class: Digest::XXH32
|
392
|
+
*
|
393
|
+
* This class implements XXH32.
|
394
|
+
*/
|
395
|
+
|
396
|
+
static VALUE _Digest_XXH32_internal_allocate(VALUE klass)
|
397
|
+
{
|
398
|
+
XXH32_state_t *state_p;
|
399
|
+
VALUE obj = TypedData_Make_Struct(klass, XXH32_state_t, &_xxh32_state_data_type, state_p);
|
400
|
+
_xxh32_reset(state_p, 0);
|
401
|
+
return obj;
|
402
|
+
}
|
403
|
+
|
404
|
+
/*
|
405
|
+
* call-seq: update(str) -> self
|
406
|
+
*
|
407
|
+
* Updates current digest value with string.
|
408
|
+
*/
|
409
|
+
static VALUE _Digest_XXH32_update(VALUE self, VALUE str)
|
410
|
+
{
|
411
|
+
if (XXH32_update(_get_state_32(self), RSTRING_PTR(str), RSTRING_LEN(str)) != XXH_OK)
|
412
|
+
rb_raise(rb_eRuntimeError, "Failed to reset state.");
|
413
|
+
|
414
|
+
return self;
|
415
|
+
}
|
416
|
+
|
417
|
+
/* :nodoc: */
|
418
|
+
static VALUE _Digest_XXH32_finish(VALUE self)
|
419
|
+
{
|
420
|
+
uint32_t result = XXH32_digest(_get_state_32(self));
|
421
|
+
return _encode_big_endian_32(result);
|
422
|
+
}
|
423
|
+
|
424
|
+
/* :nodoc: */
|
425
|
+
static VALUE _Digest_XXH32_ifinish(VALUE self)
|
426
|
+
{
|
427
|
+
uint32_t result = XXH32_digest(_get_state_32(self));
|
428
|
+
return ULONG2NUM(result);
|
429
|
+
}
|
430
|
+
|
431
|
+
/*
|
432
|
+
* call-seq: reset(seed = 0) -> self
|
433
|
+
*
|
434
|
+
* Resets state to initial form with seed.
|
435
|
+
*
|
436
|
+
* This would discard previous calculations with #update.
|
437
|
+
*
|
438
|
+
* +seed+ can be in the form of a string, a hex string, or a number.
|
439
|
+
*
|
440
|
+
* If +seed+ is not provided, the default value would be 0.
|
441
|
+
*/
|
442
|
+
static VALUE _Digest_XXH32_reset(int argc, VALUE* argv, VALUE self)
|
443
|
+
{
|
444
|
+
VALUE seed;
|
445
|
+
|
446
|
+
if (argc > 0 && rb_scan_args(argc, argv, "01", &seed) > 0) {
|
447
|
+
switch (TYPE(seed)) {
|
448
|
+
case T_STRING:
|
449
|
+
{
|
450
|
+
int len = RSTRING_LEN(seed);
|
451
|
+
uint32_t decoded_seed;
|
452
|
+
|
453
|
+
if (len == (sizeof(uint32_t) * 2)) {
|
454
|
+
unsigned char hex_decoded_seed[sizeof(uint32_t)];
|
455
|
+
|
456
|
+
if (! hex_decode_str_implied(RSTRING_PTR(seed), sizeof(uint32_t) * 2, hex_decoded_seed))
|
457
|
+
rb_raise(rb_eArgError, "Invalid hex string seed: %s\n", StringValueCStr(seed));
|
458
|
+
|
459
|
+
decoded_seed = _decode_big_endian_32_cstr(hex_decoded_seed);
|
460
|
+
} else if (len == sizeof(uint32_t)) {
|
461
|
+
decoded_seed = _decode_big_endian_32_cstr(RSTRING_PTR(seed));
|
462
|
+
} else {
|
463
|
+
rb_raise(rb_eArgError, "Invalid seed length. Expecting an 8-character hex string or a 4-byte string.");
|
464
|
+
}
|
465
|
+
|
466
|
+
_xxh32_reset(_get_state_32(self), decoded_seed);
|
467
|
+
}
|
468
|
+
|
469
|
+
break;
|
470
|
+
case T_FIXNUM:
|
471
|
+
_xxh32_reset(_get_state_32(self), FIX2UINT(seed));
|
472
|
+
break;
|
473
|
+
case T_BIGNUM:
|
474
|
+
_xxh32_reset(_get_state_32(self), NUM2UINT(seed));
|
475
|
+
break;
|
476
|
+
default:
|
477
|
+
rb_raise(rb_eArgError, "Invalid argument type for seed. Expecting a string or number.");
|
478
|
+
}
|
479
|
+
} else {
|
480
|
+
_xxh32_reset(_get_state_32(self), _XXH32_DEFAULT_SEED);
|
481
|
+
}
|
482
|
+
|
483
|
+
return self;
|
484
|
+
}
|
485
|
+
|
486
|
+
/*
|
487
|
+
* call-seq: initialize_copy(orig) -> self
|
488
|
+
*
|
489
|
+
* This method is called when instances are cloned. It is responsible for
|
490
|
+
* replicating internal data.
|
491
|
+
*/
|
492
|
+
static VALUE _Digest_XXH32_initialize_copy(VALUE self, VALUE orig)
|
493
|
+
{
|
494
|
+
XXH32_copyState(_get_state_32(self), _get_state_32(orig));
|
495
|
+
return self;
|
496
|
+
}
|
497
|
+
|
498
|
+
/*
|
499
|
+
* call-seq: digest_length -> int
|
500
|
+
*
|
501
|
+
* Returns 4.
|
502
|
+
*/
|
503
|
+
static VALUE _Digest_XXH32_digest_length(VALUE self)
|
504
|
+
{
|
505
|
+
return INT2FIX(_XXH32_DIGEST_SIZE);
|
506
|
+
}
|
507
|
+
|
508
|
+
/*
|
509
|
+
* call-seq: block_length -> int
|
510
|
+
*
|
511
|
+
* Returns 4.
|
512
|
+
*/
|
513
|
+
static VALUE _Digest_XXH32_block_length(VALUE self)
|
514
|
+
{
|
515
|
+
return INT2FIX(_XXH32_BLOCK_SIZE);
|
516
|
+
}
|
517
|
+
|
518
|
+
/*
|
519
|
+
* call-seq: digest_length -> int
|
520
|
+
*
|
521
|
+
* Returns 4.
|
522
|
+
*/
|
523
|
+
static VALUE _Digest_XXH32_singleton_digest_length(VALUE self)
|
524
|
+
{
|
525
|
+
return INT2FIX(_XXH32_DIGEST_SIZE);
|
526
|
+
}
|
527
|
+
|
528
|
+
/*
|
529
|
+
* call-seq: block_length -> int
|
530
|
+
*
|
531
|
+
* Returns 4.
|
532
|
+
*/
|
533
|
+
static VALUE _Digest_XXH32_singleton_block_length(VALUE self)
|
534
|
+
{
|
535
|
+
return INT2FIX(_XXH32_BLOCK_SIZE);
|
536
|
+
}
|
537
|
+
|
538
|
+
/*
|
539
|
+
* Document-class: Digest::XXH64
|
540
|
+
*
|
541
|
+
* This class implements XXH64.
|
542
|
+
*/
|
543
|
+
|
544
|
+
static VALUE _Digest_XXH64_internal_allocate(VALUE klass)
|
545
|
+
{
|
546
|
+
XXH64_state_t *state_p;
|
547
|
+
VALUE obj = TypedData_Make_Struct(klass, XXH64_state_t, &_xxh64_state_data_type, state_p);
|
548
|
+
_xxh64_reset(state_p, 0);
|
549
|
+
return obj;
|
550
|
+
}
|
551
|
+
|
552
|
+
/*
|
553
|
+
* call-seq: update(str) -> self
|
554
|
+
*
|
555
|
+
* Updates current digest value with string.
|
556
|
+
*/
|
557
|
+
static VALUE _Digest_XXH64_update(VALUE self, VALUE str)
|
558
|
+
{
|
559
|
+
if (XXH64_update(_get_state_64(self), RSTRING_PTR(str), RSTRING_LEN(str)) != XXH_OK)
|
560
|
+
rb_raise(rb_eRuntimeError, "Failed to reset state.");
|
561
|
+
|
562
|
+
return self;
|
563
|
+
}
|
564
|
+
|
565
|
+
/* :nodoc: */
|
566
|
+
static VALUE _Digest_XXH64_finish(VALUE self)
|
567
|
+
{
|
568
|
+
uint64_t result = XXH64_digest(_get_state_64(self));
|
569
|
+
return _encode_big_endian_64(result);
|
570
|
+
}
|
571
|
+
|
572
|
+
/* :nodoc: */
|
573
|
+
static VALUE _Digest_XXH64_ifinish(VALUE self)
|
574
|
+
{
|
575
|
+
uint64_t result = XXH64_digest(_get_state_64(self));
|
576
|
+
return ULL2NUM(result);
|
577
|
+
}
|
578
|
+
|
579
|
+
/*
|
580
|
+
* call-seq: reset(seed = 0) -> self
|
581
|
+
*
|
582
|
+
* Resets state to initial form with seed.
|
583
|
+
*
|
584
|
+
* This would discard previous calculations with #update.
|
585
|
+
*
|
586
|
+
* +seed+ can be in the form of a string, a hex string, or a number.
|
587
|
+
*
|
588
|
+
* If +seed+ is not provided, the default value would be 0.
|
589
|
+
*/
|
590
|
+
static VALUE _Digest_XXH64_reset(int argc, VALUE* argv, VALUE self)
|
591
|
+
{
|
592
|
+
VALUE seed;
|
593
|
+
|
594
|
+
if (rb_scan_args(argc, argv, "01", &seed) > 0) {
|
595
|
+
switch (TYPE(seed)) {
|
596
|
+
case T_STRING:
|
597
|
+
{
|
598
|
+
int len = RSTRING_LEN(seed);
|
599
|
+
uint64_t decoded_seed;
|
600
|
+
|
601
|
+
if (len == (sizeof(uint64_t) * 2)) {
|
602
|
+
unsigned char hex_decoded_seed[sizeof(uint64_t)];
|
603
|
+
|
604
|
+
if (! hex_decode_str_implied(RSTRING_PTR(seed), sizeof(uint64_t) * 2, hex_decoded_seed))
|
605
|
+
rb_raise(rb_eArgError, "Invalid hex string seed: %s\n", StringValueCStr(seed));
|
606
|
+
|
607
|
+
decoded_seed = _decode_big_endian_64_cstr(hex_decoded_seed);
|
608
|
+
} else if (len == sizeof(uint64_t)) {
|
609
|
+
decoded_seed = _decode_big_endian_64_cstr(RSTRING_PTR(seed));
|
610
|
+
} else {
|
611
|
+
rb_raise(rb_eArgError, "Invalid seed length. Expecting a 16-character hex string or an 8-byte string.");
|
612
|
+
}
|
613
|
+
|
614
|
+
_xxh64_reset(_get_state_64(self), decoded_seed);
|
615
|
+
}
|
616
|
+
|
617
|
+
break;
|
618
|
+
case T_FIXNUM:
|
619
|
+
_xxh64_reset(_get_state_64(self), FIX2UINT(seed));
|
620
|
+
break;
|
621
|
+
case T_BIGNUM:
|
622
|
+
_xxh64_reset(_get_state_64(self), NUM2ULL(seed));
|
623
|
+
break;
|
624
|
+
default:
|
625
|
+
rb_raise(rb_eArgError, "Invalid argument type for seed. Expecting a string or number.");
|
626
|
+
}
|
627
|
+
} else {
|
628
|
+
_xxh64_reset(_get_state_64(self), _XXH64_DEFAULT_SEED);
|
629
|
+
}
|
630
|
+
|
631
|
+
return self;
|
632
|
+
}
|
633
|
+
|
634
|
+
/*
|
635
|
+
* call-seq: initialize_copy(orig) -> self
|
636
|
+
*
|
637
|
+
* This method is called when instances are cloned. It is responsible for
|
638
|
+
* replicating internal data.
|
639
|
+
*/
|
640
|
+
static VALUE _Digest_XXH64_initialize_copy(VALUE self, VALUE orig)
|
641
|
+
{
|
642
|
+
XXH64_copyState(_get_state_64(self), _get_state_64(orig));
|
643
|
+
return self;
|
644
|
+
}
|
645
|
+
|
646
|
+
/*
|
647
|
+
* call-seq: digest_length -> int
|
648
|
+
*
|
649
|
+
* Returns 8.
|
650
|
+
*/
|
651
|
+
static VALUE _Digest_XXH64_digest_length(VALUE self)
|
652
|
+
{
|
653
|
+
return INT2FIX(_XXH64_DIGEST_SIZE);
|
654
|
+
}
|
655
|
+
|
656
|
+
/*
|
657
|
+
* call-seq: block_length -> int
|
658
|
+
*
|
659
|
+
* Returns 8.
|
660
|
+
*/
|
661
|
+
static VALUE _Digest_XXH64_block_length(VALUE self)
|
662
|
+
{
|
663
|
+
return INT2FIX(_XXH64_BLOCK_SIZE);
|
664
|
+
}
|
665
|
+
|
666
|
+
/*
|
667
|
+
* call-seq: digest_length -> int
|
668
|
+
*
|
669
|
+
* Returns 8.
|
670
|
+
*/
|
671
|
+
static VALUE _Digest_XXH64_singleton_digest_length(VALUE self)
|
672
|
+
{
|
673
|
+
return INT2FIX(_XXH64_DIGEST_SIZE);
|
674
|
+
}
|
675
|
+
|
676
|
+
/*
|
677
|
+
* call-seq: block_length -> int
|
678
|
+
*
|
679
|
+
* Returns 8.
|
680
|
+
*/
|
681
|
+
static VALUE _Digest_XXH64_singleton_block_length(VALUE self)
|
682
|
+
{
|
683
|
+
return INT2FIX(_XXH64_BLOCK_SIZE);
|
684
|
+
}
|
685
|
+
|
686
|
+
/*
|
687
|
+
* Initialization
|
688
|
+
*/
|
689
|
+
|
690
|
+
void Init_xxhash()
|
691
|
+
{
|
692
|
+
#define DEFINE_ID(x) _id_##x = rb_intern_const(#x);
|
693
|
+
|
694
|
+
DEFINE_ID(digest)
|
695
|
+
DEFINE_ID(finish)
|
696
|
+
DEFINE_ID(hexdigest)
|
697
|
+
DEFINE_ID(idigest)
|
698
|
+
DEFINE_ID(ifinish)
|
699
|
+
DEFINE_ID(new)
|
700
|
+
DEFINE_ID(reset)
|
701
|
+
DEFINE_ID(update)
|
702
|
+
|
703
|
+
#if 0
|
704
|
+
_Digest = rb_define_module("Digest"); /* Tell RDoc about Digest since it doesn't recognize rb_path2class. */
|
705
|
+
#endif
|
706
|
+
|
707
|
+
rb_require("digest");
|
708
|
+
_Digest = rb_path2class("Digest");
|
709
|
+
|
710
|
+
/*
|
711
|
+
* Document-class: Digest::XXHash
|
712
|
+
*/
|
713
|
+
|
714
|
+
_Digest_XXHash = rb_define_class_under(_Digest, "XXHash", rb_path2class("Digest::Class"));
|
715
|
+
|
716
|
+
rb_define_method(_Digest_XXHash, "digest", _Digest_XXHash_digest, -1);
|
717
|
+
rb_define_method(_Digest_XXHash, "hexdigest", _Digest_XXHash_hexdigest, -1);
|
718
|
+
rb_define_method(_Digest_XXHash, "idigest", _Digest_XXHash_idigest, -1);
|
719
|
+
rb_define_method(_Digest_XXHash, "idigest!", _Digest_XXHash_idigest_bang, 0);
|
720
|
+
rb_define_method(_Digest_XXHash, "initialize", _Digest_XXHash_initialize, -1);
|
721
|
+
rb_define_method(_Digest_XXHash, "inspect", _Digest_XXHash_inspect, 0);
|
722
|
+
rb_define_method(_Digest_XXHash, "initialize_copy", _Digest_XXHash_initialize_copy, 1);
|
723
|
+
|
724
|
+
rb_define_protected_method(_Digest_XXHash, "ifinish", _Digest_XXHash_ifinish, 0);
|
725
|
+
|
726
|
+
rb_define_singleton_method(_Digest_XXHash, "digest", _Digest_XXHash_singleton_digest, -1);
|
727
|
+
rb_define_singleton_method(_Digest_XXHash, "hexdigest", _Digest_XXHash_singleton_hexdigest, -1);
|
728
|
+
rb_define_singleton_method(_Digest_XXHash, "idigest", _Digest_XXHash_singleton_idigest, -1);
|
729
|
+
|
730
|
+
rb_define_alloc_func(_Digest_XXHash, _Digest_XXHash_internal_allocate);
|
731
|
+
|
732
|
+
/*
|
733
|
+
* Document-class: Digest::XXH32
|
734
|
+
*/
|
735
|
+
|
736
|
+
_Digest_XXH32 = rb_define_class_under(_Digest, "XXH32", _Digest_XXHash);
|
737
|
+
|
738
|
+
rb_define_alloc_func(_Digest_XXH32, _Digest_XXH32_internal_allocate);
|
739
|
+
|
740
|
+
rb_define_private_method(_Digest_XXH32, "finish", _Digest_XXH32_finish, 0);
|
741
|
+
rb_define_private_method(_Digest_XXH32, "ifinish", _Digest_XXH32_ifinish, 0);
|
742
|
+
|
743
|
+
rb_define_method(_Digest_XXH32, "update", _Digest_XXH32_update, 1);
|
744
|
+
rb_define_method(_Digest_XXH32, "reset", _Digest_XXH32_reset, -1);
|
745
|
+
rb_define_method(_Digest_XXH32, "digest_length", _Digest_XXH32_digest_length, 0);
|
746
|
+
rb_define_method(_Digest_XXH32, "block_length", _Digest_XXH32_block_length, 0);
|
747
|
+
rb_define_method(_Digest_XXH32, "initialize_copy", _Digest_XXH32_initialize_copy, 1);
|
748
|
+
|
749
|
+
rb_define_singleton_method(_Digest_XXH32, "digest_length", _Digest_XXH32_singleton_digest_length, 0);
|
750
|
+
rb_define_singleton_method(_Digest_XXH32, "block_length", _Digest_XXH32_singleton_block_length, 0);
|
751
|
+
|
752
|
+
/*
|
753
|
+
* Document-class: Digest::XXH64
|
754
|
+
*/
|
755
|
+
|
756
|
+
_Digest_XXH64 = rb_define_class_under(_Digest, "XXH64", _Digest_XXHash);
|
757
|
+
|
758
|
+
rb_define_alloc_func(_Digest_XXH64, _Digest_XXH64_internal_allocate);
|
759
|
+
|
760
|
+
rb_define_private_method(_Digest_XXH64, "finish", _Digest_XXH64_finish, 0);
|
761
|
+
rb_define_private_method(_Digest_XXH64, "ifinish", _Digest_XXH64_ifinish, 0);
|
762
|
+
|
763
|
+
rb_define_method(_Digest_XXH64, "update", _Digest_XXH64_update, 1);
|
764
|
+
rb_define_method(_Digest_XXH64, "reset", _Digest_XXH64_reset, -1);
|
765
|
+
rb_define_method(_Digest_XXH64, "digest_length", _Digest_XXH64_digest_length, 0);
|
766
|
+
rb_define_method(_Digest_XXH64, "block_length", _Digest_XXH64_block_length, 0);
|
767
|
+
rb_define_method(_Digest_XXH64, "initialize_copy", _Digest_XXH64_initialize_copy, 1);
|
768
|
+
|
769
|
+
rb_define_singleton_method(_Digest_XXH64, "digest_length", _Digest_XXH64_singleton_digest_length, 0);
|
770
|
+
rb_define_singleton_method(_Digest_XXH64, "block_length", _Digest_XXH64_singleton_block_length, 0);
|
771
|
+
}
|