crc 0.3.1.1 → 0.4

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
@@ -2,14 +2,14 @@
2
2
 
3
3
  #--
4
4
  # File:: _byruby.rb
5
- # Author:: dearblue <dearblue@users.osdn.me>
5
+ # Author:: dearblue <dearblue@users.noreply.github.com>
6
6
  # License:: Creative Commons License Zero (CC0 / Public Domain)
7
7
  #++
8
8
 
9
9
  #
10
10
  # \* \* \* \* \* \* \* \*
11
11
  #
12
- # Pure ruby implemented general CRC generator.
12
+ # Pure ruby implemented general CRC calcurator.
13
13
  # It's used slice-by-16 algorithm with byte-order free.
14
14
  # This is based on the Intel's slice-by-eight algorithm.
15
15
  #
@@ -28,8 +28,7 @@ class CRC
28
28
  #
29
29
  # call-seq:
30
30
  # new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil) -> new crc module class (CRC based class)
31
- # new(initial_crc = nil, size = 0) -> new crc generator (CRC instance)
32
- # new(seq, initial_crc = nil, size = 0) -> new crc generator (CRC instance)
31
+ # new(initial_crc = nil, size = 0) -> new crc calcurator (CRC instance)
33
32
  #
34
33
  def new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
35
34
  bitsize = bitsize.to_i
@@ -57,11 +56,7 @@ class CRC
57
56
  # CRC クラスを普通に派生させた場合でも、CRC.new の基底メソッドが呼ばれるための細工
58
57
  define_singleton_method(:new, &Class.instance_method(:new).bind(self))
59
58
 
60
- singleton_class.class_eval do
61
- alias_method :[], :new
62
- end
63
-
64
- extend CRC::ModuleClass
59
+ extend CRC::Calcurator
65
60
  end
66
61
  end
67
62
 
@@ -259,7 +254,7 @@ class CRC
259
254
  end
260
255
  end
261
256
 
262
- module ModuleClass
257
+ module Calcurator
263
258
  attr_reader :bitsize, :bitmask, :polynomial, :initial_crc,
264
259
  :reflect_input, :reflect_output, :xor_output, :name
