crc 0.3 → 0.4.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.
@@ -0,0 +1,37 @@
1
+ class CRC
2
+ #
3
+ # Internal using module.
4
+ #
5
+ module Aux
6
+ def self.DIGEST(num, bitsize)
7
+ bits = (bitsize + 7) / 8 * 8
8
+ seq = ""
9
+ (bits - 8).step(0, -8) { |i| seq << yield((num >> i) & 0xff) }
10
+ seq
11
+ end
12
+
13
+ def self.digest(num, bitsize)
14
+ DIGEST(num, bitsize) { |n| n.chr(Encoding::BINARY) }
15
+ end
16
+
17
+ def self.hexdigest(num, bitsize)
18
+ DIGEST(num, bitsize) { |n| "%02X" % n }
19
+ end
20
+
21
+ #
22
+ # call-seq:
23
+ # slide_to_head(bitsize, state, polynomial, bitmask) { |padded_state, padded_polynomial, shift_input, off_msb, carries_mask, padding_size| padded_new_state } -> new_state
24
+ #
25
+ # YIELD(padded_state, padded_polynomial, shift_input, off_msb, carries_mask, padding_size) -> padded_new_state
26
+ #
27
+ def self.slide_to_head(bitsize, state, polynomial, bitmask)
28
+ pad = bitsize & 0x07
29
+ if pad == 0
30
+ yield(state, polynomial, bitsize - 8, bitsize - 1, bitmask >> 1, 0)
31
+ else
32
+ pad = 8 - pad
33
+ yield(state << pad, polynomial << pad, bitsize - 8 + pad, bitsize - 1 + pad, (bitmask << pad >> 1) | 0x7f, pad) >> pad
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,14 +1,15 @@
1
1
  #!ruby
2
2
 
3
3
  #--
4
- # Author:: dearblue <dearblue@users.osdn.me>
4
+ # File:: _byruby.rb
5
+ # Author:: dearblue <dearblue@users.noreply.github.com>
5
6
  # License:: Creative Commons License Zero (CC0 / Public Domain)
6
7
  #++
7
8
 
8
9
  #
9
10
  # \* \* \* \* \* \* \* \*
10
11
  #
11
- # Ruby implemented CRC generator.
12
+ # Pure ruby implemented generic CRC calculator.
12
13
  # It's used slice-by-16 algorithm with byte-order free.
13
14
  # This is based on the Intel's slice-by-eight algorithm.
14
15
  #
@@ -22,17 +23,12 @@
22
23
  # * xz-5.2.2/src/liblzma/check/crc32_fast.c
23
24
  # * xz-5.2.2/src/liblzma/check/crc32_tablegen.c
24
25
  #
25
- # If defined "RUBY_CRC_NOFAST=2" enviroment variable, switch to lookup-table algorithm.
26
- #
27
- # If defined "RUBY_CRC_NOFAST=3" enviroment variable, switch to reference algorithm.
28
- #
29
26
  class CRC
30
27
  class << self
31
28
  #
32
29
  # call-seq:
33
- # new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil) -> new crc module class (CRC based class)
34
- # new(initial_crc = nil, size = 0) -> new crc generator (CRC instance)
35
- # new(seq, initial_crc = nil, size = 0) -> new crc generator (CRC instance)
30
+ # new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil) -> new crc model class (CRC based class)
31
+ # new(initial_crc = nil, size = 0) -> new crc calculator (CRC instance)
36
32
  #
37
33
  def new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
38
34
  bitsize = bitsize.to_i
@@ -60,11 +56,7 @@ class CRC
60
56
  # CRC クラスを普通に派生させた場合でも、CRC.new の基底メソッドが呼ばれるための細工
61
57
  define_singleton_method(:new, &Class.instance_method(:new).bind(self))
62
58
 
63
- singleton_class.class_eval do
64
- alias_method :[], :new
65
- end
66
-
67
- extend CRC::ModuleClass
59
+ extend CRC::Calculator
68
60
  end
69
61
  end
70
62
 
@@ -111,7 +103,7 @@ class CRC
111
103
  end
112
104
  end
113
105
 
114
- def update_with_slice_by_eight(seq, s)
106
+ def update_with_slice_by_16(seq, s)
115
107
  tX = table
116
108
  t0 = tX[ 0]; t1 = tX[ 1]; t2 = tX[ 2]; t3 = tX[ 3]
117
109
  t4 = tX[ 4]; t5 = tX[ 5]; t6 = tX[ 6]; t7 = tX[ 7]
@@ -120,15 +112,29 @@ class CRC
120
112
 
