xxhash 0.2.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/xxhash.rb CHANGED
@@ -1,20 +1,104 @@
1
1
  require 'xxhash/version'
2
2
  require 'xxhash/xxhash'
3
+ require 'digest'
3
4
 
4
5
  module XXhash
5
- def self.xxh32(input, seed)
6
- Internal.xxh32(input, seed)
6
+ def self.xxh32(input, seed = 0)
7
+ XXhashInternal.xxh32(input.to_s, seed.to_i)
7
8
  end
8
9
 
9
- def self.xxh32_stream(io, seed, chunk_size = 32)
10
- raise ArgumentError, 'first argument should be IO' if !io.is_a?(IO) && !io.is_a?(StringIO)
10
+ def self.xxh64(input, seed = 0)
11
+ XXhashInternal.xxh64(input.to_s, seed.to_i)
12
+ end
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
11
21
 
12
- hash = Internal::StreamingHash.new(seed)
22
+ def self.xxh32_stream(io, seed = 0, chunk_size = 32)
23
+ seed = seed.to_i
24
+ chunk_size = chunk_size.to_i
25
+ raise ArgumentError, 'first argument should be IO' if !io.respond_to?(:read)
26
+
27
+ hash = XXhashInternal::StreamingHash32.new(seed)
13
28
 
14
29
  while chunk = io.read(chunk_size)
15
- hash.update(chunk)
30
+ hash.update(chunk.to_s)
16
31
  end
17
32
 
18
33
  hash.digest
19
34
  end
35
+
36
+ def self.xxh64_stream(io, seed = 0, chunk_size = 32)
37
+ seed = seed.to_i
38
+ chunk_size = chunk_size.to_i
39
+ raise ArgumentError, 'first argument should be IO' if !io.respond_to?(:read)
40
+
41
+ hash = XXhashInternal::StreamingHash64.new(seed)
42
+
43
+ while chunk = io.read(chunk_size)
44
+ hash.update(chunk.to_s)
45
+ end
46
+
47
+ hash.digest
48
+ end
49
+
50
+ end
51
+
52
+ module Digest
53
+ class XXHash < Digest::Class
54
+ attr_reader :digest_length
55
+
56
+ def initialize(bitlen, seed = 0)
57
+ bitlen = bitlen.to_i
58
+ seed = seed.to_i
59
+ @hash = case bitlen
60
+ when 32
61
+ XXhash::XXhashInternal::StreamingHash32.new(seed)
62
+ when 64
63
+ XXhash::XXhashInternal::StreamingHash64.new(seed)
64
+ else
65
+ raise ArgumentError, "Unsupported bit length: %s" % bitlen.inspect
66
+ end
67
+
68
+ @digest_length = bitlen
69
+ end
70
+
71
+ def update(chunk)
72
+ @hash.update(chunk.to_s)
73
+ end
74
+
75
+ def digest(val = nil)
76
+ @hash.update(val) if val
77
+
78
+ @hash.digest
79
+ end
80
+
81
+ def digest!(val = nil)
82
+ result = digest(val)
83
+ @hash.reset
84
+
85
+ result
86
+ end
87
+
88
+ def reset
89
+ @hash.reset
90
+ end
91
+ end
92
+
93
+ class XXHash32 < Digest::XXHash
94
+ def initialize(seed = 0)
95
+ super(32, seed.to_i)
96
+ end
97
+ end
98
+
99
+ class XXHash64 < Digest::XXHash
100
+ def initialize(seed = 0)
101
+ super(64, seed.to_i)
102
+ end
103
+ end
20
104
  end
data/test/xxhash_test.rb CHANGED
@@ -1,13 +1,54 @@
1
- require 'test_helper'
1
+ require_relative 'test_helper'
2
2
  require 'stringio'
3
3
 
4
4
  describe XXhash do
5
- it 'returns hash' 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
+
16
+ it 'returns 32-bit hash' do
6
17
  assert_equal 2758658570, XXhash.xxh32('test', 123)
7
18
  end
8
19
 
9
- describe 'StreamingHash' do
10
- it 'rises ArgumentError if forst argument is not IO object' do
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
+
25
+ it 'returns 64-bit hash' do
26
+ assert_equal 3134990500624303823, XXhash.xxh64('test', 123)
27
+ end
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
+
34
+ it 'uses 0 (default value) if seed is not specified' do
35
+ assert_equal 1042293711, XXhash.xxh32('test')
36
+ assert_equal 5754696928334414137, XXhash.xxh64('test')
37
+ end
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
+
49
+ describe 'XXhashInternal::StreamingHash32' do
50
+
51
+ it 'rises ArgumentError if first argument is not IO object' do
11
52
  assert_raises(ArgumentError) do
12
53
  XXhash.xxh32_stream('test', 123)
13
54
  end
@@ -23,4 +64,98 @@ describe XXhash do
23
64
  assert_equal h1, h2
24
65
  end
25
66
  end
67
+
68
+ describe 'XXhashInternal::StreamingHash64' do
69
+ it 'rises ArgumentError if first argument is not IO object' do
70
+ assert_raises(ArgumentError) do
71
+ XXhash.xxh64_stream('test', 123)
72
+ end
73
+ end
74
+
75
+ it 'returns the hash for streamed strings' do
76
+ assert_equal 3134990500624303823, XXhash.xxh64_stream(StringIO.new('test'), 123)
77
+ end
78
+
79
+ it 'returns the hash for streamed files' do
80
+ h1 = XXhash.xxh64(File.read(__FILE__), 123)
81
+ h2 = XXhash.xxh64_stream(File.open(__FILE__), 123)
82
+ assert_equal h1, h2
83
+ end
84
+
85
+ it 'exception (not segfault) on nil' do
86
+ begin
87
+ XXhash.xxh64(nil)
88
+ fail
89
+ rescue
90
+ end
91
+ end
92
+ end
93
+
94
+ def use_external_hash hash, io, chunk_size=1024
95
+ while chunk=io.read(chunk_size)
96
+ hash.update(chunk)
97
+ end
98
+ hash.digest
99
+ end
100
+
101
+ describe 'Digest::XXhash32' do
102
+
103
+ it 'returns the hash for streamed strings' do
104
+ StringIO.open('test') do |io|
105
+ xxhash = Digest::XXHash32.new(123)
106
+ result = use_external_hash xxhash, io
107
+ assert_equal 2758658570, result
108
+ end
109
+ end
110
+
111
+ it 'returns the hash for streamed files' do
112
+ h1 = XXhash.xxh32(File.read(__FILE__), 123)
113
+ xxhash = Digest::XXHash32.new(123)
114
+ result = use_external_hash xxhash, File.open(__FILE__)
115
+ assert_equal h1, result
116
+ end
117
+
118
+ it 'returns correct hash after a reset' do
119
+ h1 = XXhash.xxh32(File.read(__FILE__), 123)
120
+ xxhash = Digest::XXHash32.new(123)
121
+ assert_equal 2758658570, xxhash.digest('test')
122
+ xxhash.reset
123
+ result = use_external_hash xxhash, File.open(__FILE__)
124
+ assert_equal h1, result
125
+ end
126
+
127
+ it 'exception (not segfault) on nil' do
128
+ begin
129
+ XXhash.xxh32(nil)
130
+ rescue
131
+ end
132
+ end
133
+ end
134
+
135
+ describe 'Digest::XXhash64' do
136
+ it 'returns the hash for streamed strings' do
137
+ StringIO.open('test') do |io|
138
+ xxhash = Digest::XXHash64.new(123)
139
+ result = use_external_hash xxhash, io
140
+ assert_equal 3134990500624303823, result
141
+ end
142
+ end
143
+
144
+ it 'returns the hash for streamed files' do
145
+ h1 = XXhash.xxh64(File.read(__FILE__), 123)
146
+ xxhash = Digest::XXHash64.new(123)
147
+ result = use_external_hash xxhash, File.open(__FILE__)
148
+ assert_equal h1, result
149
+ end
150
+
151
+ it 'returns correct hash after reset' do
152
+ h1 = XXhash.xxh64(File.read(__FILE__), 123)
153
+ xxhash = Digest::XXHash64.new(123)
154
+ assert_equal 3134990500624303823, xxhash.digest('test')
155
+ xxhash.reset
156
+ result = use_external_hash xxhash, File.open(__FILE__)
157
+ assert_equal h1, result
158
+ end
159
+ end
160
+
26
161
  end
data/xxhash.gemspec CHANGED
@@ -11,7 +11,8 @@ Gem::Specification.new do |gem|
11
11
  gem.description = %q{Ruby wrapper for xxHash lib}
12
12
  gem.summary = %q{Ruby wrapper for xxHash lib}
13
13
  gem.homepage = "http://github.com/nashby/xxhash"
14
-
14
+ gem.license = 'MIT'
15
+
15
16
  gem.files = `git ls-files`.split($/)
16
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xxhash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
5
- prerelease:
4
+ version: 0.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Vasiliy Ermolovich
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-09-04 00:00:00.000000000 Z
11
+ date: 2022-07-28 00:00:00.000000000 Z
13
12
  dependencies: []
14
13
  description: Ruby wrapper for xxHash lib
15
14
  email:
@@ -19,8 +18,8 @@ extensions:
19
18
  - ext/xxhash/extconf.rb
20
19
  extra_rdoc_files: []
21
20
  files:
22
- - .gitignore
23
- - .travis.yml
21
+ - ".github/workflows/ruby.yml"
22
+ - ".gitignore"
24
23
  - CHANGELOG.md
25
24
  - Gemfile
26
25
  - LICENSE.txt
@@ -29,41 +28,35 @@ files:
29
28
  - ext/xxhash/extconf.rb
30
29
  - ext/xxhash/libxxhash.c
31
30
  - ext/xxhash/libxxhash.h
32
- - ext/xxhash/xxhash.cc
31
+ - ext/xxhash/xxhash.c
32
+ - ext/xxhash/xxhash.h
33
33
  - lib/xxhash.rb
34
34
  - lib/xxhash/version.rb
35
35
  - test/test_helper.rb
36
36
  - test/xxhash_test.rb
37
37
  - xxhash.gemspec
38
38
  homepage: http://github.com/nashby/xxhash
39
- licenses: []
39
+ licenses:
40
+ - MIT
41
+ metadata: {}
40
42
  post_install_message:
41
43
  rdoc_options: []
42
44
  require_paths:
43
45
  - lib
44
46
  required_ruby_version: !ruby/object:Gem::Requirement
45
- none: false
46
47
  requirements:
47
- - - ! '>='
48
+ - - ">="
48
49
  - !ruby/object:Gem::Version
49
50
  version: '0'
50
- segments:
51
- - 0
52
- hash: -3728750430932162062
53
51
  required_rubygems_version: !ruby/object:Gem::Requirement
54
- none: false
55
52
  requirements:
56
- - - ! '>='
53
+ - - ">="
57
54
  - !ruby/object:Gem::Version
58
55
  version: '0'
59
- segments:
60
- - 0
61
- hash: -3728750430932162062
62
56
  requirements: []
63
- rubyforge_project:
64
- rubygems_version: 1.8.24
57
+ rubygems_version: 3.0.9
65
58
  signing_key:
66
- specification_version: 3
59
+ specification_version: 4
67
60
  summary: Ruby wrapper for xxHash lib
68
61
  test_files:
69
62
  - test/test_helper.rb
data/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- - rbx-19mode
data/ext/xxhash/xxhash.cc DELETED
@@ -1,56 +0,0 @@
1
- #include <ruby.h>
2
- #include "libxxhash.h"
3
-
4
- // Use this typedef to make the compiler happy when
5
- // calling rb_define_method()
6
- typedef VALUE (ruby_method)(...);
7
-
8
- extern "C" VALUE xxhash_xxh32(VALUE mod, VALUE input, VALUE seed)
9
- {
10
- return ULL2NUM(XXH32(StringValuePtr(input), RSTRING_LEN(input), NUM2ULL(seed)));
11
- }
12
-
13
- extern "C" void xxhash_streaming_hash_free(void* state)
14
- {
15
- // Digest frees the memory.
16
- (void) XXH32_digest(state);
17
- }
18
-
19
- extern "C" VALUE xxhash_streaming_hash_new(VALUE klass, VALUE seed)
20
- {
21
- void* state = XXH32_init(NUM2ULL(seed));
22
- return Data_Wrap_Struct(klass, 0, xxhash_streaming_hash_free, state);
23
- }
24
-
25
- extern "C" VALUE xxhash_streaming_hash_update(VALUE self, VALUE data)
26
- {
27
- void* state;
28
- Data_Get_Struct(self, void, state);
29
-
30
- XXH32_update(state, StringValuePtr(data), RSTRING_LEN(data));
31
- return Qnil;
32
- }
33
-
34
- extern "C" VALUE xxhash_streaming_hash_digest(VALUE self)
35
- {
36
- void* state;
37
- Data_Get_Struct(self, void, state);
38
-
39
- // Do not free memory now.
40
- return ULL2NUM(XXH32_intermediateDigest(state));
41
- }
42
-
43
- extern "C" void Init_xxhash()
44
- {
45
- VALUE mXXhash = rb_define_module("XXhash");
46
- VALUE mInternal = rb_define_module_under(mXXhash, "Internal");
47
-
48
- rb_define_singleton_method(mInternal, "xxh32", (ruby_method*) &xxhash_xxh32, 2);
49
-
50
- VALUE cStreamingHash = rb_define_class_under(mInternal, "StreamingHash", rb_cObject);
51
-
52
- rb_define_singleton_method(cStreamingHash, "new", (ruby_method*) &xxhash_streaming_hash_new, 1);
53
- rb_define_method(cStreamingHash, "update", (ruby_method*) &xxhash_streaming_hash_update, 1);
54
- rb_define_method(cStreamingHash, "digest", (ruby_method*) &xxhash_streaming_hash_digest, 0);
55
- rb_define_method(cStreamingHash, "intermediate_digest", (ruby_method*) &xxhash_streaming_hash_digest, 0);
56
- }