extbzip3 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d337adb887c6e5dbda229b8536addfcd5b5e91af292ff118ae586c94ce90d5c9
4
+ data.tar.gz: feea5218e03eb301e8b346993803572076259f446e8260bd4ff73b882735f85f
5
+ SHA512:
6
+ metadata.gz: b8e1c8883e87f405f263451d479bd00f0ac3bf0631da8d2f19fb3faedac0e342f90815bdc3143c3c772d459778dc6f80df6ee779d751096bf61f432c510463a5
7
+ data.tar.gz: 918a07bcb7f75f91bea44e7e10fe5746d314393ecae805e48484324291cd8c92ddcd3c6900e330b9323273fc79ce54825cffe8d46e2472ec5c677f464bc5b1c4
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2023, 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.
data/README.md ADDED
@@ -0,0 +1,159 @@
1
+ extbzip3 - bzip3 for Ruby
2
+ =========================
3
+
4
+ This document is written in Japanese.
5
+
6
+ [bzip3](https://github.com/kspalaiologos/bzip3) の非公式 Ruby バインディングです。
7
+
8
+
9
+ できること
10
+ ----------
11
+
12
+ - `require "extbzip3"`
13
+ - `Bzip3` module
14
+
15
+ | method | annotation
16
+ | ----- | -----
17
+ | `Bzip3.decode(str, ...)` | see `Bzip3::Decoder.decode`
18
+ | `Bzip3.encode(str, ...)` | see `Bzip3::Encoder.encode`
19
+ | `Bzip3.decode(obj, ...)` | see `Bzip3::Decoder.open`
20
+ | `Bzip3.encode(obj, ...)` | see `Bzip3::Encoder.open`
21
+
22
+ - `Bzip3::Decoder` class
23
+
24
+ | method | annotation
25
+ | ----- | -----
26
+ | `Bzip3::Decoder.decode(str, maxdest = nil, dest = "", *opts)` | returns dest with bzip3 decoded
27
+ | `Bzip3::Decoder.decode(str, dest, *opts)` | returns dest with bzip3 decoded
28
+ | `Bzip3::Decoder.open(obj, *opts)` | returns bzip3 decoder
29
+ | `Bzip3::Decoder.open(obj, *opts) { \|decoder\| ... }` | returns object from yield returned
30
+ | `Bzip3::Decoder#read(size = nil, dest = "")` | returns dest with bzip3 decoded
31
+ | `Bzip3::Decoder#close` |
32
+ | `Bzip3::Decoder#eof?` |
33
+
34
+ - `Bzip3::Encoder` class
35
+
36
+ | method | annotation
37
+ | ----- | -----
38
+ | `Bzip3::Encoder.encode(str, maxdest = nil, dest = "", *opts)` | returns dest with bzip3'ed sequence
39
+ | `Bzip3::Encoder.encode(str, dest, *opts)` | returns dest with bzip3'ed sequence
40
+ | `Bzip3::Encoder.open(obj, *opts)` | returns bzip3 encoder
41
+ | `Bzip3::Encoder.open(obj, *opts) { \|encoder\| ... }` | returns object from yield returned
42
+ | `Bzip3::Encoder#write(src)` | returns receiver
43
+ | `Bzip3::Encoder#flush` | returns receiver
44
+ | `Bzip3::Encoder#close` |
45
+ | `Bzip3::Encoder#eof?` |
46
+
47
+ - `Bzip3::BlockProcessor` class
48
+
49
+ | method | annotation
50
+ | ----- | -----
51
+ | `Bzip3::BlockProcessor.new(blocksize)` |
52
+ | `Bzip3::BlockProcessor#decode(src, dest, original_size)` | returns `dest` string as original data
53
+ | `Bzip3::BlockProcessor#encode(src, dest)` | returns `dest` string as bzip3'ed data
54
+ | `Bzip3::BlockProcessor#blocksize` | returns `blocksize` integer with when `new`
55
+
56
+ - `using Bzip3` (refinements)
57
+
58
+ | method | annotation
59
+ | ----- | -----
60
+ | `String#to_bzip3(...)` | see `Bzip3::Encoder.encode`
61
+ | `String#bunzip3(...)` | see `Bzip3::Decoder.decode`
62
+ | `Object#to_bzip3(...)` | see `Bzip3::Encoder.open`
63
+ | `Object#bunzip3(...)` | see `Bzip3::Decoder.open`
64
+
65
+ ### データ形式について
66
+
67
+ - extbzip3 は [「bzip3 ファイル形式」](https://github.com/kspalaiologos/bzip3/blob/1.3.1/doc/file_format.md) を標準で扱います。
68
+ 利用者は特別な操作や指定を行う必要がありません。
69
+ - extbzip3 は [「bzip3 ブロック形式」](https://github.com/kspalaiologos/bzip3/blob/1.3.1/doc/low_level_format.md) を扱うことも出来ます。
70
+ `Bzip3::BlockProcessor` クラスを使ってください。
71
+ - extbzip3 は [「bzip3 フレーム形式」](https://github.com/kspalaiologos/bzip3/blob/1.3.1/doc/high_level_format.md) を扱うことも出来ます。
72
+ 文字列を圧縮・伸長する特異メソッド `Bzip3::Encoder.encode` または `Bzip3::Decoder.decode` にキーワード引数として `format: Bzip3::V1_FRAME_FORMAT` を与えてください。
73
+ ストリーム指向 API を「bzip3 フレーム形式」に対応させる予定はありません。
74
+
75
+
76
+ つかいかた
77
+ ----------
78
+
79
+ ### 導入
80
+
81
+ 事前にシステム上へ [bzip3](https://github.com/kspalaiologos/bzip3) をインストールしてください。
82
+
83
+ ```console
84
+ % sudo gem install extbzip3
85
+ ```
86
+
87
+ ### 単発圧縮・伸長
88
+
89
+ ```ruby
90
+ require "extbzip3"
91
+
92
+ src = "123456789"
93
+ bin = Bzip3.encode(src)
94
+ # => "BZ3v1\x00\x00\x10\x00\x11\x00\x00\x00\t\x00\x00\x00'F\xE3\xEB\xFF\xFF\xFF\xFF123456789"
95
+ src1 = Bzip3.decode(bin)
96
+ # => "123456789"
97
+ ```
98
+
99
+ ### ストリーミング圧縮と伸長
100
+
101
+ ```ruby
102
+ require "extbzip3"
103
+
104
+ # 圧縮処理してファイルとして出力
105
+ File.open("/boot/kernel/kernel", "rb") do |src|
106
+ File.open("kernel.bz3", "wb") do |dest|
107
+ Bzip3.encode(dest) do |bz3|
108
+ buf = ""
109
+ bz3.write buf while src.read(123456, buf)
110
+ end
111
+ end
112
+ end
113
+
114
+ # 伸張処理してファイルとして出力
115
+ File.open("kernel.bz3", "rb") do |src|
116
+ File.open("kernel.1", "wb") do |dest|
117
+ Bzip3.decode(src) do |bz3|
118
+ buf = ""
119
+ dest.write buf while bz3.read(123456, buf)
120
+ end
121
+ end
122
+ end
123
+
124
+ # ファイルの比較
125
+ system "md5 /boot/kernel/kernel kernel.1"
126
+ # => MD5 (/boot/kernel/kernel) = 71b8f6c6a29f4d647f45d9501d549cf3
127
+ # => MD5 (kernel.1) = 71b8f6c6a29f4d647f45d9501d549cf3
128
+ ```
129
+
130
+ ### bzip3 フレーム形式による単発圧縮・伸長
131
+
132
+ ```ruby
133
+ require "extbzip3"
134
+
135
+ src = "123456789"
136
+ bin = Bzip3.encode(src, format: Bzip3::V1_FRAME_FORMAT)
137
+ # => "BZ3v1\x00\x00\x10\x00\x01\x00\x00\x00\x11\x00\x00\x00\t\x00\x00\x00'F\xE3\xEB\xFF\xFF\xFF\xFF123456789"
138
+ src1 = Bzip3.decode(bin, format: Bzip3::V1_FRAME_FORMAT)
139
+ # => "123456789"
140
+ ```
141
+
142
+
143
+ しょげん
144
+ --------
145
+
146
+ - Project page: <https://github.com/dearblue/ruby-extbzip3>
147
+ - Licensing: [2-clause BSD License](LICENSE) by [dearblue](https://github.com/dearblue)
148
+ - Version: 0.0.1
149
+ - Project status: CONCEPT
150
+ - Dependency gems: none
151
+ - Dependency external C libraries:
152
+ - [bzip3](https://github.com/kspalaiologos/bzip3)
153
+ version 1.3.2 or later
154
+ under [GNU Lesser General Public License version 3 or later](https://github.com/kspalaiologos/bzip3/blob/master/LICENSE)
155
+ by [Kamila Szewczyk](https://github.com/kspalaiologos)
156
+ and [Apache License, Version 2.0](https://github.com/kspalaiologos/bzip3/blob/master/libsais-LICENSE)
157
+ by [Ilya Grebnov](https://github.com/IlyaGrebnov)
158
+ and [Kamila Szewczyk](https://github.com/kspalaiologos)
159
+ - Bundled external C libraries: none
data/Rakefile ADDED
@@ -0,0 +1,247 @@
1
+
2
+ require "pathname"
3
+ require "rake/clean"
4
+
5
+ RUBYSET ||= (ENV["RUBYSET"] || "").split(",").yield_self { |me| me.empty? ? nil : me }
6
+
7
+ docnames = "{README,LICENSE,CHANGELOG,Changelog,HISTORY}"
8
+ doctypes = "{,.txt,.rd,.rdoc,.md,.markdown}"
9
+ cexttypes = "{c,C,cc,cxx,cpp,h,H,hh}"
10
+
11
+ DOC = FileList["#{docnames}{,.ja}#{doctypes}"] +
12
+ FileList["{contrib,ext}/**/#{docnames}{,.ja}#{doctypes}"] +
13
+ FileList["ext/**/*.#{cexttypes}"]
14
+ EXT = FileList["ext/**/*"]
15
+ BIN = FileList["bin/*"]
16
+ LIB = FileList["lib/**/*.rb"]
17
+ SPEC = FileList["spec/**/*"]
18
+ TEST = FileList["test/**/*"]
19
+ EXAMPLE = FileList["examples/**/*"]
20
+ GEMSTUB_SRC = "gemstub.rb"
21
+ RAKEFILE = [File.basename(__FILE__), GEMSTUB_SRC]
22
+ EXTRA = []
23
+ EXTCONF = FileList["ext/**/extconf.rb"]
24
+ EXTCONF.reject! { |n| !File.file?(n) }
25
+ EXTMAP = {}
26
+
27
+ load GEMSTUB_SRC
28
+
29
+ EXTMAP.dup.each_pair do |dir, name|
30
+ EXTMAP[Pathname.new(dir).cleanpath.to_s] = Pathname.new(name).cleanpath.to_s
31
+ end
32
+
33
+ GEMSTUB.extensions += EXTCONF
34
+ GEMSTUB.executables += FileList["bin/*"].map { |n| File.basename n }
35
+ GEMSTUB.executables.sort!
36
+
37
+ PACKAGENAME = "#{GEMSTUB.name}-#{GEMSTUB.version}"
38
+ GEMFILE = "#{PACKAGENAME}.gem"
39
+ GEMSPEC = "#{PACKAGENAME}.gemspec"
40
+ BUNDLER_GEMFILE = "Gemfile"
41
+
42
+ GEMSTUB.files += DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + EXTRA
43
+ GEMSTUB.files.sort!
44
+ if GEMSTUB.rdoc_options.nil? || GEMSTUB.rdoc_options.empty?
45
+ readme = %W(.md .markdown .rd .rdoc .txt #{""}).map { |ext| "README#{ext}" }.find { |m| DOC.find { |n| n == m } }
46
+ GEMSTUB.rdoc_options = %w(--charset UTF-8) + (readme ? %W(-m #{readme}) : [])
47
+ end
48
+ GEMSTUB.extra_rdoc_files += DOC + LIB + EXT.reject { |n| n.include?("/externals/") || !%w(.h .hh .c .cc .cpp .cxx).include?(File.extname(n)) }
49
+ GEMSTUB.extra_rdoc_files.sort!
50
+
51
+ GEMSTUB_TRYOUT = GEMSTUB.dup
52
+ GEMSTUB_TRYOUT.version = "#{GEMSTUB.version}#{Time.now.strftime(".TRYOUT.%Y%m%d.%H%M%S")}"
53
+ PACKAGENAME_TRYOUT = "#{GEMSTUB.name}-#{GEMSTUB_TRYOUT.version}"
54
+ GEMFILE_TRYOUT = "#{PACKAGENAME_TRYOUT}.gem"
55
+ GEMSPEC_TRYOUT = "#{PACKAGENAME_TRYOUT}.gemspec"
56
+
57
+ CLEAN << GEMSPEC << GEMSPEC_TRYOUT
58
+ CLOBBER << GEMFILE
59
+
60
+ task :default => :tryout do
61
+ $stderr.puts <<-EOS
62
+ #{__FILE__}:#{__LINE__}:
63
+ \ttype ``rake release'' to build release package.
64
+ EOS
65
+ end
66
+
67
+ desc "build tryout package"
68
+ task :tryout
69
+
70
+ desc "build release package"
71
+ task :release => :all
72
+
73
+ unless EXTCONF.empty?
74
+ if RUBYSET.nil?
75
+ $stderr.puts <<-EOS
76
+ #{__FILE__}:
77
+ |
78
+ | If you want binary gem package, launch rake with ``RUBYSET`` enviroment
79
+ | variable for set ruby interpreters by comma separated.
80
+ |
81
+ | e.g.) $ rake RUBYSET=ruby
82
+ | or) $ rake RUBYSET=ruby21,ruby22,ruby23
83
+ |
84
+ EOS
85
+ else
86
+ platforms = RUBYSET.map { |ruby| `#{ruby} --disable-gems -e "puts RUBY_PLATFORM"`.chomp }
87
+ platforms1 = platforms.uniq
88
+ unless platforms1.size == 1 && !platforms1[0].empty?
89
+ abort <<-EOS
90
+ #{__FILE__}:#{__LINE__}: different platforms:
91
+ #{RUBYSET.zip(platforms).map { |ruby, platform| "%24s => %s" % [ruby, platform] }.join("\n")}
92
+ ABORTED.
93
+ EOS
94
+ end
95
+ PLATFORM = platforms1[0]
96
+
97
+ RUBY_VERSIONS = RUBYSET.map do |ruby|
98
+ ver = `#{ruby} --disable-gems -e "puts RUBY_VERSION"`.slice(/\d+\.\d+/)
99
+ raise "failed ruby checking - ``#{ruby}''" unless $?.success?
100
+ [ver, ruby]
101
+ end
102
+
103
+ SOFILES_SET = RUBY_VERSIONS.map { |(ver, ruby)|
104
+ EXTCONF.map { |extconf|
105
+ extdir = Pathname.new(extconf).cleanpath.dirname.to_s
106
+ case
107
+ when soname = EXTMAP[extdir.sub(/^ext\//i, "")]
108
+ soname = soname.sub(/\.so$/i, "")
109
+ when extdir == "ext" || extdir == "."
110
+ soname = GEMSTUB.name
111
+ else
112
+ soname = File.basename(extdir)
113
+ end
114
+
115
+ [ruby, File.join("lib", "#{soname.sub(/(?<=\/)|^(?!.*\/)/, "#{ver}/")}.so"), extconf]
116
+ }
117
+ }.flatten(1)
118
+ SOFILES = SOFILES_SET.map { |(ruby, sopath, extconf)| sopath }
119
+
120
+ GEMSTUB_NATIVE = GEMSTUB.dup
121
+ GEMSTUB_NATIVE.files += SOFILES
122
+ GEMSTUB_NATIVE.platform = Gem::Platform.new(PLATFORM).to_s
123
+ GEMSTUB_NATIVE.extensions.clear
124
+ GEMFILE_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.version}-#{GEMSTUB_NATIVE.platform}.gem"
125
+ GEMSPEC_NATIVE = "#{GEMSTUB_NATIVE.name}-#{GEMSTUB_NATIVE.platform}.gemspec"
126
+
127
+ task :all => ["native-gem", GEMFILE]
128
+
129
+ desc "build binary gem package"
130
+ task "native-gem" => GEMFILE_NATIVE
131
+
132
+ desc "generate binary gemspec"
133
+ task "native-gemspec" => GEMSPEC_NATIVE
134
+
135
+ file GEMFILE_NATIVE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + SOFILES + RAKEFILE + [GEMSPEC_NATIVE] do
136
+ sh "gem build #{GEMSPEC_NATIVE}"
137
+ end
138
+
139
+ file GEMSPEC_NATIVE => RAKEFILE do
140
+ File.write(GEMSPEC_NATIVE, GEMSTUB_NATIVE.to_ruby, mode: "wb")
141
+ end
142
+
143
+ desc "build c-extension libraries"
144
+ task "sofiles" => SOFILES
145
+
146
+ task "test" => SOFILES
147
+
148
+ SOFILES_SET.each do |(ruby, soname, extconf)|
149
+ sodir = File.dirname(soname)
150
+ makefile = File.join(sodir, "Makefile")
151
+
152
+ CLEAN << GEMSPEC_NATIVE << sodir
153
+ CLOBBER << GEMFILE_NATIVE
154
+
155
+ directory sodir
156
+
157
+ desc "generate Makefile for binary extension library"
158
+ file makefile => [sodir, extconf] do
159
+ rel_extconf = Pathname.new(extconf).relative_path_from(Pathname.new(sodir)).to_s
160
+ cd sodir do
161
+ sh *%W"#{ruby} #{rel_extconf} --ruby=#{ruby} #{ENV["EXTCONF"]}"
162
+ end
163
+ end
164
+
165
+ desc "build binary extension library"
166
+ file soname => [makefile] + EXT do
167
+ cd sodir do
168
+ sh "make"
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+
175
+
176
+ task :all => GEMFILE
177
+ task :tryout => GEMFILE_TRYOUT
178
+
179
+ desc "generate local rdoc"
180
+ task :rdoc => DOC + LIB do
181
+ sh *(%w(rdoc) + GEMSTUB.rdoc_options + DOC + LIB)
182
+ end
183
+
184
+ desc "launch rspec"
185
+ task rspec: :all do
186
+ sh "rspec"
187
+ end
188
+
189
+ desc "test library"
190
+ task "test" do
191
+ (RUBYSET || ["ruby"]).each do |ruby|
192
+ lib = File.join(__dir__, "lib")
193
+ dir2 = __dir__.gsub(/[\[\{\*\?]/) { |m| "\\#{m}" }
194
+ Dir.glob(File.join(dir2, "test/**/test_*.rb")) do |test|
195
+ sh *%W(#{ruby} -I#{lib} #{test})
196
+ end
197
+ end
198
+ end
199
+
200
+ desc "build gem package"
201
+ task gem: GEMFILE
202
+
203
+ desc "generate gemspec"
204
+ task gemspec: GEMSPEC
205
+
206
+ desc "print package name"
207
+ task "package-name" do
208
+ puts PACKAGENAME
209
+ end
210
+
211
+ desc "generate Gemfile for bundler"
212
+ task "gemfile" => BUNDLER_GEMFILE
213
+
214
+ file GEMFILE => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + [GEMSPEC] do
215
+ sh "gem build #{GEMSPEC}"
216
+ end
217
+
218
+ file GEMFILE_TRYOUT => DOC + EXT + EXTCONF + BIN + LIB + SPEC + TEST + EXAMPLE + RAKEFILE + [GEMSPEC_TRYOUT] do
219
+ #file GEMFILE_TRYOUT do
220
+ sh "gem build #{GEMSPEC_TRYOUT}"
221
+ end
222
+
223
+ file GEMSPEC => RAKEFILE do
224
+ File.write(GEMSPEC, GEMSTUB.to_ruby, mode: "wb")
225
+ end
226
+
227
+ file GEMSPEC_TRYOUT => RAKEFILE do
228
+ File.write(GEMSPEC_TRYOUT, GEMSTUB_TRYOUT.to_ruby, mode: "wb")
229
+ end
230
+
231
+ file BUNDLER_GEMFILE => RAKEFILE do
232
+ File.write(BUNDLER_GEMFILE, <<~GemfileSource, mode: "wb")
233
+ source "https://rubygems.org/"
234
+
235
+ group "default" do
236
+ #{GEMSTUB.runtime_dependencies.map { |e|
237
+ %( gem #{e.name.inspect}, #{e.requirements_list.map { |ee| ee.inspect }.join(", ")})
238
+ }.join("\n")}
239
+ end
240
+
241
+ group "development", "test" do
242
+ #{GEMSTUB.development_dependencies.map { |e|
243
+ %( gem #{e.name.inspect}, #{e.requirements_list.map { |ee| ee.inspect }.join(", ")})
244
+ }.join("\n")}
245
+ end
246
+ GemfileSource
247
+ end
data/ext/compat.h ADDED
@@ -0,0 +1,32 @@
1
+ /*
2
+ * Licensed under Creative Commons Zero License (CC0; Public Domain)
3
+ */
4
+
5
+ #ifndef AUX_COMPAT_H
6
+
7
+ // for older than 2.7.0
8
+ #ifndef RUBY_ASSERT_ALWAYS
9
+ # define RUBY_ASSERT_ALWAYS(...)
10
+ #endif
11
+
12
+ // for older than 3.0.0
13
+ #ifndef TRUE
14
+ # define TRUE 1
15
+ #endif
16
+
17
+ // for older than 3.0.0
18
+ #ifndef RB_EXT_RACTOR_SAFE
19
+ # define RB_EXT_RACTOR_SAFE(FEATURE)
20
+ #endif
21
+
22
+ // for older than 3.2.0
23
+ #ifndef RB_UNDEF_P
24
+ # define RB_UNDEF_P(OBJ) ((OBJ) == Qundef)
25
+ #endif
26
+
27
+ // for older than 3.2.0
28
+ #ifndef RB_NIL_OR_UNDEF_P
29
+ # define RB_NIL_OR_UNDEF_P(OBJ) (RB_NIL_P(OBJ) || RB_UNDEF_P(OBJ))
30
+ #endif
31
+
32
+ #endif // AUX_COMPAT_H
data/ext/extbzip3.c ADDED
@@ -0,0 +1,220 @@
1
+ #include "extbzip3.h"
2
+
3
+ static uint32_t
4
+ aux_version_code(const char *ver)
5
+ {
6
+ uint32_t code = 0;
7
+ const char *o = ver, *p = o;
8
+ int i = 4;
9
+
10
+ while (i > 0) {
11
+ if (*p == '\0' || *p == '.') {
12
+ char *pp = (char *)p;
13
+ unsigned long n = strtoul(o, &pp, 10);
14
+ code = (code << 8) | (uint32_t)n;
15
+ i--;
16
+
17
+ if (*p == '\0' || i <= 1) {
18
+ for (; i > 0; i--) {
19
+ code <<= 8;
20
+ }
21
+
22
+ break;
23
+ }
24
+
25
+ o = p + 1;
26
+ }
27
+
28
+ p++;
29
+ }
30
+
31
+ return code;
32
+ }
33
+
34
+ static VALUE
35
+ version_to_s(VALUE self)
36
+ {
37
+ return rb_iv_get(self, "LIBBZIP3_VERSION");
38
+ }
39
+
40
+ static void
41
+ init_version(VALUE bzip3_module)
42
+ {
43
+ RDOCFAKE(VALUE bzip3_module = rb_define_module("Bzip3"))
44
+
45
+ VALUE libver = rb_ary_new_capa(3);
46
+ const char *bz3ver = bz3_version();
47
+ uint32_t code = aux_version_code(bz3ver);
48
+
49
+ if (code < 0x01030200) {
50
+ const char *e = getenv("RUBY_EXTBZIP3_USE_BZIP3_1_3_1_OR_OLDER");
51
+
52
+ if (!e || strtol(e, NULL, 10) < 1) {
53
+ rb_raise(rb_eLoadError, "%s",
54
+ "YOU ARE USING AN BZIP3-1.3.1 OR OLDER LIBRARY.\n"
55
+ "PLEASE UPDATE TO BZIP3-1.3.2 OR A NEWER LIBRARY ON YOUR SYSTEM.\n"
56
+ "\n"
57
+ "BZIP3-1.3.1 OR OLDER HAS DATA COMPATIBILITY ISSUES.\n"
58
+ "IF YOU WANT TO FORCE THE USE OF EXTBZIP3,\n"
59
+ "PLEASE SET THE FOLLOWING ENVIRONMENT VARIABLES:\n"
60
+ "\n"
61
+ " RUBY_EXTBZIP3_USE_BZIP3_1_3_1_OR_OLDER=1");
62
+ } else {
63
+ rb_warn("%s",
64
+ "YOU ARE USING AN BZIP3-1.3.1 OR OLDER LIBRARY.\n"
65
+ "PLEASE UPDATE TO BZIP3-1.3.2 OR A NEWER LIBRARY ON YOUR SYSTEM.\n"
66
+ "\n"
67
+ "BZIP3-1.3.1 OR OLDER HAS DATA COMPATIBILITY ISSUES.\n"
68
+ "IF YOU CONTINUE USE, YOUR DATA WILL NOT BE ABLE TO BE MIGRATED IN THE FUTURE.");
69
+ }
70
+ }
71
+
72
+ rb_ary_push(libver, INT2FIX((code >> 24) & 0xff));
73
+ rb_ary_push(libver, INT2FIX((code >> 16) & 0xff));
74
+ rb_ary_push(libver, INT2FIX((code >> 8) & 0xff));
75
+
76
+ rb_iv_set(libver, "LIBBZIP3_VERSION", rb_str_new_static(bz3ver, strlen(bz3ver)));
77
+ rb_iv_set(libver, "LIBBZIP3_VERSION_CODE", UINT2NUM(code));
78
+
79
+ rb_define_singleton_method(libver, "to_s", version_to_s, 0);
80
+ rb_obj_freeze(libver);
81
+
82
+ rb_define_const(bzip3_module, "LIBRARY_VERSION", libver);
83
+ }
84
+
85
+ static void
86
+ init_constants(VALUE bzip3_module)
87
+ {
88
+ RDOCFAKE(VALUE bzip3_module = rb_define_module("Bzip3"))
89
+
90
+ rb_define_const(bzip3_module, "V1_FILE_FORMAT", INT2FIX(AUX_BZIP3_V1_FILE_FORMAT));
91
+ rb_define_const(bzip3_module, "V1_FRAME_FORMAT", INT2FIX(AUX_BZIP3_V1_FRAME_FORMAT));
92
+ rb_define_const(bzip3_module, "BLOCKSIZE_MIN", UINT2NUM(65 << 10));
93
+ rb_define_const(bzip3_module, "BLOCKSIZE_MAX", UINT2NUM(511 << 20));
94
+ }
95
+
96
+ struct block_processor
97
+ {
98
+ struct bz3_state *bzip3;
99
+ size_t blocksize;
100
+ };
101
+
102
+ #define BLOCK_PROCESSOR_FREE_BLOCK(P) \
103
+ if ((P)->bzip3) { \
104
+ bz3_free((P)->bzip3); \
105
+ } \
106
+
107
+ #define BLOCK_PROCESSOR_VALUE_FOREACH(DEF)
108
+
109
+ AUX_DEFINE_TYPED_DATA(block_processor, block_processor_allocate, BLOCK_PROCESSOR_FREE_BLOCK, BLOCK_PROCESSOR_VALUE_FOREACH)
110
+
111
+ /*
112
+ * @overload initialize(blocksize)
113
+ */
114
+ static VALUE
115
+ block_processor_initialize(VALUE self, VALUE blocksize)
116
+ {
117
+ struct block_processor *p = get_block_processor_ptr(self);
118
+ if (p->bzip3 != NULL) {
119
+ rb_raise(rb_eTypeError, "wrong re-initializing - %" PRIsVALUE, self);
120
+ }
121
+
122
+ p->blocksize = NUM2UINT(blocksize);
123
+
124
+ if (p->blocksize < AUX_BZIP3_BLOCKSIZE_MIN) {
125
+ p->blocksize = AUX_BZIP3_BLOCKSIZE_MIN;
126
+ } else if (p->blocksize > AUX_BZIP3_BLOCKSIZE_MAX) {
127
+ rb_raise(rb_eRuntimeError, "blocksize too big - %" PRIsVALUE " (expect ..%u)",
128
+ blocksize, AUX_BZIP3_BLOCKSIZE_MAX);
129
+ }
130
+
131
+ p->bzip3 = aux_bz3_new((uint32_t)p->blocksize);
132
+
133
+ return self;
134
+ }
135
+
136
+ static VALUE
137
+ block_processor_blocksize(VALUE self)
138
+ {
139
+ return SIZET2NUM(get_block_processor(self)->blocksize);
140
+ }
141
+
142
+ static VALUE
143
+ block_processor_decode(VALUE self, VALUE src, VALUE dest, VALUE originalsize)
144
+ {
145
+ rb_check_type(src, RUBY_T_STRING);
146
+ rb_check_type(dest, RUBY_T_STRING);
147
+
148
+ struct block_processor *p = get_block_processor(self);
149
+
150
+ size_t origsize = NUM2SIZET(originalsize);
151
+ if (origsize > (size_t)p->blocksize) {
152
+ rb_raise(rb_eRuntimeError, "originalsize too big - %" PRIsVALUE, originalsize);
153
+ }
154
+
155
+ size_t srclen = RSTRING_LEN(src);
156
+ size_t destcapa = bz3_bound((uint32_t)origsize);
157
+ rb_str_modify(dest);
158
+ rb_str_set_len(dest, 0);
159
+ rb_str_modify_expand(dest, destcapa);
160
+
161
+ memmove(RSTRING_PTR(dest), RSTRING_PTR(src), srclen);
162
+ int32_t ret = aux_bz3_decode_block_nogvl(p->bzip3, RSTRING_PTR(dest), srclen, NUM2UINT(originalsize));
163
+ extbzip3_check_error(ret);
164
+
165
+ rb_str_set_len(dest, ret);
166
+
167
+ return dest;
168
+ }
169
+
170
+ static VALUE
171
+ block_processor_encode(VALUE self, VALUE src, VALUE dest)
172
+ {
173
+ rb_check_type(src, RUBY_T_STRING);
174
+ rb_check_type(dest, RUBY_T_STRING);
175
+
176
+ struct block_processor *p = get_block_processor(self);
177
+
178
+ size_t srclen = RSTRING_LEN(src);
179
+ if (srclen > p->blocksize) {
180
+ rb_raise(rb_eRuntimeError, "src too big - #<%" PRIsVALUE ":0x%" PRIxVALUE ">", rb_class_of(src), src);
181
+ }
182
+
183
+ size_t destcapa = bz3_bound((uint32_t)srclen);
184
+ rb_str_modify(dest);
185
+ rb_str_set_len(dest, 0);
186
+ rb_str_modify_expand(dest, (uint32_t)destcapa);
187
+
188
+ memmove(RSTRING_PTR(dest), RSTRING_PTR(src), srclen);
189
+ int32_t ret = aux_bz3_encode_block_nogvl(p->bzip3, RSTRING_PTR(dest), (int32_t)srclen);
190
+ extbzip3_check_error(ret);
191
+
192
+ rb_str_set_len(dest, ret);
193
+
194
+ return dest;
195
+ }
196
+
197
+ static void
198
+ init_processor(VALUE bzip3_module)
199
+ {
200
+ VALUE block_processor_class = rb_define_class_under(bzip3_module, "BlockProcessor", rb_cObject);
201
+ rb_define_alloc_func(block_processor_class, block_processor_allocate);
202
+ rb_define_method(block_processor_class, "initialize", block_processor_initialize, 1);
203
+ rb_define_method(block_processor_class, "blocksize", block_processor_blocksize, 0);
204
+ rb_define_method(block_processor_class, "decode", block_processor_decode, 3);
205
+ rb_define_method(block_processor_class, "encode", block_processor_encode, 2);
206
+ }
207
+
208
+ EXTBZIP3_API void
209
+ Init_extbzip3(void)
210
+ {
211
+ RB_EXT_RACTOR_SAFE(true);
212
+
213
+ VALUE bzip3_module = rb_define_module("Bzip3");
214
+
215
+ init_version(bzip3_module);
216
+ init_constants(bzip3_module);
217
+ init_processor(bzip3_module);
218
+ extbzip3_init_decoder(bzip3_module);
219
+ extbzip3_init_encoder(bzip3_module);
220
+ }