121
113
  i = 0
122
114
  ii = seq.bytesize
123
- iii = ii & ~15
115
+ ii16 = ii & ~15
124
116
 
125
117
  if reflect_input
126
- if bitsize <= 32
127
- # speed improvement for 32-bits CRC
118
+ case
119
+ when bitsize > 32
128
120
  i = 0
129
- while i < iii
121
+ while i < ii16
130
122
  s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
131
123
  tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) & 0xff] ^
124
+ tB[seq.getbyte(i + 4) ^ (s >> 32) & 0xff] ^ tA[seq.getbyte(i + 5) ^ (s >> 40) & 0xff] ^
125
+ t9[seq.getbyte(i + 6) ^ (s >> 48) & 0xff] ^ t8[seq.getbyte(i + 7) ^ (s >> 56) ] ^
126
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
127
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
128
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
129
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
130
+ i += 16
131
+ end
132
+ when bitsize > 16
133
+ # speed improvement for 32-bits CRC
134
+ i = 0
135
+ while i < ii16
136
+ s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
137
+ tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) ] ^
132
138
  tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
133
139
  t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
134
140
  t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
@@ -137,13 +143,14 @@ class CRC
137
143
  t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
138
144
  i += 16
139
145
  end
140
- else
146
+ else # when bitsize <= 16
147
+ # speed improvement for 16-bits CRC
141
148
  i = 0
142
- while i < iii
143
- s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
144
- tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) & 0xff] ^
145
- tB[seq.getbyte(i + 4) ^ (s >> 32) & 0xff] ^ tA[seq.getbyte(i + 5) ^ (s >> 40) & 0xff] ^
146
- t9[seq.getbyte(i + 6) ^ (s >> 48) & 0xff] ^ t8[seq.getbyte(i + 7) ^ (s >> 56) & 0xff] ^
149
+ while i < ii16
150
+ s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) ] ^
151
+ tD[seq.getbyte(i + 2) ] ^ tC[seq.getbyte(i + 3) ] ^
152
+ tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
153
+ t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
147
154
  t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
148
155
  t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
149
156
  t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
@@ -152,26 +159,65 @@ class CRC
152
159
  end
153
160
  end
154
161
 
155
- (iii...ii).each do |n|
162
+ (i...ii).each do |n|
156
163
  s = t0[seq.getbyte(n) ^ s & 0xff] ^ (s >> 8)
157
164
  end
158
165
 
159
166
  s
160
167
  else
161
168
  Aux.slide_to_head(bitsize, s, polynomial, bitmask) do |s, poly, csh, head, carries|
162
- sh = 64 - (head + 1)
163
-
164
- while i < iii
165
- s <<= sh
166
- s = t7[seq.getbyte(i ) ^ (s >> 56) & 0xff] ^ t6[seq.getbyte(i + 1) ^ (s >> 48) & 0xff] ^
167
- t5[seq.getbyte(i + 2) ^ (s >> 40) & 0xff] ^ t4[seq.getbyte(i + 3) ^ (s >> 32) & 0xff] ^
168
- t3[seq.getbyte(i + 4) ^ (s >> 24) & 0xff] ^ t2[seq.getbyte(i + 5) ^ (s >> 16) & 0xff] ^
169
- t1[seq.getbyte(i + 6) ^ (s >> 8) & 0xff] ^ t0[seq.getbyte(i + 7) ^ (s >> 0) & 0xff]
170
- i += 8
169
+ case
170
+ when bitsize > 32
171
+ sh = 64 - (head + 1)
172
+
173
+ while i < ii16
174
+ s <<= sh
175
+ s = tF[seq.getbyte(i ) ^ (s >> 56) ] ^ tE[seq.getbyte(i + 1) ^ (s >> 48) & 0xff] ^
176
+ tD[seq.getbyte(i + 2) ^ (s >> 40) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 32) & 0xff] ^
177
+ tB[seq.getbyte(i + 4) ^ (s >> 24) & 0xff] ^ tA[seq.getbyte(i + 5) ^ (s >> 16) & 0xff] ^
178
+ t9[seq.getbyte(i + 6) ^ (s >> 8) & 0xff] ^ t8[seq.getbyte(i + 7) ^ (s ) & 0xff] ^
179
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
180
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
181
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
182
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
183
+ i += 16
184
+ end
185
+ when bitsize > 16
186
+ # speed improvement for 32-bits CRC
187
+ sh = 32 - (head + 1)
188
+
189
+ while i < ii16
190
+ s <<= sh
191
+ s = tF[seq.getbyte(i ) ^ (s >> 24) ] ^ tE[seq.getbyte(i + 1) ^ (s >> 16) & 0xff] ^
192
+ tD[seq.getbyte(i + 2) ^ (s >> 8) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s ) & 0xff] ^
193
+ tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
194
+ t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
195
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
196
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
197
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
198
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
199
+ i += 16
200
+ end
201
+ else # when bitsize <= 16
202
+ # speed improvement for 16-bits CRC
203
+ sh = 16 - (head + 1)
204
+
205
+ while i < ii16
206
+ s <<= sh
207
+ s = tF[seq.getbyte(i ) ^ (s >> 8) ] ^ tE[seq.getbyte(i + 1) ^ (s ) & 0xff] ^
208
+ tD[seq.getbyte(i + 2) ] ^ tC[seq.getbyte(i + 3) ] ^
209
+ tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
210
+ t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
211
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
212
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
213
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
214
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
215
+ i += 16
216
+ end
171
217
  end
