crc 0.3 → 0.3.1.1

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