265
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,201 @@
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
+ # refinements:
41
+ # * convert_internal_state_for
42
+ # * convert_target_state_for
43
+ ;
44
+
45
+ refine BasicObject do
46
+ def convert_internal_state_for(crc)
47
+ raise TypeError, "cant convertion to #{crc.to_s} (for #{inspect})"
48
+ end
49
+
50
+ def convert_target_state_for(crc)
51
+ raise TypeError, "cant convertion to #{crc.to_s} (for #{inspect})"
52
+ end
53
+ end
54
+
55
+ refine NilClass do
56
+ def convert_internal_state_for(crc)
57
+ crc.setup(crc.initial_crc)
58
+ end
59
+
60
+ def convert_target_state_for(crc)
61
+ crc.setup(0)
62
+ end
63
+ end
64
+
65
+ refine String do
66
+ def convert_internal_state_for(crc)
67
+ crc.update(self, crc.setup(crc.initial_crc))
68
+ end
69
+ end
70
+
71
+ refine Integer do
72
+ def convert_internal_state_for(crc)
73
+ crc.setup(self)
74
+ end
75
+
76
+ def convert_target_state_for(crc)
77
+ crc.setup(self)
78
+ end
79
+ end
80
+
81
+ refine CRC do
82
+ def convert_internal_state_for(crc)
83
+ unless crc.variant?(self)
84
+ raise "not variant crc module (expect #{crc.to_s}, but self is #{inspect})"
85
+ end
86
+
87
+ state
88
+ end
89
+
90
+ def convert_target_state_for(crc)
91
+ unless crc.variant?(self)
92
+ raise "not variant crc module (expect #{crc.to_s}, but self is #{inspect})"
93
+ end
94
+
95
+ state
96
+ end
97
+ end
98
+
99
+ # refinements:
100
+ # * splitbytes
101
+ ;
102
+
103
+ refine Integer do
104
+ def splitbytes(bucket, bytes, is_little_endian)
105
+ if is_little_endian
106
+ bytes.times { |i| bucket.pushbyte self >> (i * 8) }
107
+ else
108
+ (bytes - 1).downto(0) { |i| bucket.pushbyte self >> (i * 8) }
109
+ end
110
+
111
+ bucket
112
+ end
113
+ end
114
+
115
+ refine String do
116
+ def pushbyte(ch)
117
+ self << (0xff & ch).chr(Encoding::BINARY)
118
+ end
119
+ end
120
+
121
+ refine Array do
122
+ def pushbyte(ch)
123
+ self << (0xff & ch)
124
+ end
125
+ end
126
+
127
+ # refinements:
128
+ # * bitsize_to_bytesize
129
+ # * bitsize_to_intsize
130
+ # * byte_paddingsize
131
+ # * int_paddingsize
132
+ ;
133
+
134
+ refine Integer do
135
+ def bitsize_to_bytesize
136
+ (self + 7) / 8
137
+ end
138
+
139
+ def bitsize_to_intsize
140
+ bitsize = 8
141
+ intsize = 1
142
+ 10.times do
143
+ return intsize if self <= bitsize
144
+ bitsize <<= 1
145
+ intsize <<= 1
146
+ end
147
+
148
+ raise "数値が巨大すぎるため、intsize が決定できません - #{inspect}"
149
+ end
150
+
151
+ def byte_paddingsize
152
+ (bitsize_to_bytesize * 8) - bitsize
153
+ end
154
+
155
+ def int_paddingsize
156
+ (bitsize_to_intsize * 8) - bitsize
157
+ end
158
+ end
159
+
160
+ # refinements:
161
+ # * get_crc_module
162
+ # * variant_for?
163
+ ;
164
+
165
+ refine BasicObject do
166
+ def get_crc_module
167
+ nil
168
+ end
169
+
170
+ def variant_for?(m)
171
+ false
172
+ end
173
+ end
174
+
175
+ refine CRC do
176
+ alias get_crc_module class
177
+
178
+ def variant_for?(m)
179
+ get_crc_module.variant_for?(m)
180
+ end
181
+ end
182
+
183
+ refine CRC.singleton_class do
184
+ alias get_crc_module itself
185
+
186
+ def variant_for?(m)
187
+ return false unless m = m.get_crc_module
188
+
189
+ if bitsize == m.bitsize &&
190
+ polynomial == m.polynomial &&
191
+ reflect_input? == m.reflect_input? &&
192
+ reflect_output? == m.reflect_output? &&
193
+ xor_output == m.xor_output
194
+ true
195
+ else
196
+ false
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,15 @@
1
+ class CRC
2
+ def file(path)
3
+ File.open(path, "rb") do |file|
4
+ buf = "".b
5
+ update(buf) while file.read(65536, buf)
6
+ end
7
+ self
8
+ end
9
+
10
+ module Calcurator
11
+ def file(path, *args)
12
+ new(*args).file(path)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,93 @@
1
+ class CRC
2
+ module Extensions
3
+ refine Integer do
4
+ def to_magicdigest_for(m, bytesize = m.bitsize.bitsize_to_bytesize)
5
+ if m.reflect_input? ^ m.reflect_output?
6
+ tmp = CRC.bitreflect(self, m.bitsize)
7
+ else
8
+ tmp = self
9
+ end
10
+
11
+ if m.reflect_input?
12
+ magic = tmp.splitbytes("".b, bytesize, true)
13
+ else
14
+ tmp <<= ((bytesize * 8) - m.bitsize)
15
+ magic = tmp.splitbytes("".b, bytesize, false)
16
+ end
17
+ end
18
+ end
19
+
20
+ refine String do
21
+ def to_magicdigest_for(m)
22
+ bytes = m.bitsize.bitsize_to_bytesize
23
+ case bytesize
24
+ when bytes
25
+ crc = unpack("C*").reduce { |a, ch| (a << 8) | ch }
26
+ when bytes * 2
27
+ crc = hex
28
+ else
29
+ raise TypeError, "wrong byte size (expect #{bytes} or #{bytes * 2} bytes, but given #{inspect})", caller
30
+ end
31
+
32
+ crc.to_magicdigest_for(m, bytes)
33
+ end
34
+ end
35
+
36
+ refine CRC do
37
+ def to_magicdigest_for(m)
38
+ unless m.variant?(get_crc_module)
39
+ raise TypeError, "different crc type - #{get_crc_module.inspect} (expect #{m.inspect})", caller
40
+ end
41
+
42
+ magicdigest
43
+ end
44
+ end
45
+
46
+ refine BasicObject do
47
+ def to_magicdigest_for(m)
48
+ raise TypeError, "cant convert type - #{get_crc_module}", caller
49
+ end
50
+ end
51
+
52
+ refine CRC.singleton_class do
53
+ def __cached_magic_code__
54
+ @__cached_magic_code__ = initial_crc.to_magicdigest_for(self).freeze
55
+ singleton_class.class_eval { attr_reader :__cached_magic_code__ }
56
+ @__cached_magic_code__
57
+ end
58
+ end
59
+ end
60
+
61
+ using CRC::Extensions
62
+
63
+ module Calcurator
64
+ def magicnumber
65
+ @magicnumber = crc(__cached_magic_code__)
66
+ singleton_class.class_eval { attr_reader :magicnumber }
67
+ @magicnumber
68
+ end
69
+
70
+ def magic
71
+ @magic = hexdigest(__cached_magic_code__).freeze
72
+ singleton_class.class_eval { attr_reader :magic }
73
+ @magic
74
+ end
75
+
76
+ def magicdigest(seq, crc = nil)
77
+ crc(seq, crc).to_magicdigest_for(self)
78
+ end
79
+
80
+ #
81
+ # crc 値を与えると magicdigest へと変換したバイナリデータを返します。
82
+ #
83
+ # crc には整数値、digest/hexdigest データ、変種を含む CRC インスタンスを渡すことが出来ます。
84
+ #
85
+ def to_magicdigest(crc)
86
+ crc.to_magicdigest_for(self)
87
+ end
88
+ end
89
+
90
+ def magicdigest
91
+ crc.to_magicdigest_for(get_crc_module)
92
+ end
93
+ end
@@ -1,7 +1,7 @@
1
1
  #!ruby
