digest-xxhash 0.0.3 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 70bda38e968bd286bb529fdaea93306867b2711c
4
- data.tar.gz: e70942cbba4e25c06b124e3adc8fd008665c2888
2
+ SHA256:
3
+ metadata.gz: 67c1180d8629bae85bc269796cdae0b67e1fb1942dd5048906c5b785b94b878b
4
+ data.tar.gz: 0f35b3b820f91b12e0439e91dac4bf45a390dfc901d20c730d746886c132ca5a
5
5
  SHA512:
6
- metadata.gz: 987ccbba297ee355686df25fd14225dac3ba89a460fc31b36bcac876c78d18bbac4765cd58f0c8c7cbac9e06c788827de1d7783511a5d76627dff8a545bd180e
7
- data.tar.gz: ae6af3b301e27d9d0d120b9a440f309468337557e829205a7908126e5b34c947e18107e6446af4f217fd423f613c7c679d3f78da5ee68e3add67cce05b34d6c7
6
+ metadata.gz: e7177998d433255ccb0e222257f9161c2e9514418052cf757621b3b13fbdb348dc6a47bd460b94398466496b28ebc7c06b845fc44329156a46309aef749c3bd5
7
+ data.tar.gz: af71a1e091b287e7d2ff9a41f74fc1adb2af73f625a66c9a5f1d64d3001c99034ec00e5b88085d93362b0820e0a33e2ad1f5f70df8b19551247d9a8d84d757da
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017 konsolebox
1
+ Copyright (c) 2021 konsolebox
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # digest-xxhash-ruby
1
+ # digest-xxhash
2
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.
3
+ This gem provides XXH32, XXH64, XXH3_64bits and XXH3_128bits
4
+ functionalities for Ruby. It inherits Digest::Class and complies
5
+ with Digest::Instance's functional design.
6
6
 
7
- Its core implementation was taken from the official source, which is
8
- in https://github.com/Cyan4973/xxHash.
7
+ Its core implementation comes from the official source, which is in
8
+ https://github.com/Cyan4973/xxHash.
9
9
 
10
10
  ## Installation
11
11
 
12
- Add this line to your application's Gemfile:
12
+ Add this line to the application's Gemfile:
13
13
 
14
14
  gem 'digest-xxhash'
15
15
 
@@ -17,10 +17,21 @@ And then execute:
17
17
 
18
18
  $ bundle
19
19
 
20
- Or install it yourself as:
20
+ It can also be installed manually with:
21
21
 
22
22
  $ gem install digest-xxhash
23
23
 
24
+ The library can also be installed in Gentoo system-wide using 'layman':
25
+
26
+ # Fetch remote list of overlays, and add 'konsolebox' overlay
27
+ layman -f && layman -a konsolebox
28
+
29
+ # Unmask unstable keyword
30
+ echo 'dev-ruby/digest-xxhash' > /etc/portage/package.keywords/dev-ruby.digest-xxhash
31
+
32
+ # Merge package
33
+ emerge dev-ruby/digest-xxhash
34
+
24
35
  ## Example Usage
25
36
 
26
37
  require 'digest/xxhash'
@@ -52,10 +63,35 @@ Or install it yourself as:
52
63
  Digest::XXH64.new.reset("0123456789abcdef").update("12").update("34").hexdigest
53
64
  => "d7544504de216507"
54
65
 
66
+ Digest::XXH3_64bits.hexdigest("1234", "0123456789abcdef")
67
+ => "4156724c7605b1be"
68
+
69
+ Digest::XXH3_64bits.new.reset_with_secret("abcd" * 34).update("1234").hexdigest
70
+ => "f7bbdbf9ec8c6394"
71
+
72
+ Digest::XXH3_128bits.hexdigest("1234", "0123456789abcdef") # XXH3_128bits() only allows 64-bit seeds
73
+ => "ad6108fb0b9a6b51b7f80d053c76c0fd"
74
+
75
+ Digest::XXH3_128bits.new.reset_with_secret("abcd" * 34).update("1234").hexdigest
76
+ => "0d44dd7fde8ea2b4ba961e1a26f71f21"
77
+
78
+ ## API Documentation
79
+
80
+ RubyGems.org provides autogenerated API documentation of the library in
81
+ https://www.rubydoc.info/gems/digest-xxhash/.
82
+
83
+ ## Homepage
84
+
85
+ https://rubygems.org/gems/digest-xxhash
86
+
55
87
  ## Contributing
56
88
 
57
89
  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'`).
90
+ 2. Create feature branch (`git checkout -b my-new-feature`).
91
+ 3. Commit changes (`git commit -am 'Add some feature'`).
60
92
  4. Push to the branch (`git push origin my-new-feature`).
61
93
  5. Create a new Pull Request.
94
+
95
+ [![Build Status](https://travis-ci.org/konsolebox/digest-xxhash-ruby.svg?branch=master)](https://travis-ci.org/konsolebox/digest-xxhash-ruby)
96
+ [![Build Status](https://ci.appveyor.com/api/projects/status/kb6hvlxjms3ftw7u?svg=true)](https://ci.appveyor.com/project/konsolebox/digest-xxhash-ruby)
97
+ [![Build Status](https://github.com/konsolebox/digest-xxhash-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/konsolebox/digest-xxhash-ruby/actions/workflows/ruby.yml)
data/Rakefile CHANGED
@@ -1,10 +1,21 @@
1
1
  require 'bundler/gem_tasks'
2
+ require 'rake/extensiontask'
2
3
  require 'rake/testtask'
3
4
 
4
5
  # clean, clobber, compile, and compile:digest/xxhash
5
- require 'rake/extensiontask'
6
6
  Rake::ExtensionTask.new('digest/xxhash', Bundler::GemHelper.gemspec)
7
7
 
8
+ # install
9
+ Rake::Task[:install].clear
10
+ task :install => :build do
11
+ name = Bundler::GemHelper.gemspec.name
12
+ pkg_dir = File.join(Bundler::GemHelper.instance.base, "pkg")
13
+ built_gem = Dir.chdir(pkg_dir){ Dir.glob("#{name}-*.gem").sort_by{ |f| File.mtime(f) }.last }
14
+ gem_command = (ENV["GEM_COMMAND"].shellsplit rescue nil) || ["gem"]
15
+ options = ARGV.select{ |e| e =~ /\A--?/ }
16
+ Process.wait spawn(*gem_command, "install", File.join(pkg_dir, built_gem), *options)
17
+ end
18
+
8
19
  # test
9
20
  Rake::TestTask.new(:test => :compile) do |t|
10
21
  t.test_files = FileList['test/test.rb']
@@ -17,4 +28,7 @@ task :clean do
17
28
  rm_f list unless list.empty?
18
29
  end
19
30
 
31
+ # default
32
+ task :default => :test
33
+
20
34
  # Run `rake --tasks` for a list of tasks.
@@ -9,15 +9,19 @@ Gem::Specification.new do |spec|
9
9
  spec.version = Digest::XXHash::VERSION
10
10
  spec.authors = ["konsolebox"]
11
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."
12
+ spec.summary = "A Digest framework based XXHash library for Ruby"
13
+ spec.description = <<-EOF
14
+ This gem provides XXH32, XXH64, XXH3_64bits and XXH3_128bits
15
+ functionalities for Ruby. It inherits Digest::Class and complies
16
+ with Digest::Instance's functional design.
17
+ EOF
14
18
  spec.homepage = "https://github.com/konsolebox/digest-xxhash-ruby"
15
19
  spec.license = "MIT"
16
20
 
17
21
  spec.required_ruby_version = '>= 2.2'
18
22
 
19
- spec.files = `git ls-files -z`.split("\x0")
20
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.files = `git ls-files -z`.split("\x0").reject{ |f| f =~ /\.yml$/ }
24
+ spec.executables = spec.files.grep(%r{^bin/}){ |f| File.basename(f) }
21
25
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
26
  spec.require_paths = ["lib"]
23
27
 
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2017 konsolebox
2
+ * Copyright (c) 2021 konsolebox
3
3
  *
4
4
  * MIT License
5
5
  *
@@ -23,12 +23,10 @@
23
23
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
24
  */
25
25
 
26
-
27
26
  #include <ruby.h>
28
27
  #include <ruby/digest.h>
29
- #include <stdint.h>
30
28
 
31
- #define XXH_STATIC_LINKING_ONLY
29
+ #define XXH_INLINE_ALL
32
30
  #include "xxhash.h"
33
31
  #include "utils.h"
34
32
 
@@ -39,14 +37,21 @@
39
37
  #endif
40
38
 
41
39
  #define _XXH32_DIGEST_SIZE 4
42
- #define _XXH64_DIGEST_SIZE 8
43
-
44
40
  #define _XXH32_BLOCK_SIZE 4
45
- #define _XXH64_BLOCK_SIZE 8
46
-
47
41
  #define _XXH32_DEFAULT_SEED 0
42
+
43
+ #define _XXH64_DIGEST_SIZE 8
44
+ #define _XXH64_BLOCK_SIZE 8
48
45
  #define _XXH64_DEFAULT_SEED 0
49
46
 
47
+ #define _XXH3_64BITS_DIGEST_SIZE 8
48
+ #define _XXH3_64BITS_BLOCK_SIZE 8
49
+ #define _XXH3_64BITS_DEFAULT_SEED 0
50
+
51
+ #define _XXH3_128BITS_DIGEST_SIZE 16
52
+ #define _XXH3_128BITS_BLOCK_SIZE 16
53
+ #define _XXH3_128BITS_DEFAULT_SEED 0
54
+
50
55
  #if 0
51
56
  # define _DEBUG(...) fprintf(stderr, __VA_ARGS__)
52
57
  #else
@@ -63,9 +68,19 @@ static ID _id_reset;
63
68
  static ID _id_update;
64
69
 
65
70
  static VALUE _Digest;
71
+ static VALUE _Digest_Class;
66
72
  static VALUE _Digest_XXHash;
67
73
  static VALUE _Digest_XXH32;
68
74
  static VALUE _Digest_XXH64;
75
+ static VALUE _Digest_XXH3_64bits;
76
+ static VALUE _Digest_XXH3_128bits;
77
+
78
+ #define _RSTRING_PTR_U(x) ((unsigned char *)RSTRING_PTR(x))
79
+ #define _TWICE(x) (x * 2)
80
+
81
+ static void _xxh32_free_state(void *);
82
+ static void _xxh64_free_state(void *);
83
+ static void _xxh3_free_state(void *);
69
84
 
70
85
  /*
71
86
  * Data types
@@ -73,13 +88,25 @@ static VALUE _Digest_XXH64;
73
88
 
74
89
  static const rb_data_type_t _xxh32_state_data_type = {
75
90
  "xxh32_state_data",
76
- { 0, RUBY_TYPED_DEFAULT_FREE, 0, }, 0, 0,
91
+ { 0, _xxh32_free_state, 0, }, 0, 0,
77
92
  RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
78
93
  };
79
94
 
80
95
  static const rb_data_type_t _xxh64_state_data_type = {
81
96
  "xxh64_state_data",
82
- { 0, RUBY_TYPED_DEFAULT_FREE, 0, }, 0, 0,
97
+ { 0, _xxh64_free_state, 0, }, 0, 0,
98
+ RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
99
+ };
100
+
101
+ static const rb_data_type_t _xxh3_64bits_state_data_type = {
102
+ "xxh3_64bits_state_data",
103
+ { 0, _xxh3_free_state, 0, }, 0, 0,
104
+ RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
105
+ };
106
+
107
+ static const rb_data_type_t _xxh3_128bits_state_data_type = {
108
+ "xxh3_128bits_state_data",
109
+ { 0, _xxh3_free_state, 0, }, 0, 0,
83
110
  RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
84
111
  };
85
112
 
@@ -87,108 +114,93 @@ static const rb_data_type_t _xxh64_state_data_type = {
87
114
  * Common functions
88
115
  */
89
116
 
90
- static XXH32_state_t *_get_state_32(VALUE self)
117
+ static XXH32_state_t *_get_state_xxh32(VALUE self)
91
118
  {
92
119
  XXH32_state_t *state_p;
93
120
  TypedData_Get_Struct(self, XXH32_state_t, &_xxh32_state_data_type, state_p);
94
121
  return state_p;
95
122
  }
96
123
 
97
- static XXH64_state_t *_get_state_64(VALUE self)
124
+ static XXH64_state_t *_get_state_xxh64(VALUE self)
98
125
  {
99
126
  XXH64_state_t *state_p;
100
127
  TypedData_Get_Struct(self, XXH64_state_t, &_xxh64_state_data_type, state_p);
101
128
  return state_p;
102
129
  }
103
130
 
104
- static void _xxh32_reset(XXH32_state_t *state_p, uint32_t seed)
131
+ static XXH3_state_t *_get_state_xxh3_64bits(VALUE self)
105
132
  {
106
- if (XXH32_reset(state_p, seed) != XXH_OK)
107
- rb_raise(rb_eRuntimeError, "Failed to reset state.");
133
+ XXH3_state_t *state_p;
134
+ TypedData_Get_Struct(self, XXH3_state_t, &_xxh3_64bits_state_data_type, state_p);
135
+ return state_p;
108
136
  }
109
137
 
110
- static void _xxh64_reset(XXH64_state_t *state_p, uint64_t seed)
138
+ static XXH3_state_t *_get_state_xxh3_128bits(VALUE self)
111
139
  {
112
- if (XXH64_reset(state_p, seed) != XXH_OK)
113
- rb_raise(rb_eRuntimeError, "Failed to reset state.");
140
+ XXH3_state_t *state_p;
141
+ TypedData_Get_Struct(self, XXH3_state_t, &_xxh3_128bits_state_data_type, state_p);
142
+ return state_p;
114
143
  }
115
144
 
116
- static VALUE _encode_big_endian_32(uint32_t num)
145
+ static void _xxh32_reset(XXH32_state_t *state_p, XXH32_hash_t seed)
117
146
  {
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));
147
+ if (XXH32_reset(state_p, seed) != XXH_OK)
148
+ rb_raise(rb_eRuntimeError, "Failed to reset state.");
127
149
  }
128
150
 
129
- static uint32_t _decode_big_endian_32_cstr(unsigned char *str)
151
+ static void _xxh64_reset(XXH64_state_t *state_p, XXH64_hash_t seed)
130
152
  {
131
- uint32_t temp = read32(str);
132
-
133
- if (is_little_endian()) {
134
- return swap_uint32(temp);
135
- } else {
136
- return temp;
137
- }
153
+ if (XXH64_reset(state_p, seed) != XXH_OK)
154
+ rb_raise(rb_eRuntimeError, "Failed to reset state.");
138
155
  }
139
156
 
140
- static uint32_t _decode_big_endian_32(VALUE str)
157
+ static void _xxh3_64bits_reset(XXH3_state_t *state_p, XXH64_hash_t seed)
141
158
  {
142
- return _decode_big_endian_32_cstr(RSTRING_PTR(str));
159
+ if (XXH3_64bits_reset_withSeed(state_p, seed) != XXH_OK)
160
+ rb_raise(rb_eRuntimeError, "Failed to reset state.");
143
161
  }
144
162
 
145
- static VALUE _encode_big_endian_64(uint64_t num)
163
+ static void _xxh3_128bits_reset(XXH3_state_t *state_p, XXH64_hash_t seed)
146
164
  {
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));
165
+ if (XXH3_128bits_reset_withSeed(state_p, seed) != XXH_OK)
166
+ rb_raise(rb_eRuntimeError, "Failed to reset state.");
156
167
  }
157
168
 
158
- static uint64_t _decode_big_endian_64_cstr(unsigned char *str)
169
+ static void _xxh32_free_state(void* state)
159
170
  {
160
- uint64_t temp = read64(str);
171
+ XXH32_freeState((XXH32_state_t *)state);
172
+ }
161
173
 
162
- if (is_little_endian()) {
163
- return swap_uint64(temp);
164
- } else {
165
- return temp;
166
- }
174
+ static void _xxh64_free_state(void* state)
175
+ {
176
+ XXH64_freeState((XXH64_state_t *)state);
167
177
  }
168
178
 
169
- static uint64_t _decode_big_endian_64(VALUE str)
179
+ static void _xxh3_free_state(void* state)
170
180
  {
171
- return _decode_big_endian_64_cstr(RSTRING_PTR(str));
181
+ XXH3_freeState((XXH3_state_t *)state);
172
182
  }
173
183
 
174
184
  static VALUE _hex_encode_str(VALUE str)
175
185
  {
176
186
  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));
187
+ VALUE hex = rb_usascii_str_new(0, _TWICE(len));
188
+ hex_encode_str_implied(_RSTRING_PTR_U(str), len, _RSTRING_PTR_U(hex));
179
189
  return hex;
180
190
  }
