xxhash 0.4.0 → 0.6.0

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.
data/ext/xxhash/xxhash.c CHANGED
@@ -1,17 +1,96 @@
1
1
  #include "xxhash.h"
2
2
 
3
+ VALUE xxhash_xxh32_file(VALUE mod, VALUE filename, VALUE seed)
4
+ {
5
+ StringValue(filename);
6
+
7
+ XXH32_state_t* state = XXH32_createState();
8
+ if (state == NULL) {
9
+ rb_raise(rb_eRuntimeError, "%s", "Cannot create state, out of memory");
10
+ }
11
+
12
+ XXH32_reset(state, NUM2INT(seed));
13
+
14
+ char buffer[16384];
15
+ size_t count;
16
+ FILE *fp = fopen(RSTRING_PTR(filename), "rb");
17
+ if (fp == NULL) {
18
+ XXH32_freeState(state);
19
+ VALUE error = INT2FIX(errno);
20
+ rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
21
+ }
22
+
23
+ while ((count = fread(buffer, 1, sizeof(buffer), fp)) != 0) {
24
+ XXH32_update(state, buffer, count);
25
+ }
26
+ fclose(fp);
27
+
28
+ XXH32_hash_t result = XXH32_digest(state);
29
+
30
+ XXH32_freeState(state);
31
+ return ULL2NUM(result);
32
+ }
33
+
34
+ VALUE xxhash_xxh64_file(VALUE mod, VALUE filename, VALUE seed)
35
+ {
36
+ StringValue(filename);
37
+
38
+ XXH64_state_t* state = XXH64_createState();
39
+ if (state == NULL) {
40
+ rb_raise(rb_eRuntimeError, "%s", "Cannot create state, out of memory");
41
+ }
42
+
43
+ XXH64_reset(state, NUM2INT(seed));
44
+
45
+ char buffer[16384];
46
+ size_t count;
47
+ FILE *fp = fopen(RSTRING_PTR(filename), "rb");
48
+ if (fp == NULL) {
49
+ XXH64_freeState(state);
50
+ VALUE error = INT2FIX(errno);
51
+ rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
52
+ }
53
+
54
+ while ((count = fread(buffer, 1, sizeof(buffer), fp)) != 0) {
55
+ XXH64_update(state, buffer, count);
56
+ }
57
+ fclose(fp);
58
+
59
+ XXH64_hash_t result = XXH64_digest(state);
60
+
61
+ XXH64_freeState(state);
62
+ return ULL2NUM(result);
63
+ }
64
+
3
65
  VALUE xxhash_xxh32(VALUE mod, VALUE input, VALUE seed)
4
66
  {
5
67
  return ULL2NUM(XXH32(StringValuePtr(input), (size_t)RSTRING_LEN(input), (unsigned int)NUM2ULL(seed)));
6
68
  }
7
69
 
8
- void xxhash32_streaming_hash_free(xxhash_xxh32_t* storage)
70
+ static void xxhash32_streaming_hash_free(void *ptr)
9
71
  {
72
+ xxhash_xxh32_t* storage = (xxhash_xxh32_t*)ptr;
10
73
  // Digest frees the memory.
11
74
  XXH32_freeState(storage->state);
12
75
  xfree(storage);
13
76
  }
14
77
 
78
+ static size_t xxhash32_streaming_hash_memsize(const void *ptr)
79
+ {
80
+ // Ideally we'd include sizeof(XXH32_state_t) too, but the type is opaque.
81
+ return sizeof(xxhash_xxh32_t);
82
+ }
83
+
84
+ static const rb_data_type_t xxhash_xxh32_type = {
85
+ .wrap_struct_name = "xxhash/xxhash32_streaming_hash",
86
+ .function = {
87
+ .dmark = NULL,
88
+ .dfree = xxhash32_streaming_hash_free,
89
+ .dsize = xxhash32_streaming_hash_memsize,
90
+ },
91
+ .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
92
+ };
93
+
15
94
  VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed)
16
95
  {
17
96
  XXH_errorcode code;
@@ -24,14 +103,14 @@ VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed)
24
103
  rb_raise(rb_eRuntimeError, "Error during reset.");
25
104
  return Qnil;
26
105
  }
27
- return Data_Wrap_Struct(klass, 0, xxhash32_streaming_hash_free, storage);
106
+ return TypedData_Wrap_Struct(klass, &xxhash_xxh32_type, storage);
28
107
  }
29
108
 
30
109
  VALUE xxhash32_streaming_hash_reset(VALUE self)
31
110
  {
32
111
  XXH_errorcode code;
33
112
  xxhash_xxh32_t* storage;
34
- Data_Get_Struct(self, xxhash_xxh32_t, storage);
113
+ TypedData_Get_Struct(self, xxhash_xxh32_t, &xxhash_xxh32_type, storage);
35
114
 
36
115
  code = XXH32_reset(storage->state, storage->seed);
37
116
  if(code != XXH_OK) {
@@ -45,7 +124,7 @@ VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data)
45
124
  {
46
125
  XXH_errorcode code;
47
126
  xxhash_xxh32_t* storage;
48
- Data_Get_Struct(self, xxhash_xxh32_t, storage);
127
+ TypedData_Get_Struct(self, xxhash_xxh32_t, &xxhash_xxh32_type, storage);
49
128
 
50
129
  code = XXH32_update(storage->state, StringValuePtr(data), (size_t)RSTRING_LEN(data));
51
130
  if(code != XXH_OK) {
@@ -57,7 +136,7 @@ VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data)
57
136
  VALUE xxhash32_streaming_hash_digest(VALUE self)
58
137
  {
59
138
  xxhash_xxh32_t* storage;
60
- Data_Get_Struct(self, xxhash_xxh32_t, storage);
139
+ TypedData_Get_Struct(self, xxhash_xxh32_t, &xxhash_xxh32_type, storage);
61
140
 
62
141
  // Do not free memory now.
63
142
  return ULL2NUM(XXH32_digest(storage->state));
@@ -68,13 +147,30 @@ VALUE xxhash_xxh64(VALUE mod, VALUE input, VALUE seed)
68
147
  return ULL2NUM(XXH64(StringValuePtr(input), (size_t)RSTRING_LEN(input), (unsigned int)NUM2ULL(seed)));
69
148
  }
70
149
 
71
- void xxhash64_streaming_hash_free(xxhash_xxh64_t* storage)
150
+ static void xxhash64_streaming_hash_free(void *ptr)
72
151
  {
152
+ xxhash_xxh64_t* storage = (xxhash_xxh64_t*)ptr;
73
153
  // Digest frees the memory.
74
154
  XXH64_freeState(storage->state);
75
155
  xfree(storage);
76
156
  }
77
157
 
158
+ static size_t xxhash64_streaming_hash_memsize(const void *ptr)
159
+ {
160
+ // Ideally we'd include sizeof(XXH64_state_t) too, but the type is opaque.
161
+ return sizeof(xxhash_xxh64_t);
162
+ }
163
+
164
+ static const rb_data_type_t xxhash_xxh64_type = {
165
+ .wrap_struct_name = "xxhash/xxhash64_streaming_hash",
166
+ .function = {
167
+ .dmark = NULL,
168
+ .dfree = xxhash64_streaming_hash_free,
169
+ .dsize = xxhash64_streaming_hash_memsize,
170
+ },
171
+ .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
172
+ };
173
+
78
174
  VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed)
79
175
  {
80
176
  XXH_errorcode code;
@@ -88,14 +184,14 @@ VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed)
88
184
  rb_raise(rb_eRuntimeError, "Error during reset.");
89
185
  return Qnil;
90
186
  }
91
- return Data_Wrap_Struct(klass, 0, xxhash64_streaming_hash_free, storage);
187
+ return TypedData_Wrap_Struct(klass, &xxhash_xxh64_type, storage);
92
188
  }
93
189
 
94
190
  VALUE xxhash64_streaming_hash_reset(VALUE self)
