crc 0.3.1.1 → 0.4

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