crc 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: