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 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"