181
191
 
182
192
  /*
183
193
  * Document-class: Digest::XXHash
184
194
  *
185
- * This is the base class of Digest::XXH32 and Digest::XXH64.
195
+ * This is the base class of Digest::XXH32, Digest::XXH64,
196
+ * Digest::XXH3_64bits, and Digest::XXH3_128bits.
186
197
  */
187
198
 
188
199
  static VALUE _Digest_XXHash_internal_allocate(VALUE klass)
189
200
  {
190
201
  if (klass == _Digest_XXHash)
191
- rb_raise(rb_eRuntimeError, "Digest::XXHash is an incomplete class and cannot be instantiated.");
202
+ rb_raise(rb_eRuntimeError, "Digest::XXHash is an incomplete class and cannot be "
203
+ "instantiated.");
192
204
 
193
205
  rb_raise(rb_eNotImpError, "Allocator function not implemented.");
194
206
  }
@@ -221,7 +233,7 @@ static VALUE _Digest_XXHash_ifinish(VALUE self)
221
233
 
222
234
  static VALUE _do_digest(int argc, VALUE* argv, VALUE self, ID finish_method_id)
223
235
  {
224
- VALUE str, seed;
236
+ VALUE str, seed, result;
225
237
  int argc2 = argc > 0 ? rb_scan_args(argc, argv, "02", &str, &seed) : 0;
226
238
 
227
239
  if (argc2 > 0) {
@@ -236,7 +248,7 @@ static VALUE _do_digest(int argc, VALUE* argv, VALUE self, ID finish_method_id)
236
248
  rb_funcall(self, _id_update, 1, str);
237
249
  }
238
250
 
239
- VALUE result = rb_funcall(self, finish_method_id, 0);
251
+ result = rb_funcall(self, finish_method_id, 0);
240
252
 
241
253
  if (argc2 > 0)
242
254
  rb_funcall(self, _id_reset, 0);
@@ -258,8 +270,9 @@ static VALUE _do_digest(int argc, VALUE* argv, VALUE self, ID finish_method_id)
258
270
  * with +seed+, and is used as the return value. The instance's state is reset
259
271
  * to default afterwards.
260
272
  *
261
- * Providing an argument means that previous calculations done with #update
262
- * would be discarded, so be careful with its use.
273
+ * Providing an argument means that previous initializations done with custom
274
+ * seeds or secrets, and previous calculations done with #update would be
275
+ * discarded, so be careful with its use.
263
276
  *
264
277
  * +seed+ can be in the form of a string, a hex string, or a number.
265
278
  */
@@ -278,8 +291,7 @@ static VALUE _Digest_XXHash_digest(int argc, VALUE* argv, VALUE self)
278
291
  */
279
292
  static VALUE _Digest_XXHash_hexdigest(int argc, VALUE* argv, VALUE self)
280
293
  {
281
- VALUE result = _do_digest(argc, argv, self, _id_finish);
282
- return _hex_encode_str(result);
294
+ return _hex_encode_str(_do_digest(argc, argv, self, _id_finish));
283
295
  }
284
296
 
285
297
  /*
@@ -302,7 +314,8 @@ static VALUE _Digest_XXHash_idigest(int argc, VALUE* argv, VALUE self)
302
314
  */
303
315
  static VALUE _Digest_XXHash_idigest_bang(VALUE self)
304
316
  {
305
- VALUE result = rb_funcall(self, _id_ifinish, 0);
317
+ VALUE result;
318
+ result = rb_funcall(self, _id_ifinish, 0);
306
319
  rb_funcall(self, _id_reset, 0);
307
320
  return result;
308
321
  }
@@ -313,7 +326,7 @@ static VALUE _Digest_XXHash_idigest_bang(VALUE self)
313
326
  * This method is called when instances are cloned. It is responsible for
314
327
  * replicating internal data.
315
328
  */
316
- static VALUE _Digest_XXHash_initialize_copy(VALUE orig)
329
+ static VALUE _Digest_XXHash_initialize_copy(VALUE self, VALUE orig)
317
330
  {
318
331
  rb_raise(rb_eNotImpError, "initialize_copy method not implemented.");
319
332
  }
@@ -325,27 +338,31 @@ static VALUE _Digest_XXHash_initialize_copy(VALUE orig)
325
338
  */
326
339
  static VALUE _Digest_XXHash_inspect(VALUE self)
327
340
  {
328
- VALUE klass = rb_obj_class(self);
329
- VALUE klass_name = rb_class_name(klass);
341
+ VALUE klass, klass_name, hexdigest, args[2];
342
+ klass = rb_obj_class(self);
343
+ klass_name = rb_class_name(klass);
330
344
 
331
345
  if (klass_name == Qnil)
332
346
  klass_name = rb_inspect(klass);
333
347
 
334
- VALUE hexdigest = rb_funcall(self, _id_hexdigest, 0);
348
+ hexdigest = rb_funcall(self, _id_hexdigest, 0);
335
349
 
336
- VALUE args[] = { klass_name, hexdigest };
350
+ args[0] = klass_name;
351
+ args[1] = hexdigest;
337
352
  return rb_str_format(sizeof(args), args, rb_str_new_literal("#<%s|%s>"));
338
353
  }
339
354
 
340
355
  static VALUE _instantiate_and_digest(int argc, VALUE* argv, VALUE klass, ID digest_method_id)
341
356
  {
342
- VALUE str, seed;
343
- int argc2 = rb_scan_args(argc, argv, "11", &str, &seed);
357
+ VALUE str, seed, instance;
358
+ int argc2;
359
+
360
+ argc2 = rb_scan_args(argc, argv, "11", &str, &seed);
344
361
 
345
362
  if (TYPE(str) != T_STRING)
346
363
  rb_raise(rb_eTypeError, "Argument type not string.");
347
364
 
348
- VALUE instance = rb_funcall(klass, _id_new, 0);
365
+ instance = rb_funcall(klass, _id_new, 0);
349
366
 
350
367
  if (argc2 > 1)
351
368
  return rb_funcall(instance, digest_method_id, 2, str, seed);
@@ -395,10 +412,9 @@ static VALUE _Digest_XXHash_singleton_idigest(int argc, VALUE* argv, VALUE self)
395
412
 
396
413
  static VALUE _Digest_XXH32_internal_allocate(VALUE klass)
397
414
  {
398
- XXH32_state_t *state_p;
399
- VALUE obj = TypedData_Make_Struct(klass, XXH32_state_t, &_xxh32_state_data_type, state_p);
415
+ XXH32_state_t *state_p = XXH32_createState();
400
416
  _xxh32_reset(state_p, 0);
401
- return obj;
417
+ return TypedData_Wrap_Struct(klass, &_xxh32_state_data_type, state_p);
402
418
  }
403
419
 
404
420
  /*
@@ -408,8 +424,8 @@ static VALUE _Digest_XXH32_internal_allocate(VALUE klass)
408
424
  */
409
425
  static VALUE _Digest_XXH32_update(VALUE self, VALUE str)
410
426
  {
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.");
427
+ if (XXH32_update(_get_state_xxh32(self), RSTRING_PTR(str), RSTRING_LEN(str)) != XXH_OK)
428
+ rb_raise(rb_eRuntimeError, "Failed to update state.");
413
429
 
414
430
  return self;
415
431
  }
@@ -417,15 +433,17 @@ static VALUE _Digest_XXH32_update(VALUE self, VALUE str)
417
433
  /* :nodoc: */
418
434
  static VALUE _Digest_XXH32_finish(VALUE self)
419
435
  {
420
- uint32_t result = XXH32_digest(_get_state_32(self));
421
- return _encode_big_endian_32(result);
436
+ XXH64_hash_t hash = XXH32_digest(_get_state_xxh32(self));
437
+ VALUE str = rb_usascii_str_new(0, sizeof(XXH32_canonical_t));
438
+ XXH32_canonicalFromHash((XXH32_canonical_t *)RSTRING_PTR(str), hash);
439
+ return str;
422
440
  }
423
441
 
424
442
  /* :nodoc: */
425
443
  static VALUE _Digest_XXH32_ifinish(VALUE self)
426
444
  {
427
- uint32_t result = XXH32_digest(_get_state_32(self));
428
- return ULONG2NUM(result);
445
+ XXH32_hash_t hash = XXH32_digest(_get_state_xxh32(self));
446
+ return ULONG2NUM(hash);
429
447
  }
430
448
 
431
449
  /*
@@ -433,9 +451,10 @@ static VALUE _Digest_XXH32_ifinish(VALUE self)
433
451
  *
434
452
  * Resets state to initial form with seed.
435
453
  *
436
- * This would discard previous calculations with #update.
454
+ * This discards previous calculations with #update.
437
455
  *
438
456
  * +seed+ can be in the form of a string, a hex string, or a number.
457
+ * Its virtual length should be 32-bits.
439
458
  *
440
459
  * If +seed+ is not provided, the default value would be 0.
441
460
  */
@@ -448,36 +467,39 @@ static VALUE _Digest_XXH32_reset(int argc, VALUE* argv, VALUE self)
448
467
  case T_STRING:
449
468
  {
450
469
  int len = RSTRING_LEN(seed);
451
- uint32_t decoded_seed;
470
+ XXH32_hash_t decoded_seed;
452
471
 
453
- if (len == (sizeof(uint32_t) * 2)) {
454
- unsigned char hex_decoded_seed[sizeof(uint32_t)];
472
+ if (len == _TWICE(sizeof(XXH32_hash_t))) {
473
+ unsigned char hex_decoded_seed[sizeof(XXH32_hash_t)];
455
474
 
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));
475
+ if (! hex_decode_str_implied(_RSTRING_PTR_U(seed), len, hex_decoded_seed))
476
+ rb_raise(rb_eArgError, "Invalid hex string seed: %s\n",
477
+ StringValueCStr(seed));
458
478
 
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));
479
+ decoded_seed = XXH_readBE32(hex_decoded_seed);
480
+ } else if (len == sizeof(XXH32_hash_t)) {
481
+ decoded_seed = XXH_readBE32(RSTRING_PTR(seed));
462
482
  } else {
463
- rb_raise(rb_eArgError, "Invalid seed length. Expecting an 8-character hex string or a 4-byte string.");
483
+ rb_raise(rb_eArgError, "Invalid seed length. "
484
+ "Expecting an 8-character hex string or a 4-byte string.");
464
485
  }
