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.
- checksums.yaml +5 -5
- data/HISTORY.ja.md +85 -0
- data/README.ja.md +281 -0
- data/README.md +167 -73
- data/bin/rbcrc +297 -0
- data/bin/rbcrc.orig +295 -0
- data/gemstub.rb +30 -10
- data/lib/crc.rb +63 -257
- data/lib/crc/_aux.rb +37 -0
- data/lib/crc/_byruby.rb +94 -41
- data/lib/crc/_combine.rb +1 -1
- data/lib/crc/_extensions.rb +211 -0
- data/lib/crc/_file.rb +15 -0
- data/lib/crc/_magic.rb +93 -0
- data/lib/crc/{_modules.rb → _models.rb} +7 -6
- data/lib/crc/_shift.rb +198 -0
- data/lib/crc/_utils.rb +114 -0
- data/lib/crc/acrc.rb +18 -73
- data/lib/crc/codegen.rb +881 -0
- data/lib/crc/version.rb +1 -1
- data/test/common.rb +23 -0
- data/test/self_check.rb +31 -0
- data/test/test_arc.rb +23 -0
- data/test/test_block.rb +28 -0
- data/test/test_magic.rb +25 -0
- metadata +42 -19
data/lib/crc/_file.rb
ADDED
data/lib/crc/_magic.rb
ADDED
@@ -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.
|
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
|
-
#
|
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,
|
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,
|
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,
|
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,
|
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"],
|
data/lib/crc/_shift.rb
ADDED
@@ -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
|
data/lib/crc/_utils.rb
ADDED
@@ -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
|