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,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 Calculator
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_model)
39
+ raise TypeError, "different crc type - #{get_crc_model.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_model}", 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 Calculator
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_model)
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:
@@ -19,7 +19,7 @@ class CRC
19
19
  LIST = [
20
20
  #
21
21
  # bit size, polynomial, initial crc,
22
- # refrect input, xor output,
22
+ # reflect input, xor output,
23
23
  # reflect output, crc("123456789"), names...
24
24
  #
25
25
  [ 1, 0x01, true, true, 0, ~0, 0x01, "CRC-1"],
@@ -78,11 +78,11 @@ class CRC
78
78
  [16, 0x6F63, false, false, 0, 0, 0xBDF4, "CRC-16-LJ1200"],
79
79
  [16, 0x8005, true, true, ~0, ~0, 0x44C2, "CRC-16-MAXIM"],
80
80
  [16, 0x1021, true, true, ~0, 0, 0x6F91, "CRC-16-MCRF4XX"],
81
- [16, 0x1021, true, true, 0xB2AA, 0, 0x63D0, "CRC-16-RIELLO"],
81
+ [16, 0x1021, true, true, 0x554D, 0, 0x63D0, "CRC-16-RIELLO"],
82
82
  [16, 0xA097, false, false, 0, 0, 0x0FB3, "CRC-16-TELEDISK"],
83
- [16, 0x1021, true, true, 0x89EC, 0, 0x26B1, "CRC-16-TMS37157"],
83
+ [16, 0x1021, true, true, 0x3791, 0, 0x26B1, "CRC-16-TMS37157"],
84
84
  [16, 0x8005, true, true, 0, ~0, 0xB4C8, "CRC-16-USB"],
85
- [16, 0x1021, true, true, 0xC6C6, 0, 0xBF05, "CRC-16-A", "CRC-A", "CRC-16-ISO/IEC FCD 14443-3"],
85
+ [16, 0x1021, true, true, 0x6363, 0, 0xBF05, "CRC-16-A", "CRC-A", "CRC-16-ISO/IEC FCD 14443-3"],
86
86
  [16, 0x1021, true, true, 0, 0, 0x2189, "CRC-16-KERMIT", "KERMIT", "CRC-16-CCITT", "CRC-16-CCITT-TRUE", "CRC-CCITT"],
87
87
  [16, 0x8005, true, true, ~0, 0, 0x4B37, "CRC-16-MODBUS", "MODBUS"],
88
88
  [16, 0x1021, true, true, 0, ~0, 0x906E, "CRC-16-X-25", "X-25", "CRC-16-IBM-SDLC", "CRC-16-ISO-HDLC", "CRC-16-CRC-B", "CRC-B"],
@@ -92,7 +92,7 @@ class CRC
92
92
  #[24, 0x005D6DCB, false, false, 0, 0, nil, "CRC-24"],
93
93
  [24, 0x00864CFB, false, false, 0, 0, 0x00CDE703, "CRC-24-Radix-64"],
94
94
  [24, 0x00864CFB, false, false, 0x00B704CE, 0, 0x0021CF02, "CRC-24-OPENPGP"],
95
- [24, 0x0000065B, true, true, 0x00555555, 0, 0x00C25A56, "CRC-24-BLE"],
95
+ [24, 0x0000065B, true, true, 0x00AAAAAA, 0, 0x00C25A56, "CRC-24-BLE"],
96
96
  [24, 0x005D6DCB, false, false, 0x00FEDCBA, 0, 0x007979BD, "CRC-24-FLEXRAY-A"],
97
97
  [24, 0x005D6DCB, false, false, 0x00ABCDEF, 0, 0x001F23B8, "CRC-24-FLEXRAY-B"],
98
98
  [24, 0x00328B63, false, false, 0, ~0, 0x00B4F3E6, "CRC-24-INTERLAKEN"],
@@ -114,6 +114,7 @@ class CRC
114
114
  [32, 0x000000AF, false, false, 0, 0, 0xBD0BE338, "CRC-32-XFER", "XFER"],
115
115
  [40, 0x0004820009, false, false, ~0, ~0, 0xD4164FC646, "CRC-40-GSM"],
116
116
  [64, 0x42F0E1EBA9EA3693, true, true, 0, ~0, 0x995DC9BBDF1939FA, "CRC-64-XZ", "CRC-64"],
117
+ [64, 0xAD93D23594C935A9, true, true, ~0, 0, 0xCAA717168609F281, "CRC-64-JONES"],
117
118
  [64, 0x42F0E1EBA9EA3693, false, false, 0, 0, 0x6C40DF5F0B497347, "CRC-64-ECMA", "CRC-64-ECMA-182"],
118
119
  [64, 0x42F0E1EBA9EA3693, false, false, 0, ~0, 0x62EC59E3F1A4F00A, "CRC-64-WE"],
119
120
  [64, 0x000000000000001B, true, true, 0, 0, 0x46A5A9388A5BEFFE, "CRC-64-ISO", "CRC-64-ISO-3309"],
@@ -0,0 +1,198 @@
1
+ require_relative "_extensions"
2
+
3
+ class CRC
4
+ using Extensions
5
+
6
+ module Calculator
7
+ #
8
+ # call-seq:
9
+ # shiftbits_by_bitbybit(bitset, state) -> state
10
+ #
11
+ def shiftbits_by_bitbybit(bitset, state)
12
+ bitset = Array(bitset)
13
+
14
+ if reflect_input?
15
+ poly = CRC.bitreflect(polynomial, bitsize)
16
+ bitset.each do |b|
17
+ state ^= (1 & b)
18
+ state = (state[0] == 0) ? (state >> 1) : ((state >> 1) ^ poly)
19
+ end
20
+
21
+ state
22
+ else
23
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
24
+ bitset.each do |b|
25
+ s ^= (1 & b) << head
26
+ s = (s[head] == 0) ? (s << 1) : (((carries & s) << 1) ^ poly)
27
+ end
28
+
29
+ s
30
+ end
31
+ end
32
+ end
33
+
34
+ #
35
+ # call-seq:
36
+ # shiftbytes_by_bitbybit(byteset, state)
37
+ #
38
+ # standard input の場合は byte は上位ビットから、reflect input の場合は byte は下位ビットから計算されます。
39
+ #
40
+ def shiftbytes_by_bitbybit(byteset, state)
41
+ if reflect_input?
42
+ poly = CRC.bitreflect(polynomial, bitsize)
43
+ byteset.each_byte do |b|
44
+ state ^= 0xff & b
45
+ 8.times do
46
+ state = (state[0] == 0) ? (state >> 1) : ((state >> 1) ^ poly)
47
+ end
48
+ end
49
+
50
+ state
51
+ else
52
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
53
+ byteset.each_byte do |b|
54
+ s ^= (0xff & b) << csh
55
+ 8.times do
56
+ s = (s[head] == 0) ? (s << 1) : (((carries & s) << 1) ^ poly)
57
+ end
58
+ end
59
+
60
+ s
61
+ end
62
+ end
63
+ end
64
+
65
+ #
66
+ # call-seq:
67
+ # unshiftbits_by_bitbybit(bitset, state)
68
+ #
69
+ # bitset を与えることで state となるような内部状態を逆算します。
70
+ #
71
+ def unshiftbits_by_bitbybit(bitset, state)
72
+ bitset = Array(bitset)
73
+
74
+ if reflect_input?
75
+ poly = (CRC.bitreflect(polynomial, bitsize) << 1) | 1
76
+ head = bitsize
77
+ bitset.reverse_each do |b|
78
+ state <<= 1
79
+ state ^= poly unless state[head] == 0
80
+ state ^= 1 & b
81
+ end
82
+
83
+ state
84
+ else
85
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
86
+ headbit = 1 << head
87
+ lowoff = (head + 1) - bitsize
88
+ poly = (poly >> 1) | headbit
89
+ bitset.reverse_each do |b|
90
+ tmp = s[lowoff]
91
+ s >>= 1
92
+ s ^= poly unless tmp == 0
93
+ s ^= (1 & b) << head
94
+ end
95
+
96
+ s
97
+ end
98
+ end
99
+ end
100
+
101
+ #
102
+ # call-seq:
103
+ # unshiftbytes_by_bitbybit(byteset, state)
104
+ #
105
+ # byteset を与えることで state となるような内部状態を逆算します。
106
+ #
107
+ def unshiftbytes_by_bitbybit(byteset, state)
108
+ if reflect_input?
109
+ poly = (CRC.bitreflect(polynomial, bitsize) << 1) | 1
110
+ head = bitsize
111
+ byteset.reverse_each_byte do |b|
112
+ 7.downto(0) do |i|
113
+ state <<= 1
114
+ state ^= poly unless state[head] == 0
115
+ state ^= b[i]
116
+ end
117
+ end
118
+
119
+ state
120
+ else
121
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
122
+ headbit = 1 << head
123
+ lowoff = (head + 1) - bitsize
124
+ poly = (poly >> 1) | headbit
125
+ byteset.reverse_each_byte do |b|
126
+ 8.times do |i|
127
+ tmp = s[lowoff]
128
+ s >>= 1
129
+ s ^= poly unless tmp == 0
130
+ s ^= b[i] << head
131
+ end
132
+ end
133
+
134
+ s
135
+ end
136
+ end
137
+ end
138
+
139
+ def unshift_table
140
+ if reflect_input?
141
+ if bitsize < 8
142
+ pad = 8 - bitsize
143
+ shift = 0
144
+ else
145
+ pad = 0
146
+ shift = bitsize - 8
147
+ end
148
+ poly = ((CRC.bitreflect(polynomial, bitsize) << 1) | 1) << pad
149
+ head = bitsize + pad
150
+ @unshift_table = 256.times.map do |ch|
151
+ state = ch << shift
152
+ 8.times do |i|
153
+ state <<= 1
154
+ state ^= poly unless state[head] == 0
155
+ end
156
+ state >> pad
157
+ end
158
+ else
159
+ raise NotImplementedError
160
+ end
161
+
162
+ singleton_class.module_eval { attr_reader :unshift_table }
163
+
164
+ @unshift_table
165
+ end
166
+
167
+ def unshiftbytes_by_table(byteset, state)
168
+ if reflect_input?
169
+ table = unshift_table
170
+ if bitsize < 8
171
+ pad = 8 - bitsize
172
+ shift = 0
173
+ mask = bitmask
174
+ byteset.reverse_each_byte do |ch|
175
+ state = (state << 8) ^ ch
176
+ state = table[state >> bitsize] ^ (ch & mask)
177
+ end
178
+ else
179
+ shift = bitsize - 8
180
+ mask = ~(~0 << shift)
181
+ byteset.reverse_each_byte do |ch|
182
+ state = table[state >> shift] ^ ((state & mask) << 8)
183
+ state ^= ch
184
+ end
185
+ end
186
+
187
+ state
188
+ else
189
+ unshiftbytes_by_bitbybit(byteset, state)
190
+ end
191
+ end
192
+
193
+ alias shiftbits shiftbits_by_bitbybit
194
+ alias shiftbytes shiftbytes_by_bitbybit
195
+ alias unshiftbits unshiftbits_by_bitbybit
196
+ alias unshiftbytes unshiftbytes_by_table
197
+ end
198
+ end
@@ -0,0 +1,114 @@
1
+ class CRC
2
+ #
3
+ # Utilities.
4
+ #
5
+ module Utils
6
+ extend self
7
+
8
+ def bitreflect_reference(num, bitsize)
9
+ n = 0
10
+ bitsize.times { n <<= 1; n |= (num & 0x01); num >>= 1 }
11
+ n
12
+ end
13
+
14
+ def bitreflect(num, bitsize)
15
+ case
16
+ when bitsize > 128
17
+ bitreflect_reference(num, bitsize)
18
+ when bitsize > 64
19
+ bitreflect128(num) >> (128 - bitsize)
20
+ when bitsize > 32
21
+ bitreflect64(num) >> (64 - bitsize)
22
+ when bitsize > 16
23
+ bitreflect32(num) >> (32 - bitsize)
24
+ when bitsize > 8
25
+ bitreflect16(num) >> (16 - bitsize)
26
+ else
27
+ bitreflect8(num) >> (8 - bitsize)
28
+ end
29
+ end
30
+
31
+ def build_table(bitsize, polynomial, unfreeze = false, slice: 16)
32
+ bitmask = ~(~0 << bitsize)
33
+ table = []
34
+ Aux.slide_to_head(bitsize, 0, bitmask & polynomial, bitmask) do |xx, poly, csh, head, carries, pad|
35
+ table << (t = [])
36
+ 256.times do |b|
37
+ b <<= csh
38
+ 8.times { b = (b[head] == 0) ? (b << 1) : (((carries & b) << 1) ^ poly) }
39
+ t << b
40
+ end
41
+ t.freeze unless unfreeze
42
+
43
+ carries8 = carries >> 7
44
+ (1...slice).step do
45
+ tt = table[-1]
46
+ table << (t = [])
47
+ 256.times do |b|
48
+ t << (table[0][tt[b] >> csh] ^ ((carries8 & tt[b]) << 8))
49
+ end
50
+ t.freeze unless unfreeze
51
+ end
52
+ 0
53
+ end
54
+ table.freeze unless unfreeze
55
+ table
56
+ end
57
+
58
+ def build_reflect_table(bitsize, polynomial, unfreeze = false, slice: 16)
59
+ polynomial = bitreflect(polynomial, bitsize)
60
+ table = []
61
+
62
+ table << (t = [])
63
+ 256.times do |b|
64
+ 8.times { b = (b[0] == 0) ? (b >> 1) : ((b >> 1) ^ polynomial) }
65
+ t << b
66
+ end
67
+ t.freeze unless unfreeze
68
+
69
+ (1...slice).step do
70
+ tt = table[-1]
71
+ table << (t = [])
72
+ 256.times do |b|
73
+ t << (table[0][tt[b] & 0xff] ^ (tt[b] >> 8))
74
+ end
75
+ t.freeze unless unfreeze
76
+ end
77
+
78
+ table.freeze unless unfreeze
79
+ table
80
+ end
81
+
82
+ def export_table(table, bitsize, linewidth, indentsize = 2)
83
+ bitsize0 = bitsize.to_i
84
+ indent = " " * indentsize.to_i
85
+ case
86
+ when bitsize0 > 64 || bitsize0 < 1
87
+ raise "invalid bitsize (expected to 1..64, but given #{bitsize})"
88
+ when bitsize0 > 32
89
+ packformat = "Q>"
90
+ hexwidth = 16
91
+ when bitsize0 > 16
92
+ packformat = "N"
93
+ hexwidth = 8
94
+ when bitsize0 > 8
95
+ packformat = "n"
96
+ hexwidth = 4
97
+ else # when bitsize0 > 0
98
+ packformat = "C"
99
+ hexwidth = 2
100
+ end
101
+ table = table.to_a.pack("#{packformat}*").unpack("H*")[0]
102
+ table.gsub!(/(?<=\w)(?=\w{#{hexwidth}}{#{linewidth}}+$)/, "\n")
103
+ table.gsub!(/(?<=\w)(?=\w{#{hexwidth}}+$)/, " ")
104
+ table.gsub!(/(?<=\w)(?=\s|$)/, ",")
105
+ table.gsub!(/(?:(?<=^)|(?<=\s))(?=\w)/, "0x")
106
+ table.gsub!(/^/, "#{indent} ")
107
+ <<-EOS
108
+ #{indent}TABLE = [
109
+ #{table}
110
+ #{indent}].freeze
111
+ EOS
112
+ end
113
+ end
114
+ end