crc 0.3 → 0.3.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/gemstub.rb CHANGED
@@ -1,13 +1,18 @@
1
- require_relative "lib/crc/version"
1
+ #!ruby
2
+
3
+ unless File.read("README.md", mode: "rt") =~ /^\s*\*\s*version: (\d+(?:\.\w+)+)/i
4
+ raise "version number is not found in ``README.md''"
5
+ end
6
+
7
+ ver = $1
2
8
 
3
9
  GEMSTUB = Gem::Specification.new do |s|
4
10
  s.name = "crc"
5
- s.version = CRC::VERSION
11
+ s.version = ver
6
12
  s.summary = "general CRC generator"
7
13
  s.description = <<EOS
8
- This is a general CRC (Cyclic Redundancy Check) generator for ruby.
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.
14
+ Pure ruby implemented general CRC (Cyclic Redundancy Check) generator.
15
+ Customization is posible for 1 to 64 bit width, any polynomials, and with/without bit reflection input/output.
11
16
  If you need more speed, please use crc-turbo.
12
17
  EOS
13
18
  s.homepage = "https://osdn.jp/projects/rutsubo/"
@@ -16,7 +21,22 @@ EOS
16
21
  s.email = "dearblue@users.osdn.me"
17
22
 
18
23
  s.required_ruby_version = ">= 2.0"
19
- s.add_development_dependency "rake"
24
+ s.add_development_dependency "rake", "~> 11"
25
+ end
26
+
27
+ verfile = "lib/crc/version.rb"
28
+ task "version" => verfile
29
+ file verfile => "README.md" do
30
+ File.write(verfile, <<-"EOS", mode: "wb")
31
+ #!ruby
32
+
33
+ class CRC
34
+ VERSION = "#{ver}"
20
35
  end
36
+ EOS
37
+ end
38
+
39
+ LIB << verfile
40
+ LIB.uniq!
21
41
 
22
42
  EXTRA << "benchmark.rb"
data/lib/crc.rb CHANGED
@@ -2,11 +2,14 @@
2
2
 
3
3
  if ENV["RUBY_CRC_NOFAST"].to_i > 0
4
4
  require_relative "crc/_byruby"
5
+ CRC::IMPLEMENT = :ruby
5
6
  else
6
7
  begin
7
8
  require File.join("crc", RUBY_VERSION[/\d+\.\d+/], "_turbo.so")
9
+ CRC::IMPLEMENT = :turbo
8
10
  rescue LoadError
9
11
  require_relative "crc/_byruby"
12
+ CRC::IMPLEMENT = :ruby
10
13
  end
11
14
  end
12
15
 
@@ -74,15 +77,22 @@ class CRC
74
77
  bitmask = ~(~0 << bitsize)
75
78
  table = []
76
79
  Aux.slide_to_head(bitsize, 0, bitmask & polynomial, bitmask) do |xx, poly, csh, head, carries, pad|
77
- slice.times do |s|
80
+ table << (t = [])
81
+ 256.times do |b|
82
+ b <<= csh
83
+ 8.times { b = (b[head] == 0) ? (b << 1) : (((carries & b) << 1) ^ poly) }
84
+ t << b
85
+ end
86
+ t.freeze unless unfreeze
87
+
88
+ carries8 = carries >> 7
89
+ (1...slice).step do
90
+ tt = table[-1]
78
91
  table << (t = [])
79
92
  256.times do |b|
80
- r = (s == 0 ? (b << csh) : (table[-2][b]))
81
- 8.times { r = (r[head] == 0) ? (r << 1) : (((carries & r) << 1) ^ poly) }
82
- t << r
93
+ t << (table[0][tt[b] >> csh] ^ ((carries8 & tt[b]) << 8))
83
94
  end
84
95
  t.freeze unless unfreeze
85
- t
86
96
  end
87
97
  0
88
98
  end
@@ -93,15 +103,21 @@ class CRC
93
103
  def build_reflect_table(bitsize, polynomial, unfreeze = false, slice: 16)
94
104
  polynomial = bitreflect(polynomial, bitsize)
95
105
  table = []
96
- slice.times do |s|
106
+
107
+ table << (t = [])
108
+ 256.times do |b|
109
+ 8.times { b = (b[0] == 0) ? (b >> 1) : ((b >> 1) ^ polynomial) }
110
+ t << b
111
+ end
112
+ t.freeze unless unfreeze
113
+
114
+ (1...slice).step do
115
+ tt = table[-1]
97
116
  table << (t = [])
98
117
  256.times do |b|
99
- r = (s == 0) ? b : table[-2][b]
100
- 8.times { r = (r[0] == 0) ? (r >> 1) : ((r >> 1) ^ polynomial) }
101
- t << r
118
+ t << (table[0][tt[b] & 0xff] ^ (tt[b] >> 8))
102
119
  end
103
120
  t.freeze unless unfreeze
104
- t
105
121
  end
106
122
 
107
123
  table.freeze unless unfreeze
@@ -139,9 +155,6 @@ class CRC
139
155
  #{indent}].freeze
140
156
  EOS
141
157
  end
142
-
143
- #puts export_table(build_table(16, 0x1021), 16, 8); #abort "DEBUG EXIT"
144
- #puts export_table(build_table!(32, 0xEDB88320), 32, 8); abort "DEBUG EXIT"
145
158
  end
146
159
 
147
160
  extend Utils
@@ -492,11 +505,22 @@ class CRC
492
505
  checked = crc.crc("123456789")
493
506
  case check
494
507
  when nil
495
- $stderr.puts "| %20s(\"123456789\") = %16X (check only)\n" % [crc.name, checked]
508
+ $stderr.puts "| %20s(\"123456789\" * 1) = %16X (check only)\n" % [crc.name, checked]
509
+ when checked
510
+ ;
511
+ else
512
+ $stderr.puts "| %20s(\"123456789\" * 1) = %16X (expect to %X)\n" % [crc.name, checked, check]
513
+ end
514
+
515
+ check = 9.times.reduce(crc.new) { |a, x| a + crc[crc::CHECK, 9] }
516
+ checked = crc["123456789" * 9]
517
+ case check
518
+ when nil
519
+ $stderr.puts "| %20s(\"123456789\" * 9) = %16X (check only)\n" % [crc.name, checked]
496
520
  when checked
497
521
  ;
498
522
  else
499
- $stderr.puts "| %20s(\"123456789\") = %16X (expect to %X)\n" % [crc.name, checked, check]
523
+ $stderr.puts "| %20s(\"123456789\" * 9) = %16X (expect to %X)\n" % [crc.name, checked, check]
500
524
  end
501
525
  end
502
526
  $stderr.puts "#{__FILE__}:#{__LINE__}: DONE SELF CHECK\n"
@@ -1,6 +1,7 @@
1
1
  #!ruby
2
2
 
3
3
  #--
4
+ # File:: _byruby.rb
4
5
  # Author:: dearblue <dearblue@users.osdn.me>
5
6
  # License:: Creative Commons License Zero (CC0 / Public Domain)
6
7
  #++
@@ -8,7 +9,7 @@
8
9
  #
9
10
  # \* \* \* \* \* \* \* \*
10
11
  #
11
- # Ruby implemented CRC generator.
12
+ # Pure ruby implemented general CRC generator.
12
13
  # It's used slice-by-16 algorithm with byte-order free.
13
14
  # This is based on the Intel's slice-by-eight algorithm.
14
15
  #
@@ -22,10 +23,6 @@
22
23
  # * xz-5.2.2/src/liblzma/check/crc32_fast.c
