digest-xxhash 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|