465
486
 
466
- _xxh32_reset(_get_state_32(self), decoded_seed);
487
+ _xxh32_reset(_get_state_xxh32(self), decoded_seed);
467
488
  }
468
489
 
469
490
  break;
470
491
  case T_FIXNUM:
471
- _xxh32_reset(_get_state_32(self), FIX2UINT(seed));
492
+ _xxh32_reset(_get_state_xxh32(self), FIX2UINT(seed));
472
493
  break;
473
494
  case T_BIGNUM:
474
- _xxh32_reset(_get_state_32(self), NUM2UINT(seed));
495
+ _xxh32_reset(_get_state_xxh32(self), NUM2UINT(seed));
475
496
  break;
476
497
  default:
477
- rb_raise(rb_eArgError, "Invalid argument type for seed. Expecting a string or number.");
498
+ rb_raise(rb_eArgError, "Invalid argument type for 'seed'. "
499
+ "Expecting a string or a number.");
478
500
  }
479
501
  } else {
480
- _xxh32_reset(_get_state_32(self), _XXH32_DEFAULT_SEED);
502
+ _xxh32_reset(_get_state_xxh32(self), _XXH32_DEFAULT_SEED);
481
503
  }
482
504
 
483
505
  return self;
@@ -491,14 +513,14 @@ static VALUE _Digest_XXH32_reset(int argc, VALUE* argv, VALUE self)
491
513
  */
492
514
  static VALUE _Digest_XXH32_initialize_copy(VALUE self, VALUE orig)
493
515
  {
494
- XXH32_copyState(_get_state_32(self), _get_state_32(orig));
516
+ XXH32_copyState(_get_state_xxh32(self), _get_state_xxh32(orig));
495
517
  return self;
496
518
  }
497
519
 
498
520
  /*
499
521
  * call-seq: digest_length -> int
500
522
  *
501
- * Returns 4.
523
+ * Returns 4
502
524
  */
503
525
  static VALUE _Digest_XXH32_digest_length(VALUE self)