23
24
  # * xz-5.2.2/src/liblzma/check/crc32_tablegen.c
24
25
  #
25
- # If defined "RUBY_CRC_NOFAST=2" enviroment variable, switch to lookup-table algorithm.
26
- #
27
- # If defined "RUBY_CRC_NOFAST=3" enviroment variable, switch to reference algorithm.
28
- #
29
26
  class CRC
30
27
  class << self
31
28
  #
@@ -111,7 +108,7 @@ class CRC
111
108
  end
112
109
  end
113
110
 
114
- def update_with_slice_by_eight(seq, s)
111
+ def update_with_slice_by_16(seq, s)
115
112
  tX = table
116
113
  t0 = tX[ 0]; t1 = tX[ 1]; t2 = tX[ 2]; t3 = tX[ 3]
117
114
  t4 = tX[ 4]; t5 = tX[ 5]; t6 = tX[ 6]; t7 = tX[ 7]
@@ -120,15 +117,29 @@ class CRC
120
117
 
121
118
  i = 0
122
119
  ii = seq.bytesize
123
- iii = ii & ~15
120
+ ii16 = ii & ~15
124
121
 
125
122
  if reflect_input
126
- if bitsize <= 32
127
- # speed improvement for 32-bits CRC
123
+ case
124
+ when bitsize > 32
128
125
  i = 0
129
- while i < iii
126
+ while i < ii16
130
127
  s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
131
128
  tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) & 0xff] ^
129
+ tB[seq.getbyte(i + 4) ^ (s >> 32) & 0xff] ^ tA[seq.getbyte(i + 5) ^ (s >> 40) & 0xff] ^
130
+ t9[seq.getbyte(i + 6) ^ (s >> 48) & 0xff] ^ t8[seq.getbyte(i + 7) ^ (s >> 56) ] ^
131
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
132
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
133
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
134
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
135
+ i += 16
136
+ end
137
+ when bitsize > 16
138
+ # speed improvement for 32-bits CRC
139
+ i = 0
140
+ while i < ii16
141
+ s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
142
+ tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) ] ^
132
143
  tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
133
144
  t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
134
145
  t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
@@ -137,13 +148,14 @@ class CRC
137
148
  t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
138
149
  i += 16
139
150
  end
140
- else
151
+ else # when bitsize <= 16
152
+ # speed improvement for 16-bits CRC
141
153
  i = 0
142
- while i < iii
143
- s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
144
- tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) & 0xff] ^
145
- tB[seq.getbyte(i + 4) ^ (s >> 32) & 0xff] ^ tA[seq.getbyte(i + 5) ^ (s >> 40) & 0xff] ^
146
- t9[seq.getbyte(i + 6) ^ (s >> 48) & 0xff] ^ t8[seq.getbyte(i + 7) ^ (s >> 56) & 0xff] ^
154
+ while i < ii16
155
+ s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) ] ^
156
+ tD[seq.getbyte(i + 2) ] ^ tC[seq.getbyte(i + 3) ] ^
157
+ tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
158
+ t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
147
159
  t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
148
160
  t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
149
161
  t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
@@ -152,26 +164,65 @@ class CRC
152
164
  end
153
165
  end
154
166
 
155
- (iii...ii).each do |n|
167
+ (i...ii).each do |n|
156
168
  s = t0[seq.getbyte(n) ^ s & 0xff] ^ (s >> 8)
157
169
  end
158
170
 
159
171
  s
160
172
  else
161
173
  Aux.slide_to_head(bitsize, s, polynomial, bitmask) do |s, poly, csh, head, carries|
162
- sh = 64 - (head + 1)
163
-
164
- while i < iii
165
- s <<= sh
166
- s = t7[seq.getbyte(i ) ^ (s >> 56) & 0xff] ^ t6[seq.getbyte(i + 1) ^ (s >> 48) & 0xff] ^
167
- t5[seq.getbyte(i + 2) ^ (s >> 40) & 0xff] ^ t4[seq.getbyte(i + 3) ^ (s >> 32) & 0xff] ^
168
- t3[seq.getbyte(i + 4) ^ (s >> 24) & 0xff] ^ t2[seq.getbyte(i + 5) ^ (s >> 16) & 0xff] ^
169
- t1[seq.getbyte(i + 6) ^ (s >> 8) & 0xff] ^ t0[seq.getbyte(i + 7) ^ (s >> 0) & 0xff]
170
- i += 8
174
+ case
175
+ when bitsize > 32
176
+ sh = 64 - (head + 1)
177
+
178
+ while i < ii16
179
+ s <<= sh
180
+ s = tF[seq.getbyte(i ) ^ (s >> 56) ] ^ tE[seq.getbyte(i + 1) ^ (s >> 48) & 0xff] ^
181
+ tD[seq.getbyte(i + 2) ^ (s >> 40) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 32) & 0xff] ^
182
+ tB[seq.getbyte(i + 4) ^ (s >> 24) & 0xff] ^ tA[seq.getbyte(i + 5) ^ (s >> 16) & 0xff] ^
183
+ t9[seq.getbyte(i + 6) ^ (s >> 8) & 0xff] ^ t8[seq.getbyte(i + 7) ^ (s ) & 0xff] ^
184
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
185
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
186
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
187
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
188
+ i += 16
189
+ end
190
+ when bitsize > 16
191
+ # speed improvement for 32-bits CRC
192
+ sh = 32 - (head + 1)
193
+
194
+ while i < ii16
195
+ s <<= sh
196
+ s = tF[seq.getbyte(i ) ^ (s >> 24) ] ^ tE[seq.getbyte(i + 1) ^ (s >> 16) & 0xff] ^
197
+ tD[seq.getbyte(i + 2) ^ (s >> 8) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s ) & 0xff] ^
198
+ tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
199
+ t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
200
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
201
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
202
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
203
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
204
+ i += 16
205
+ end
206
+ else # when bitsize <= 16
207
+ # speed improvement for 16-bits CRC
208
+ sh = 16 - (head + 1)
209
+
210
+ while i < ii16
211
+ s <<= sh
212
+ s = tF[seq.getbyte(i ) ^ (s >> 8) ] ^ tE[seq.getbyte(i + 1) ^ (s ) & 0xff] ^
213
+ tD[seq.getbyte(i + 2) ] ^ tC[seq.getbyte(i + 3) ] ^
214
+ tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
215
+ t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
216
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
217
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
218
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
219
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
220
+ i += 16
221
+ end
171
222
  end
172
223
 
173
224
  carries8 = carries >> 7
174
- (iii...ii).each do |n|
225
+ (i...ii).each do |n|
175
226
  s = t0[(s >> csh) ^ seq.getbyte(n)] ^ ((carries8 & s) << 8)
176
227
  end
177
228
  s
@@ -180,10 +231,14 @@ class CRC
180
231
  end
181
232
 
182
233
  def table
183
- if reflect_input
184
- @table = CRC.build_reflect_table(bitsize, polynomial, slice: 16)
234
+ if SLICING_SIZE
235
+ if reflect_input
236
+ @table = CRC.build_reflect_table(bitsize, polynomial, slice: SLICING_SIZE)
237
+ else
238
+ @table = CRC.build_table(bitsize, polynomial, slice: SLICING_SIZE)
239
+ end
185
240
  else
186
- @table = CRC.build_table(bitsize, polynomial, slice: 16)
241
+ @table = nil
187
242
  end
188
243
 
189
244
  singleton_class.class_eval "attr_reader :table"
@@ -193,11 +248,14 @@ class CRC
193
248
 
194
249
  case ENV["RUBY_CRC_NOFAST"].to_i
195
250
  when 0, 1
196
- alias update update_with_slice_by_eight
251
+ alias update update_with_slice_by_16
252
+ SLICING_SIZE = 16
197
253
  when 2
198
254
  alias update update_with_lookup_table
255
+ SLICING_SIZE = 1
199
256
  else
200
257
  alias update update_with_reference
258
+ SLICING_SIZE = nil
201
259
  end
202
260
  end
203
261
 
@@ -19,7 +19,7 @@ class CRC
19
19
  LIST = [
20
20
  #
21
21
  # bit size, polynomial, initial crc,
22
- # refrect input, xor output,
22
+ # reflect input, xor output,
23
23
  # reflect output, crc("123456789"), names...
24
24
  #
25
25
  [ 1, 0x01, true, true, 0, ~0, 0x01, "CRC-1"],
@@ -114,6 +114,7 @@ class CRC
114
114
  [32, 0x000000AF, false, false, 0, 0, 0xBD0BE338, "CRC-32-XFER", "XFER"],
115
115
  [40, 0x0004820009, false, false, ~0, ~0, 0xD4164FC646, "CRC-40-GSM"],
116
116
  [64, 0x42F0E1EBA9EA3693, true, true, 0, ~0, 0x995DC9BBDF1939FA, "CRC-64-XZ", "CRC-64"],
117
+ [64, 0xAD93D23594C935A9, true, true, ~0, 0, 0xCAA717168609F281, "CRC-64-JONES"],
117
118
  [64, 0x42F0E1EBA9EA3693, false, false, 0, 0, 0x6C40DF5F0B497347, "CRC-64-ECMA", "CRC-64-ECMA-182"],
118
119
  [64, 0x42F0E1EBA9EA3693, false, false, 0, ~0, 0x62EC59E3F1A4F00A, "CRC-64-WE"],
119
120
  [64, 0x000000000000001B, true, true, 0, 0, 0x46A5A9388A5BEFFE, "CRC-64-ISO", "CRC-64-ISO-3309"],
@@ -17,8 +17,8 @@ class CRC
17
17
  # * crc32("123456789????") の結果が 0 となるような、???? の部分を逆算する
18
18
  #
19
19
  # seq = "123456789"
20
- # seq << CRC::CRC32.acrc(seq)
21
- # p CRC::CRC32[seq] # => #<CRC::CRC32:00000000>
20
+ # arced_seq = CRC::CRC32.acrc(seq)
21
+ # p CRC::CRC32[seq + arced_seq] # => #<CRC::CRC32:00000000>
22
22
  #
23
23
  # * crc32("123456789????ABCDEFG") の結果が 0 となるような、???? の部分を逆算する
24
24
  #
@@ -0,0 +1,891 @@
1
+ #!ruby
2
+
3
+ require_relative "../crc"
4
+
5
+ class CRC
6
+ ALGORITHM_BITBYBIT = -2
7
+ ALGORITHM_BITBYBIT_FAST = -1
8
+ ALGORITHM_HALFBYTE_TABLE = 0
9
+ ALGORITHM_STANDARD_TABLE = 1
10
+ ALGORITHM_SLICING_BY_4 = 4
11
+ ALGORITHM_SLICING_BY_8 = 8
12
+ ALGORITHM_SLICING_BY_16 = 16
13
+
14
+ def self.dump_to_c(func_name = nil, header_name = nil, source_name = nil, indent: 4, visible: true, algorithm: ALGORITHM_SLICING_BY_16)
15
+ func_name ||= self.to_s.slice(/\w+$/).downcase
16
+ #func_name ||= self.name.gsub(/[\W]+/, "_").gsub(/_{2,}/, "_").gsub(/^_|_$/, "").downcase
17
+ header_name ||= "#{func_name}.h"
18
+ source_name ||= "#{func_name}.c"
19
+ indentunit = " " * Integer(indent.to_i)
20
+ indent = ->(level) { indentunit * level }
21
+ visibility = visible ? "" : "static "
22
+
23
+ case
24
+ when bitsize <= 8
25
+ type = "uint8_t"
26
+ sizeof = 1
27
+ suffix = "u"
28
+ when bitsize <= 16
29
+ type = "uint16_t"
30
+ sizeof = 2
31
+ suffix = "u"
32
+ when bitsize <= 32
33
+ type = "uint32_t"
34
+ sizeof = 4
35
+ suffix = "ul"
36
+ else
37
+ type = "uint64_t"
38
+ sizeof = 8
39
+ suffix = "ull"
40
+ end
41
+
42
+ typesize = sizeof * 8
43
+ alignedbytes = (bitsize + 7) / 8
44
+ alignedbits = (bitsize + 7) & ~0x07 # 8 bit alignmented bitsize
45
+ bitreflect = func_name + "_bitreflect"
46
+ hexnum = ->(n) { "0x%0#{sizeof * 2}X%s" % [n, suffix] }
47
+ hexbyte = ->(n) { "0x%02Xu" % n }
48
+
49
+ if reflect_input?
50
+ getleadbyte = ->(expr, off = 0) { "(uint8_t)(#{expr} >> %2d)" % (off * 8) }
51
+ getheadbit_from_byte = ->(expr, off = 0) { "((#{expr} >> #{off}) & 1)" }
52
+ getleadbit = ->(expr, off = 0, width = 1) { "((%s >> %2d) & 0x%02X)" % [expr, off, ~(~0 << width)] }
53
+ slideinput = ->(expr) { "#{expr}" }
54
+ slidestate1 = ->(expr) { "(#{expr} >> 1)" }
55
+ slidestate4 = ->(expr) { "(#{expr} >> 4)" }
56
+ slidestate8 = ->(expr) { "(#{expr} >> 8)" }
57
+ slideslicing = ->(expr) { "(#{expr} >> #{algorithm * 8})" }
58
+ padding = depadding = nil
59
+ workpoly = hexnum[Utils.bitreflect(polynomial, bitsize)]
60
+ if algorithm >= 0
61
+ table = Utils.build_reflect_table(bitsize, polynomial, true, slice: (algorithm < 1 ? 1 : algorithm))
62
+ end
63
+ else
64
+ getleadbyte = ->(expr, off = 0) { "(uint8_t)(#{expr} >> %2d)" % (alignedbits - (off + 1) * 8) }
65
+ getheadbit_from_byte = ->(expr, off = 0) { "((#{expr} >> #{8 - (off + 1)}) & 1)" }
66
+ getleadbit = ->(expr, off = 0, width = 1) { "((%s >> %2d) & 0x%02X)" % [expr, (alignedbits - (off + 1) - (width - 1)), ~(~0 << width)] }
67
+ slideinput = ->(expr) { "((#{type})#{expr} << #{alignedbits - 8})" }
68
+ slidestate1 = ->(expr) { "(#{expr} << 1)" }
69
+ slidestate4 = ->(expr) { "(#{expr} << 4)" }
70
+ slidestate8 = ->(expr) { "(#{expr} << 8)" }
71
+ slideslicing = ->(expr) { "(#{expr} << #{algorithm * 8})" }
72
+ if (pad = (alignedbits - bitsize)) > 0
73
+ padding = " << #{pad}"
74
+ depadding = " >> #{pad}"
75
+ workpoly = "#{func_name.upcase}_POLYNOMIAL << #{pad}"
76
+ else
77
+ padding = depadding = nil
78
+ workpoly = "#{func_name.upcase}_POLYNOMIAL"
79
+ end
80
+ if algorithm >= 0
81
+ table = Utils.build_table(bitsize, polynomial, true, slice: (algorithm < 1 ? 1 : algorithm))
82
+ end
83
+ end
84
+
85
+ case algorithm
86
+ when ALGORITHM_BITBYBIT
87
+ comment = " /* bit reflected */" if reflect_input?
88
+ prepare = <<-PREPARE_BITBYBIT
89
+ static const #{type} workpoly = #{workpoly};#{comment}
90
+ PREPARE_BITBYBIT
91
+ update = <<-UPDATE_BITBYBIT
92
+ for (; p < pp; p ++) {
93
+ int i;
94
+ s ^= #{slideinput["*p"]};
95
+ for (i = 0; i < 8; i ++) {
96
+ s = #{slidestate1["s"]} ^ (workpoly & -(#{type})#{getleadbit["s"]});
97
+ }
98
+ }
99
+ UPDATE_BITBYBIT
100
+ when ALGORITHM_BITBYBIT_FAST
101
+ comment = " /* bit reflected */" if reflect_input?
102
+ tspc = " " * type.size
103
+ prepare = <<-PREPARE_BITBYBIT_FAST
104
+ static const #{type} workpoly = #{workpoly};#{comment}
105
+ static const #{type} g0 = workpoly,
106
+ #{tspc} g1 = #{slidestate1["g0"]} ^ (workpoly & -(#{type})#{getleadbit["g0"]}),
107
+ #{tspc} g2 = #{slidestate1["g1"]} ^ (workpoly & -(#{type})#{getleadbit["g1"]}),
108
+ #{tspc} g3 = #{slidestate1["g2"]} ^ (workpoly & -(#{type})#{getleadbit["g2"]}),
109
+ #{tspc} g4 = #{slidestate1["g3"]} ^ (workpoly & -(#{type})#{getleadbit["g3"]}),
110
+ #{tspc} g5 = #{slidestate1["g4"]} ^ (workpoly & -(#{type})#{getleadbit["g4"]}),
111
+ #{tspc} g6 = #{slidestate1["g5"]} ^ (workpoly & -(#{type})#{getleadbit["g5"]}),
112
+ #{tspc} g7 = #{slidestate1["g6"]} ^ (workpoly & -(#{type})#{getleadbit["g6"]});
113
+ PREPARE_BITBYBIT_FAST
114
+ update = <<-UPDATE_BITBYBIT_FAST
115
+ for (; p < pp; p ++) {
116
+ const uint8_t s1 = #{getleadbit["s", 0, 8]} ^ *p;
117
+ s = #{slidestate8["s"]} ^
118
+ (g7 & -(#{type})#{getheadbit_from_byte["s1", 0]}) ^
119
+ (g6 & -(#{type})#{getheadbit_from_byte["s1", 1]}) ^
120
+ (g5 & -(#{type})#{getheadbit_from_byte["s1", 2]}) ^
121
+ (g4 & -(#{type})#{getheadbit_from_byte["s1", 3]}) ^
122
+ (g3 & -(#{type})#{getheadbit_from_byte["s1", 4]}) ^
123
+ (g2 & -(#{type})#{getheadbit_from_byte["s1", 5]}) ^
124
+ (g1 & -(#{type})#{getheadbit_from_byte["s1", 6]}) ^
125
+ (g0 & -(#{type})#{getheadbit_from_byte["s1", 7]});
126
+ }
127
+ UPDATE_BITBYBIT_FAST
128
+ when ALGORITHM_HALFBYTE_TABLE
129
+ table = table[0]
130
+ if reflect_input?
131
+ table = 16.times.map { |i| table[i * 16] }
132
+ else
133
+ table = 16.times.map { |i| table[i] }
134
+ end
135
+ prepare = <<-PREPARE_HALFBYTE_TABLE
136
+ static const #{type} table[16] = {
137
+ #{Aux.export_slicing_table(table, " ", 4, nil, nil, nil, nil, sizeof > 2 ? 4 : 8, &hexnum)}
138
+ };
139
+ PREPARE_HALFBYTE_TABLE
140
+ update = <<-UPDATE_HALFBYTE_TABLE
141
+ for (; p < pp; p ++) {
142
+ s ^= #{slideinput["(#{type})*p"]};
143
+ s = table[#{getleadbit["s", 0, 4]}] ^ #{slidestate4["s"]};
144
+ s = table[#{getleadbit["s", 0, 4]}] ^ #{slidestate4["s"]};
145
+ }
146
+ UPDATE_HALFBYTE_TABLE
147
+ when ALGORITHM_STANDARD_TABLE
148
+ prepare = <<-PREPARE_STANDARD_TABLE
149
+ static const #{type} table[256] = {
150
+ #{Aux.export_slicing_table(table[0], " ", 4, nil, nil, nil, nil, sizeof > 2 ? 4 : 8, &hexnum)}
151
+ };
152
+ PREPARE_STANDARD_TABLE
153
+ update = <<-UPDATE_STANDARD_TABLE
154
+ for (; p < pp; p ++) {
155
+ s ^= #{slideinput["(#{type})*p"]};
156
+ s = table[(uint8_t)#{getleadbit["s", 0, 8]}] ^ #{slidestate8["s"]};
157
+ }
158
+ UPDATE_STANDARD_TABLE
159
+ when ALGORITHM_SLICING_BY_4,
160
+ ALGORITHM_SLICING_BY_8,
161
+ ALGORITHM_SLICING_BY_16
162
+ slicing = algorithm.times.map { |off|
163
+ ioff = (algorithm - 1) - off
164
+ "table[%2d][p[%2d] %20s]" % [
165
+ off, ioff,
166
+ ioff >= alignedbytes ? nil : "^ #{getleadbyte["s", ioff]}"]
167
+ }
168
+ if algorithm < alignedbytes
169
+ slicing.insert 0, slideslicing["s"]
170
+ end
171
+ slicing = slicing.join(" ^\n ")
172
+
173
+ prepare = <<-PREPARE_SLICING_TABLE
174
+ static const #{type} table[#{algorithm}][256] = {
175
+ #{Aux.export_slicing_table(table, " ", 4, nil, nil, "{", "}", sizeof > 2 ? 4 : 8, &hexnum)}
176
+ };
177
+ PREPARE_SLICING_TABLE
178
+ update = <<-UPDATE_SLICING_TABLE
179
+ const uint8_t *ppby = p + (len / #{algorithm} * #{algorithm});
180
+ for (; p < ppby; p += #{algorithm}) {
181
+ s = #{slicing};
182
+ }
183
+
184
+ for (; p < pp; p ++) {
185
+ s = table[0][*p ^ #{getleadbyte["s"]}] ^ #{slidestate8["s"]};
186
+ }
187
+ UPDATE_SLICING_TABLE
188
+ else
189
+ raise ArgumentError, "wrong algorithm code - #{algorithm}"
190
+ end
191
+
192
+ if reflect_output? ^ reflect_input?
193
+ slideleft = (typesize == bitsize) ? nil : "\n" << <<-SLIDELEFT.chomp!
194
+ n <<= #{typesize - bitsize};
195
+ SLIDELEFT
196
+ swapby32 = (sizeof < 8) ? nil : "\n" << <<-SWAPBY32.chomp!
197
+ n = ((n & 0X00000000FFFFFFFF#{suffix}) << 32) | (n >> 32);
198
+ SWAPBY32
199
+ swapby16 = (sizeof < 4) ? nil : "\n" << <<-SWAPBY16.chomp!
200
+ n = ((n & 0x#{"0000FFFF" * (sizeof / 4)}#{suffix}) << 16) | ((n >> 16) & 0x#{"0000FFFF" * (sizeof / 4)}#{suffix});
201
+ SWAPBY16
202
+ swapby8 = (sizeof < 2) ? nil : "\n" << <<-SWAPBY8.chomp!
203
+ n = ((n & 0x#{"00FF" * (sizeof / 2)}#{suffix}) << 8) | ((n >> 8) & 0x#{"00FF" * (sizeof / 2)}#{suffix});
204
+ SWAPBY8
205
+
206
+ func_bitreflect = "\n" << <<-BITREFLECT
207
+ static #{type}
208
+ #{bitreflect}(#{type} n)
209
+ {#{slideleft}#{swapby32}#{swapby16}#{swapby8}
210
+ n = ((n & 0x#{"0F" * sizeof}#{suffix}) << 4) | ((n >> 4) & 0x#{"0F" * sizeof}#{suffix});
211
+ n = ((n & 0x#{"33" * sizeof}#{suffix}) << 2) | ((n >> 2) & 0x#{"33" * sizeof}#{suffix});
212
+ n = ((n & 0x#{"55" * sizeof}#{suffix}) << 1) | ((n >> 1) & 0x#{"55" * sizeof}#{suffix});
213
+ return n;
214
+ }
215
+ BITREFLECT
216
+ else
217
+ bitreflect = nil
218
+ end
219
+
220
+ { header: <<-CHEADER, source: <<-CSOURCE }
221
+ /*
222
+ #{Aux.dump_banner(" *", "#{self.name}{#{to_str}}", algorithm)}
223
+ */
224
+
225
+ #ifndef #{func_name.upcase}_H__
226
+ #define #{func_name.upcase}_H__ 1
227
+
228
+ #include <stdlib.h>
229
+ #include <stdint.h>
230
+
231
+ #define #{func_name.upcase}_TYPE #{type}
232
+ #define #{func_name.upcase}_BITSIZE #{bitsize}
233
+ #define #{func_name.upcase}_BITMASK #{hexnum[bitmask]}
234
+ #define #{func_name.upcase}_POLYNOMIAL #{hexnum[polynomial]}
235
+ #define #{func_name.upcase}_INITIAL_CRC #{hexnum[initial_crc]}
236
+ #define #{func_name.upcase}_XOR_OUTPUT #{hexnum[xor_output]}
237
+ #define #{func_name.upcase}_REFLECT_INPUT #{reflect_input? ? 1 : 0}
238
+ #define #{func_name.upcase}_REFLECT_OUTPUT #{reflect_output? ? 1 : 0}
239
+
240
+ #ifdef __cplusplus
241
+ extern "C"
242
+ #{visibility}#{type} #{func_name}(const void *ptr, size_t len, #{type} crc = #{func_name.upcase}_INITIAL_CRC);
243
+ #else
244
+ #{visibility}#{type} #{func_name}(const void *ptr, size_t len, #{type} crc);
245
+ #endif
246
+
247
+ #endif /* #{func_name.upcase}_H__ */
248
+ CHEADER
249
+ /*
250
+ #{Aux.dump_banner(" *", "#{self.name}{#{to_str}}", algorithm)}
251
+ */
252
+
253
+ #include "#{header_name}"
254
+ #{func_bitreflect}
255
+ #{visibility}#{type}
256
+ #{func_name}(const void *ptr, size_t len, #{type} crc)
257
+ {
258
+ #{prepare}
259
+ #{type} s = ((#{bitreflect}(crc) & #{func_name.upcase}_BITMASK) ^ #{func_name.upcase}_XOR_OUTPUT)#{padding};
260
+ const uint8_t *p = (const uint8_t *)ptr;
261
+ const uint8_t *pp = p + len;
262
+
263
+ #{update}
264
+ return #{bitreflect}((s#{depadding}) & #{func_name.upcase}_BITMASK) ^ #{func_name.upcase}_XOR_OUTPUT;
265
+ }
266
+ CSOURCE
267
+ end
268
+
269
+ def self.dump_to_ruby(class_name = nil)
270
+ class_name ||= self.to_s.slice(/\w+$/)
271
+ name = class_name.split("::")
272
+ name.map! { |nm| nm.gsub!(/[\W]+/m, "_"); nm.sub!(/^_+/, ""); nm.sub!(/^[a-z]/) { |m| m.upcase! }; nm }
273
+ case
274
+ when bitsize <= 8
275
+ sizeof = 1
276
+ pack = "C"
277
+ when bitsize <= 16
278
+ sizeof = 2
279
+ pack = "n"
280
+ when bitsize <= 32
281
+ sizeof = 4
282
+ pack = "N"
283
+ else
284
+ sizeof = 8
285
+ pack = "Q>"
286
+ end
287
+
288
+ typebits = sizeof * 8
289
+ hexnum = ->(n) { "0x%0*X" % [sizeof * 2, n] }
290
+ if reflect_input?
291
+ table1 = Utils.build_reflect_table(bitsize, polynomial, slice: 16)
292
+ headstate = "(s & 0xFF)"
293
+ slidestate = "(s >> 8)"
294
+ slicing = ->(off) {
295
+ t = "t%X" % (15 - off)
296
+ getbyte = off > 0 ? "+ %2d" % off : ""
297
+ shiftstate = off < sizeof ? "^ (s %5s) & 0xFF" % (off > 0 ? ">> %2d" % (off * 8) : "") : ""
298
+ "%s[seq.getbyte(i %4s) %18s]" % [t, getbyte, shiftstate]
299
+ }
300
+ else
301
+ table1 = Utils.build_table(bitsize, polynomial, true, slice: 16)
302
+ bitpad = typebits - bitsize
303
+ headstate = "((s >> #{typebits - 8}) & 0xFF)"
304
+ slidestate = "((s & #{hexnum[~(~0 << typebits) >> 8]}) << 8)"
305
+ slicing = ->(off) {
306
+ t = "t%X" % (15 - off)
307
+ getbyte = off > 0 ? "+ %2d" % off : ""
308
+ shiftstate = off < sizeof ? "^ (s %5s) & 0xFF" % (off + 1 < sizeof ? ">> %2d" % ((sizeof - off) * 8 - 8) : "") : ""
309
+ "%s[seq.getbyte(i %4s) %18s]" % [t, getbyte, shiftstate]
310
+ }
311
+ end
312
+
313
+ code = <<-EOS
314
+ #!ruby
315
+
316
+ #
317
+ #{Aux.dump_banner("#", "#{self.name}{#{to_str}}", ALGORITHM_SLICING_BY_16)}
318
+ #
319
+
320
+ # for ruby-1.8
321
+ unless "".respond_to?(:getbyte)
322
+ class String
323
+ alias getbyte []
324
+ end
325
+ end
326
+
327
+ # for mruby
328
+ unless [].respond_to?(:freeze)
329
+ class Array
330
+ def freeze
331
+ self
332
+ end
333
+ end
334
+ end
335
+
336
+ class #{name.join("::")}
337
+ BITSIZE = #{bitsize}
338
+ BITMASK = #{hexnum[bitmask]}
339
+ POLYNOMIAL = #{hexnum[polynomial]}
340
+ INITIAL_CRC = #{hexnum[initial_crc]}
341
+ REFLECT_INPUT = #{reflect_input?.inspect}
342
+ REFLECT_OUTPUT = #{reflect_output?.inspect}
343
+ XOR_OUTPUT = #{hexnum[xor_output]}
344
+
345
+ attr_accessor :state
346
+
347
+ #
348
+ # call-seq:
349
+ # initialize(prevcrc = nil)
350
+ # initialize(seq, prevcrc = nil)
351
+ #
352
+ def initialize(*args)
353
+ case args.size
354
+ when 0
355
+ seq = nil
356
+ prevcrc = nil
357
+ when 1
358
+ if args[0].kind_of?(String)
359
+ seq = args[0]
360
+ else
361
+ prevcrc = args[0]
362
+ end
363
+ when 2
364
+ (seq, prevcrc) = args
365
+ else
366
+ raise ArgumentError, "wrong number of argument (given \#{args.size}, expect 0..2)"
367
+ end
368
+
369
+ reset(prevcrc)
370
+ update(seq) if seq
371
+ end
372
+
373
+ def reset(prevcrc = nil)
374
+ @state = self.class.setup(prevcrc || INITIAL_CRC)
375
+ self
376
+ end
377
+
378
+ def update(seq)
379
+ @state = self.class.update(seq, state)
380
+ self
381
+ end
382
+
383
+ alias << update
384
+
385
+ def crc
386
+ self.class.finish(state)
387
+ end
388
+
389
+ alias finish crc
390
+
391
+ def digest
392
+ [crc].pack(#{pack.inspect})
393
+ end
394
+
395
+ def hexdigest
396
+ "%0#{sizeof * 2}X" % crc
397
+ end
398
+
399
+ def inspect
400
+ "#<\#{self.class}:\#{hexdigest}>"
401
+ end
402
+
403
+ def pretty_print(q)
404
+ q.text inspect
405
+ end
406
+
407
+ class << self
408
+ def [](seq, prevcrc = nil)
409
+ new(seq, prevcrc)
410
+ end
411
+
412
+ def setup(crc = INITIAL_CRC)
413
+ #{
414
+ s = "(BITMASK & crc ^ XOR_OUTPUT)"
415
+
416
+ if reflect_output? ^ reflect_input?
417
+ s = "bitreflect#{s}"
418
+ end
419
+
420
+ if !reflect_input? && typebits > bitsize
421
+ s << " << #{typebits - bitsize}"
422
+ end
423
+
424
+ s
425
+ }
426
+ end
427
+
428
+ alias init setup
429
+
430
+ def finish(state)
431
+ #{
432
+ if !reflect_input? && typebits > bitsize
433
+ state = "(state >> #{typebits - bitsize})"
434
+ else
435
+ state = "state"
436
+ end
437
+
438
+ if reflect_output? ^ reflect_input?
439
+ "bitreflect(BITMASK & #{state} ^ XOR_OUTPUT)"
440
+ else
441
+ "BITMASK & #{state} ^ XOR_OUTPUT"
442
+ end
443
+ }
444
+ end
445
+
446
+ #
447
+ # call-seq:
448
+ # update(seq, state) -> state
449
+ #
450
+ def update(seq, s)
451
+ i = 0
452
+ ii = seq.bytesize
453
+ ii16 = ii & ~15
454
+ t0 = TABLE[ 0]; t1 = TABLE[ 1]; t2 = TABLE[ 2]; t3 = TABLE[ 3]
455
+ t4 = TABLE[ 4]; t5 = TABLE[ 5]; t6 = TABLE[ 6]; t7 = TABLE[ 7]
456
+ t8 = TABLE[ 8]; t9 = TABLE[ 9]; tA = TABLE[10]; tB = TABLE[11]
457
+ tC = TABLE[12]; tD = TABLE[13]; tE = TABLE[14]; tF = TABLE[15]
458
+ while i < ii16
459
+ s = #{slicing[ 0]} ^
460
+ #{slicing[ 1]} ^
461
+ #{slicing[ 2]} ^
462
+ #{slicing[ 3]} ^
463
+ #{slicing[ 4]} ^
464
+ #{slicing[ 5]} ^
465
+ #{slicing[ 6]} ^
466
+ #{slicing[ 7]} ^
467
+ #{slicing[ 8]} ^
468
+ #{slicing[ 9]} ^
469
+ #{slicing[10]} ^
470
+ #{slicing[11]} ^
471
+ #{slicing[12]} ^
472
+ #{slicing[13]} ^
473
+ #{slicing[14]} ^
474
+ #{slicing[15]}
475
+ i += 16
476
+ end
477
+
478
+ while i < ii
479
+ s = t0[seq.getbyte(i) ^ #{headstate}] ^ #{slidestate}
480
+ i += 1
481
+ end
482
+
483
+ s
484
+ end
485
+
486
+ def crc(seq, initcrc = INITIAL_CRC)
487
+ finish(update(seq, setup(initcrc)))
488
+ end
489
+
490
+ def digest(seq, initcrc = INITIAL_CRC)
491
+ [crc(seq, initcrc)].pack(#{pack.inspect})
492
+ end
493
+
494
+ def hexdigest(seq, initcrc = INITIAL_CRC)
495
+ "%0#{sizeof * 2}X" % crc(seq, initcrc)
496
+ end
497
+ EOS
498
+
499
+ if reflect_output? ^ reflect_input?
500
+ code << <<-EOS
501
+
502
+ def bitreflect(n)
503
+ EOS
504
+
505
+ if typebits > bitsize
506
+ code << <<-EOS
507
+ n <<= #{typebits - bitsize}
508
+ EOS
509
+ end
510
+
511
+ if typebits > 32
512
+ code << <<-EOS
513
+ n = ((n >> 32) & 0x00000000ffffffff) | ((n & 0x00000000ffffffff) << 32)
514
+ EOS
515
+ end
516
+
517
+ if typebits > 16
518
+ code << <<-EOS
519
+ n = ((n >> 16) & 0x#{"0000ffff" * (sizeof / 4)}) | ((n & 0x#{"0000ffff" * (sizeof / 4)}) << 16)
520
+ EOS
521
+ end
522
+
523
+ if typebits > 8
524
+ code << <<-EOS
525
+ n = ((n >> 8) & 0x#{"00ff" * (sizeof / 2)}) | ((n & 0x#{"00ff" * (sizeof / 2)}) << 8)
526
+ EOS
527
+ end
528
+
529
+ code << <<-EOS
530
+ n = ((n >> 4) & 0x#{"0f" * sizeof}) | ((n & 0x#{"0f" * sizeof}) << 4)
531
+ n = ((n >> 2) & 0x#{"33" * sizeof}) | ((n & 0x#{"33" * sizeof}) << 2)
532
+ n = ((n >> 1) & 0x#{"55" * sizeof}) | ((n & 0x#{"55" * sizeof}) << 1)
533
+ end
534
+ EOS
535
+ end
536
+
537
+ code << <<-EOS
538
+ end
539
+
540
+ TABLE = [
541
+ #{Aux.export_slicing_table(table1, " ", 2, nil, nil, "[", "].freeze", sizeof > 2 ? 4 : 8, &hexnum)}
542
+ ].freeze
543
+ end
544
+ EOS
545
+
546
+ ({ source: code })
547
+ end
548
+
549
+ def self.dump_to_javascript(class_name = nil)
550
+ class_name ||= self.to_s.slice(/\w+$/).downcase
551
+ name = class_name.split("::")
552
+ name.map! { |nm| nm.gsub!(/[\W]+/m, "_"); nm.sub!(/^_+/, ""); nm }
553
+ case
554
+ when bitsize <= 8
555
+ sizeof = 1
556
+ when bitsize <= 16
557
+ sizeof = 2
558
+ when bitsize <= 32
559
+ sizeof = 4
560
+ else
561
+ sizeof = 8
562
+ end
563
+
564
+ pack = ""
565
+
566
+ typebits = sizeof * 8
567
+ hexnum = ->(n) { "0x%0*X" % [sizeof * 2, n] }
568
+ if reflect_input?
569
+ table1 = Utils.build_reflect_table(bitsize, polynomial, slice: 16)
570
+ headstate = "(s & 0xFF)"
571
+ slidestate = "(s >>> 8)"
572
+ slicing = ->(off) {
573
+ t = "t%X" % (15 - off)
574
+ getbyte = off > 0 ? "+ %2d" % off : ""
575
+ shiftstate = off < sizeof ? "^ (s %6s) & 0xFF" % (off > 0 ? ">>> %2d" % (off * 8) : "") : ""
576
+ "%s[(0xFF & seq.charCodeAt(i %4s)) %19s]" % [t, getbyte, shiftstate]
577
+ }
578
+ else
579
+ table1 = Utils.build_table(bitsize, polynomial, true, slice: 16)
580
+ bitpad = typebits - bitsize
581
+ #table1.each { |t| t.map! { |tt| tt << bitpad } }
582
+ headstate = "((s >>> #{typebits - 8}) & 0xFF)"
583
+ slidestate = "((s & #{hexnum[~(~0 << typebits) >> 8]}) << 8)"
584
+ slicing = ->(off) {
585
+ t = "t%X" % (15 - off)
586
+ getbyte = off > 0 ? "+ %2d" % off : ""
587
+ shiftstate = off < sizeof ? "^ (s %6s) & 0xFF" % (off + 1 < sizeof ? ">>> %2d" % ((sizeof - off) * 8 - 8) : "") : ""
588
+ "%s[(0xFF & seq.charCodeAt(i %4s)) %19s]" % [t, getbyte, shiftstate]
589
+ }
590
+ end
591
+
592
+ typename = name.join(".")
593
+
594
+ code = <<-EOS
595
+ /*
596
+ #{Aux.dump_banner(" *", "#{self.name}{#{to_str}}", ALGORITHM_SLICING_BY_16)}
597
+ * * Required ECMASCript version: 6th edition
598
+ *
599
+ * *** IMPORTANT BUG! ***
600
+ *
601
+ * This can not be calculated correctly,
602
+ * if string included with 0x100+ codepointed character.
603
+ */
604
+
605
+ "use strict";
606
+
607
+ /*
608
+ * #{typename}(prevcrc = null)
609
+ * #{typename}(seq, prevcrc = null)
610
+ * new #{typename}(prevcrc = null)
611
+ * new #{typename}(seq, prevcrc = null)
612
+ */
613
+ (function(root, undefined) {
614
+ if (typeof(module) != "undefined") {
615
+ // case node-js
616
+ root = global;
617
+ }
618
+
619
+ var BITSIZE = #{bitsize};
620
+ var BITMASK = #{hexnum[bitmask]} >>> 0;
621
+ var POLYNOMIAL = #{hexnum[polynomial]} >>> 0;
622
+ var INITIAL_CRC = #{hexnum[initial_crc]} >>> 0;
623
+ var REFLECT_INPUT = #{reflect_input?.inspect};
624
+ var REFLECT_OUTPUT = #{reflect_output?.inspect};
625
+ var XOR_OUTPUT = #{hexnum[xor_output]} >>> 0;
626
+
627
+ var #{typename} = function() {
628
+ if(!(this instanceof #{typename})) {
629
+ return new #{typename}(...arguments).crc;
630
+ }
631
+
632
+ var seq, prevcrc;
633
+
634
+ switch (arguments.length) {
635
+ case 0:
636
+ seq = null;
637
+ prevcrc = null;
638
+ break;
639
+ case 1:
640
+ if (typeof(arguments[0]) == "string") {
641
+ seq = arguments[0];
642
+ } else {
643
+ prevcrc = arguments[0];
644
+ }
645
+ break;
646
+ case 2:
647
+ seq = arguments[0];
648
+ prevcrc = arguments[1];
649
+ break;
650
+ default:
651
+ throw `wrong number of argument (given ${arguments.size}, expect 0..2)`;
652
+ }
653
+
654
+ this.reset(prevcrc);
655
+ if (seq) { this.update(seq); }
656
+ };
657
+
658
+ var proto = #{typename}.prototype;
659
+
660
+ proto.reset = function(prevcrc = null) {
661
+ this.state = #{typename}.setup(prevcrc || INITIAL_CRC);
662
+ return this;
663
+ };
664
+
665
+ proto.update = function(seq) {
666
+ this.state = #{typename}.update(seq, this.state);
667
+ return this;
668
+ };
669
+
670
+ // proto.operator << = proto.update;
671
+
672
+ proto.finish = function() {
673
+ return #{typename}.finish(this.state);
674
+ };
675
+
676
+ Object.defineProperty(proto, "crc", {
677
+ get: proto.finish
678
+ });
679
+
680
+ Object.defineProperty(proto, "hexdigest", {
681
+ get: function() {
682
+ var s = this.crc.toString(16);
683
+ for (var i = s.length; i < #{sizeof * 2}; i ++) {
684
+ s = "0" + s;
685
+ }
686
+ return s;
687
+ }
688
+ });
689
+
690
+ proto.toString = function() {
691
+ return `#<#{typename}:${this.hexdigest}>`;
692
+ };
693
+
694
+ #{typename}.setup = function(crc = INITIAL_CRC) {
695
+ return #{
696
+ s = "(BITMASK & crc ^ XOR_OUTPUT)"
697
+
698
+ if reflect_output? ^ reflect_input?
699
+ s = "bitreflect#{s}"
700
+ end
701
+
702
+ if !reflect_input? && typebits > bitsize
703
+ s << " << #{typebits - bitsize}"
704
+ end
705
+
706
+ s
707
+ };
708
+ };
709
+
710
+ #{typename}.init = #{typename}.setup;
711
+
712
+ #{typename}.finish = function(state) {
713
+ return (#{
714
+ if !reflect_input? && typebits > bitsize
715
+ state = "(state >>> #{typebits - bitsize})"
716
+ else
717
+ state = "state"
718
+ end
719
+
720
+ if reflect_output? ^ reflect_input?
721
+ "bitreflect(BITMASK & #{state} ^ XOR_OUTPUT)"
722
+ else
723
+ "BITMASK & #{state} ^ XOR_OUTPUT"
724
+ end
725
+ }) >>> 0;
726
+ };
727
+
728
+ /*
729
+ * update(seq, state) -> state
730
+ */
731
+ #{typename}.update = function(seq, s) {
732
+ var i = 0;
733
+ var ii = seq.length;
734
+ var ii16 = ii & ~15;
735
+ var t0 = TABLE[ 0], t1 = TABLE[ 1], t2 = TABLE[ 2], t3 = TABLE[ 3],
736
+ t4 = TABLE[ 4], t5 = TABLE[ 5], t6 = TABLE[ 6], t7 = TABLE[ 7],
737
+ t8 = TABLE[ 8], t9 = TABLE[ 9], tA = TABLE[10], tB = TABLE[11],
738
+ tC = TABLE[12], tD = TABLE[13], tE = TABLE[14], tF = TABLE[15];
739
+ for (; i < ii16; i += 16) {
740
+ s = #{slicing[ 0]} ^
741
+ #{slicing[ 1]} ^
742
+ #{slicing[ 2]} ^
743
+ #{slicing[ 3]} ^
744
+ #{slicing[ 4]} ^
745
+ #{slicing[ 5]} ^
746
+ #{slicing[ 6]} ^
747
+ #{slicing[ 7]} ^
748
+ #{slicing[ 8]} ^
749
+ #{slicing[ 9]} ^
750
+ #{slicing[10]} ^
751
+ #{slicing[11]} ^
752
+ #{slicing[12]} ^
753
+ #{slicing[13]} ^
754
+ #{slicing[14]} ^
755
+ #{slicing[15]};
756
+ }
757
+
758
+ for (; i < ii; i ++) {
759
+ s = t0[(0xFF & seq.charCodeAt(i)) ^ #{headstate}] ^ #{slidestate}
760
+ }
761
+
762
+ return s;
763
+ }
764
+
765
+ #{typename}.crc = function(seq, initcrc = INITIAL_CRC) {
766
+ return #{typename}.finish(#{typename}.update(seq, #{typename}.setup(initcrc)));
767
+ };
768
+
769
+ #{typename}.hexdigest = function(seq, initcrc = INITIAL_CRC) {
770
+ var s = #{typename}.crc(seq, initcrc).toString(16);
771
+ for (var i = s.length; i < #{sizeof * 2}; i ++) {
772
+ s = "0" + s;
773
+ }
774
+ return s;
775
+ };
776
+ EOS
777
+
778
+ if reflect_output? ^ reflect_input?
779
+ code << <<-EOS
780
+
781
+ #{typename}.bitreflect = function(n) {
782
+ EOS
783
+
784
+ if typebits > bitsize
785
+ code << <<-EOS
786
+ n <<= #{typebits - bitsize}
787
+ EOS
788
+ end
789
+
790
+ if typebits > 32
791
+ code << <<-EOS
792
+ n = ((n >>> 32) & 0x00000000ffffffff) | ((n & 0x00000000ffffffff) << 32)
793
+ EOS
794
+ end
795
+
796
+ if typebits > 16
797
+ code << <<-EOS
798
+ n = ((n >>> 16) & 0x#{"0000ffff" * (sizeof / 4)}) | ((n & 0x#{"0000ffff" * (sizeof / 4)}) << 16)
799
+ EOS
800
+ end
801
+
802
+ if typebits > 8
803
+ code << <<-EOS
804
+ n = ((n >>> 8) & 0x#{"00ff" * (sizeof / 2)}) | ((n & 0x#{"00ff" * (sizeof / 2)}) << 8)
805
+ EOS
806
+ end
807
+
808
+ code << <<-EOS
809
+ n = ((n >>> 4) & 0x#{"0f" * sizeof}) | ((n & 0x#{"0f" * sizeof}) << 4)
810
+ n = ((n >>> 2) & 0x#{"33" * sizeof}) | ((n & 0x#{"33" * sizeof}) << 2)
811
+ n = ((n >>> 1) & 0x#{"55" * sizeof}) | ((n & 0x#{"55" * sizeof}) << 1)
812
+ return n;
813
+ }
814
+ EOS
815
+ end
816
+
817
+ code << <<-EOS
818
+
819
+ var TABLE = [
820
+ #{Aux.export_slicing_table(table1, " ", 2, nil, nil, "[", "]", sizeof > 2 ? 4 : 8, &hexnum)}
821
+ ];
822
+
823
+ root.#{typename} = #{typename};
824
+
825
+ Object.defineProperty(#{typename}, "BITSIZE", { get: function() { return BITSIZE } });
826
+ Object.defineProperty(#{typename}, "BITMASK", { get: function() { return BITMASK } });
827
+ Object.defineProperty(#{typename}, "POLYNOMIAL", { get: function() { return POLYNOMIAL } });
828
+ Object.defineProperty(#{typename}, "INITIAL_CRC", { get: function() { return INITIAL_CRC } });
829
+ Object.defineProperty(#{typename}, "REFLECT_INPUT", { get: function() { return REFLECT_INPUT } });
830
+ Object.defineProperty(#{typename}, "REFLECT_OUTPUT", { get: function() { return REFLECT_OUTPUT } });
831
+ Object.defineProperty(#{typename}, "XOR_OUTPUT", { get: function() { return XOR_OUTPUT } });
832
+
833
+ return #{typename};
834
+ })(this);
835
+ EOS
836
+
837
+ ({ source: code })
838
+ end
839
+
840
+ module Aux
841
+ def self.dump_banner(line_prefix, crcname, algorithm)
842
+ case algorithm
843
+ when ALGORITHM_BITBYBIT
844
+ algorithm = "bit-by-bit"
845
+ when ALGORITHM_BITBYBIT_FAST
846
+ algorithm = "bit-by-bit-fast"
847
+ when ALGORITHM_HALFBYTE_TABLE
848
+ algorithm = "halfbyte-table"
849
+ when ALGORITHM_STANDARD_TABLE
850
+ algorithm = "standard-table"
851
+ when ALGORITHM_SLICING_BY_4, ALGORITHM_SLICING_BY_8, ALGORITHM_SLICING_BY_16
852
+ algorithm = "slicing-by-#{algorithm} (with byte-order free), based Intel's slicing-by-8"
853
+ else
854
+ raise ArgumentError, "out of algorithm code (given #{algorithm})"
855
+ end
856
+ (<<-EOS).gsub!(/^(?!$)/, " ").gsub!(/^/) { line_prefix }.chomp!
857
+ A CRC generator for #{crcname}.
858
+
859
+ This code is auto generated by <https://rubygems.org/gems/crc>.
860
+
861
+ * License:: Creative Commons License Zero (CC0 / Public Domain)
862
+ See <https://creativecommons.org/publicdomain/zero/1.0/>
863
+ * Version:: crc-#{CRC::VERSION} (powered by #{RUBY_DESCRIPTION})
864
+ * Generated at:: #{Time.now.strftime "%Y-%m-%d"}
865
+ * Algorithm:: #{algorithm}
866
+ * Need available memory:: about 1 MiB
867
+ EOS
868
+ end
869
+
870
+ def self.export_slicing_table(table, baseindent, indentsize, tableprefix, tablesuffix, elementprefix, elementsuffix, lineinelements, &hexnum)
871
+ indent = ->(n = 0) { baseindent + (" " * (indentsize * n)) }
872
+ tableprefix &&= "#{indent[0]}#{tableprefix}\n"
873
+ tablesuffix &&= "\n#{indent[0]}#{tablesuffix}"
874
+ if table[0].kind_of?(Array)
875
+ (<<-TABLE2).chomp!
876
+ #{tableprefix}#{indent[1]}#{elementprefix}
877
+ #{
878
+ table = table.map { |tt|
879
+ tt = tt.map(&hexnum)
880
+ %(#{indent[2]}#{tt.each_slice(lineinelements).map { |ttt| ttt.join(", ") }.join(",\n#{indent[2]}")}\n)
881
+ }.join("#{indent[1]}#{elementsuffix},\n#{indent[1]}#{elementprefix}\n").chomp!
882
+ }
883
+ #{indent[1]}#{elementsuffix}#{tablesuffix}
884
+ TABLE2
885
+ else
886
+ table = table.map(&hexnum)
887
+ %(#{indent[1]}#{table.each_slice(lineinelements).map { |ttt| ttt.join(", ") }.join(",\n#{indent[1]}")}\n).chomp!
888
+ end
889
+ end
890
+ end
891
+ end