crc 0.2 → 0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.ja.md +22 -0
- data/README.md +140 -30
- data/benchmark.rb +15 -9
- data/gemstub.rb +6 -5
- data/lib/crc.rb +211 -220
- data/lib/crc/_byruby.rb +89 -65
- data/lib/crc/_combine.rb +5 -5
- data/lib/crc/_modules.rb +24 -23
- data/lib/crc/acrc.rb +195 -0
- data/lib/crc/finder.rb +4 -4
- data/lib/crc/version.rb +5 -0
- metadata +12 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e420d67c8c057164c47f3fd4a1d6096d28f66a2
|
4
|
+
data.tar.gz: 77ec3196b4ba3164e0659fcffa7a9833e162aa0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b313c40122e1ee2d953e8fe07520f7787bbea4af884de0fcea1b92263b4791ed189b70696b8885d19bbf33fb56fdcf0f12412a44ade7e2a5f6f91e57d946421
|
7
|
+
data.tar.gz: 157a966f25728523a2edb3de9bf293f0af0bbc1e6484a0bc7b5db8548f6a34abdb5c599d532c5e7b5a119bd41174161517b81d0cf75c49cccdf2596619adfdb8
|
data/HISTORY.ja.md
CHANGED
@@ -2,6 +2,28 @@ This document is written in Japanese.
|
|
2
2
|
|
3
3
|
# crc for ruby の更新履歴
|
4
4
|
|
5
|
+
## crc-0.3 (平成28年7月31日 日曜日)
|
6
|
+
|
7
|
+
互換性を損なう変更があります。
|
8
|
+
|
9
|
+
* CRC::BasicCRC クラスと CRC::Generator クラスを、CRC クラスに統合
|
10
|
+
* ruby オブジェクト CRC をモジュールからクラスに変更しました。
|
11
|
+
* CRC::BasicCRC クラスと CRC::Generator クラスを削除しました。
|
12
|
+
* crc-0.2 まで CRC::BasicCRC の派生クラスだった各 crc モジュールは
|
13
|
+
CRC クラスから派生するようになりました。
|
14
|
+
* CRC.create\_module を削除し、CRC.new に統合
|
15
|
+
* crc-0.2 まであった CRC.create\_module メソッドを削除しました。
|
16
|
+
* CRC.new メソッドが変わりの役割を担うようになりました。
|
17
|
+
* crc モジュールの別名も CRC クラスの定数 (クラスの別名) として追加するように変更
|
18
|
+
* CRC としての整数値を得るメソッドを引数なしで呼び出した場合、CRC モジュールを返すように変更
|
19
|
+
* 例えば ``CRC.crc32`` を引数なしで呼び出すと、CRC::CRC32 クラスオブジェクトが返るようになりました。
|
20
|
+
* CRC-64-ISO の修正
|
21
|
+
* CRC モジュール名の整理
|
22
|
+
* 初期値以外が同じかどうかを確認する CRC.variant? メソッドを追加
|
23
|
+
* ``CRC#initial_crc`` を廃止
|
24
|
+
* 定義が不確かな CRC モジュールを無効化
|
25
|
+
* (実験的) 任意の CRC 値から逆算してバイト列を生成する機能 CRC.acrc (crc/acrc.rb) を追加
|
26
|
+
|
5
27
|
## crc-0.2 (平成28年5月15日 (日))
|
6
28
|
|
7
29
|
* CRC モジュールの追加と修正
|
data/README.md
CHANGED
@@ -7,7 +7,7 @@ It is written by pure ruby with based on slice-by-eight algorithm (slice-by-16 a
|
|
7
7
|
|
8
8
|
Included built-in CRC modules are CRC-32, CRC-64-ECMA, CRC-64-ISO, CRC-16-CCITT, CRC-16-IBM, CRC-8, CRC-5-USB, CRC-5-EPC and many more.
|
9
9
|
|
10
|
-
|
10
|
+
Customization is posible for 1 to 64 bit width, any polynomial primitives, and with/without bit reflection input/output.
|
11
11
|
|
12
12
|
This library is slower than ×85+ of zlib/crc32, and slower than ×120+ of extlzma/crc32 on FreeBSD 10.3R amd64.
|
13
13
|
|
@@ -20,51 +20,98 @@ If you need more speed, please use [crc-turbo](https://rubygems/gems/crc-turbo).
|
|
20
20
|
* author: dearblue (mailto:dearblue@users.osdn.me)
|
21
21
|
* report issue to: <https://osdn.jp/projects/rutsubo/ticket/>
|
22
22
|
* how to install: ``gem install crc``
|
23
|
-
* version: 0.
|
24
|
-
* release quality:
|
23
|
+
* version: 0.3
|
24
|
+
* release quality: technical preview
|
25
25
|
* licensing: BSD-2-Clause<br>any parts are under Creative Commons License Zero (CC0 / Public Domain), and zlib-style License.
|
26
26
|
* dependency gems: none
|
27
|
-
* dependency external
|
28
|
-
* bundled external
|
27
|
+
* dependency external C libraries: none
|
28
|
+
* bundled external C libraries: none
|
29
29
|
|
30
30
|
|
31
|
-
##
|
31
|
+
## API Guide
|
32
32
|
|
33
|
-
This examples are used CRC-32 module. Please see CRC
|
33
|
+
This examples are used CRC-32 module. Please see CRC for more details.
|
34
34
|
|
35
|
-
*
|
36
|
-
* CRC::CRC32.crc(seq, init = 0) -> crc-32 integer (likely as ``Zlib.crc32``)
|
37
|
-
* CRC::CRC32.digest(seq, init = 0) -> crc-32 digest (likely as ``Digest::XXXX.digest``)
|
38
|
-
* CRC::CRC32.hexdigest(seq, init = 0) -> crc-32 hex-digest (likely as ``Digest::XXXX.hexdigest``)
|
39
|
-
* CRC::CRC32.new(init = 0) -> crc-32 context (likely as ``Digest::XXXX.new``)
|
40
|
-
* CRC::CRC32#update(seq) -> self (likely as ``Digest::XXXX#update``)
|
41
|
-
* CRC::CRC32#state -> crc-32 integer
|
42
|
-
* CRC::CRC32#digest -> crc-32 digest (likely as ``Digest::XXXX#digest``)
|
43
|
-
* CRC::CRC32#hexdigest -> crc-32 hex-digest (likely as ``Digest::XXXX#hexdigest``)
|
44
|
-
* CRC.crc("crc-32", seq, init = 0) -> crc-32 integer
|
45
|
-
* CRC.digest("crc-32", seq, init = 0) -> crc-32 digest
|
46
|
-
* CRC.hexdigest("crc-32", seq, init = 0) -> crc-32 hex-digest
|
47
|
-
* CRC::CRC32.combine(CRC.crc32("123"), CRC.crc32("456789"), 6) -> 3421780262 (likely as ``Zlib.crc32_comibne``)
|
48
|
-
* CRC.CRC32("123") + CRC.CRC32("456") + CRC.CRC32("789") -> #<CRC::CRC32:CBF43926>
|
35
|
+
* Calcurate by direct
|
49
36
|
|
50
|
-
|
37
|
+
* ``CRC.crc32(seq, init = CRC::CRC32.initial_crc) => crc-32 integer`` (likely as ``Zlib.crc32``)
|
38
|
+
* ``CRC.crc32.crc(seq, init = CRC::CRC32.initial_crc) => crc-32 integer`` (likely as ``Zlib.crc32``)
|
39
|
+
* ``CRC.crc32.digest(seq, init = CRC::CRC32.initial_crc) => crc-32 digest`` (likely as ``Digest::XXXX.digest``)
|
40
|
+
* ``CRC.crc32.hexdigest(seq, init = 0) -> crc-32 hex-digest`` (likely as ``Digest::XXXX.hexdigest``)
|
41
|
+
* ``CRC.crc32[seq, init = 0, current_length = 0] -> crc-32 generator``
|
42
|
+
* ``CRC.crc32.new(seq, init = 0, current_length = 0) -> crc-32 generator``
|
51
43
|
|
52
|
-
*
|
44
|
+
* Calcurate by streaming
|
45
|
+
|
46
|
+
* ``CRC.crc32[init = 0, current_length = 0] => crc-32 generator``
|
47
|
+
* ``CRC.crc32.new(init = 0, current_length = 0) => crc-32 generator``
|
48
|
+
* ``CRC.crc32#update(seq) => self`` (likely as ``Digest::XXXX.update``)
|
49
|
+
* ``CRC.crc32#finish => crc-32 integer`` (likely as ``Digest::XXXX.finish``)
|
50
|
+
* ``CRC.crc32#crc => crc-32 integer`` (same as ``CRC.crc32#finish``)
|
51
|
+
* ``CRC.crc32#digest => crc-32 digest`` (likely as ``Digest::XXXX.digest``)
|
52
|
+
* ``CRC.crc32#hexdigest => crc-32 hex-digest`` (likely as ``Digest::XXXX.hexdigest``)
|
53
|
+
|
54
|
+
Example:
|
55
|
+
|
56
|
+
``` ruby:ruby
|
57
|
+
x = CRC.crc32.new # => #<CRC::CRC32:00000000>
|
58
|
+
x.update "123" # => #<CRC::CRC32:884863D2>
|
59
|
+
x.update "456789" # => #<CRC::CRC32:CBF43926>
|
60
|
+
x.crc # => 3421780262
|
61
|
+
x.digest # => "\xCB\xF49&"
|
62
|
+
x.hexdigest # => "CBF43926"
|
63
|
+
```
|
64
|
+
|
65
|
+
* Combine
|
66
|
+
|
67
|
+
* ``CRC.combine(crc1, crc2, len2) => combined crc integer`` (likely as ``Zlib.crc32_comibne``)
|
68
|
+
* ``CRC#+(right_crc) => combined crc generator``
|
69
|
+
|
70
|
+
Example-1:
|
71
|
+
|
72
|
+
``` ruby:ruby
|
73
|
+
CRC.crc32.combine(CRC.crc32("123"), CRC.crc32("456789"), 6) # => 3421780262
|
74
|
+
```
|
75
|
+
|
76
|
+
Example-2:
|
77
|
+
|
78
|
+
``` ruby:ruby
|
79
|
+
CRC.crc32["123"] + CRC.crc32["456"] + CRC.crc32["789"] # => #<CRC::CRC32:CBF43926>
|
80
|
+
```
|
81
|
+
|
82
|
+
* Create customized crc module
|
83
|
+
|
84
|
+
* ``CRC.new(bitsize, poly, initial_crc = 0, refin = true, refout = true, xor_output = ~0) => new crc module class``
|
53
85
|
|
54
86
|
``` ruby:ruby
|
55
|
-
MyCRC32 = CRC.
|
56
|
-
|
57
|
-
|
87
|
+
MyCRC32 = CRC.new(32, 0x04C11DB7)
|
88
|
+
MyCRC32.class # => Class
|
89
|
+
MyCRC32.hexdigest("123456789") # => "CBF43926"
|
90
|
+
MyCRC32.new("123456789") # => #<MyCRC32:CBF43926>
|
58
91
|
```
|
59
92
|
|
93
|
+
* Calcurate arc-crc (***EXPERIMENTAL***)
|
94
|
+
|
95
|
+
* ``CRC.acrc(pre, post = nil, want_crc = 0) => arc-crc byte string``
|
96
|
+
|
97
|
+
``` ruby:ruby
|
98
|
+
a = "12"
|
99
|
+
c = "789"
|
100
|
+
wantcrc = 0xCBF43926
|
101
|
+
b = CRC.crc32.acrc(a, c, wantcrc) # => "3456"
|
102
|
+
CRC.crc32[a + b + c] # => #<CRC::CRC32:CBF43926>
|
103
|
+
```
|
104
|
+
|
105
|
+
See CRC::ModuleClass.acrc for more detail.
|
106
|
+
|
60
107
|
|
61
108
|
## Built-in CRC modules
|
62
109
|
|
63
110
|
``` shell:shell
|
64
|
-
% ruby -rcrc -e 'puts CRC::MODULE_TABLE.values.uniq.map { |m| m
|
111
|
+
% ruby -rcrc -e 'puts CRC::MODULE_TABLE.values.uniq.map { |m| m.name }.join(", ")'
|
65
112
|
```
|
66
113
|
|
67
|
-
CRC-1, CRC-3-ROHC, CRC-4-INTERLAKEN, CRC-4-ITU, CRC-5-EPC, CRC-5-ITU, CRC-5-USB, CRC-6-CDMA2000-A, CRC-6-CDMA2000-B, CRC-6-DARC, CRC-6-ITU, CRC-7, CRC-7-MVB, CRC-7-ROHC, CRC-7-UMTS, CRC-8, CRC-8-CCITT, CRC-8-MAXIM, CRC-8-DARC, CRC-8-SAE, CRC-8-WCDMA, CRC-8-CDMA2000, CRC-8-DVB-S2, CRC-8-EBU, CRC-8-I-CODE, CRC-8-ITU, CRC-8-LTE, CRC-8-ROHC, CRC-10, CRC-10-CDMA2000, CRC-11, CRC-11-UMTS, CRC-12-CDMA2000, CRC-12-DECT, CRC-12-UMTS, CRC-13-BBC, CRC-14-DARC, CRC-15, CRC-15-MPT1327, Chakravarty,
|
114
|
+
CRC-1, CRC-3-ROHC, CRC-4-INTERLAKEN, CRC-4-ITU, CRC-5-EPC, CRC-5-ITU, CRC-5-USB, CRC-6-CDMA2000-A, CRC-6-CDMA2000-B, CRC-6-DARC, CRC-6-ITU, CRC-7, CRC-7-MVB, CRC-7-ROHC, CRC-7-UMTS, CRC-8, CRC-8-CCITT, CRC-8-MAXIM, CRC-8-DARC, CRC-8-SAE, CRC-8-WCDMA, CRC-8-CDMA2000, CRC-8-DVB-S2, CRC-8-EBU, CRC-8-I-CODE, CRC-8-ITU, CRC-8-LTE, CRC-8-ROHC, CRC-10, CRC-10-CDMA2000, CRC-11, CRC-11-UMTS, CRC-12-CDMA2000, CRC-12-DECT, CRC-12-UMTS, CRC-13-BBC, CRC-14-DARC, CRC-15, CRC-15-MPT1327, Chakravarty, CRC-16, CRC-16-ARINC, CRC-16-AUG-CCITT, CRC-16-CDMA2000, CRC-16-DECT-R, CRC-16-DECT-X, CRC-16-T10-DIF, CRC-16-DNP, CRC-16-BUYPASS, CRC-16-CCITT-FALSE, CRC-16-DDS-110, CRC-16-EN-13757, CRC-16-GENIBUS, CRC-16-LJ1200, CRC-16-MAXIM, CRC-16-MCRF4XX, CRC-16-RIELLO, CRC-16-TELEDISK, CRC-16-TMS37157, CRC-16-USB, CRC-16-A, CRC-16-KERMIT, CRC-16-MODBUS, CRC-16-X-25, CRC-16-XMODEM, CRC-17-CAN, CRC-21-CAN, CRC-24, CRC-24-Radix-64, CRC-24-OPENPGP, CRC-24-BLE, CRC-24-FLEXRAY-A, CRC-24-FLEXRAY-B, CRC-24-INTERLAKEN, CRC-24-LTE-A, CRC-24-LTE-B, CRC-30, CRC-30-CDMA, CRC-31-PHILIPS, CRC-32, CRC-32-BZIP2, CRC-32C, CRC-32D, CRC-32-MPEG-2, CRC-32-POSIX, CRC-32K, CRC-32K2, CRC-32Q, CRC-32-JAMCRC, CRC-32-XFER, CRC-40-GSM, CRC-64-XZ, CRC-64-ECMA, CRC-64-WE, CRC-64-ISO
|
68
115
|
|
69
116
|
|
70
117
|
## Environment variables for behavior
|
@@ -75,6 +122,69 @@ CRC-1, CRC-3-ROHC, CRC-4-INTERLAKEN, CRC-4-ITU, CRC-5-EPC, CRC-5-ITU, CRC-5-USB,
|
|
75
122
|
* ``RUBY_CRC_NOFAST=3``: Switch to reference algorithm from slice-by-16 algorithm. Slower than about 7% (when CRC-32).
|
76
123
|
|
77
124
|
|
78
|
-
## About CRC
|
125
|
+
## About CRC.combine
|
126
|
+
|
127
|
+
CRC.combine is ported from Mark Adler's crccomb.c in <https://stackoverflow.com/questions/29915764/generic-crc-8-16-32-64-combine-implementation#29928573>.
|
128
|
+
|
129
|
+
|
130
|
+
## arc-crc (***EXPERIMENTAL***)
|
131
|
+
|
132
|
+
(Written in japanese from here)
|
133
|
+
|
134
|
+
crc-0.3 にて、任意の CRC となるバイト列を逆算する機能が***実験的に***追加されました。
|
135
|
+
|
136
|
+
今のところは、reflect-input/output 限定となっています。
|
137
|
+
|
138
|
+
``require "crc/acrc"`` にて、その機能が利用可能となります。
|
139
|
+
|
140
|
+
名前の由来は、arc-sin などの C 関数である asin と同様に、arc-crc => acrc となっています。
|
141
|
+
|
142
|
+
以下は使用例です。
|
143
|
+
|
144
|
+
* 文字列 "123456789????" を CRC32 した場合に 0 となるような、???? の部分を逆算する
|
145
|
+
|
146
|
+
``` ruby:ruby
|
147
|
+
require "crc/acrc"
|
148
|
+
|
149
|
+
seq = "123456789"
|
150
|
+
seq << CRC.crc32.acrc(seq)
|
151
|
+
p CRC.crc32[seq] # => #<CRC::CRC32:00000000>
|
152
|
+
```
|
153
|
+
|
154
|
+
* 文字列 "123456789????ABCDEFG" の、???? の部分を逆算する
|
155
|
+
|
156
|
+
``` ruby:ruby
|
157
|
+
require "crc/acrc"
|
158
|
+
|
159
|
+
seq1 = "123456789"
|
160
|
+
seq2 = "ABCDEFG"
|
161
|
+
seq = seq1 + CRC.crc32.acrc(seq1, seq2) + seq2
|
162
|
+
p CRC.crc32[seq] # => #<CRC::CRC32:00000000>
|
163
|
+
```
|
164
|
+
|
165
|
+
* 文字列 "123456789????ABCDEFG" を CRC32 した場合に 0x12345678 となるような、???? の部分を逆算する
|
166
|
+
|
167
|
+
``` ruby:ruby
|
168
|
+
require "crc/acrc"
|
169
|
+
|
170
|
+
seq1 = "123456789"
|
171
|
+
seq2 = "ABCDEFG"
|
172
|
+
target_crc = 0x12345678
|
173
|
+
seq = seq1 + CRC.crc32.acrc(seq1, seq2, target_crc) + seq2
|
174
|
+
p CRC.crc32[seq] # => #<CRC::CRC32:12345678>
|
175
|
+
```
|
176
|
+
|
177
|
+
* 独自仕様の CRC モジュールにも対応
|
178
|
+
|
179
|
+
``` ruby:ruby
|
180
|
+
require "crc/acrc"
|
181
|
+
|
182
|
+
seq1 = "123456789"
|
183
|
+
seq2 = "ABCDEFG"
|
184
|
+
target_crc = 0x12345678
|
185
|
+
MyCRC = CRC.new(29, rand(1 << 29) | 1)
|
186
|
+
seq = seq1 + MyCRC.acrc(seq1, seq2, target_crc) + seq2
|
187
|
+
p MyCRC[seq] # => #<MyCRC:12345678>
|
188
|
+
```
|
79
189
|
|
80
|
-
|
190
|
+
[EOF]
|
data/benchmark.rb
CHANGED
@@ -9,8 +9,9 @@ require "zlib"
|
|
9
9
|
require "crc"
|
10
10
|
begin; require "extlzma"; rescue LoadError; no_extlzma = true; end
|
11
11
|
begin; require "digest/crc"; rescue LoadError; no_digest_crc = true; end
|
12
|
+
begin; require "crc32"; rescue LoadError; no_crc32 = true; end
|
12
13
|
|
13
|
-
def measure(generator_name)
|
14
|
+
def measure(size, generator_name)
|
14
15
|
print " * measuring for #{generator_name}..."
|
15
16
|
$stdout.flush
|
16
17
|
realms = 5.times.map do
|
@@ -19,7 +20,7 @@ def measure(generator_name)
|
|
19
20
|
$stdout.flush
|
20
21
|
real
|
21
22
|
end.min
|
22
|
-
|
23
|
+
printf " (%.2f ms.) (peak: %0.2f MiB / s)\n", realms, size / (realms / 1000)
|
23
24
|
[generator_name, realms]
|
24
25
|
end
|
25
26
|
|
@@ -38,17 +39,22 @@ puts " ** preparing #{size} MiB data...\n"
|
|
38
39
|
#s = SecureRandom.random_bytes(size << 20)
|
39
40
|
s = "0" * (size << 20)
|
40
41
|
|
41
|
-
crc = measure("
|
42
|
+
crc = measure(size, "crc/crc32") { CRC.crc32(s) }[1]
|
42
43
|
comparisons = []
|
43
|
-
comparisons << measure("zlib/crc-32") { Zlib.crc32(s) }
|
44
|
-
comparisons << measure("extlzma/crc-32") { LZMA.crc32(s) } unless no_extlzma
|
45
|
-
comparisons << measure("digest/crc-32") { Digest::CRC32.digest(s) } unless no_digest_crc
|
46
|
-
comparisons << measure("
|
47
|
-
comparisons << measure("
|
44
|
+
comparisons << measure(size, "zlib/crc-32") { Zlib.crc32(s) }
|
45
|
+
comparisons << measure(size, "extlzma/crc-32") { LZMA.crc32(s) } unless no_extlzma
|
46
|
+
comparisons << measure(size, "digest/crc-32") { Digest::CRC32.digest(s) } unless no_digest_crc
|
47
|
+
comparisons << measure(size, "crc32/crc-32") { Crc32.calculate(s, s.bytesize, 0) } unless no_crc32
|
48
|
+
comparisons << measure(size, "crc/crc-64") { CRC.crc64(s) }
|
49
|
+
comparisons << measure(size, "extlzma/crc-64") { LZMA.crc64(s) } unless no_extlzma
|
50
|
+
comparisons << measure(size, "crc/crc-5-usb") { CRC.crc5_usb(s) }
|
51
|
+
comparisons << measure(size, "crc/crc-16-usb") { CRC.crc16_usb(s) }
|
52
|
+
comparisons << measure(size, "crc/crc-32-posix") { CRC.crc32_posix(s) }
|
53
|
+
comparisons << measure(size, "crc/crc-32c") { CRC.crc32c(s) }
|
48
54
|
|
49
55
|
puts <<'EOS'
|
50
56
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
51
|
-
|
57
|
+
(ruby-crc/crc32 is slowly at over 1.0)
|
52
58
|
EOS
|
53
59
|
|
54
60
|
comparisons.each do |name, meas|
|
data/gemstub.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
+
require_relative "lib/crc/version"
|
2
|
+
|
1
3
|
GEMSTUB = Gem::Specification.new do |s|
|
2
4
|
s.name = "crc"
|
3
|
-
s.version =
|
5
|
+
s.version = CRC::VERSION
|
4
6
|
s.summary = "general CRC generator"
|
5
7
|
s.description = <<EOS
|
6
8
|
This is a general CRC (Cyclic Redundancy Check) generator for ruby.
|
7
|
-
It is written by pure ruby
|
8
|
-
|
9
|
-
Additional your customized CRC modules are defined to posible.
|
9
|
+
It is written by pure ruby.
|
10
|
+
Customization is posible for 1 to 64 bit width, any polynomial primitives, and with/without bit reflection input/output.
|
10
11
|
If you need more speed, please use crc-turbo.
|
11
12
|
EOS
|
12
13
|
s.homepage = "https://osdn.jp/projects/rutsubo/"
|
@@ -15,7 +16,7 @@ EOS
|
|
15
16
|
s.email = "dearblue@users.osdn.me"
|
16
17
|
|
17
18
|
s.required_ruby_version = ">= 2.0"
|
18
|
-
s.add_development_dependency "rake"
|
19
|
+
s.add_development_dependency "rake"
|
19
20
|
end
|
20
21
|
|
21
22
|
EXTRA << "benchmark.rb"
|
data/lib/crc.rb
CHANGED
@@ -10,6 +10,8 @@ else
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
+
require_relative "crc/version"
|
14
|
+
|
13
15
|
#
|
14
16
|
# This is a general CRC generator.
|
15
17
|
#
|
@@ -30,15 +32,18 @@ end
|
|
30
32
|
# crc32 << s
|
31
33
|
# end
|
32
34
|
# p crc32 # => #<CRC::CRC32:6A632AA5>
|
33
|
-
# p crc32.
|
35
|
+
# p crc32.crc # => 1784883877
|
34
36
|
# p crc32.digest # => "jc*\xA5"
|
35
37
|
# p crc32.hexdigest # => "6A632AA5"
|
36
38
|
#
|
37
|
-
|
39
|
+
class CRC
|
38
40
|
CRC = self
|
39
41
|
|
40
42
|
extend Utils
|
41
43
|
|
44
|
+
#
|
45
|
+
# Utilities.
|
46
|
+
#
|
42
47
|
module Utils
|
43
48
|
extend self
|
44
49
|
|
@@ -141,20 +146,23 @@ module CRC
|
|
141
146
|
|
142
147
|
extend Utils
|
143
148
|
|
149
|
+
#
|
150
|
+
# Internal using module.
|
151
|
+
#
|
144
152
|
module Aux
|
145
|
-
def self.DIGEST(
|
153
|
+
def self.DIGEST(num, bitsize)
|
146
154
|
bits = (bitsize + 7) / 8 * 8
|
147
|
-
seq = ""
|
148
|
-
(bits - 8).step(0, -8) { |i| seq << yield((
|
155
|
+
seq = ""
|
156
|
+
(bits - 8).step(0, -8) { |i| seq << yield((num >> i) & 0xff) }
|
149
157
|
seq
|
150
158
|
end
|
151
159
|
|
152
|
-
def self.digest(
|
153
|
-
DIGEST(
|
160
|
+
def self.digest(num, bitsize)
|
161
|
+
DIGEST(num, bitsize) { |n| n.chr(Encoding::BINARY) }
|
154
162
|
end
|
155
163
|
|
156
|
-
def self.hexdigest(
|
157
|
-
DIGEST(
|
164
|
+
def self.hexdigest(num, bitsize)
|
165
|
+
DIGEST(num, bitsize) { |n| "%02X" % n }
|
158
166
|
end
|
159
167
|
|
160
168
|
#
|
@@ -174,34 +182,75 @@ module CRC
|
|
174
182
|
end
|
175
183
|
end
|
176
184
|
|
177
|
-
|
178
|
-
def crc
|
179
|
-
|
185
|
+
module ModuleClass
|
186
|
+
def setup(crc = nil)
|
187
|
+
crc ||= initial_crc
|
188
|
+
crc = CRC.bitreflect(crc, bitsize) if reflect_input? ^ reflect_output?
|
189
|
+
crc ^ xor_output
|
180
190
|
end
|
181
191
|
|
182
|
-
|
183
|
-
state ||= initial_state
|
184
|
-
state = CRC.bitreflect(state, bitsize) if reflect_input ^ reflect_output
|
185
|
-
state ^ xor_output
|
186
|
-
end
|
192
|
+
alias init setup
|
187
193
|
|
188
194
|
def finish(state)
|
189
|
-
state = CRC.bitreflect(state, bitsize) if reflect_input ^ reflect_output
|
195
|
+
state = CRC.bitreflect(state, bitsize) if reflect_input? ^ reflect_output?
|
190
196
|
state ^ xor_output
|
191
197
|
end
|
192
198
|
|
193
|
-
|
194
|
-
|
199
|
+
def crc(seq, crc = nil)
|
200
|
+
finish(update(seq, setup(crc)))
|
201
|
+
end
|
195
202
|
|
196
|
-
def digest(seq,
|
197
|
-
Aux.digest(crc(seq,
|
203
|
+
def digest(seq, crc = nil)
|
204
|
+
Aux.digest(crc(seq, crc), bitsize)
|
198
205
|
end
|
199
206
|
|
200
|
-
def hexdigest(seq,
|
201
|
-
Aux.hexdigest(crc(seq,
|
207
|
+
def hexdigest(seq, crc = nil)
|
208
|
+
Aux.hexdigest(crc(seq, crc), bitsize)
|
202
209
|
end
|
203
210
|
|
204
|
-
def
|
211
|
+
def variant?(obj)
|
212
|
+
case
|
213
|
+
when obj.kind_of?(CRC)
|
214
|
+
mod = obj.class
|
215
|
+
when obj.kind_of?(Class) && obj < CRC
|
216
|
+
mod = obj
|
217
|
+
else
|
218
|
+
return false
|
219
|
+
end
|
220
|
+
|
221
|
+
if bitsize == mod.bitsize &&
|
222
|
+
polynomial == mod.polynomial &&
|
223
|
+
reflect_input? == mod.reflect_input? &&
|
224
|
+
reflect_output? == mod.reflect_output? &&
|
225
|
+
xor_output == mod.xor_output
|
226
|
+
true
|
227
|
+
else
|
228
|
+
false
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
#
|
233
|
+
# call-seq:
|
234
|
+
# combine(crc1, crc2) -> new combined crc
|
235
|
+
# combine(crc1_int, crc2_int, crc2_len) -> new combined crc
|
236
|
+
#
|
237
|
+
def combine(*args)
|
238
|
+
case args.size
|
239
|
+
when 2
|
240
|
+
unless args[0].kind_of?(CRC) && args[1].kind_of?(CRC)
|
241
|
+
raise ArgumentError, "When given two arguments, both arguments are should be CRC instance"
|
242
|
+
end
|
243
|
+
|
244
|
+
crc1 + crc2
|
245
|
+
when 3
|
246
|
+
Aux.combine(Integer(args[0].to_i), Integer(args[1].to_i), Integer(args[2].to_i),
|
247
|
+
bitsize, polynomial, initial_crc, reflect_input?, reflect_output?, xor_output)
|
248
|
+
else
|
249
|
+
raise ArgumentError, "wrong number of arguments (given #{args.size}, expect 2..3)"
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def to_str
|
205
254
|
case
|
206
255
|
when bitsize > 64 then width = 20
|
207
256
|
when bitsize > 32 then width = 16
|
@@ -210,17 +259,17 @@ module CRC
|
|
210
259
|
else width = 2
|
211
260
|
end
|
212
261
|
|
213
|
-
if reflect_input
|
214
|
-
ref = "
|
262
|
+
if reflect_input?
|
263
|
+
ref = " reflect-in#{reflect_output? ? "/out" : ""}"
|
215
264
|
else
|
216
|
-
ref = reflect_output ? "
|
265
|
+
ref = reflect_output? ? " reflect-out" : ""
|
217
266
|
end
|
218
267
|
|
219
|
-
case
|
268
|
+
case initial_crc
|
220
269
|
when 0 then init = "0"
|
221
270
|
when bitmask then init = "~0"
|
222
271
|
when 1 then init = "1"
|
223
|
-
else init = "0x%0#{width}X" %
|
272
|
+
else init = "0x%0#{width}X" % initial_crc
|
224
273
|
end
|
225
274
|
|
226
275
|
case xor_output
|
@@ -230,15 +279,11 @@ module CRC
|
|
230
279
|
else xor = "0x%0#{width}X" % xor_output
|
231
280
|
end
|
232
281
|
|
233
|
-
|
234
|
-
"#{nm}(CRC-%d-0x%0#{width}X%s init=%s, xor=%s)" % [bitsize, polynomial, ref, init, xor]
|
235
|
-
else
|
236
|
-
"(CRC-%d-0x%0#{width}X%s init=%s, xor=%s)" % [bitsize, polynomial, ref, init, xor]
|
237
|
-
end
|
282
|
+
"CRC-%d-0x%0#{width}X%s init=%s xor=%s" % [bitsize, polynomial, ref, init, xor]
|
238
283
|
end
|
239
284
|
|
240
285
|
def inspect
|
241
|
-
"
|
286
|
+
"#{super}{#{to_str}}"
|
242
287
|
end
|
243
288
|
|
244
289
|
def pretty_inspect(q)
|
@@ -246,189 +291,136 @@ module CRC
|
|
246
291
|
end
|
247
292
|
end
|
248
293
|
|
249
|
-
|
250
|
-
BasicStruct = superclass
|
251
|
-
|
252
|
-
class BasicStruct
|
253
|
-
alias state! internal_state
|
254
|
-
alias set_state! internal_state=
|
255
|
-
end
|
294
|
+
attr_accessor :state, :size
|
256
295
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
end
|
296
|
+
#
|
297
|
+
# call-seq:
|
298
|
+
# initialize(initial_crc = nil, size = 0)
|
299
|
+
# initialize(seq, initial_crc = nil, size = 0)
|
300
|
+
#
|
301
|
+
def initialize(*args)
|
302
|
+
initialize_args(args) do |seq, initial_crc, size|
|
303
|
+
m = self.class
|
304
|
+
@state = m.setup((initial_crc || m.initial_crc).to_i)
|
305
|
+
@size = size.to_i
|
306
|
+
update(seq) if seq
|
269
307
|
end
|
308
|
+
end
|
270
309
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
self
|
278
|
-
end
|
310
|
+
def reset(initial_crc = nil, size = 0)
|
311
|
+
m = self.class
|
312
|
+
@state = m.setup((initial_crc || m.initial_crc).to_i)
|
313
|
+
@size = size.to_i
|
314
|
+
self
|
315
|
+
end
|
279
316
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
317
|
+
def update(seq)
|
318
|
+
@state = self.class.update(seq, state)
|
319
|
+
@size += seq.bytesize
|
320
|
+
self
|
321
|
+
end
|
285
322
|
|
286
|
-
|
323
|
+
alias << update
|
287
324
|
|
288
|
-
|
289
|
-
|
290
|
-
|
325
|
+
def crc
|
326
|
+
self.class.finish(state)
|
327
|
+
end
|
291
328
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
end
|
329
|
+
def +(crc2)
|
330
|
+
raise ArgumentError, "not a CRC instance (#{crc2.inspect})" unless crc2.kind_of?(CRC)
|
331
|
+
m1 = self.class
|
332
|
+
m2 = crc2.class
|
333
|
+
unless m1.bitsize == m2.bitsize &&
|
334
|
+
m1.polynomial == m2.polynomial &&
|
335
|
+
m1.reflect_input? == m2.reflect_input? &&
|
336
|
+
m1.reflect_output? == m2.reflect_output? &&
|
337
|
+
# m1.initial_crc == m2.initial_crc &&
|
338
|
+
m1.xor_output == m2.xor_output
|
339
|
+
raise ArgumentError, "different CRC module (#{m1.inspect} and #{m2.inspect})"
|
340
|
+
end
|
341
|
+
m1.new(m1.combine(crc, crc2.crc, crc2.size), size + crc2.size)
|
342
|
+
end
|
307
343
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
true
|
322
|
-
else
|
323
|
-
false
|
324
|
-
end
|
325
|
-
when Integer
|
326
|
-
state == a
|
344
|
+
def ==(a)
|
345
|
+
case a
|
346
|
+
when CRC
|
347
|
+
m1 = self.class
|
348
|
+
m2 = a.class
|
349
|
+
if m1.bitsize == m2.bitsize &&
|
350
|
+
m1.polynomial == m2.polynomial &&
|
351
|
+
m1.reflect_input? == m2.reflect_input? &&
|
352
|
+
m1.reflect_output? == m2.reflect_output? &&
|
353
|
+
# m1.initial_crc == m2.initial_crc &&
|
354
|
+
m1.xor_output == m2.xor_output &&
|
355
|
+
state == a.state
|
356
|
+
true
|
327
357
|
else
|
328
|
-
|
358
|
+
false
|
329
359
|
end
|
360
|
+
when Integer
|
361
|
+
crc == a
|
362
|
+
else
|
363
|
+
super
|
330
364
|
end
|
365
|
+
end
|
331
366
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
def to_a
|
336
|
-
[state]
|
337
|
-
end
|
338
|
-
|
339
|
-
def digest
|
340
|
-
Aux.DIGEST(state, self.class::GENERATOR.bitsize) { |n| [n].pack("C") }
|
341
|
-
end
|
342
|
-
|
343
|
-
# return digest as internal state
|
344
|
-
def digest!
|
345
|
-
Aux.DIGEST(state!, self.class::GENERATOR.bitsize) { |n| [n].pack("C") }
|
346
|
-
end
|
347
|
-
|
348
|
-
def hexdigest
|
349
|
-
Aux.DIGEST(state, self.class::GENERATOR.bitsize) { |n| "%02X" % n }
|
350
|
-
end
|
351
|
-
|
352
|
-
# return hex-digest as internal state
|
353
|
-
def hexdigest!
|
354
|
-
Aux.DIGEST(state!, self.class::GENERATOR.bitsize) { |n| "%02X" % n }
|
355
|
-
end
|
367
|
+
alias to_i crc
|
368
|
+
alias to_int crc
|
356
369
|
|
357
|
-
|
358
|
-
|
370
|
+
def to_a
|
371
|
+
[crc]
|
372
|
+
end
|
359
373
|
|
360
|
-
|
361
|
-
|
362
|
-
|
374
|
+
def digest
|
375
|
+
Aux.digest(crc, self.class.bitsize)
|
376
|
+
end
|
363
377
|
|
364
|
-
|
365
|
-
|
366
|
-
|
378
|
+
# return digest as internal state
|
379
|
+
def digest!
|
380
|
+
Aux.digest(state, self.class.bitsize)
|
381
|
+
end
|
367
382
|
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
#
|
372
|
-
# call-seq:
|
373
|
-
# combine(crc1, crc2) -> new combined crc
|
374
|
-
# combine(crc1_int, crc2_int, crc2_len) -> new combined crc
|
375
|
-
#
|
376
|
-
def combine(crc1, crc2, len2 = nil)
|
377
|
-
return crc1 + crc2 if crc1.kind_of?(BasicCRC) && crc2.kind_of?(BasicCRC)
|
378
|
-
self::GENERATOR.combine(crc1.to_i, crc2.to_i, len2)
|
379
|
-
end
|
383
|
+
def hexdigest
|
384
|
+
Aux.hexdigest(crc, self.class.bitsize)
|
385
|
+
end
|
380
386
|
|
381
|
-
|
382
|
-
|
383
|
-
|
387
|
+
# return hex-digest as internal state
|
388
|
+
def hexdigest!
|
389
|
+
Aux.hexdigest(state, self.class.bitsize)
|
390
|
+
end
|
384
391
|
|
385
|
-
|
386
|
-
|
387
|
-
end
|
392
|
+
alias to_str hexdigest
|
393
|
+
alias to_s hexdigest
|
388
394
|
|
389
|
-
|
390
|
-
|
391
|
-
|
395
|
+
def inspect
|
396
|
+
"\#<#{self.class}:#{hexdigest}>"
|
397
|
+
end
|
392
398
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
"#{nm}(#{self::GENERATOR.to_s})"
|
397
|
-
else
|
398
|
-
super.sub(/(?=\>$)/) { " #{self::GENERATOR.to_s}" }
|
399
|
-
end
|
400
|
-
else
|
401
|
-
super
|
402
|
-
end
|
403
|
-
end
|
399
|
+
def pretty_inspect(q)
|
400
|
+
q.text inspect
|
401
|
+
end
|
404
402
|
|
405
|
-
|
406
|
-
|
403
|
+
private
|
404
|
+
def initialize_args(args)
|
405
|
+
case args.size
|
406
|
+
when 0
|
407
|
+
yield nil, nil, 0
|
408
|
+
when 1
|
409
|
+
if args[0].kind_of?(String)
|
410
|
+
yield args[0], nil, 0
|
411
|
+
else
|
412
|
+
yield nil, args[0], 0
|
407
413
|
end
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
def initialize_args(args)
|
412
|
-
case args.size
|
413
|
-
when 0
|
414
|
-
yield nil, nil, 0
|
415
|
-
when 1
|
416
|
-
if args[0].kind_of?(String)
|
417
|
-
yield args[0], nil, 0
|
418
|
-
else
|
419
|
-
yield nil, args[0], 0
|
420
|
-
end
|
421
|
-
when 2
|
422
|
-
if args[0].kind_of?(String)
|
423
|
-
yield args[0], args[1], 0
|
424
|
-
else
|
425
|
-
yield nil, args[0], args[1].to_i
|
426
|
-
end
|
427
|
-
when 3
|
428
|
-
yield args[0], args[1], args[2].to_i
|
414
|
+
when 2
|
415
|
+
if args[0].kind_of?(String)
|
416
|
+
yield args[0], args[1], 0
|
429
417
|
else
|
430
|
-
|
418
|
+
yield nil, args[0], args[1].to_i
|
431
419
|
end
|
420
|
+
when 3
|
421
|
+
yield args[0], args[1], args[2].to_i
|
422
|
+
else
|
423
|
+
raise ArgumentError, "wrong argument size (given #{args.size}, expect 0..3)"
|
432
424
|
end
|
433
425
|
end
|
434
426
|
|
@@ -443,23 +435,16 @@ module CRC
|
|
443
435
|
|
444
436
|
alias [] lookup
|
445
437
|
|
446
|
-
def crc(modulename, seq,
|
447
|
-
lookup(modulename).crc(seq,
|
448
|
-
end
|
449
|
-
|
450
|
-
def digest(modulename, seq, state = nil)
|
451
|
-
lookup(modulename).digest(seq, state)
|
438
|
+
def crc(modulename, seq, crc = nil)
|
439
|
+
lookup(modulename).crc(seq, crc)
|
452
440
|
end
|
453
441
|
|
454
|
-
def
|
455
|
-
lookup(modulename).
|
442
|
+
def digest(modulename, seq, crc = nil)
|
443
|
+
lookup(modulename).digest(seq, crc)
|
456
444
|
end
|
457
445
|
|
458
|
-
def
|
459
|
-
|
460
|
-
crc = Class.new(BasicCRC)
|
461
|
-
crc.const_set :GENERATOR, g
|
462
|
-
crc
|
446
|
+
def hexdigest(modulename, seq, crc = nil)
|
447
|
+
lookup(modulename).hexdigest(seq, crc)
|
463
448
|
end
|
464
449
|
end
|
465
450
|
|
@@ -469,10 +454,11 @@ module CRC
|
|
469
454
|
#
|
470
455
|
# Create CRC module classes.
|
471
456
|
#
|
472
|
-
LIST.each do |bitsize, polynomial, refin, refout,
|
457
|
+
LIST.each do |bitsize, polynomial, refin, refout, initial_crc, xor, check, *names|
|
458
|
+
names.flatten!
|
473
459
|
names.map! { |nm| nm.freeze }
|
474
460
|
|
475
|
-
crc =
|
461
|
+
crc = CRC.new(bitsize, polynomial, initial_crc, refin, refout, xor, names[0])
|
476
462
|
crc.const_set :NAME, names
|
477
463
|
|
478
464
|
names.each do |nm|
|
@@ -481,31 +467,36 @@ module CRC
|
|
481
467
|
raise NameError, "collision crc-module name: #{nm} (#{crc::GENERATOR} and #{MODULE_TABLE[nm1]::GENERATOR})"
|
482
468
|
end
|
483
469
|
MODULE_TABLE[nm1] = crc
|
470
|
+
|
471
|
+
name = nm.sub(/(?<=\bCRC)-(?=\d+)/, "").gsub(/[\W]+/, "_")
|
472
|
+
const_set(name, crc)
|
473
|
+
|
474
|
+
define_singleton_method(name.upcase, ->(*args) { crc.new(*args) })
|
475
|
+
define_singleton_method(name.downcase, ->(*args) {
|
476
|
+
if args.size == 0
|
477
|
+
crc
|
478
|
+
else
|
479
|
+
crc.crc(*args)
|
480
|
+
end
|
481
|
+
})
|
484
482
|
end
|
485
|
-
name = names[0].sub(/(?<=\bCRC)-(?=\d+)/, "").gsub(/[\W]+/, "_")
|
486
|
-
const_set(name, crc)
|
487
483
|
|
488
484
|
check = Integer(check.to_i) if check
|
489
485
|
crc.const_set :CHECK, check
|
490
|
-
|
491
|
-
g = crc::GENERATOR
|
492
|
-
define_singleton_method(name.upcase, ->(*args) { crc.new(*args) })
|
493
|
-
define_singleton_method(name.downcase, ->(*args) { g.crc(*args) })
|
494
486
|
end
|
495
487
|
|
496
488
|
if $0 == __FILE__
|
497
489
|
$stderr.puts "#{__FILE__}:#{__LINE__}: SELF CHECK for CRC modules (#{File.basename($".grep(/_(?:byruby|turbo)/)[0]||"")})\n"
|
498
490
|
MODULE_TABLE.values.uniq.each do |crc|
|
499
|
-
g = crc::GENERATOR
|
500
491
|
check = crc::CHECK
|
501
|
-
checked =
|
492
|
+
checked = crc.crc("123456789")
|
502
493
|
case check
|
503
494
|
when nil
|
504
|
-
$stderr.puts "| %20s(\"123456789\") = %16X (check only)\n" % [
|
495
|
+
$stderr.puts "| %20s(\"123456789\") = %16X (check only)\n" % [crc.name, checked]
|
505
496
|
when checked
|
506
497
|
;
|
507
498
|
else
|
508
|
-
$stderr.puts "| %20s(\"123456789\") = %16X (expect to %X)\n" % [
|
499
|
+
$stderr.puts "| %20s(\"123456789\") = %16X (expect to %X)\n" % [crc.name, checked, check]
|
509
500
|
end
|
510
501
|
end
|
511
502
|
$stderr.puts "#{__FILE__}:#{__LINE__}: DONE SELF CHECK\n"
|