crc 0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bee58adf97d048655d45b3f33a14781b150638c7
4
+ data.tar.gz: bd49389a8b03124937b87c7a09deaf1fd03b3f8e
5
+ SHA512:
6
+ metadata.gz: ba1a3e68cef316f5e46db132c8fceeb66bace335427ec49b01987f87bb12b74ab7409649b5240baa4876231fd52da93f999fb6fdb01fa1f56657a9183f3b03fd
7
+ data.tar.gz: 707b71a8fcd2dfe0593ce3d94b4fbd3b2265c202e67d6e704c39c758c275e1386fe14626090c8ace254c78edb6e7ff03846b8ea551bf4335e110c1eef78f9a41
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2016, dearblue. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or
4
+ without modification, are permitted provided that the following
5
+ conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in
11
+ the documentation and/or other materials provided with the
12
+ distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,67 @@
1
+
2
+ # crc - CRC generator for ruby
3
+
4
+ This is a general CRC (Cyclic Redundancy Check) generator for ruby.
5
+
6
+ It is written by pure ruby with based on slice-by-eight algorithm (byte-order-free slice-by-16 algorithm).
7
+
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 more.
9
+
10
+ And your defined CRC modules to use.
11
+
12
+ This is slower than x95+ of zlib/crc32, and slower than x135+ of extlzma/crc32 on FreeBSD 10.3R amd64.
13
+
14
+ If you need more speed, please use crc-turbo.
15
+
16
+
17
+ ## SUMMARY
18
+
19
+ * package name: crc
20
+ * author: dearblue (mailto:dearblue@users.osdn.me)
21
+ * report issue to: <https://osdn.jp/projects/rutsubo/ticket/>
22
+ * how to install: ``gem install crc``
23
+ * version: 0.1
24
+ * release quality: thechnical preview
25
+ * licensing: BSD-2-Clause
26
+ * dependency gems: none
27
+ * dependency external c libraries: none
28
+ * bundled external c libraries: none
29
+
30
+ ## FEATURES
31
+
32
+ * ``CRC.crc32(seq, init = 0) -> crc-32 integer`` (likely as ``Zlib.crc32``)
33
+ * ``CRC::CRC32.crc(seq, init = 0) -> crc-32 integer`` (likely as ``Zlib.crc32``)
34
+ * ``CRC::CRC32.digest(seq, init = 0) -> crc-32 digest`` (likely as ``Digest::XXXX.digest``)
35
+ * ``CRC::CRC32.hexdigest(seq, init = 0) -> crc-32 hex-digest`` (likely as ``Digest::XXXX.hexdigest``)
36
+ * ``CRC::CRC32.new(init = 0) -> crc-32 context`` (likely as ``Digest::XXXX.new``)
37
+ * ``CRC::CRC32#update(seq) -> self`` (likely as ``Digest::XXXX#update``)
38
+ * ``CRC::CRC32#finish -> crc-32 integer`` (likely as ``Digest::XXXX#finish``)
39
+ * ``CRC.crc("crc-32", seq, init = 0) -> crc-32 integer``
40
+ * ``CRC.digest("crc-32", seq, init = 0) -> crc-32 digest``
41
+ * ``CRC.hexdigest("crc-32", seq, init = 0) -> crc-32 hex-digest``
42
+
43
+ ----
44
+
45
+ * ``CRC.create_module(bitsize, poly, init_state, refin, refout, xorout) -> new crc module class``
46
+
47
+ ``` ruby:ruby
48
+ MyCRC32 = CRC.create_module(32, 0x04C11DB7)
49
+ p MyCRC32.class # => Class
50
+ p MyCRC32.hexdigest("123456789") # => "CBF43926"
51
+ ```
52
+
53
+
54
+ ## BUILD-IN CRC MODULES
55
+
56
+ ``` shell:shell
57
+ % ruby -rcrc -e 'puts CRC::MODULE_TABLE.values.uniq.map { |m| m::TRAITS.name }.join(", ")'
58
+ ```
59
+
60
+ CRC-1, CRC-3-ROHC, 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-8, CRC-8-CCITT, CRC-8-Dallas/Maxim, CRC-8-DARC, CRC-8-SAE, CRC-8-WCDMA, CRC-10, CRC-10-CDMA2000, CRC-11, CRC-12, CRC-12-CDMA2000, CRC-13-BBC, CRC-14-DARC, CRC-15-CAN, CRC-15-MPT1327, Chakravarty, CRC-16-ARINC, CRC-16-CCITT, CRC-16-CDMA2000, CRC-16-DECT, CRC-16-T10-DIF, CRC-16-DNP, CRC-16-IBM, CRC-16-LZH, CRC-17-CAN, CRC-21-CAN, CRC-24, CRC-24-Radix-64, CRC-30, CRC-32, CRC-32C, CRC-32K, CRC-32K2, CRC-32Q, CRC-40-GSM, CRC-64-ECMA, CRC-64-ISO
61
+
62
+
63
+ ## ENVIRONMENT VARIABLES FOR BEHAVIOR
64
+
65
+ * ``RUBY_CRC_NOFAST=1``: Force use ruby implementation with slice-by-16 algorithm. Not used "crc-turbo".
66
+ * ``RUBY_CRC_NOFAST=2``: Switch to lookup table algorithm from slice-by-16 algorithm. Slower to about 52% (when CRC-32).
67
+ * ``RUBY_CRC_NOFAST=3``: Switch to reference algorithm from slice-by-16 algorithm. Slower to about 7% (when CRC-32).
@@ -0,0 +1,212 @@
1
+
2
+ require "pathname"
3
+ require "rake/clean"
4
+
5
+ docnames = "{README,LICENSE,CHANGELOG,Changelog,HISTORY}"
6
+ doctypes = "{,.txt,.rd,.rdoc,.md,.markdown}"
7
+ cexttypes = "{c,C,cc,cxx,cpp,h,H,hh}"
8
+
9
+ DOC = FileList["#{docnames}{,.ja}#{doctypes}"] +
10
+ FileList["{contrib,ext}/**/#{docnames}{,.ja}#{doctypes}"] +
11
+ FileList["ext/**/*.#{cexttypes}"]
12
+ EXT = FileList["ext/**/*"]
13
+ BIN = FileList["bin/*"]
14
+ LIB = FileList["lib/**/*.rb"]
15
+ SPEC = FileList["spec/**/*"]
16
+ TEST = FileList["test/**/*"]
17
+ EXAMPLE = FileList["examples/**/*"]
18
+ GEMSTUB_SRC = "gemstub.rb"
19
+ RAKEFILE = [File.basename(__FILE__), GEMSTUB_SRC]
20
+ EXTRA = []
21
+ EXTCONF = FileList["ext/**/extconf.rb"]
22
+ EXTCONF.reject! { |n| !File.file?(n) }
23
+ EXTMAP = {}
24
+
25
+ load GEMSTUB_SRC
26
+
27
+ EXTMAP.dup.each_pair do |dir, name|
28
+ EXTMAP[Pathname.new(dir).cleanpath.to_s] = Pathname.new(name).cleanpath.to_s
29
+ end
30
+
31
+ GEMSTUB.extensions += EXTCONF
32
+ GEMSTUB.executables += FileList["bin/*"].map { |n| File.basename n }
33
+ GEMSTUB.executables.sort!
34
+
35
+ PACKAGENAME = "#{GEMSTUB.name}-#{GEMSTUB.version}"
36
+ GEMFILE = "#{PACKAGENAME}.gem"
37
+ GEMSPEC = "#{PACKAGENAME}.gemspec"
38
+
39
+ GEMSTUB.files += DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + EXTRA
40
+ GEMSTUB.files.sort!
41
+ if GEMSTUB.rdoc_options.nil? || GEMSTUB.rdoc_options.empty?
42
+ readme = %W(.md .markdown .rd .rdoc .txt #{""}).map { |ext| "README#{ext}" }.find { |m| DOC.find { |n| n == m } }
43
+ GEMSTUB.rdoc_options = %w(--charset UTF-8) + (readme ? %W(-m #{readme}) : [])
44
+ end
45
+ GEMSTUB.extra_rdoc_files += DOC + LIB + EXT.reject { |n| n.include?("/externals/") || !%w(.h .hh .c .cc .cpp .cxx).include?(File.extname(n)) }
46
+ GEMSTUB.extra_rdoc_files.sort!
47
+
48
+ GEMSTUB_TRYOUT = GEMSTUB.dup
49
+ GEMSTUB_TRYOUT.version = "#{GEMSTUB.version}#{Time.now.strftime(".TRYOUT.%Y%m%d.%H%M%S")}"
50
+ PACKAGENAME_TRYOUT = "#{GEMSTUB.name}-#{GEMSTUB_TRYOUT.version}"
51
+ GEMFILE_TRYOUT = "#{PACKAGENAME_TRYOUT}.gem"
52
+ GEMSPEC_TRYOUT = "#{PACKAGENAME_TRYOUT}.gemspec"
53
+
54
+ CLEAN << GEMSPEC << GEMSPEC_TRYOUT
55
+ CLOBBER << GEMFILE
56
+
57
+ task :default => :tryout do
58
+ $stderr.puts <<-EOS
59
+ #{__FILE__}:#{__LINE__}:
60
+ \ttype ``rake release'' to build release package.
61
+ EOS
62
+ end
63
+
64
+ desc "build tryout package"
65
+ task :tryout
66
+
67
+ desc "build release package"
68
+ task :release => :all
69
+
70
+ unless EXTCONF.empty?
71
+ RUBYSET ||= (ENV["RUBYSET"] || "").split(",")
72
+
73
+ if RUBYSET.nil? || RUBYSET.empty?
74
+ $stderr.puts <<-EOS
75
+ #{__FILE__}:
76
+ |
77
+ | If you want binary gem package, launch rake with ``RUBYSET`` enviroment
78
+ | variable for set ruby interpreters by comma separated.
79
+ |
80
+ | e.g.) $ rake RUBYSET=ruby
81
+ | or) $ rake RUBYSET=ruby21,ruby22,ruby23
82
+ |
83
+ EOS
84
+ else
85
+ platforms = RUBYSET.map { |ruby| `#{ruby} --disable-gems -e "puts RUBY_PLATFORM"`.chomp }
86
+ platforms1 = platforms.uniq
87
+ unless platforms1.size == 1 && !platforms1[0].empty?
88
+ abort <<-EOS
89
+ #{__FILE__}:#{__LINE__}: different platforms:
90
+ #{RUBYSET.zip(platforms).map { |ruby, platform| "%24s => %s" % [ruby, platform] }.join("\n")}
91
+ ABORTED.
92
+ EOS
93
+ end
94
+ PLATFORM = platforms1[0]
95
+
96
+ RUBY_VERSIONS = RUBYSET.map do |ruby|
97
+ ver = `#{ruby} --disable-gems -e "puts RUBY_VERSION"`.slice(/\d+\.\d+/)
98
+ raise "failed ruby checking - ``#{ruby}''" unless $?.success?
99
+ [ver, ruby]
100
+ end
101
+
102
+ SOFILES_SET = RUBY_VERSIONS.map { |(ver, ruby)|
103
+ EXTCONF.map { |extconf|
104
+ extdir = Pathname.new(extconf).cleanpath.dirname.to_s
105
+ case
106
+ when soname = EXTMAP[extdir.sub(/^ext\//i, "")]
107
+ soname = soname.sub(/\.so$/i, "")
108
+ when extdir == "ext" || extdir == "."
109
+ soname = GEMSTUB.name
110
+ else
111
+ soname = File.basename(extdir)
112
+ end
113
+
114
+ [ruby, File.join("lib", "#{soname.sub(/(?<=\/)|^(?!.*\/)/, "#{ver}/")}.so"), extconf]
115
+ }
116
+ }.flatten(1)
117
+ SOFILES = SOFILES_SET.map { |(ruby, sopath, extconf)| sopath }
118
+
119
+ GEMSTUB_NATIVE = GEMSTUB.dup
120
+ GEMSTUB_NATIVE.files += SOFILES
121
+ GEMSTUB_NATIVE.platform = Gem::Platform.new(PLATFORM).to_s
122
+ GEMSTUB_NATIVE.extensions.clear
123
+ GEMFILE_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.version}-#{GEMSTUB_NATIVE.platform}.gem"
124
+ GEMSPEC_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.platform}.gemspec"
125
+
126
+ task :all => ["native-gem", GEMFILE]
127
+
128
+ desc "build binary gem package"
129
+ task "native-gem" => GEMFILE_NATIVE
130
+
131
+ desc "generate binary gemspec"
132
+ task "native-gemspec" => GEMSPEC_NATIVE
133
+
134
+ file GEMFILE_NATIVE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + SOFILES + RAKEFILE + [GEMSPEC_NATIVE] do
135
+ sh "gem build #{GEMSPEC_NATIVE}"
136
+ end
137
+
138
+ file GEMSPEC_NATIVE => RAKEFILE do
139
+ File.write(GEMSPEC_NATIVE, GEMSTUB_NATIVE.to_ruby, mode: "wb")
140
+ end
141
+
142
+ desc "build c-extension libraries"
143
+ task "sofiles" => SOFILES
144
+
145
+ SOFILES_SET.each do |(ruby, soname, extconf)|
146
+ sodir = File.dirname(soname)
147
+ makefile = File.join(sodir, "Makefile")
148
+
149
+ CLEAN << GEMSPEC_NATIVE << sodir
150
+ CLOBBER << GEMFILE_NATIVE
151
+
152
+ directory sodir
153
+
154
+ desc "generate Makefile for binary extension library"
155
+ file makefile => [sodir, extconf] do
156
+ rel_extconf = Pathname.new(extconf).relative_path_from(Pathname.new(sodir)).to_s
157
+ cd sodir do
158
+ sh *%W"#{ruby} #{rel_extconf} --ruby=#{ruby} #{ENV["EXTCONF"]}"
159
+ end
160
+ end
161
+
162
+ desc "build binary extension library"
163
+ file soname => [makefile] + EXT do
164
+ cd sodir do
165
+ sh "make"
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+
172
+
173
+ task :all => GEMFILE
174
+ task :tryout => GEMFILE_TRYOUT
175
+
176
+ desc "generate local rdoc"
177
+ task :rdoc => DOC + LIB do
178
+ sh *(%w(rdoc) + GEMSTUB.rdoc_options + DOC + LIB)
179
+ end
180
+
181
+ desc "launch rspec"
182
+ task rspec: :all do
183
+ sh "rspec"
184
+ end
185
+
186
+ desc "build gem package"
187
+ task gem: GEMFILE
188
+
189
+ desc "generate gemspec"
190
+ task gemspec: GEMSPEC
191
+
192
+ desc "print package name"
193
+ task "package-name" do
194
+ puts PACKAGENAME
195
+ end
196
+
197
+ file GEMFILE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + [GEMSPEC] do
198
+ sh "gem build #{GEMSPEC}"
199
+ end
200
+
201
+ file GEMFILE_TRYOUT => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + [GEMSPEC_TRYOUT] do
202
+ #file GEMFILE_TRYOUT do
203
+ sh "gem build #{GEMSPEC_TRYOUT}"
204
+ end
205
+
206
+ file GEMSPEC => RAKEFILE do
207
+ File.write(GEMSPEC, GEMSTUB.to_ruby, mode: "wb")
208
+ end
209
+
210
+ file GEMSPEC_TRYOUT => RAKEFILE do
211
+ File.write(GEMSPEC_TRYOUT, GEMSTUB_TRYOUT.to_ruby, mode: "wb")
212
+ end
@@ -0,0 +1,45 @@
1
+ #
2
+ # Only this code to the PUBLIC DOMAIN.
3
+ #
4
+
5
+ require "benchmark"
6
+ #require "securerandom"
7
+ require "zlib"
8
+ require "crc"
9
+ begin; require "extlzma"; rescue LoadError; no_extlzma = true; end
10
+ begin; require "digest/crc"; rescue LoadError; no_digest_crc = true; end
11
+
12
+ def measure(generator_name)
13
+ print " * measuring for #{generator_name}..."
14
+ $stdout.flush
15
+ realms = 5.times.map do
16
+ real = (Benchmark.measure { yield }.real * 1000)
17
+ print " #{real.ceil} ms."
18
+ $stdout.flush
19
+ real
20
+ end.min
21
+ puts " (#{realms.ceil} ms.)\n"
22
+ [generator_name, realms]
23
+ end
24
+
25
+ size = 20
26
+ puts " ** preparing #{size} MiB data...\n"
27
+ #s = SecureRandom.random_bytes(size << 20)
28
+ s = "0" * (size << 20)
29
+
30
+ crc = measure("ruby-crc/crc32") { CRC.crc32(s) }[1]
31
+ comparisons = []
32
+ comparisons << measure("zlib/crc-32") { Zlib.crc32(s) }
33
+ comparisons << measure("extlzma/crc-32") { LZMA.crc32(s) } unless no_extlzma
34
+ comparisons << measure("digest/crc-32") { Digest::CRC32.digest(s) } unless no_digest_crc
35
+ comparisons << measure("ruby-crc/crc-64") { CRC.crc64(s) }
36
+ comparisons << measure("extlzma/crc-64") { LZMA.crc64(s) } unless no_extlzma
37
+
38
+ puts <<'EOS'
39
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
40
+ (slowly at over 1.0)
41
+ EOS
42
+
43
+ comparisons.each do |name, meas|
44
+ puts "%24s : ruby-crc/crc32 = %10.5f : 1.0\n" % [name, crc / meas]
45
+ end
@@ -0,0 +1,21 @@
1
+ GEMSTUB = Gem::Specification.new do |s|
2
+ s.name = "crc"
3
+ s.version = "0.1"
4
+ s.summary = "general CRC generator"
5
+ s.description = <<EOS
6
+ 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 (byte-order-free slice-by-16 algorithm).
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 more.
9
+ And your defined CRC modules to use.
10
+ If you need more speed, please use crc-turbo.
11
+ EOS
12
+ s.homepage = "https://osdn.jp/projects/rutsubo/"
13
+ s.license = "BSD-2-Clause"
14
+ s.author = "dearblue"
15
+ s.email = "dearblue@users.osdn.me"
16
+
17
+ s.required_ruby_version = ">= 2.0"
18
+ s.add_development_dependency "rake", "~> 11.0"
19
+ end
20
+
21
+ EXTRA << "benchmark.rb"
@@ -0,0 +1,405 @@
1
+ #!ruby
2
+
3
+ if ENV["RUBY_CRC_NOFAST"].to_i > 0
4
+ require_relative "crc/_byruby"
5
+ else
6
+ begin
7
+ require File.join("crc", RUBY_VERSION[/\d+\.\d+/], "_turbo.so")
8
+ rescue LoadError
9
+ require_relative "crc/_byruby"
10
+ end
11
+ end
12
+
13
+ module CRC
14
+ CRC = self
15
+
16
+ extend Utils
17
+
18
+ module Utils
19
+ extend self
20
+
21
+ def bitreflect_reference(num, bitsize)
22
+ n = 0
23
+ bitsize.times { n <<= 1; n |= (num & 0x01); num >>= 1 }
24
+ n
25
+ end
26
+
27
+ def bitreflect(num, bitsize)
28
+ case
29
+ when bitsize > 64
30
+ bitreflect_reference(num, bitsize)
31
+ when bitsize > 32
32
+ bitreflect64(num) >> (64 - bitsize)
33
+ when bitsize > 16
34
+ bitreflect32(num) >> (32 - bitsize)
35
+ when bitsize > 8
36
+ bitreflect16(num) >> (16 - bitsize)
37
+ else
38
+ bitreflect8(num) >> ( 8 - bitsize)
39
+ end
40
+ end
41
+
42
+ if false
43
+ 20.times do
44
+ n = rand(1 << 62)
45
+ bitsize = rand(64) + 1
46
+ a = bitreflect_reference(n, bitsize)
47
+ b = bitreflect(n, bitsize)
48
+ puts "0x%016X (%2d) => 0x%016X, 0x%016X (%s)" % [n, bitsize, a, b, (a == b)]
49
+ end
50
+ puts
51
+ require "benchmark"
52
+ Benchmark.bm(24) do |bm|
53
+ t = 1 << 16
54
+ 4.times do
55
+ bm.report("reference(-1, 8)") { t.times { bitreflect_reference(-1, 8) } }
56
+ bm.report("reference(-1, 16)") { t.times { bitreflect_reference(-1, 16) } }
57
+ bm.report("reference(-1, 24)") { t.times { bitreflect_reference(-1, 24) } }
58
+ bm.report("reference(-1, 32)") { t.times { bitreflect_reference(-1, 32) } }
59
+ bm.report("reference(-1, 64)") { t.times { bitreflect_reference(-1, 64) } }
60
+ bm.report("bitreflect(-1, 8)") { t.times { bitreflect(-1, 8) } }
61
+ bm.report("bitreflect(-1, 16)") { t.times { bitreflect(-1, 16) } }
62
+ bm.report("bitreflect(-1, 24)") { t.times { bitreflect(-1, 24) } }
63
+ bm.report("bitreflect(-1, 32)") { t.times { bitreflect(-1, 32) } }
64
+ bm.report("bitreflect(-1, 64)") { t.times { bitreflect(-1, 64) } }
65
+ puts
66
+ end
67
+ end
68
+ abort "TEST ABORT"
69
+ end
70
+
71
+ def build_table(bitsize, polynomial)
72
+ bitmask = ~(~0 << bitsize)
73
+ carrydown = bitmask >> 1
74
+ polynomial = bitmask & polynomial
75
+ table = []
76
+ head = 7
77
+ 256.times do |i|
78
+ 8.times { i = (i[head] == 0) ? (i << 1) : (((i & carrydown) << 1) ^ polynomial) }
79
+ table << i
80
+ end
81
+
82
+ table.freeze
83
+ end
84
+
85
+ def build_table8(bitsize, polynomial, unfreeze = false)
86
+ bitmask = ~(~0 << bitsize)
87
+ table = []
88
+ Aux.slide_to_head(bitsize, 0, bitmask & polynomial, bitmask) do |xx, poly, csh, head, carries, pad|
89
+ 8.times do |s|
90
+ table << (t = [])
91
+ 256.times do |b|
92
+ r = (s == 0 ? (b << csh) : (table[-2][b]))
93
+ 8.times { r = (r[head] == 0) ? (r << 1) : (((carries & r) << 1) ^ poly) }
94
+ t << r
95
+ end
96
+ t.freeze unless unfreeze
97
+ t
98
+ end
99
+ 0
100
+ end
101
+ table.freeze unless unfreeze
102
+ table
103
+ end
104
+
105
+ def build_table!(bitsize, polynomial)
106
+ polynomial = bitreflect(polynomial, bitsize)
107
+ table = []
108
+ 256.times do |i|
109
+ 8.times { i = (i[0] == 0) ? (i >> 1) : ((i >> 1) ^ polynomial) }
110
+ table << i
111
+ end
112
+
113
+ table.freeze
114
+ end
115
+
116
+ def build_table8!(bitsize, polynomial, unfreeze = false)
117
+ polynomial = bitreflect(polynomial, bitsize)
118
+ table = []
119
+ 16.times do |s|
120
+ table << (t = [])
121
+ 256.times do |b|
122
+ r = (s == 0) ? b : table[-2][b]
123
+ 8.times { r = (r[0] == 0) ? (r >> 1) : ((r >> 1) ^ polynomial) }
124
+ t << r
125
+ end
126
+ t.freeze unless unfreeze
127
+ t
128
+ end
129
+
130
+ table.freeze unless unfreeze
131
+ table
132
+ end
133
+
134
+ def export_table(table, bitsize, linewidth, indentsize = 2)
135
+ bitsize0 = bitsize.to_i
136
+ indent = " " * indentsize.to_i
137
+ case
138
+ when bitsize0 > 64 || bitsize0 < 1
139
+ raise "invalid bitsize (expected to 1..64, but given #{bitsize})"
140
+ when bitsize0 > 32
141
+ packformat = "Q>"
142
+ hexwidth = 16
143
+ when bitsize0 > 16
144
+ packformat = "N"
145
+ hexwidth = 8
146
+ when bitsize0 > 8
147
+ packformat = "n"
148
+ hexwidth = 4
149
+ else # when bitsize0 > 0
150
+ packformat = "C"
151
+ hexwidth = 2
152
+ end
153
+ table = table.to_a.pack("#{packformat}*").unpack("H*")[0]
154
+ table.gsub!(/(?<=\w)(?=\w{#{hexwidth}}{#{linewidth}}+$)/, "\n")
155
+ table.gsub!(/(?<=\w)(?=\w{#{hexwidth}}+$)/, " ")
156
+ table.gsub!(/(?<=\w)(?=\s|$)/, ",")
157
+ table.gsub!(/(?:(?<=^)|(?<=\s))(?=\w)/, "0x")
158
+ table.gsub!(/^/, "#{indent} ")
159
+ <<-EOS
160
+ #{indent}TABLE = [
161
+ #{table}
162
+ #{indent}].freeze
163
+ EOS
164
+ end
165
+
166
+ #puts export_table(build_table(16, 0x1021), 16, 8); #abort "DEBUG EXIT"
167
+ #puts export_table(build_table!(32, 0xEDB88320), 32, 8); abort "DEBUG EXIT"
168
+ end
169
+
170
+ extend Utils
171
+
172
+ module Aux
173
+ def self.DIGEST(state, bitsize)
174
+ bits = (bitsize + 7) / 8 * 8
175
+ seq = "".b
176
+ (bits - 8).step(0, -8) { |i| seq << yield((state >> i) & 0xff) }
177
+ seq
178
+ end
179
+
180
+ def self.digest(state, bitsize)
181
+ DIGEST(state, bitsize) { |n| [n].pack("C") }
182
+ end
183
+
184
+ def self.hexdigest(state, bitsize)
185
+ DIGEST(state, bitsize) { |n| "%02X" % n }
186
+ end
187
+
188
+ #
189
+ # call-seq:
190
+ # slide_to_head(bitsize, state, polynomial, bitmask) { |padded_state, padded_polynomial, shift_input, off_msb, carries_mask, padding_size| padded_new_state } -> new_state
191
+ #
192
+ # YIELD(padded_state, padded_polynomial, shift_input, off_msb, carries_mask, padding_size) -> padded_new_state
193
+ #
194
+ def self.slide_to_head(bitsize, state, polynomial, bitmask)
195
+ pad = bitsize & 0x07
196
+ if pad == 0
197
+ yield(state, polynomial, bitsize - 8, bitsize - 1, bitmask >> 1, 0)
198
+ else
199
+ pad = 8 - pad
200
+ yield(state << pad, polynomial << pad, bitsize - 8 + pad, bitsize - 1 + pad, (bitmask << pad >> 1) | 0x7f, pad) >> pad
201
+ end
202
+ end
203
+ end
204
+
205
+ class Generator
206
+ def crc(seq, state = nil)
207
+ finish(update(seq, setup(state)))
208
+ end
209
+
210
+ def setup(state = nil)
211
+ state ||= initial_state
212
+ state ^= xor_output
213
+ state = CRC.bitreflect(state, bitsize) if reflect_input ^ reflect_output
214
+ state
215
+ end
216
+
217
+ def finish(state)
218
+ state = CRC.bitreflect(state, bitsize) if reflect_input ^ reflect_output
219
+ state ^ xor_output
220
+ end
221
+
222
+ def digest(seq, state = nil)
223
+ Aux.digest(crc(seq, state), bitsize)
224
+ end
225
+
226
+ def hexdigest(seq, state = nil)
227
+ Aux.hexdigest(crc(seq, state), bitsize)
228
+ end
229
+
230
+ def to_s
231
+ case
232
+ when bitsize > 64 then width = 20
233
+ when bitsize > 32 then width = 16
234
+ when bitsize > 16 then width = 8
235
+ when bitsize > 8 then width = 4
236
+ else width = 2
237
+ end
238
+
239
+ if reflect_input
240
+ ref = ", reflect-in#{reflect_output ? "/out" : ""}"
241
+ else
242
+ ref = reflect_output ? ", reflect-out" : ""
243
+ end
244
+
245
+ case initial_state
246
+ when 0 then init = "0"
247
+ when bitmask then init = "~0"
248
+ when 1 then init = "1"
249
+ else init = "0x%0#{width}X" % initial_state
250
+ end
251
+
252
+ case xor_output
253
+ when 0 then xor = "0"
254
+ when bitmask then xor = "~0"
255
+ when 1 then xor = "1"
256
+ else xor = "0x%0#{width}X" % xor_output
257
+ end
258
+
259
+ if nm = name
260
+ "#{nm}(CRC-%d-0x%0#{width}X init=%s%s, xor=%s)" % [bitsize, polynomial, init, ref, xor]
261
+ else
262
+ "(CRC-%d-0x%0#{width}X init=%s%s, xor=%s)" % [bitsize, polynomial, init, ref, xor]
263
+ end
264
+ end
265
+
266
+ def inspect
267
+ "\#<#{self.class} #{to_s}>"
268
+ end
269
+
270
+ def pretty_inspect(q)
271
+ q.text inspect
272
+ end
273
+ end
274
+
275
+ class BasicCRC < Struct.new(:internal_state, :initial_state)
276
+ BasicStruct = superclass
277
+
278
+ class BasicStruct
279
+ alias state! internal_state
280
+ alias set_state! internal_state=
281
+ end
282
+
283
+ def initialize(initial_state = nil)
284
+ generator = self.class::GENERATOR
285
+ initial_state ||= generator.initial_state
286
+ super generator.setup(initial_state), initial_state
287
+ end
288
+
289
+ def reset(initial_state = self.initial_state)
290
+ generator = self.class::GENERATOR
291
+ initial_state ||= generator.initial_state
292
+ set_state! generator.setup(initial_state)
293
+ self.initial_state = initial_state
294
+ self
295
+ end
296
+
297
+ def update(seq)
298
+ set_state! self.class::GENERATOR.update!(seq, state!)
299
+ self
300
+ end
301
+
302
+ alias << update
303
+
304
+ def finish
305
+ self.class::GENERATOR.finish(state!)
306
+ end
307
+
308
+ alias state finish
309
+
310
+ def digest
311
+ Aux.DIGEST(state, self.class::GENERATOR.bitsize) { |n| [n].pack("C") }
312
+ end
313
+
314
+ # ビット反転せずに値を返す
315
+ def digest!
316
+ Aux.DIGEST(state!, self.class::GENERATOR.bitsize) { |n| [n].pack("C") }
317
+ end
318
+
319
+ def hexdigest
320
+ Aux.DIGEST(state, self.class::GENERATOR.bitsize) { |n| "%02X" % n }
321
+ end
322
+
323
+ # ビット反転せずに値を返す
324
+ def hexdigest!
325
+ Aux.DIGEST(state!, self.class::GENERATOR.bitsize) { |n| "%02X" % n }
326
+ end
327
+
328
+ alias to_str hexdigest
329
+ alias to_s hexdigest
330
+
331
+ def inspect
332
+ "\#<#{self.class}:#{hexdigest}>"
333
+ end
334
+
335
+ def pretty_inspect(q)
336
+ q.text inspect
337
+ end
338
+
339
+ class << self
340
+ def inspect
341
+
342
+ if const_defined?(:GENERATOR)
343
+ if nm = name
344
+ "#{nm}(#{self::GENERATOR.to_s})"
345
+ else
346
+ super.sub(/(?=\>$)/) { " #{self::GENERATOR.to_s}" }
347
+ end
348
+ else
349
+ super
350
+ end
351
+ end
352
+
353
+ def pretty_inspect(q)
354
+ q.text inspect
355
+ end
356
+
357
+ def crc(seq, state = nil)
358
+ self::GENERATOR.crc(seq, state)
359
+ end
360
+
361
+ def digest(seq, state = nil)
362
+ Aux.digest(self::GENERATOR.crc(seq, state), self::GENERATOR.bitsize)
363
+ end
364
+
365
+ def hexdigest(seq, state = nil)
366
+ Aux.hexdigest(self::GENERATOR.crc(seq, state), self::GENERATOR.bitsize)
367
+ end
368
+ end
369
+ end
370
+
371
+ MODULE_TABLE = {}
372
+
373
+ class << self
374
+ def lookup(modulename)
375
+ modulename1 = modulename.to_s.gsub(/[\W_]+/, "")
376
+ modulename1.downcase!
377
+ MODULE_TABLE[modulename1] or raise NameError, "modulename is not matched (for #{modulename})"
378
+ end
379
+
380
+ alias [] lookup
381
+
382
+ def crc(modulename, seq, state = nil)
383
+ lookup(modulename).crc(seq, state)
384
+ end
385
+
386
+ def digest(modulename, seq, state = nil)
387
+ lookup(modulename).digest(seq, state)
388
+ end
389
+
390
+ def hexdigest(modulename, seq, state = nil)
391
+ lookup(modulename).hexdigest(seq, state)
392
+ end
393
+
394
+ def create_module(bitsize, polynomial, initial_state = 0, refin = true, refout = true, xor = ~0, name = nil)
395
+ generator = Generator.new(bitsize, polynomial, initial_state, refin, refout, xor, name)
396
+ crc = Class.new(BasicCRC)
397
+ crc.const_set :GENERATOR, generator
398
+ crc
399
+ end
400
+ end
401
+
402
+ SELF_TEST = ($0 == __FILE__) ? true : false
403
+ end
404
+
405
+ require_relative "crc/_modules"
@@ -0,0 +1,226 @@
1
+ #--
2
+ # Author:: dearblue <dearblue@users.osdn.me>
3
+ # License:: BSD-2-Clause
4
+ #++
5
+
6
+ #
7
+ # Ruby implemented CRC generator.
8
+ # It's Based on the Intel's slice-by-eight algorithm (but byte-order-free).
9
+ #
10
+ # It's faster than about 50% (CRC-32) and about 30% (CRC-64) of
11
+ # lookup-table algorithm. But need more memory.
12
+ #
13
+ # reference:
14
+ # * http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
15
+ # * xz-utils (src/liblzma/check/crc32_fast.c, src/liblzma/check/crc32_tablegen.c)
16
+ #
17
+ # If defined "RUBY_CRC_NOFAST=2" enviroment variable, switch to lookup-table algorithm.
18
+ #
19
+ # If defined "RUBY_CRC_NOFAST=3" enviroment variable, switch to reference algorithm.
20
+ #
21
+ module CRC
22
+ module Utils
23
+ def bitreflect8(n)
24
+ n = n.to_i
25
+ n = ((n & 0x55) << 1) | ((n >> 1) & 0x55)
26
+ n = ((n & 0x33) << 2) | ((n >> 2) & 0x33)
27
+ return ((n & 0x0f) << 4) | (n >> 4) # 0x0f
28
+ end
29
+
30
+ def bitreflect16(n)
31
+ n = n.to_i
32
+ n = ((n & 0x5555) << 1) | ((n >> 1) & 0x5555)
33
+ n = ((n & 0x3333) << 2) | ((n >> 2) & 0x3333)
34
+ n = ((n & 0x0f0f) << 4) | ((n >> 4) & 0x0f0f)
35
+ return ((n & 0x00ff) << 8) | (n >> 8) # 0x00ff
36
+ end
37
+
38
+ def bitreflect32(n)
39
+ n = n.to_i
40
+ n = ((n & 0x55555555) << 1) | ((n >> 1) & 0x55555555)
41
+ n = ((n & 0x33333333) << 2) | ((n >> 2) & 0x33333333)
42
+ n = ((n & 0x0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f)
43
+ n = ((n & 0x00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff)
44
+ return ((n & 0x0000ffff) << 16) | (n >> 16) # 0x0000ffff
45
+ end
46
+
47
+ def bitreflect64(n)
48
+ n = n.to_i
49
+ n = ((n & 0x5555555555555555) << 1) | ((n >> 1) & 0x5555555555555555)
50
+ n = ((n & 0x3333333333333333) << 2) | ((n >> 2) & 0x3333333333333333)
51
+ n = ((n & 0x0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f)
52
+ n = ((n & 0x00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff)
53
+ n = ((n & 0x0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff)
54
+ return ((n & 0x00000000ffffffff) << 32) | (n >> 32) # 0x00000000ffffffff
55
+ end
56
+
57
+ def bitreflect128(n)
58
+ n = n.to_i
59
+ n = ((n & 0x55555555555555555555555555555555) << 1) | ((n >> 1) & 0x55555555555555555555555555555555)
60
+ n = ((n & 0x33333333333333333333333333333333) << 2) | ((n >> 2) & 0x33333333333333333333333333333333)
61
+ n = ((n & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f)
62
+ n = ((n & 0x00ff00ff00ff00ff00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff00ff00ff00ff00ff)
63
+ n = ((n & 0x0000ffff0000ffff0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff0000ffff0000ffff)
64
+ n = ((n & 0x00000000ffffffff00000000ffffffff) << 32) | ((n >> 32) & 0x00000000ffffffff00000000ffffffff)
65
+ return ((n & 0x0000000000000000ffffffffffffffff) << 64) | (n >> 64) # 0x0000000000000000ffffffffffffffff
66
+ end
67
+ end
68
+
69
+ class Generator < Struct.new(:bitsize, :bitmask, :polynomial, :initial_state, :table8, :reflect_input, :reflect_output, :xor_output, :name)
70
+ BasicStruct = superclass
71
+
72
+ def initialize(bitsize, polynomial, initial_state = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
73
+ bitsize = bitsize.to_i
74
+ if bitsize < 1 || bitsize > 64
75
+ raise ArgumentError, "wrong bitsize (except 1..64, but given #{bitsize})"
76
+ end
77
+ bitmask = ~(~0 << bitsize)
78
+ polynomial = bitmask & polynomial
79
+ initial_state = bitmask & initial_state
80
+ xor_output = bitmask & xor_output
81
+ name = (name.nil? || ((name = String(name)).empty?)) ? nil : name
82
+ super(bitsize, bitmask, polynomial, initial_state, nil,
83
+ !!reflect_input, !!reflect_output, xor_output, name)
84
+ end
85
+
86
+ def update_with_reference(seq, state)
87
+ if reflect_input
88
+ poly = CRC.bitreflect(polynomial, bitsize)
89
+ seq.each_byte do |ch|
90
+ state ^= ch
91
+ 8.times { state = (state[0] == 0) ? (state >> 1) : ((state >> 1) ^ poly) }
92
+
93
+ # 8.times { state = (state >> 1) ^ (poly & -state[0]) }
94
+ # NOTE: ruby だと、分岐したほうが2割くらい高速
95
+ end
96
+
97
+ state
98
+ else
99
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
100
+ seq.each_byte do |ch|
101
+ s ^= ch << csh
102
+ 8.times { s = (s[head] == 0) ? (s << 1) : (((carries & s) << 1) ^ poly) }
103
+ end
104
+
105
+ s
106
+ end
107
+ end
108
+ end
109
+
110
+ def update_with_lookup_table(seq, state)
111
+ t = table8[0]
112
+
113
+ if reflect_input
114
+ String(seq).each_byte do |ch|
115
+ state = t[state & 0xff ^ ch] ^ (state >> 8)
116
+ end
117
+ state
118
+ else
119
+ Aux.slide_to_head(bitsize, state, polynomial, bitmask) do |s, poly, csh, head, carries|
120
+ carries8 = carries >> 7
121
+ String(seq).each_byte do |ch|
122
+ s = t[(s >> csh) ^ ch] ^ ((carries8 & s) << 8)
123
+ end
124
+ s
125
+ end
126
+ end
127
+ end
128
+
129
+ def update_with_slice_by_eight(seq, s)
130
+ tX = table8
131
+ t0 = tX[ 0]; t1 = tX[ 1]; t2 = tX[ 2]; t3 = tX[ 3]
132
+ t4 = tX[ 4]; t5 = tX[ 5]; t6 = tX[ 6]; t7 = tX[ 7]
133
+ t8 = tX[ 8]; t9 = tX[ 9]; tA = tX[10]; tB = tX[11]
134
+ tC = tX[12]; tD = tX[13]; tE = tX[14]; tF = tX[15]
135
+
136
+ i = 0
137
+ ii = seq.bytesize
138
+ iii = ii & ~15
139
+
140
+ if reflect_input
141
+ if bitsize <= 32
142
+ # speed improvement for 32-bits CRC
143
+ while i < iii
144
+ s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
145
+ tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) & 0xff] ^
146
+ tB[seq.getbyte(i + 4) ] ^ tA[seq.getbyte(i + 5) ] ^
147
+ t9[seq.getbyte(i + 6) ] ^ t8[seq.getbyte(i + 7) ] ^
148
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
149
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
150
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
151
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
152
+ i += 16
153
+ end
154
+ else
155
+ while i < iii
156
+ s = tF[seq.getbyte(i ) ^ (s ) & 0xff] ^ tE[seq.getbyte(i + 1) ^ (s >> 8) & 0xff] ^
157
+ tD[seq.getbyte(i + 2) ^ (s >> 16) & 0xff] ^ tC[seq.getbyte(i + 3) ^ (s >> 24) & 0xff] ^
158
+ tB[seq.getbyte(i + 4) ^ (s >> 32) & 0xff] ^ tA[seq.getbyte(i + 5) ^ (s >> 40) & 0xff] ^
159
+ t9[seq.getbyte(i + 6) ^ (s >> 48) & 0xff] ^ t8[seq.getbyte(i + 7) ^ (s >> 56) & 0xff] ^
160
+ t7[seq.getbyte(i + 8) ] ^ t6[seq.getbyte(i + 9) ] ^
161
+ t5[seq.getbyte(i + 10) ] ^ t4[seq.getbyte(i + 11) ] ^
162
+ t3[seq.getbyte(i + 12) ] ^ t2[seq.getbyte(i + 13) ] ^
163
+ t1[seq.getbyte(i + 14) ] ^ t0[seq.getbyte(i + 15) ]
164
+ i += 16
165
+ end
166
+ end
167
+
168
+ (iii...ii).each do |n|
169
+ s = t0[seq.getbyte(n) ^ s & 0xff] ^ (s >> 8)
170
+ end
171
+
172
+ s
173
+ else
174
+ Aux.slide_to_head(bitsize, s, polynomial, bitmask) do |s, poly, csh, head, carries|
175
+ sh = 64 - (head + 1)
176
+
177
+ while i < iii
178
+ s <<= sh
179
+ s = t7[seq.getbyte(i ) ^ (s >> 56) & 0xff] ^ t6[seq.getbyte(i + 1) ^ (s >> 48) & 0xff] ^
180
+ t5[seq.getbyte(i + 2) ^ (s >> 40) & 0xff] ^ t4[seq.getbyte(i + 3) ^ (s >> 32) & 0xff] ^
181
+ t3[seq.getbyte(i + 4) ^ (s >> 24) & 0xff] ^ t2[seq.getbyte(i + 5) ^ (s >> 16) & 0xff] ^
182
+ t1[seq.getbyte(i + 6) ^ (s >> 8) & 0xff] ^ t0[seq.getbyte(i + 7) ^ (s >> 0) & 0xff]
183
+ i += 8
184
+ end
185
+
186
+ carries8 = carries >> 7
187
+ (iii...ii).each do |n|
188
+ s = t0[(s >> csh) ^ seq.getbyte(n)] ^ ((carries8 & s) << 8)
189
+ end
190
+ s
191
+ end
192
+ end
193
+ end
194
+
195
+ def table8
196
+ unless t = super
197
+ if reflect_input
198
+ set_table8 t = CRC.build_table8!(bitsize, polynomial)
199
+ else
200
+ set_table8 t = CRC.build_table8(bitsize, polynomial)
201
+ end
202
+ end
203
+
204
+ define_singleton_method :table8, self.class.superclass.instance_method(:table8)
205
+
206
+ t
207
+ end
208
+
209
+ case ENV["RUBY_CRC_NOFAST"].to_i
210
+ when 0, 1
211
+ alias update update_with_slice_by_eight
212
+ when 2
213
+ alias update update_with_lookup_table
214
+ else
215
+ alias update update_with_reference
216
+ end
217
+
218
+ class BasicStruct
219
+ alias set_table8 table8=
220
+ private :set_table8
221
+
222
+ undef :bitsize=, :bitmask=, :polynomial=, :initial_state=, :table8=,
223
+ :reflect_input=, :reflect_output=, :xor_output=, :name=, :[]=
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,105 @@
1
+ #!ruby
2
+
3
+ module CRC
4
+
5
+ #
6
+ # references from:
7
+ # * https://en.wikipedia.org/wiki/Cyclic_redundancy_check
8
+ # * https://ja.wikipedia.org/wiki/%E5%B7%A1%E5%9B%9E%E5%86%97%E9%95%B7%E6%A4%9C%E6%9F%BB
9
+ # * http://reveng.sourceforge.net/crc-catalogue/all.htm
10
+ # * http://crcmod.sourceforge.net/crcmod.predefined.html
11
+ # * https://users.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf
12
+ #
13
+
14
+ list = [
15
+ #
16
+ # module name, polynomial, refrect input,
17
+ # bit size, reflect output,
18
+ # initial state, xor external, crc("123456789"), alias names...
19
+ #
20
+ [:CRC1, 0x01, 1, 0, true, true, ~0, nil, "CRC-1"],
21
+ [:CRC3_ROHC, 0x03, 3, ~0, true, true, 0, 0x06, "CRC-3-ROHC"],
22
+ [:CRC4_ITU, 0x03, 4, 0, true, true, 0, 0x07, "CRC-4-ITU"],
23
+ [:CRC5_EPC, 0x09, 5, 0x09, false, false, 0, 0x00, "CRC-5-EPC"],
24
+ [:CRC5_ITU, 0x15, 5, 0, true, true, 0, 0x07, "CRC-5-ITU"],
25
+ [:CRC5_USB, 0x05, 5, 0, true, true, ~0, 0x19, "CRC-5-USB"],
26
+ [:CRC6_CDMA2000_A, 0x27, 6, ~0, false, false, 0, 0x0D, "CRC-6-CDMA2000-A"],
27
+ [:CRC6_CDMA2000_B, 0x07, 6, ~0, false, false, 0, 0x3B, "CRC-6-CDMA2000-B"],
28
+ [:CRC6_DARC, 0x19, 6, 0, true, true, 0, 0x26, "CRC-6-DARC"],
29
+ [:CRC6_ITU, 0x03, 6, 0, true, true, 0, 0x06, "CRC-6-ITU"],
30
+ [:CRC7, 0x09, 7, 0, false, false, 0, 0x75, "CRC-7"],
31
+ [:CRC7_MVB, 0x65, 7, 0, true, true, ~0, nil, "CRC-7-MVB"],
32
+ [:CRC8, 0xD5, 8, 0, true, true, ~0, nil, "CRC-8"],
33
+ [:CRC8_CCITT, 0x07, 8, 0, true, true, ~0, nil, "CRC-8-CCITT"],
34
+ [:CRC8_DALLAS_MAXIM, 0x31, 8, 0, true, true, ~0, nil, "CRC-8-Dallas/Maxim"],
35
+ [:CRC8_DARC, 0x39, 8, 0, true, true, 0, 0x15, "CRC-8-DARC"],
36
+ [:CRC8_SAE, 0x1D, 8, 0, true, true, ~0, nil, "CRC-8-SAE"],
37
+ [:CRC8_WCDMA, 0x9B, 8, 0, true, true, 0, 0x25, "CRC-8-WCDMA"],
38
+ [:CRC10, 0x0233, 10, 0, false, false, 0, 0x0199, "CRC-10"],
39
+ [:CRC10_CDMA2000, 0x03D9, 10, ~0, false, false, 0, 0x0233, "CRC-10-CDMA2000"],
40
+ [:CRC11, 0x0385, 11, 0x1a, false, false, 0, 0x05a3, "CRC-11"],
41
+ [:CRC12, 0x080F, 12, 0, false, true, 0, 0x0daf, "CRC-12"],
42
+ [:CRC12_CDMA2000, 0x0F13, 12, ~0, false, false, 0, 0x0d4d, "CRC-12-CDMA2000"],
43
+ [:CRC13_BBC, 0x1CF5, 13, 0, false, false, 0, 0x04fa, "CRC-13-BBC"],
44
+ [:CRC14_DARC, 0x0805, 14, 0, true, true, 0, 0x082d, "CRC-14-DARC"],
45
+ [:CRC15_CAN, 0x4599, 15, 0, false, false, 0, 0x059e, "CRC-15-CAN"],
46
+ [:CRC15_MPT1327, 0x6815, 15, 1, false, false, 1, nil, "CRC-15-MPT1327"],
47
+ [:CHAKRAVARTY, 0x2F15, 16, 0, true, true, ~0, nil, "Chakravarty"],
48
+ [:CRC16_ARINC, 0xA02B, 16, 0, true, true, ~0, nil, "CRC-16-ARINC"],
49
+ [:CRC16_CCITT, 0x1021, 16, 0, true, true, ~0, nil, "CRC-16-CCITT", "CRC-CCITT"],
50
+ [:CRC16_CDMA2000, 0xC867, 16, 0, true, true, ~0, nil, "CRC-16-CDMA2000"],
51
+ [:CRC16_DECT, 0x0589, 16, 0, true, true, ~0, nil, "CRC-16-DECT"],
52
+ [:CRC16_T10_DIF, 0x8BB7, 16, 0, true, true, ~0, nil, "CRC-16-T10-DIF"],
53
+ [:CRC16_DNP, 0x3D65, 16, 0, true, true, ~0, nil, "CRC-16-DNP"],
54
+ [:CRC16_IBM, 0x8005, 16, 0, true, true, ~0, nil, "CRC-16-IBM", "CRC-16", "CRC-16-ANSI"],
55
+ [:CRC16_LZH, 0x8005, 16, 0, true, true, 0, 0xBB3D, "CRC-16-LZH", "CRC-LZH"],
56
+ [:CRC17_CAN, 0x0001685B, 17, 0, true, true, ~0, nil, "CRC-17-CAN"],
57
+ [:CRC21_CAN, 0x00102899, 21, 0, true, true, ~0, nil, "CRC-21-CAN"],
58
+ [:CRC24, 0x005D6DCB, 24, 0, true, true, ~0, nil, "CRC-24"],
59
+ [:CRC24_RADIX_64, 0x00864CFB, 24, 0, true, true, ~0, nil, "CRC-24-Radix-64"],
60
+ [:CRC30, 0x2030B9C7, 30, 0, true, true, ~0, nil, "CRC-30"],
61
+ [:CRC32, 0x04c11db7, 32, 0, true, true, ~0, 0xCBF43926, "CRC-32"],
62
+ [:CRC32C, 0x1edc6f41, 32, 0, true, true, ~0, 0xE3069283, "CRC-32C"],
63
+ [:CRC32K, 0x741B8CD7, 32, 0, true, true, ~0, nil, "CRC-32K"],
64
+ [:CRC32K2, 0x32583499, 32, 0, true, true, ~0, nil, "CRC-32K2"],
65
+ [:CRC32Q, 0x814141AB, 32, 0, false, false, 0, 0x3010BF7F, "CRC-32Q"],
66
+ [:CRC40_GSM, 0x0000000004820009, 40, ~0, false, false, ~0, 0xD4164FC646, "CRC-40-GSM"],
67
+ [:CRC64_ECMA, 0x42F0E1EBA9EA3693, 64, 0, true, true, ~0, 0x995DC9BBDF1939FA, "CRC-64-ECMA", "CRC-64"],
68
+ [:CRC64_ISO, 0x000000000000001B, 64, 0, true, true, ~0, nil, "CRC-64-ISO"],
69
+ ]
70
+
71
+ $stderr.puts "#{__FILE__}:#{__LINE__}: SELF CHECK for CRC modules (#{File.basename($".grep(/\/crc\/_(?:byruby|turbo)/)[0]||"")})\n" if SELF_TEST
72
+ list.each do |name, polynomial, bitsize, initial_state, refin, refout, xor, check, *names|
73
+ names.map! { |nm| nm.freeze }
74
+
75
+ crc = create_module(bitsize, polynomial, initial_state, refin, refout, xor, names[0])
76
+
77
+ const_set(name, crc)
78
+ names.each { |nm| MODULE_TABLE[nm.downcase.gsub(/[\W_]+/, "")] = crc }
79
+
80
+ check = Integer(check.to_i) if check
81
+ crc.const_set :CHECK, check
82
+
83
+ generator = crc::GENERATOR
84
+ define_singleton_method(name.downcase, ->(*args) { generator.crc(*args) })
85
+ define_singleton_method("#{name.downcase}_digest", ->(*args) { generator.digest(*args) })
86
+ define_singleton_method("#{name.downcase}_hexdigest", ->(*args) { generator.hexdigest(*args) })
87
+
88
+ if SELF_TEST
89
+ checked = generator.crc("123456789")
90
+ case
91
+ when check.nil?
92
+ $stderr.puts "| %20s(\"123456789\") = %16X (check only)\n" % [names[0], checked]
93
+ when check != checked
94
+ $stderr.puts "| %20s(\"123456789\") = %16X (expect to %016X)\n" % [names[0], checked, check]
95
+ end
96
+ end
97
+ end
98
+ exit if SELF_TEST
99
+
100
+ class << self
101
+ alias crc64 crc64_ecma
102
+ end
103
+
104
+ CRC64 = CRC64_ECMA
105
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "../crc"
2
+
3
+ module CRC
4
+ def self.find(crc, seq, bitsize, polynomial, initstate = [0, ~0, 1], xor = [0, ~0, 1])
5
+ bitsize0 = bitsize.to_i
6
+ if bitsize0 < 1 || bitsize0 > 128
7
+ raise ArgumentError, "wrong bitsize (expect 1..128, but given #{bitsize})"
8
+ end
9
+ bitmask = ~(~0 << bitsize0)
10
+ crc &= bitmask
11
+ [polynomial, Utils.bitreflect(polynomial, bitsize0)].each do |poly|
12
+ poly &= bitmask
13
+ [false, true].each do |refin|
14
+ [false, true].each do |refout|
15
+ Array(xor).each do |xormask|
16
+ xormask &= bitmask
17
+ Array(initstate).each do |init|
18
+ init &= bitmask
19
+ mod = CRC.create_module(bitsize0, poly, init, refin, refout, xormask)
20
+ return mod if mod.crc(seq) == crc
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ nil
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: crc
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - dearblue
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '11.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '11.0'
27
+ description: |
28
+ This is a general CRC (Cyclic Redundancy Check) generator for ruby.
29
+ It is written by pure ruby with based on slice-by-eight algorithm (byte-order-free slice-by-16 algorithm).
30
+ 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 more.
31
+ And your defined CRC modules to use.
32
+ If you need more speed, please use crc-turbo.
33
+ email: dearblue@users.osdn.me
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files:
37
+ - LICENSE
38
+ - README.md
39
+ - lib/crc.rb
40
+ - lib/crc/_byruby.rb
41
+ - lib/crc/_modules.rb
42
+ - lib/crc/finder.rb
43
+ files:
44
+ - LICENSE
45
+ - README.md
46
+ - Rakefile
47
+ - benchmark.rb
48
+ - gemstub.rb
49
+ - lib/crc.rb
50
+ - lib/crc/_byruby.rb
51
+ - lib/crc/_modules.rb
52
+ - lib/crc/finder.rb
53
+ homepage: https://osdn.jp/projects/rutsubo/
54
+ licenses:
55
+ - BSD-2-Clause
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options:
59
+ - "--charset"
60
+ - UTF-8
61
+ - "-m"
62
+ - README.md
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '2.0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.6.2
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: general CRC generator
81
+ test_files: []
82
+ has_rdoc: