crc 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ccf4d480da684a319f684082517b687ec6bd9974
4
- data.tar.gz: c97ed329ce7093405e7db797ede21ff6f8d9acbc
3
+ metadata.gz: 0e420d67c8c057164c47f3fd4a1d6096d28f66a2
4
+ data.tar.gz: 77ec3196b4ba3164e0659fcffa7a9833e162aa0c
5
5
  SHA512:
6
- metadata.gz: 2c026e783622209e7fd9ff23783a773a6da6c2514f685c177ade3225b560b9c2db5ebe126e6bedbe98e7a039c24d0974ae73139bf623d771fc47f07cb04b39ce
7
- data.tar.gz: a4b27b3b7262c4c46e616048d587c3ae9b809dd104d7e76686f611f830c9f761eccbef0a693cf46acede424205a1984247b351e7f9ef78442fc800489577a68d
6
+ metadata.gz: 7b313c40122e1ee2d953e8fe07520f7787bbea4af884de0fcea1b92263b4791ed189b70696b8885d19bbf33fb56fdcf0f12412a44ade7e2a5f6f91e57d946421
7
+ data.tar.gz: 157a966f25728523a2edb3de9bf293f0af0bbc1e6484a0bc7b5db8548f6a34abdb5c599d532c5e7b5a119bd41174161517b81d0cf75c49cccdf2596619adfdb8
@@ -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
- Additional your customized CRC modules are defined to posible.
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.2
24
- * release quality: thechnical preview
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 c libraries: none
28
- * bundled external c libraries: none
27
+ * dependency external C libraries: none
28
+ * bundled external C libraries: none
29
29
 
30
30
 
31
- ## Features
31
+ ## API Guide
32
32
 
33
- This examples are used CRC-32 module. Please see CRC::BasicCRC for more details.
33
+ This examples are used CRC-32 module. Please see CRC for more details.
34
34
 
35
- * CRC.crc32(seq, init = 0) -> crc-32 integer (likely as ``Zlib.crc32``)
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") -> &#35;&lt;CRC::CRC32:CBF43926&gt;
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
- * CRC.create\_module(bitsize, poly, init\_state, refin, refout, xorout) -> new crc module class
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.create_module(32, 0x04C11DB7)
56
- p MyCRC32.class # => Class
57
- p MyCRC32.hexdigest("123456789") # => "CBF43926"
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::GENERATOR.name }.join(", ")'
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, ARC, 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-A, KERMIT, MODBUS, X-25, 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, JAMCRC, XFER, CRC-40-GSM, CRC-64, CRC-64-ECMA, CRC-64-WE, CRC-64-ISO
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::Generator#combine
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
- CRC::Generator#combine is ported from Mark Adler's crccomb.c in https://stackoverflow.com/questions/29915764/generic-crc-8-16-32-64-combine-implementation#29928573 .
190
+ [EOF]
@@ -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
- puts " (#{(realms * 100).round / 100.0} ms.)\n"
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("ruby-crc/crc32") { CRC.crc32(s) }[1]
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("ruby-crc/crc-64") { CRC.crc64(s) }
47
- comparisons << measure("extlzma/crc-64") { LZMA.crc64(s) } unless no_extlzma
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
- (slowly at over 1.0)
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 = "0.2"
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 with based on slice-by-eight algorithm (slice-by-16 algorithm as byte-order free and byte-alignment free).
8
- Included built-in CRC modules are CRC-32, CRC-64-XZ, CRC-64-ECMA, CRC-64-ISO, CRC-16-CCITT, CRC-16-IBM, CRC-8, CRC-5-USB, CRC-5-EPC and many more.
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", "~> 11.0"
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.state # => 1784883877
35
+ # p crc32.crc # => 1784883877
34
36
  # p crc32.digest # => "jc*\xA5"
35
37
  # p crc32.hexdigest # => "6A632AA5"
36
38
  #
37
- module CRC
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(state, bitsize)
153
+ def self.DIGEST(num, bitsize)
146
154
  bits = (bitsize + 7) / 8 * 8
147
- seq = "".b
148
- (bits - 8).step(0, -8) { |i| seq << yield((state >> i) & 0xff) }
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(state, bitsize)
153
- DIGEST(state, bitsize) { |n| [n].pack("C") }
160
+ def self.digest(num, bitsize)
161
+ DIGEST(num, bitsize) { |n| n.chr(Encoding::BINARY) }
154
162
  end
155
163
 
156
- def self.hexdigest(state, bitsize)
157
- DIGEST(state, bitsize) { |n| "%02X" % n }
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
- class Generator
178
- def crc(seq, state = nil)
179
- finish(update(seq, setup(state)))
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
- def setup(state = nil)
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
- alias reflect_input? reflect_input
194
- alias reflect_output? reflect_output
199
+ def crc(seq, crc = nil)
200
+ finish(update(seq, setup(crc)))
201
+ end
195
202
 
196
- def digest(seq, state = nil)
197
- Aux.digest(crc(seq, state), bitsize)
203
+ def digest(seq, crc = nil)
204
+ Aux.digest(crc(seq, crc), bitsize)
198
205
  end
199
206
 
200
- def hexdigest(seq, state = nil)
201
- Aux.hexdigest(crc(seq, state), bitsize)
207
+ def hexdigest(seq, crc = nil)
208
+ Aux.hexdigest(crc(seq, crc), bitsize)
202
209
  end
203
210
 
204
- def to_s
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 = ", reflect-in#{reflect_output ? "/out" : ""}"
262
+ if reflect_input?
263
+ ref = " reflect-in#{reflect_output? ? "/out" : ""}"
215
264
  else
216
- ref = reflect_output ? ", reflect-out" : ""
265
+ ref = reflect_output? ? " reflect-out" : ""
217
266
  end
218
267
 
219
- case initial_state
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" % initial_state
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
- if nm = name
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
- "\#<#{self.class} #{to_s}>"
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
- class BasicCRC < Struct.new(:internal_state, :initial_state, :size)
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
- # call-seq:
259
- # initialize(initial_state = nil, size = 0)
260
- # initialize(seq, initial_state = nil, size = 0)
261
- #
262
- def initialize(*args)
263
- initialize_args(args) do |seq, initial_state, size|
264
- g = self.class::GENERATOR
265
- initial_state ||= g.initial_state
266
- super g.setup(initial_state.to_i), initial_state.to_i, size.to_i
267
- update(seq) if seq
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
- def reset(initial_state = self.initial_state, size = 0)
272
- g = self.class::GENERATOR
273
- initial_state ||= g.initial_state
274
- set_state! g.setup(initial_state)
275
- self.initial_state = initial_state
276
- self.size = size.to_i
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
- def update(seq)
281
- set_state! self.class::GENERATOR.update(seq, state!)
282
- self.size += seq.bytesize
283
- self
284
- end
317
+ def update(seq)
318
+ @state = self.class.update(seq, state)
319
+ @size += seq.bytesize
320
+ self
321
+ end
285
322
 
286
- alias << update
323
+ alias << update
287
324
 
288
- def state
289
- self.class::GENERATOR.finish(state!)
290
- end
325
+ def crc
326
+ self.class.finish(state)
327
+ end
291
328
 
292
- def +(crc2)
293
- raise ArgumentError, "not a CRC instance (#{crc2.inspect})" unless crc2.kind_of?(BasicCRC)
294
- c1 = self.class
295
- g1 = c1::GENERATOR
296
- g2 = crc2.class::GENERATOR
297
- unless g1.bitsize == g2.bitsize &&
298
- g1.polynomial == g2.polynomial &&
299
- g1.reflect_input == g2.reflect_input &&
300
- g1.reflect_output == g2.reflect_output &&
301
- # g1.initial_state == g2.initial_state &&
302
- g1.xor_output == g2.xor_output
303
- raise ArgumentError, "different CRC module (#{g1.inspect} and #{g2.inspect})"
304
- end
305
- c1.new(g1.combine(state, crc2.state, crc2.size), size + crc2.size)
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
- def ==(a)
309
- case a
310
- when BasicCRC
311
- c1 = self.class
312
- g1 = c1::GENERATOR
313
- g2 = a.class::GENERATOR
314
- if g1.bitsize == g2.bitsize &&
315
- g1.polynomial == g2.polynomial &&
316
- g1.reflect_input == g2.reflect_input &&
317
- g1.reflect_output == g2.reflect_output &&
318
- # g1.initial_state == g2.initial_state &&
319
- g1.xor_output == g2.xor_output &&
320
- state! == a.state!
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
- super
358
+ false
329
359
  end
360
+ when Integer
361
+ crc == a
362
+ else
363
+ super
330
364
  end
365
+ end
331
366
 
332
- alias to_i state
333
- alias to_int state
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
- alias to_str hexdigest
358
- alias to_s hexdigest
370
+ def to_a
371
+ [crc]
372
+ end
359
373
 
360
- def inspect
361
- "\#<#{self.class}:#{hexdigest}>"
362
- end
374
+ def digest
375
+ Aux.digest(crc, self.class.bitsize)
376
+ end
363
377
 
364
- def pretty_inspect(q)
365
- q.text inspect
366
- end
378
+ # return digest as internal state
379
+ def digest!
380
+ Aux.digest(state, self.class.bitsize)
381
+ end
367
382
 
368
- class << self
369
- alias [] new
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
- def crc(seq, state = nil)
382
- self::GENERATOR.crc(seq, state)
383
- end
387
+ # return hex-digest as internal state
388
+ def hexdigest!
389
+ Aux.hexdigest(state, self.class.bitsize)
390
+ end
384
391
 
385
- def digest(seq, state = nil)
386
- Aux.digest(self::GENERATOR.crc(seq, state), self::GENERATOR.bitsize)
387
- end
392
+ alias to_str hexdigest
393
+ alias to_s hexdigest
388
394
 
389
- def hexdigest(seq, state = nil)
390
- Aux.hexdigest(self::GENERATOR.crc(seq, state), self::GENERATOR.bitsize)
391
- end
395
+ def inspect
396
+ "\#<#{self.class}:#{hexdigest}>"
397
+ end
392
398
 
393
- def inspect
394
- if const_defined?(:GENERATOR)
395
- if nm = name
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
- def pretty_inspect(q)
406
- q.text inspect
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
- end
409
-
410
- private
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
- raise ArgumentError, "wrong argument size (given #{args.size}, expect 0..3)"
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, state = nil)
447
- lookup(modulename).crc(seq, state)
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 hexdigest(modulename, seq, state = nil)
455
- lookup(modulename).hexdigest(seq, state)
442
+ def digest(modulename, seq, crc = nil)
443
+ lookup(modulename).digest(seq, crc)
456
444
  end
457
445
 
458
- def create_module(bitsize, polynomial, initial_state = 0, refin = true, refout = true, xor = ~0, name = nil)
459
- g = Generator.new(bitsize, polynomial, initial_state, refin, refout, xor, name)
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, initial_state, xor, check, *names|
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 = create_module(bitsize, polynomial, initial_state, refin, refout, xor, names[0])
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 = g.crc("123456789")
492
+ checked = crc.crc("123456789")
502
493
  case check
503
494
  when nil
504
- $stderr.puts "| %20s(\"123456789\") = %16X (check only)\n" % [g.name, checked]
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" % [g.name, checked, check]
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"