172
218
 
173
219
  carries8 = carries >> 7
174
- (iii...ii).each do |n|
220
+ (i...ii).each do |n|
175
221
  s = t0[(s >> csh) ^ seq.getbyte(n)] ^ ((carries8 & s) << 8)
176
222
  end
177
223
  s
@@ -180,10 +226,14 @@ class CRC
180
226
  end
181
227
 
182
228
  def table
183
- if reflect_input
184
- @table = CRC.build_reflect_table(bitsize, polynomial, slice: 16)
229
+ if SLICING_SIZE
230
+ if reflect_input
231
+ @table = CRC.build_reflect_table(bitsize, polynomial, slice: SLICING_SIZE)
232
+ else
233
+ @table = CRC.build_table(bitsize, polynomial, slice: SLICING_SIZE)
234
+ end
185
235
  else
186
- @table = CRC.build_table(bitsize, polynomial, slice: 16)
236
+ @table = nil
187
237
  end
188
238
 
189
239
  singleton_class.class_eval "attr_reader :table"
@@ -193,15 +243,18 @@ class CRC
193
243
 
194
244
  case ENV["RUBY_CRC_NOFAST"].to_i
195
245
  when 0, 1
196
- alias update update_with_slice_by_eight
246
+ alias update update_with_slice_by_16
247
+ SLICING_SIZE = 16
197
248
  when 2
198
249
  alias update update_with_lookup_table
250
+ SLICING_SIZE = 1
199
251
  else
200
252
  alias update update_with_reference
253
+ SLICING_SIZE = nil
201
254
  end
202
255
  end
203
256
 
204
- module ModuleClass
257
+ module Calculator
205
258
  attr_reader :bitsize, :bitmask, :polynomial, :initial_crc,
206
259
  :reflect_input, :reflect_output, :xor_output, :name
207
260
 
@@ -29,7 +29,7 @@
29
29
  # > madler@alumni.caltech.edu
30
30
  # > */
31
31
  #
32
- # Ported by:: dearblue <dearblue@users.osdn.me>
32
+ # Ported by:: dearblue <dearblue@users.noreply.github.com>
33
33
  # License:: zlib-style
34
34
  #--
35
35
 