504
526
  {
@@ -508,7 +530,7 @@ static VALUE _Digest_XXH32_digest_length(VALUE self)
508
530
  /*
509
531
  * call-seq: block_length -> int
510
532
  *
511
- * Returns 4.
533
+ * Returns 4
512
534
  */
513
535
  static VALUE _Digest_XXH32_block_length(VALUE self)
514
536
  {
@@ -518,7 +540,7 @@ static VALUE _Digest_XXH32_block_length(VALUE self)
518
540
  /*
519
541
  * call-seq: digest_length -> int
520
542
  *
521
- * Returns 4.
543
+ * Returns 4
522
544
  */
523
545
  static VALUE _Digest_XXH32_singleton_digest_length(VALUE self)
524
546
  {
@@ -528,7 +550,7 @@ static VALUE _Digest_XXH32_singleton_digest_length(VALUE self)
528
550
  /*
529
551
  * call-seq: block_length -> int
530
552
  *
531
- * Returns 4.
553
+ * Returns 4
532
554
  */
533
555
  static VALUE _Digest_XXH32_singleton_block_length(VALUE self)
534
556
  {
@@ -543,10 +565,9 @@ static VALUE _Digest_XXH32_singleton_block_length(VALUE self)
543
565
 
544
566
  static VALUE _Digest_XXH64_internal_allocate(VALUE klass)
545
567
  {
546
- XXH64_state_t *state_p;
547
- VALUE obj = TypedData_Make_Struct(klass, XXH64_state_t, &_xxh64_state_data_type, state_p);
568
+ XXH64_state_t *state_p = XXH64_createState();
548
569
  _xxh64_reset(state_p, 0);
549
- return obj;
570
+ return TypedData_Wrap_Struct(klass, &_xxh64_state_data_type, state_p);
550
571
  }
551
572
 
552
573
  /*
@@ -556,8 +577,8 @@ static VALUE _Digest_XXH64_internal_allocate(VALUE klass)
556
577
  */
557
578
  static VALUE _Digest_XXH64_update(VALUE self, VALUE str)
558
579
  {
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.");
580
+ if (XXH64_update(_get_state_xxh64(self), RSTRING_PTR(str), RSTRING_LEN(str)) != XXH_OK)
581
+ rb_raise(rb_eRuntimeError, "Failed to update state.");
561
582
 
562
583
  return self;
563
584
  }
@@ -565,15 +586,17 @@ static VALUE _Digest_XXH64_update(VALUE self, VALUE str)
565
586
  /* :nodoc: */
566
587
  static VALUE _Digest_XXH64_finish(VALUE self)
567
588
  {
568
- uint64_t result = XXH64_digest(_get_state_64(self));
569
- return _encode_big_endian_64(result);
589
+ XXH64_hash_t hash = XXH64_digest(_get_state_xxh64(self));
590
+ VALUE str = rb_usascii_str_new(0, sizeof(XXH64_canonical_t));
591
+ XXH64_canonicalFromHash((XXH64_canonical_t *)RSTRING_PTR(str), hash);
592
+ return str;
570
593
  }
571
594
 
572
595
  /* :nodoc: */
573
596
  static VALUE _Digest_XXH64_ifinish(VALUE self)
574
597
  {
575
- uint64_t result = XXH64_digest(_get_state_64(self));
576
- return ULL2NUM(result);
598
+ XXH64_hash_t hash = XXH64_digest(_get_state_xxh64(self));
599
+ return ULL2NUM(hash);
577
600
  }
578
601
 
579
602
  /*
@@ -581,9 +604,10 @@ static VALUE _Digest_XXH64_ifinish(VALUE self)
581
604
  *
582
605
  * Resets state to initial form with seed.
583
606
  *
584
- * This would discard previous calculations with #update.
607
+ * This discards previous calculations with #update.
585
608
  *
586
609
  * +seed+ can be in the form of a string, a hex string, or a number.
610
+ * Its virtual length should be 64-bits.
587
611
  *
588
612
  * If +seed+ is not provided, the default value would be 0.
589
613
  */
@@ -596,36 +620,39 @@ static VALUE _Digest_XXH64_reset(int argc, VALUE* argv, VALUE self)
596
620
  case T_STRING:
597
621
  {
598
622
  int len = RSTRING_LEN(seed);
599
- uint64_t decoded_seed;
623
+ XXH64_hash_t decoded_seed;
600
624
 
601
- if (len == (sizeof(uint64_t) * 2)) {
602
- unsigned char hex_decoded_seed[sizeof(uint64_t)];
625
+ if (len == _TWICE(sizeof(XXH64_hash_t))) {
626
+ unsigned char hex_decoded_seed[sizeof(XXH64_hash_t)];
603
627
 
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));
628
+ if (! hex_decode_str_implied(_RSTRING_PTR_U(seed), len, hex_decoded_seed))
629
+ rb_raise(rb_eArgError, "Invalid hex string seed: %s\n",
630
+ StringValueCStr(seed));
606
631
 
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));
632
+ decoded_seed = XXH_readBE64(hex_decoded_seed);
633
+ } else if (len == sizeof(XXH64_hash_t)) {
634
+ decoded_seed = XXH_readBE64(RSTRING_PTR(seed));
610
635
  } else {
611
- rb_raise(rb_eArgError, "Invalid seed length. Expecting a 16-character hex string or an 8-byte string.");
636
+ rb_raise(rb_eArgError, "Invalid seed length. "
637
+ "Expecting a 16-character hex string or an 8-byte string.");
612
638
  }
613
639
 
614
- _xxh64_reset(_get_state_64(self), decoded_seed);
640
+ _xxh64_reset(_get_state_xxh64(self), decoded_seed);
615
641
  }
616
642
 
617
643
  break;
618
644
  case T_FIXNUM:
619
- _xxh64_reset(_get_state_64(self), FIX2UINT(seed));
645
+ _xxh64_reset(_get_state_xxh64(self), FIX2UINT(seed));
620
646
  break;
621
647
  case T_BIGNUM:
622
- _xxh64_reset(_get_state_64(self), NUM2ULL(seed));
648
+ _xxh64_reset(_get_state_xxh64(self), NUM2ULL(seed));
623
649
  break;
624
650
  default:
625
- rb_raise(rb_eArgError, "Invalid argument type for seed. Expecting a string or number.");
651
+ rb_raise(rb_eArgError, "Invalid argument type for 'seed'. "
652
+ "Expecting a string or a number.");
626
653
  }
627
654
  } else {
628
- _xxh64_reset(_get_state_64(self), _XXH64_DEFAULT_SEED);
655
+ _xxh64_reset(_get_state_xxh64(self), _XXH64_DEFAULT_SEED);
629
656
  }
630
657
 
631
658
  return self;
@@ -639,14 +666,14 @@ static VALUE _Digest_XXH64_reset(int argc, VALUE* argv, VALUE self)
639
666
  */
640
667
  static VALUE _Digest_XXH64_initialize_copy(VALUE self, VALUE orig)
641
668
  {
642
- XXH64_copyState(_get_state_64(self), _get_state_64(orig));
669
+ XXH64_copyState(_get_state_xxh64(self), _get_state_xxh64(orig));
643
670
  return self;
644
671
  }
645
672
 
646
673
  /*
647
674
  * call-seq: digest_length -> int
648
675
  *
649
- * Returns 8.
676
+ * Returns 8
650
677
  */
651
678
  static VALUE _Digest_XXH64_digest_length(VALUE self)