95
191
  {
96
192
  XXH_errorcode code;
97
193
  xxhash_xxh64_t* storage;
98
- Data_Get_Struct(self, xxhash_xxh64_t, storage);
194
+ TypedData_Get_Struct(self, xxhash_xxh64_t, &xxhash_xxh64_type, storage);
99
195
 
100
196
  code = XXH64_reset(storage->state, storage->seed);
101
197
  if(code != XXH_OK) {
@@ -108,7 +204,7 @@ VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data)
108
204
  {
109
205
  XXH_errorcode code;
110
206
  xxhash_xxh64_t* storage;
111
- Data_Get_Struct(self, xxhash_xxh64_t, storage);
207
+ TypedData_Get_Struct(self, xxhash_xxh64_t, &xxhash_xxh64_type, storage);
112
208
 
113
209
  code = XXH64_update(storage->state, StringValuePtr(data), (size_t)RSTRING_LEN(data));
114
210
  if(code != XXH_OK) {
@@ -120,7 +216,7 @@ VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data)
120
216
  VALUE xxhash64_streaming_hash_digest(VALUE self)
121
217
  {
122
218
  xxhash_xxh64_t* storage;
123
- Data_Get_Struct(self, xxhash_xxh64_t, storage);
219
+ TypedData_Get_Struct(self, xxhash_xxh64_t, &xxhash_xxh64_type, storage);
124
220
 
125
221
  // Do not free memory now.
126
222
  return ULL2NUM(XXH64_digest(storage->state));
@@ -129,6 +225,10 @@ VALUE xxhash64_streaming_hash_digest(VALUE self)
129
225
 
130
226
  void Init_xxhash(void)
131
227
  {
228
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
229
+ rb_ext_ractor_safe(true);
230
+ #endif
231
+
132
232
  VALUE cStreamingHash;
133
233
  VALUE cStreamingHash64;
134
234
  VALUE mXXhash;
@@ -138,9 +238,12 @@ void Init_xxhash(void)
138
238
  mInternal = rb_define_module_under(mXXhash, "XXhashInternal");
139
239
 
140
240
  rb_define_singleton_method(mInternal, "xxh32", (ruby_method*) &xxhash_xxh32, 2);
241
+ rb_define_singleton_method(mInternal, "xxh32_file", (ruby_method*) &xxhash_xxh32_file, 2);
141
242
  rb_define_singleton_method(mInternal, "xxh64", (ruby_method*) &xxhash_xxh64, 2);
243
+ rb_define_singleton_method(mInternal, "xxh64_file", (ruby_method*) &xxhash_xxh64_file, 2);
142
244
 
143
245
  cStreamingHash = rb_define_class_under(mInternal, "StreamingHash32", rb_cObject);
246
+ rb_undef_alloc_func(cStreamingHash);
144
247
 
145
248
  rb_define_singleton_method(cStreamingHash, "new", (ruby_method*) &xxhash32_streaming_hash_new, 1);
146
249
  rb_define_method(cStreamingHash, "update", (ruby_method*) &xxhash32_streaming_hash_update, 1);
@@ -148,6 +251,7 @@ void Init_xxhash(void)
148
251
  rb_define_method(cStreamingHash, "reset", (ruby_method*) &xxhash32_streaming_hash_reset, 0);
149
252
 
150
253
  cStreamingHash64 = rb_define_class_under(mInternal, "StreamingHash64", rb_cObject);
254
+ rb_undef_alloc_func(cStreamingHash64);
151
255
 
152
256
  rb_define_singleton_method(cStreamingHash64, "new", (ruby_method*) &xxhash64_streaming_hash_new, 1);
153
257
  rb_define_method(cStreamingHash64, "update", (ruby_method*) &xxhash64_streaming_hash_update, 1);
data/ext/xxhash/xxhash.h CHANGED
@@ -1,4 +1,5 @@
1
1
  #include <stdlib.h>
2
+ #include <errno.h>
2
3
  #include <ruby.h>
3
4
  #include "libxxhash.h"
4
5
 
@@ -17,13 +18,13 @@ typedef struct {
17
18
  typedef VALUE (ruby_method)();
18
19
 
19
20
  VALUE xxhash_xxh32(VALUE mod, VALUE input, VALUE seed);
20
- void xxhash32_streaming_hash_free(xxhash_xxh32_t* state);
21
+ VALUE xxhash_xxh32_file(VALUE mod, VALUE filename, VALUE seed);
21
22
  VALUE xxhash32_streaming_hash_new(VALUE klass, VALUE seed);
22
23
  VALUE xxhash32_streaming_hash_update(VALUE self, VALUE data);
23
24
  VALUE xxhash32_streaming_hash_reset(VALUE self);
24
25
  VALUE xxhash32_streaming_hash_digest(VALUE self);
25
26
  VALUE xxhash_xxh64(VALUE mod, VALUE input, VALUE seed);
26
- void xxhash64_streaming_hash_free(xxhash_xxh64_t* state);
27
+ VALUE xxhash_xxh64_file(VALUE mod, VALUE filename, VALUE seed);
27
28
  VALUE xxhash64_streaming_hash_new(VALUE klass, VALUE seed);
28
29
  VALUE xxhash64_streaming_hash_update(VALUE self, VALUE data);
29
30
  VALUE xxhash64_streaming_hash_reset(VALUE self);
@@ -1,3 +1,3 @@
1
1
  module XXhash
2
- VERSION = "0.4.0"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/xxhash.rb CHANGED
@@ -11,6 +11,14 @@ module XXhash
11
11
  XXhashInternal.xxh64(input.to_s, seed.to_i)
12
12
  end
13
13
 
14
+ def self.xxh32_file(filename, seed = 0)
15
+ XXhashInternal.xxh32_file(filename.to_s, seed.to_i)
16
+ end
17
+
18
+ def self.xxh64_file(filename, seed = 0)
19
+ XXhashInternal.xxh64_file(filename.to_s, seed.to_i)
20
+ end
21
+
14
22
  def self.xxh32_stream(io, seed = 0, chunk_size = 32)
15
23
  seed = seed.to_i
16
24
  chunk_size = chunk_size.to_i
data/test/xxhash_test.rb CHANGED
@@ -2,19 +2,50 @@ require_relative 'test_helper'
2
2
  require 'stringio'
3
3
 
4
4
  describe XXhash do
5
+ it 'is marked as ractor-safe' do
6
+ skip("Ractorrs are not supported in this version of ruby(#{RUBY_VERSION})") unless defined?(Ractor)
7
+
8
+ ractor = Ractor.new do
9
+ Ractor.yield XXhash.xxh32(Ractor.receive)
10
+ end
11
+
12
+ ractor.send('test')
13
+ assert_equal ractor.take, XXhash.xxh32('test')
14
+ end
15
+
5
16
  it 'returns 32-bit hash' do
6
17
  assert_equal 2758658570, XXhash.xxh32('test', 123)
7
18
  end
8
19
 
20
+ it 'returns 32-bit hash from a file' do
21
+ assert_equal XXhash.xxh32(File.read(__FILE__)), XXhash.xxh32_file(__FILE__)
22
+ assert_equal XXhash.xxh32(File.read(__FILE__), 123), XXhash.xxh32_file(__FILE__, 123)
23
+ end
24
+
9
25
  it 'returns 64-bit hash' do
10
26
  assert_equal 3134990500624303823, XXhash.xxh64('test', 123)
11
27
  end
12
28
 
29
+ it 'returns 64-bit hash from a file' do
30
+ assert_equal XXhash.xxh64(File.read(__FILE__)), XXhash.xxh64_file(__FILE__)
31
+ assert_equal XXhash.xxh64(File.read(__FILE__), 123), XXhash.xxh64_file(__FILE__, 123)
32
+ end
33
+
13
34
  it 'uses 0 (default value) if seed is not specified' do
14
35
  assert_equal 1042293711, XXhash.xxh32('test')
15
36
  assert_equal 5754696928334414137, XXhash.xxh64('test')
16
37
  end
17
38
 
39
+ it 'raises an Errno exception for invalid file' do
40
+ assert_raises Errno::ENOENT do
41
+ XXhash.xxh32_file('nonexistent-file')
42
+ end
43
+
44
+ assert_raises Errno::ENOENT do
45
+ XXhash.xxh64_file('nonexistent-file')
46
+ end
47
+ end
48
+
18
49
  describe 'XXhashInternal::StreamingHash32' do
19
50
 
20
51
  it 'rises ArgumentError if first argument is not IO object' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xxhash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vasiliy Ermolovich
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-12-11 00:00:00.000000000 Z
11
+ date: 2024-12-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ruby wrapper for xxHash lib
14
14
  email:
@@ -18,8 +18,8 @@ extensions:
18
18
  - ext/xxhash/extconf.rb
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - ".github/workflows/ruby.yml"
21
22
  - ".gitignore"
22
- - ".travis.yml"
23
23
  - CHANGELOG.md
24
24
  - Gemfile
25
25
  - LICENSE.txt
@@ -39,7 +39,7 @@ homepage: http://github.com/nashby/xxhash
39
39
  licenses:
40
40
  - MIT
41
41
  metadata: {}
42
- post_install_message:
42
+ post_install_message:
43
43
  rdoc_options: []
44
44
  require_paths:
45
45
  - lib
@@ -54,9 +54,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  requirements: []
57
- rubyforge_project:
58
- rubygems_version: 2.5.1
59
- signing_key:
57
+ rubygems_version: 3.5.16
58
+ signing_key:
60
59
  specification_version: 4
61
60
  summary: Ruby wrapper for xxHash lib
62
61
  test_files:
data/.travis.yml DELETED
@@ -1,9 +0,0 @@
1
- language: ruby
2
- before_install:
3
- - gem install bundler
4
- rvm:
5
- - 1.9.3
6
- - 2.0.0
7
- - 2.1
8
- - 2.2
9
- script: "bundle exec rake test"