@@ -0,0 +1,211 @@
1
+ class CRC
2
+ module Extensions
3
+ # refinements
4
+ # * each_byte
5
+ # * reverse_each_byte
6
+ ;
7
+
8
+ refine Array do
9
+ def each_byte
10
+ return to_enum(:each_byte) unless block_given?
11
+ each { |ch| yield 0xff & ch }
12
+ self
13
+ end
14
+
15
+ def reverse_each_byte
16
+ return to_enum(:reverse_each_byte) unless block_given?
17
+ reverse_each { |ch| yield 0xff & ch }
18
+ self
19
+ end
20
+ end
21
+
22
+ refine BasicObject do
23
+ def each_byte(&block)
24
+ Array(self).each_byte(&block)
25
+ end
26
+
27
+ def reverse_each_byte(&block)
28
+ Array(self).reverse_each_byte(&block)
29
+ end
30
+ end
31
+
32
+ refine String do
33
+ def reverse_each_byte
34
+ return to_enum(:reverse_each_byte) unless block_given?
35
+ (bytesize - 1).downto(0) { |i| yield getbyte(i) }
36
+ self
37
+ end
38
+ end
39
+
40
+ refine NilClass do
41
+ def each_byte
42
+ self
43
+ end
44
+
45
+ def reverse_each_byte
46
+ nil
47
+ end
48
+ end
49
+
50
+ # refinements:
51
+ # * convert_internal_state_for
52
+ # * convert_target_state_for
53
+ ;
54
+
55
+ refine BasicObject do
56
+ def convert_internal_state_for(crc)
57
+ raise TypeError, "cant convertion to #{crc.to_s} (for #{inspect})"
58
+ end
59
+
60
+ def convert_target_state_for(crc)
61
+ raise TypeError, "cant convertion to #{crc.to_s} (for #{inspect})"
62
+ end
63
+ end
64
+
65
+ refine NilClass do
66
+ def convert_internal_state_for(crc)
67
+ crc.setup(crc.initial_crc)
68
+ end
69
+
70
+ def convert_target_state_for(crc)
71
+ crc.setup(0)
72
+ end
73
+ end
74
+
75
+ refine String do
76
+ def convert_internal_state_for(crc)
77
+ crc.update(self, crc.setup(crc.initial_crc))
78
+ end
79
+ end
80
+
81
+ refine Integer do
82
+ def convert_internal_state_for(crc)
83
+ crc.setup(self)
84
+ end
85
+
86
+ def convert_target_state_for(crc)
87
+ crc.setup(self)
88
+ end
89
+ end
90
+
91
+ refine CRC do
92
+ def convert_internal_state_for(crc)
93
+ unless crc.variant?(self)
94
+ raise "not variant crc model (expect #{crc.to_s}, but self is #{inspect})"
95
+ end
96
+
97
+ state
98
+ end
99
+
100
+ def convert_target_state_for(crc)
101
+ unless crc.variant?(self)
102
+ raise "not variant crc model (expect #{crc.to_s}, but self is #{inspect})"
103
+ end
104
+
105
+ state
106
+ end
107
+ end
108
+
109
+ # refinements:
110
+ # * splitbytes
111
+ ;
112
+
113
+ refine Integer do
114
+ def splitbytes(bucket, bytes, is_little_endian)
115
+ if is_little_endian
116
+ bytes.times { |i| bucket.pushbyte self >> (i * 8) }
117
+ else
118
+ (bytes - 1).downto(0) { |i| bucket.pushbyte self >> (i * 8) }
119
+ end
120
+
121
+ bucket
122
+ end
123
+ end
124
+
125
+ refine String do
126
+ def pushbyte(ch)
127
+ self << (0xff & ch).chr(Encoding::BINARY)
128
+ end
129
+ end
130
+
131
+ refine Array do
132
+ def pushbyte(ch)
133
+ self << (0xff & ch)
134
+ end
135
+ end
136
+
137
+ # refinements:
138
+ # * bitsize_to_bytesize
139
+ # * bitsize_to_intsize
140
+ # * byte_paddingsize
141
+ # * int_paddingsize
142
+ ;
143
+
144
+ refine Integer do
145
+ def bitsize_to_bytesize
146
+ (self + 7) / 8
147
+ end
148
+
149
+ def bitsize_to_intsize
150
+ bitsize = 8
151
+ intsize = 1
152
+ 10.times do
153
+ return intsize if self <= bitsize
154
+ bitsize <<= 1
155
+ intsize <<= 1
156
+ end
157
+
158
+ raise "数値が巨大すぎるため、intsize が決定できません - #{inspect}"
159
+ end
160
+
161
+ def byte_paddingsize
162
+ (bitsize_to_bytesize * 8) - bitsize
163
+ end
164
+
165
+ def int_paddingsize
166
+ (bitsize_to_intsize * 8) - bitsize
167
+ end
168
+ end
169
+
170
+ # refinements:
171
+ # * get_crc_model
172
+ # * variant_for?
173
+ ;
174
+
175
+ refine BasicObject do
176
+ def get_crc_model
177
+ nil
178
+ end
179
+
180
+ def variant_for?(m)
181
+ false
182
+ end
183
+ end
184
+
185
+ refine CRC do
186
+ alias get_crc_model class
187
+
188
+ def variant_for?(m)
189
+ get_crc_model.variant_for?(m)
190
+ end
191
+ end
192
+
193
+ refine CRC.singleton_class do
194
+ alias get_crc_model itself
195
+
196
+ def variant_for?(m)
197
+ return false unless m = m.get_crc_model
198
+
199
+ if bitsize == m.bitsize &&
200
+ polynomial == m.polynomial &&
201
+ reflect_input? == m.reflect_input? &&
202
+ reflect_output? == m.reflect_output? &&
203
+ xor_output == m.xor_output
204
+ true
205
+ else
206
+ false
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end