xxhash 0.4.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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"