652
679
  {
@@ -656,7 +683,7 @@ static VALUE _Digest_XXH64_digest_length(VALUE self)
656
683
  /*
657
684
  * call-seq: block_length -> int
658
685
  *
659
- * Returns 8.
686
+ * Returns 8
660
687
  */
661
688
  static VALUE _Digest_XXH64_block_length(VALUE self)
662
689
  {
@@ -666,7 +693,7 @@ static VALUE _Digest_XXH64_block_length(VALUE self)
666
693
  /*
667
694
  * call-seq: digest_length -> int
668
695
  *
669
- * Returns 8.
696
+ * Returns 8
670
697
  */
671
698
  static VALUE _Digest_XXH64_singleton_digest_length(VALUE self)
672
699
  {
@@ -676,13 +703,378 @@ static VALUE _Digest_XXH64_singleton_digest_length(VALUE self)
676
703
  /*
677
704
  * call-seq: block_length -> int
678
705
  *
679
- * Returns 8.
706
+ * Returns 8
680
707
  */
681
708
  static VALUE _Digest_XXH64_singleton_block_length(VALUE self)
682
709
  {
683
710
  return INT2FIX(_XXH64_BLOCK_SIZE);
684
711
  }
685
712
 
713
+ /*
714
+ * Document-class: Digest::XXH3_64bits
715
+ *
716
+ * This class implements XXH3_64bits.
717
+ */
718
+
719
+ static VALUE _Digest_XXH3_64bits_internal_allocate(VALUE klass)
720
+ {
721
+ XXH3_state_t *state_p = XXH3_createState();
722
+ XXH3_64bits_reset(state_p);
723
+ return TypedData_Wrap_Struct(klass, &_xxh3_64bits_state_data_type, state_p);
724
+ }
725
+
726
+ /*
727
+ * call-seq: update(str) -> self
728
+ *
729
+ * Updates current digest value with string.
730
+ */
731
+ static VALUE _Digest_XXH3_64bits_update(VALUE self, VALUE str)
732
+ {
733
+ if (XXH3_64bits_update(_get_state_xxh3_64bits(self), RSTRING_PTR(str), RSTRING_LEN(str)) != XXH_OK)
734
+ rb_raise(rb_eRuntimeError, "Failed to update state.");
735
+
736
+ return self;
737
+ }
738
+
739
+ /* :nodoc: */
740
+ static VALUE _Digest_XXH3_64bits_finish(VALUE self)
741
+ {
742
+ XXH64_hash_t hash = XXH3_64bits_digest(_get_state_xxh3_64bits(self));
743
+ VALUE str = rb_usascii_str_new(0, sizeof(XXH64_canonical_t));
744
+ XXH64_canonicalFromHash((XXH64_canonical_t *)RSTRING_PTR(str), hash);
745
+ return str;
746
+ }
747
+
748
+ /* :nodoc: */
749
+ static VALUE _Digest_XXH3_64bits_ifinish(VALUE self)
750
+ {
751
+ XXH64_hash_t hash = XXH3_64bits_digest(_get_state_xxh3_64bits(self));
752
+ return ULL2NUM(hash);
753
+ }
754
+
755
+ /*
756
+ * call-seq: reset(seed = 0) -> self
757
+ *
758
+ * Resets state to initial form with seed.
759
+ *
760
+ * This discards previous calculations with #update.
761
+ *
762
+ * +seed+ can be in the form of a string, a hex string, or a number.
763
+ * Its virtual length should be 64-bits.
764
+ *
765
+ * If +seed+ is not provided, the default value would be 0.
766
+ */
767
+ static VALUE _Digest_XXH3_64bits_reset(int argc, VALUE* argv, VALUE self)
768
+ {
769
+ VALUE seed;
770
+
771
+ if (rb_scan_args(argc, argv, "01", &seed) > 0) {
772
+ switch (TYPE(seed)) {
773
+ case T_STRING:
774
+ {
775
+ int len = RSTRING_LEN(seed);
776
+ XXH64_hash_t decoded_seed;
777
+
778
+ if (len == _TWICE(sizeof(XXH64_hash_t))) {
779
+ unsigned char hex_decoded_seed[sizeof(XXH64_hash_t)];
780
+
781
+ if (! hex_decode_str_implied(_RSTRING_PTR_U(seed), len, hex_decoded_seed))
782
+ rb_raise(rb_eArgError, "Invalid hex string seed: %s\n",
783
+ StringValueCStr(seed));
784
+
785
+ decoded_seed = XXH_readBE64(hex_decoded_seed);
786
+ } else if (len == sizeof(XXH64_hash_t)) {
787
+ decoded_seed = XXH_readBE64(RSTRING_PTR(seed));
788
+ } else {
789
+ rb_raise(rb_eArgError, "Invalid seed length. "
790
+ "Expecting a 16-character hex string or an 8-byte string.");
791
+ }
792
+
793
+ _xxh3_64bits_reset(_get_state_xxh3_64bits(self), decoded_seed);
794
+ }
795
+
796
+ break;
797
+ case T_FIXNUM:
798
+ _xxh3_64bits_reset(_get_state_xxh3_64bits(self), FIX2UINT(seed));
799
+ break;
800
+ case T_BIGNUM:
801
+ _xxh3_64bits_reset(_get_state_xxh3_64bits(self), NUM2ULL(seed));
802
+ break;
803
+ default:
804
+ rb_raise(rb_eArgError, "Invalid argument type for 'seed'. "
805
+ "Expecting a string or a number.");
806
+ }
807
+ } else {
808
+ _xxh3_64bits_reset(_get_state_xxh3_64bits(self), _XXH3_64BITS_DEFAULT_SEED);
809
+ }
810
+
811
+ return self;
812
+ }
813
+
814
+ /*
815
+ * call-seq: reset_with_secret(secret) -> self
816
+ *
817
+ * Resets state to initial form using a secret.
818
+ *
819
+ * This discards previous calculations with #update.
820
+ *
821
+ * Secret should be a string and have a minimum length of XXH3_SECRET_SIZE_MIN.
822
+ */
823
+ static VALUE _Digest_XXH3_64bits_reset_with_secret(VALUE self, VALUE secret)
824
+ {
825
+ if (TYPE(secret) != T_STRING)
826
+ rb_raise(rb_eArgError, "Argument 'secret' needs to be a string.");
827
+
828
+ if (RSTRING_LEN(secret) < XXH3_SECRET_SIZE_MIN)
829
+ rb_raise(rb_eRuntimeError, "Secret needs to be at least %d bytes in length.",
830
+ XXH3_SECRET_SIZE_MIN);
831
+
832
+ if (XXH3_64bits_reset_withSecret(_get_state_xxh3_64bits(self), RSTRING_PTR(secret),
833
+ RSTRING_LEN(secret)) != XXH_OK)
834
+ rb_raise(rb_eRuntimeError, "Failed to reset state with secret.");
835
+
836
+ return self;
837
+ }
838
+
839
+ /*
840
+ * call-seq: initialize_copy(orig) -> self
841
+ *
842
+ * This method is called when instances are cloned. It is responsible for
843
+ * replicating internal data.
844
+ */
845
+ static VALUE _Digest_XXH3_64bits_initialize_copy(VALUE self, VALUE orig)
846
+ {
847
+ XXH3_copyState(_get_state_xxh3_64bits(self), _get_state_xxh3_64bits(orig));
848
+ return self;
849
+ }
850
+
851
+ /*
852
+ * call-seq: digest_length -> int
853
+ *
854
+ * Returns 8
855
+ */
856
+ static VALUE _Digest_XXH3_64bits_digest_length(VALUE self)
857
+ {
858
+ return INT2FIX(_XXH3_64BITS_DIGEST_SIZE);
859
+ }
860
+
861
+ /*
862
+ * call-seq: block_length -> int
863
+ *
864
+ * Returns 8
865
+ */
866
+ static VALUE _Digest_XXH3_64bits_block_length(VALUE self)
867
+ {
868
+ return INT2FIX(_XXH3_64BITS_BLOCK_SIZE);
869
+ }
870
+
871
+ /*
872
+ * call-seq: digest_length -> int
873
+ *
874
+ * Returns 8
875
+ */
876
+ static VALUE _Digest_XXH3_64bits_singleton_digest_length(VALUE self)
877
+ {
878
+ return INT2FIX(_XXH3_64BITS_DIGEST_SIZE);
879
+ }
880
+
881
+ /*
882
+ * call-seq: block_length -> int
883
+ *
884
+ * Returns 8
885
+ */
886
+ static VALUE _Digest_XXH3_64bits_singleton_block_length(VALUE self)
887
+ {
888
+ return INT2FIX(_XXH3_64BITS_BLOCK_SIZE);
889
+ }
890
+
891
+ /*
892
+ * Document-class: Digest::XXH3_128bits
893
+ *
894
+ * This class implements XXH3_128bits.
895
+ */
896
+
897
+ static VALUE _Digest_XXH3_128bits_internal_allocate(VALUE klass)
898
+ {
899
+ XXH3_state_t *state_p = XXH3_createState();
900
+ XXH3_128bits_reset(state_p);
901
+ return TypedData_Wrap_Struct(klass, &_xxh3_128bits_state_data_type, state_p);
902
+ }
903
+
904
+ /*
905
+ * call-seq: update(str) -> self
906
+ *
907
+ * Updates current digest value with string.
908
+ */
909
+ static VALUE _Digest_XXH3_128bits_update(VALUE self, VALUE str)
910
+ {
911
+ if (XXH3_128bits_update(_get_state_xxh3_128bits(self), RSTRING_PTR(str), RSTRING_LEN(str)) != XXH_OK)
912
+ rb_raise(rb_eRuntimeError, "Failed to update state.");
913
+
914
+ return self;
915
+ }
916
+
917
+ /* :nodoc: */
918
+ static VALUE _Digest_XXH3_128bits_finish(VALUE self)
919
+ {
920
+ XXH128_hash_t hash = XXH3_128bits_digest(_get_state_xxh3_128bits(self));
921
+ VALUE str = rb_usascii_str_new(0, sizeof(XXH128_canonical_t));
922
+ XXH128_canonicalFromHash((XXH128_canonical_t *)RSTRING_PTR(str), hash);
923
+ return str;
924
+ }
925
+
926
+ /* :nodoc: */
927
+ static VALUE _Digest_XXH3_128bits_ifinish(VALUE self)
928
+ {
929
+ XXH128_hash_t hash = XXH3_128bits_digest(_get_state_xxh3_128bits(self));
930
+
931
+ if (! XXH_CPU_LITTLE_ENDIAN) {
932
+ #define _SWAP_WORDS(x) ((x << 32) & 0xffffffff00000000ULL) | \
933
+ ((x >> 32) & 0x000000000ffffffffULL)
934
+ hash.low64 = _SWAP_WORDS(hash.low64);
935
+ hash.high64 = _SWAP_WORDS(hash.high64);
936
+ }
937
+
938
+ return rb_integer_unpack(&hash, 4, sizeof(XXH32_hash_t), 0, INTEGER_PACK_LSWORD_FIRST|
939
+ INTEGER_PACK_NATIVE_BYTE_ORDER);
940
+ }
941
+
942
+ /*
943
+ * call-seq: reset(seed = 0) -> self
944
+ *
945
+ * Resets state to initial form with seed.
946
+ *
947
+ * This discards previous calculations with #update.
948
+ *
949
+ * +seed+ can be in the form of a string, a hex string, or a number.
950
+ * Its virtual length should be 64-bits and not 128-bits.
951
+ *
952
+ * If +seed+ is not provided, the default value would be 0.
953
+ */
954
+ static VALUE _Digest_XXH3_128bits_reset(int argc, VALUE* argv, VALUE self)
955
+ {
956
+ VALUE seed;
957
+
958
+ if (rb_scan_args(argc, argv, "01", &seed) > 0) {
959
+ switch (TYPE(seed)) {
960
+ case T_STRING:
961
+ {
962
+ int len = RSTRING_LEN(seed);
963
+ XXH64_hash_t decoded_seed;
964
+
965
+ if (len == _TWICE(sizeof(XXH64_hash_t))) {
966
+ unsigned char hex_decoded_seed[sizeof(XXH64_hash_t)];
967
+
968
+ if (! hex_decode_str_implied(_RSTRING_PTR_U(seed), len, hex_decoded_seed))
969
+ rb_raise(rb_eArgError, "Invalid hex string seed: %s\n",
970
+ StringValueCStr(seed));
971
+
972
+ decoded_seed = XXH_readBE64(hex_decoded_seed);
973
+ } else if (len == sizeof(XXH64_hash_t)) {
974
+ decoded_seed = XXH_readBE64(RSTRING_PTR(seed));
975
+ } else {
976
+ rb_raise(rb_eArgError, "Invalid seed length. Expecting a 16-character hex "
977
+ "string or an 8-byte string.");
978
+ }
979
+
980
+ _xxh3_128bits_reset(_get_state_xxh3_128bits(self), decoded_seed);
981
+ }
982
+
983
+ break;
984
+ case T_FIXNUM:
985
+ _xxh3_128bits_reset(_get_state_xxh3_128bits(self), FIX2UINT(seed));
986
+ break;
987
+ case T_BIGNUM:
988
+ _xxh3_128bits_reset(_get_state_xxh3_128bits(self), NUM2ULL(seed));
989
+ break;
990
+ default:
991
+ rb_raise(rb_eArgError, "Invalid argument type for 'seed'. "
992
+ "Expecting a string or a number.");
993
+ }
994
+ } else {
995
+ _xxh3_128bits_reset(_get_state_xxh3_128bits(self), _XXH3_128BITS_DEFAULT_SEED);
996
+ }
997
+
998
+ return self;
999
+ }
1000
+
1001
+ /*
1002
+ * call-seq: reset_with_secret(secret) -> self
1003
+ *
1004
+ * Resets state to initial form using a secret.
1005
+ *
1006
+ * This discards previous calculations with #update.
1007
+ *
1008
+ * Secret should be a string having a minimum length of XXH3_SECRET_SIZE_MIN.
1009
+ */
1010
+ static VALUE _Digest_XXH3_128bits_reset_with_secret(VALUE self, VALUE secret)
1011
+ {
1012
+ if (TYPE(secret) != T_STRING)
1013
+ rb_raise(rb_eArgError, "Argument 'secret' needs to be a string.");
1014
+
1015
+ if (RSTRING_LEN(secret) < XXH3_SECRET_SIZE_MIN)
1016
+ rb_raise(rb_eRuntimeError, "Secret needs to be at least %d bytes in length.",
1017
+ XXH3_SECRET_SIZE_MIN);
1018
+
1019
+ if (XXH3_128bits_reset_withSecret(_get_state_xxh3_128bits(self), RSTRING_PTR(secret),
1020
+ RSTRING_LEN(secret)) != XXH_OK)
1021
+ rb_raise(rb_eRuntimeError, "Failed to reset state with secret.");
1022
+
1023
+ return self;
1024
+ }
1025
+
1026
+ /*
1027
+ * call-seq: initialize_copy(orig) -> self
1028
+ *
1029
+ * This method is called when instances are cloned. It is responsible for
1030
+ * replicating internal data.
1031
+ */
1032
+ static VALUE _Digest_XXH3_128bits_initialize_copy(VALUE self, VALUE orig)
1033
+ {
1034
+ XXH3_copyState(_get_state_xxh3_128bits(self), _get_state_xxh3_128bits(orig));
1035
+ return self;
1036
+ }
1037
+
1038
+ /*
1039
+ * call-seq: digest_length -> int
1040
+ *
1041
+ * Returns 16
1042
+ */
1043
+ static VALUE _Digest_XXH3_128bits_digest_length(VALUE self)
1044
+ {
1045
+ return INT2FIX(_XXH3_128BITS_DIGEST_SIZE);
1046
+ }
1047
+
1048
+ /*
1049
+ * call-seq: block_length -> int
1050
+ *
1051
+ * Returns 16
1052
+ */
1053
+ static VALUE _Digest_XXH3_128bits_block_length(VALUE self)
1054
+ {
1055
+ return INT2FIX(_XXH3_128BITS_BLOCK_SIZE);
1056
+ }
1057
+
1058
+ /*
1059
+ * call-seq: digest_length -> int
1060
+ *
1061
+ * Returns 16
1062
+ */
1063
+ static VALUE _Digest_XXH3_128bits_singleton_digest_length(VALUE self)
1064
+ {
1065
+ return INT2FIX(_XXH3_128BITS_DIGEST_SIZE);
1066
+ }
1067
+
1068
+ /*
1069
+ * call-seq: block_length -> int
1070
+ *
1071
+ * Returns 16
1072
+ */
1073
+ static VALUE _Digest_XXH3_128bits_singleton_block_length(VALUE self)
1074
+ {
1075
+ return INT2FIX(_XXH3_128BITS_BLOCK_SIZE);
1076
+ }
1077
+
686
1078
  /*
687
1079
  * Initialization
688
1080
  */
@@ -700,19 +1092,22 @@ void Init_xxhash()
700
1092
  DEFINE_ID(reset)
701
1093
  DEFINE_ID(update)
702
1094
 
703
- #if 0
704
- _Digest = rb_define_module("Digest"); /* Tell RDoc about Digest since it doesn't recognize rb_path2class. */
705
- #endif
706
-
707
1095
  rb_require("digest");
708
1096
  _Digest = rb_path2class("Digest");
1097
+ _Digest_Class = rb_path2class("Digest::Class");
1098
+
1099
+ #if 0
1100
+ /* Tell RDoc about Digest and Digest::Class since it doesn't parse rb_path2class. */
1101
+ _Digest = rb_define_module("Digest");
1102
+ _Digest_Class = rb_define_class_under(_Digest, "Class", rb_cObject);
1103
+ #endif
709
1104
 
710
1105
  /*
711
1106
  * Document-class: Digest::XXHash
712
1107
  */
713
1108
 
714
- _Digest_XXHash = rb_define_class_under(_Digest, "XXHash", rb_path2class("Digest::Class"));
715
-
1109
+ _Digest_XXHash = rb_define_class_under(_Digest, "XXHash", _Digest_Class);
1110
+ rb_define_alloc_func(_Digest_XXHash, _Digest_XXHash_internal_allocate);
716
1111
  rb_define_method(_Digest_XXHash, "digest", _Digest_XXHash_digest, -1);
717
1112
  rb_define_method(_Digest_XXHash, "hexdigest", _Digest_XXHash_hexdigest, -1);
718
1113
  rb_define_method(_Digest_XXHash, "idigest", _Digest_XXHash_idigest, -1);
@@ -720,32 +1115,24 @@ void Init_xxhash()
720
1115
  rb_define_method(_Digest_XXHash, "initialize", _Digest_XXHash_initialize, -1);
721
1116
  rb_define_method(_Digest_XXHash, "inspect", _Digest_XXHash_inspect, 0);
722
1117
  rb_define_method(_Digest_XXHash, "initialize_copy", _Digest_XXHash_initialize_copy, 1);
723
-
724
1118
  rb_define_protected_method(_Digest_XXHash, "ifinish", _Digest_XXHash_ifinish, 0);
725
-
726
1119
  rb_define_singleton_method(_Digest_XXHash, "digest", _Digest_XXHash_singleton_digest, -1);
727
1120
  rb_define_singleton_method(_Digest_XXHash, "hexdigest", _Digest_XXHash_singleton_hexdigest, -1);
728
1121
  rb_define_singleton_method(_Digest_XXHash, "idigest", _Digest_XXHash_singleton_idigest, -1);
729
1122
 
730
- rb_define_alloc_func(_Digest_XXHash, _Digest_XXHash_internal_allocate);
731
-
732
1123
  /*
733
1124
  * Document-class: Digest::XXH32
734
1125
  */
735
1126
 
736
1127
  _Digest_XXH32 = rb_define_class_under(_Digest, "XXH32", _Digest_XXHash);
737
-
738
1128
  rb_define_alloc_func(_Digest_XXH32, _Digest_XXH32_internal_allocate);
739
-
740
1129
  rb_define_private_method(_Digest_XXH32, "finish", _Digest_XXH32_finish, 0);
741
1130
  rb_define_private_method(_Digest_XXH32, "ifinish", _Digest_XXH32_ifinish, 0);
742
-
743
1131
  rb_define_method(_Digest_XXH32, "update", _Digest_XXH32_update, 1);
744
1132
  rb_define_method(_Digest_XXH32, "reset", _Digest_XXH32_reset, -1);
745
1133
  rb_define_method(_Digest_XXH32, "digest_length", _Digest_XXH32_digest_length, 0);
746
1134
  rb_define_method(_Digest_XXH32, "block_length", _Digest_XXH32_block_length, 0);
747
1135
  rb_define_method(_Digest_XXH32, "initialize_copy", _Digest_XXH32_initialize_copy, 1);
748
-
749
1136
  rb_define_singleton_method(_Digest_XXH32, "digest_length", _Digest_XXH32_singleton_digest_length, 0);
750
1137
  rb_define_singleton_method(_Digest_XXH32, "block_length", _Digest_XXH32_singleton_block_length, 0);
751
1138
 
@@ -754,18 +1141,60 @@ void Init_xxhash()
754
1141
  */
755
1142
 
756
1143
  _Digest_XXH64 = rb_define_class_under(_Digest, "XXH64", _Digest_XXHash);
757
-
758
1144
  rb_define_alloc_func(_Digest_XXH64, _Digest_XXH64_internal_allocate);
759
-
760
1145
  rb_define_private_method(_Digest_XXH64, "finish", _Digest_XXH64_finish, 0);
761
1146
  rb_define_private_method(_Digest_XXH64, "ifinish", _Digest_XXH64_ifinish, 0);
762
-
763
1147
  rb_define_method(_Digest_XXH64, "update", _Digest_XXH64_update, 1);
764
1148
  rb_define_method(_Digest_XXH64, "reset", _Digest_XXH64_reset, -1);
765
1149
  rb_define_method(_Digest_XXH64, "digest_length", _Digest_XXH64_digest_length, 0);
766
1150
  rb_define_method(_Digest_XXH64, "block_length", _Digest_XXH64_block_length, 0);
767
1151
  rb_define_method(_Digest_XXH64, "initialize_copy", _Digest_XXH64_initialize_copy, 1);
768
-
769
1152
  rb_define_singleton_method(_Digest_XXH64, "digest_length", _Digest_XXH64_singleton_digest_length, 0);
770
1153
  rb_define_singleton_method(_Digest_XXH64, "block_length", _Digest_XXH64_singleton_block_length, 0);
1154
+
1155
+ /*
1156
+ * Document-class: Digest::XXH3_64bits
1157
+ */
1158
+
1159
+ _Digest_XXH3_64bits = rb_define_class_under(_Digest, "XXH3_64bits", _Digest_XXHash);
1160
+ rb_define_alloc_func(_Digest_XXH3_64bits, _Digest_XXH3_64bits_internal_allocate);
1161
+ rb_define_private_method(_Digest_XXH3_64bits, "finish", _Digest_XXH3_64bits_finish, 0);
1162
+ rb_define_private_method(_Digest_XXH3_64bits, "ifinish", _Digest_XXH3_64bits_ifinish, 0);
1163
+ rb_define_method(_Digest_XXH3_64bits, "update", _Digest_XXH3_64bits_update, 1);
1164
+ rb_define_method(_Digest_XXH3_64bits, "reset", _Digest_XXH3_64bits_reset, -1);
1165
+ rb_define_method(_Digest_XXH3_64bits, "reset_with_secret", _Digest_XXH3_64bits_reset_with_secret, 1);
1166
+ rb_define_method(_Digest_XXH3_64bits, "digest_length", _Digest_XXH3_64bits_digest_length, 0);
1167
+ rb_define_method(_Digest_XXH3_64bits, "block_length", _Digest_XXH3_64bits_block_length, 0);
1168
+ rb_define_method(_Digest_XXH3_64bits, "initialize_copy", _Digest_XXH3_64bits_initialize_copy, 1);
1169
+ rb_define_singleton_method(_Digest_XXH3_64bits, "digest_length", _Digest_XXH3_64bits_singleton_digest_length, 0);
1170
+ rb_define_singleton_method(_Digest_XXH3_64bits, "block_length", _Digest_XXH3_64bits_singleton_block_length, 0);
1171
+
1172
+ /*
1173
+ * Document-class: Digest::XXH3_128bits
1174
+ */
1175
+
1176
+ _Digest_XXH3_128bits = rb_define_class_under(_Digest, "XXH3_128bits", _Digest_XXHash);
1177
+ rb_define_alloc_func(_Digest_XXH3_128bits, _Digest_XXH3_128bits_internal_allocate);
1178
+ rb_define_private_method(_Digest_XXH3_128bits, "finish", _Digest_XXH3_128bits_finish, 0);
1179
+ rb_define_private_method(_Digest_XXH3_128bits, "ifinish", _Digest_XXH3_128bits_ifinish, 0);
1180
+ rb_define_method(_Digest_XXH3_128bits, "update", _Digest_XXH3_128bits_update, 1);
1181
+ rb_define_method(_Digest_XXH3_128bits, "reset", _Digest_XXH3_128bits_reset, -1);
1182
+ rb_define_method(_Digest_XXH3_128bits, "reset_with_secret", _Digest_XXH3_128bits_reset_with_secret, 1);
1183
+ rb_define_method(_Digest_XXH3_128bits, "digest_length", _Digest_XXH3_128bits_digest_length, 0);
1184
+ rb_define_method(_Digest_XXH3_128bits, "block_length", _Digest_XXH3_128bits_block_length, 0);
1185
+ rb_define_method(_Digest_XXH3_128bits, "initialize_copy", _Digest_XXH3_128bits_initialize_copy, 1);
1186
+ rb_define_singleton_method(_Digest_XXH3_128bits, "digest_length", _Digest_XXH3_128bits_singleton_digest_length, 0);
1187
+ rb_define_singleton_method(_Digest_XXH3_128bits, "block_length", _Digest_XXH3_128bits_singleton_block_length, 0);
1188
+
1189
+ /*
1190
+ * Document-const: Digest::XXHash::XXH3_SECRET_SIZE_MIN
1191
+ *
1192
+ * Minimum allowed custom secret size defined in the core XXHash
1193
+ * code. The current value is 136.
1194
+ *
1195
+ * The author of Digest::XXHash doesn't know if this value would
1196
+ * change in the future.
1197
+ */
1198
+
1199
+ rb_define_const(_Digest_XXHash, "XXH3_SECRET_SIZE_MIN", INT2FIX(XXH3_SECRET_SIZE_MIN));
771
1200
  }