2
2
 
3
3
  #--
4
- # Author:: dearblue <dearblue@users.osdn.me>
4
+ # Author:: dearblue <dearblue@users.noreply.github.com>
5
5
  # License:: Creative Commons License Zero (CC0 / Public Domain)
6
6
  #
7
7
  # references from:
@@ -0,0 +1,194 @@
1
+ class CRC
2
+ module Calcurator
3
+ #
4
+ # call-seq:
5
+ # shiftbits_by_bitbybit(bitset, state) -> state
6
+ #
7
+ def shiftbits_by_bitbybit(bitset, state)
8
+ bitset = Array(bitset)
9
+
10
+ if reflect_input?
11
+ poly = CRC.bitreflect(polynomial, bitsize)
12
+ bitset.each do |b|
13
+ state ^= (1 & b)
14
+ state = (state[0] == 0) ? (state >> 1) : ((state >> 1) ^ poly)
15
+ end
16
+
17
+ state
18
+ else
19
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
20
+ bitset.each do |b|
21
+ s ^= (1 & b) << head
22
+ s = (s[head] == 0) ? (s << 1) : (((carries & s) << 1) ^ poly)
23
+ end
24
+
25
+ s
26
+ end
27
+ end
28
+ end
29
+
30
+ #
31
+ # call-seq:
32
+ # shiftbytes_by_bitbybit(byteset, state)
33
+ #
34
+ # standard input の場合は byte は上位ビットから、reflect input の場合は byte は下位ビットから計算されます。
35
+ #
36
+ def shiftbytes_by_bitbybit(byteset, state)
37
+ if reflect_input?
38
+ poly = CRC.bitreflect(polynomial, bitsize)
39
+ byteset.each_byte do |b|
40
+ state ^= 0xff & b
41
+ 8.times do
42
+ state = (state[0] == 0) ? (state >> 1) : ((state >> 1) ^ poly)
43
+ end
44
+ end
45
+
46
+ state
47
+ else
48
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
49
+ byteset.each_byte do |b|
50
+ s ^= (0xff & b) << csh
51
+ 8.times do
52
+ s = (s[head] == 0) ? (s << 1) : (((carries & s) << 1) ^ poly)
53
+ end
54
+ end
55
+
56
+ s
57
+ end
58
+ end
59
+ end
60
+
61
+ #
62
+ # call-seq:
63
+ # unshiftbits_by_bitbybit(bitset, state)
64
+ #
65
+ # bitset を与えることで state となるような内部状態を逆算します。
66
+ #
67
+ def unshiftbits_by_bitbybit(bitset, state)
68
+ bitset = Array(bitset)
69
+
70
+ if reflect_input?
71
+ poly = (CRC.bitreflect(polynomial, bitsize) << 1) | 1
72
+ head = bitsize
73
+ bitset.reverse_each do |b|
74
+ state <<= 1
75
+ state ^= poly unless state[head] == 0
76
+ state ^= 1 & b
77
+ end
78
+
79
+ state
80
+ else
81
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
82
+ headbit = 1 << head
83
+ lowoff = (head + 1) - bitsize
84
+ poly = (poly >> 1) | headbit
85
+ bitset.reverse_each do |b|
86
+ tmp = s[lowoff]
87
+ s >>= 1
88
+ s ^= poly unless tmp == 0
89
+ s ^= (1 & b) << head
90
+ end
91
+
92
+ s
93
+ end
94
+ end
95
+ end
96
+
97
+ #
98
+ # call-seq:
99
+ # unshiftbytes_by_bitbybit(byteset, state)
100
+ #
101
+ # byteset を与えることで state となるような内部状態を逆算します。
102
+ #
103
+ def unshiftbytes_by_bitbybit(byteset, state)
104
+ if reflect_input?
105
+ poly = (CRC.bitreflect(polynomial, bitsize) << 1) | 1
106
+ head = bitsize
107
+ byteset.reverse_each_byte do |b|
108
+ 7.downto(0) do |i|
109
+ state <<= 1
110
+ state ^= poly unless state[head] == 0
111
+ state ^= b[i]
112
+ end
113
+ end
114
+
115
+ state
116
+ else
117
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
118
+ headbit = 1 << head
119
+ lowoff = (head + 1) - bitsize
120
+ poly = (poly >> 1) | headbit
121
+ byteset.reverse_each_byte do |b|
122
+ 8.times do |i|
123
+ tmp = s[lowoff]
124
+ s >>= 1
125
+ s ^= poly unless tmp == 0
126
+ s ^= b[i] << head
127
+ end
128
+ end
129
+
130
+ s
131
+ end
132
+ end
133
+ end
134
+
135
+ def unshift_table
136
+ if reflect_input?
137
+ if bitsize < 8
138
+ pad = 8 - bitsize
139
+ shift = 0
140
+ else
141
+ pad = 0
142
+ shift = bitsize - 8
143
+ end
144
+ poly = ((CRC.bitreflect(polynomial, bitsize) << 1) | 1) << pad
145
+ head = bitsize + pad
146
+ @unshift_table = 256.times.map do |ch|
147
+ state = ch << shift
148
+ 8.times do |i|
149
+ state <<= 1
150
+ state ^= poly unless state[head] == 0
151
+ end
152
+ state >> pad
153
+ end
154
+ else
155
+ raise NotImplementedError
156
+ end
157
+
158
+ singleton_class.module_eval { attr_reader :unshift_table }
159
+
160
+ @unshift_table
161
+ end
162
+
163
+ def unshiftbytes_by_table(byteset, state)
164
+ if reflect_input?
165
+ table = unshift_table
166
+ if bitsize < 8
167
+ pad = 8 - bitsize
168
+ shift = 0
169
+ mask = bitmask
170
+ byteset.reverse_each_byte do |ch|
171
+ state = (state << 8) ^ ch
172
+ state = table[state >> bitsize] ^ (ch & mask)
173
+ end
174
+ else
175
+ shift = bitsize - 8
176
+ mask = ~(~0 << shift)
177
+ byteset.reverse_each_byte do |ch|
178
+ state = table[state >> shift] ^ ((state & mask) << 8)
179
+ state ^= ch
180
+ end
181
+ end
182
+
183
+ state
184
+ else
185
+ unshiftbytes_by_bitbybit(byteset, state)
186
+ end
187
+ end
188
+
189
+ alias shiftbits shiftbits_by_bitbybit
190
+ alias shiftbytes shiftbytes_by_bitbybit
191
+ alias unshiftbits unshiftbits_by_bitbybit
192
+ alias unshiftbytes unshiftbytes_by_table
193
+ end
194
+ end