crc 0.2 → 0.3
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 +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"
|