extbzip3 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,344 @@
1
+ #include "extbzip3.h"
2
+
3
+ static inline int
4
+ aux_oneshot_encode(int format, uint32_t blocksize, const void *in, void *out, size_t insize, size_t *outsize)
5
+ {
6
+ if (blocksize < AUX_BZIP3_BLOCKSIZE_MIN) {
7
+ blocksize = AUX_BZIP3_BLOCKSIZE_MIN;
8
+ } else if (blocksize > AUX_BZIP3_BLOCKSIZE_MAX) {
9
+ return BZ3_ERR_INIT;
10
+ }
11
+
12
+ if (!outsize) {
13
+ return BZ3_ERR_INIT;
14
+ }
15
+
16
+ int headersize;
17
+ size_t blockcount;
18
+ if (format == AUX_BZIP3_V1_FILE_FORMAT) {
19
+ headersize = 9;
20
+ blockcount = 0;
21
+ } else {
22
+ headersize = 13;
23
+ blockcount = (insize / blocksize) + ((insize % blocksize != 0) ? 1 : 0);
24
+
25
+ if (blockcount > (UINT32_MAX - 1)) {
26
+ return BZ3_ERR_DATA_TOO_BIG;
27
+ }
28
+ }
29
+
30
+ if (*outsize < (size_t)headersize) {
31
+ return BZ3_ERR_INIT;
32
+ }
33
+
34
+ struct bz3_state *bz3 = bz3_new(blocksize);
35
+ if (bz3 == NULL) {
36
+ return BZ3_ERR_INIT;
37
+ }
38
+
39
+ const uint8_t *inp = (const uint8_t *)in;
40
+ const uint8_t *const inend = inp + insize;
41
+ uint8_t *outp = (uint8_t *)out + headersize;
42
+ uint8_t *const outend = outp + *outsize;
43
+
44
+ while (inend - inp > 0) {
45
+ uint32_t origsize = ((inend - inp) > blocksize) ? blocksize : (uint32_t)(inend - inp);
46
+ uint32_t packedsize = (uint32_t)bz3_bound(origsize); // TODO???: 過剰な値かも?
47
+
48
+ if (outend - outp < packedsize) {
49
+ bz3_free(bz3);
50
+ return BZ3_ERR_DATA_TOO_BIG;
51
+ }
52
+
53
+ outp += 8;
54
+
55
+ memmove(outp, inp, origsize);
56
+ int32_t ret = aux_bz3_encode_block_nogvl(bz3, outp, origsize);
57
+ if (ret < 0) {
58
+ bz3_free(bz3);
59
+ return ret;
60
+ }
61
+
62
+ storeu32le(outp - 8, ret);
63
+ storeu32le(outp - 4, origsize);
64
+
65
+ inp += origsize;
66
+ outp += ret;
67
+ }
68
+
69
+ bz3_free(bz3);
70
+
71
+ *outsize = (size_t)(outp - (const uint8_t *)out);
72
+
73
+ memmove(out, aux_bzip3_signature, sizeof(aux_bzip3_signature));
74
+ storeu32le((char *)out + 5, blocksize);
75
+
76
+ if (format == AUX_BZIP3_V1_FRAME_FORMAT) {
77
+ storeu32le((char *)out + 9, (uint32_t)blockcount);
78
+ }
79
+
80
+ return BZ3_OK;
81
+ }
82
+
83
+ struct encoder
84
+ {
85
+ struct bz3_state *bzip3;
86
+ uint32_t blocksize;
87
+ int firstwrite:1;
88
+ int closed:1;
89
+ VALUE outport;
90
+ VALUE srcbuf;
91
+ VALUE destbuf;
92
+ };
93
+
94
+ #define ENCODER_FREE_BLOCK(P) \
95
+ if ((P)->bzip3) { \
96
+ bz3_free((P)->bzip3); \
97
+ } \
98
+
99
+ #define ENCODER_VALUE_FOREACH(DEF) \
100
+ DEF(outport) \
101
+ DEF(srcbuf) \
102
+ DEF(destbuf) \
103
+
104
+ AUX_DEFINE_TYPED_DATA(encoder, encoder_allocate, ENCODER_FREE_BLOCK, ENCODER_VALUE_FOREACH)
105
+
106
+ /*
107
+ * @overload initialize(blocksize: (16 << 20))
108
+ */
109
+ static VALUE
110
+ encoder_initialize(int argc, VALUE argv[], VALUE self)
111
+ {
112
+ struct { VALUE outport, opts; } args;
113
+ rb_scan_args(argc, argv, "1:", &args.outport, &args.opts);
114
+
115
+ enum { numkw = 1 };
116
+ ID idtab[numkw] = { rb_intern("blocksize") };
117
+ union { struct { VALUE blocksize; }; VALUE vect[numkw]; } opts;
118
+ rb_get_kwargs(args.opts, idtab, 0, numkw, opts.vect);
119
+
120
+ struct encoder *p = (struct encoder *)rb_check_typeddata(self, &encoder_type);
121
+ if (p == NULL || p->bzip3) {
122
+ rb_raise(rb_eTypeError, "wrong initialized or re-initializing - %" PRIsVALUE, self);
123
+ }
124
+
125
+ p->blocksize = aux_conv_to_blocksize(opts.blocksize);
126
+ p->outport = args.outport;
127
+ p->srcbuf = Qnil;
128
+ p->destbuf = Qnil;
129
+ p->bzip3 = aux_bz3_new(p->blocksize);
130
+ p->firstwrite = 1;
131
+
132
+ return self;
133
+ }
134
+
135
+ static VALUE
136
+ encoder_outport(VALUE self)
137
+ {
138
+ return get_encoder(self)->outport;
139
+ }
140
+
141
+ static void
142
+ encoder_write_encode(VALUE self, struct encoder *p, const void *buf, size_t len)
143
+ {
144
+ size_t bufoff = 8 + (p->firstwrite ? 9 : 0);
145
+
146
+ p->destbuf = aux_str_new_recycle(p->destbuf, bufoff + bz3_bound(len));
147
+ rb_str_set_len(p->destbuf, bufoff);
148
+ rb_str_cat(p->destbuf, buf, len);
149
+
150
+ int32_t res = aux_bz3_encode_block_nogvl(p->bzip3, RSTRING_PTR(p->destbuf) + bufoff, RSTRING_LEN(p->destbuf) - bufoff);
151
+
152
+ if (res < 0) {
153
+ extbzip3_check_error(res);
154
+ }
155
+
156
+ rb_str_set_len(p->destbuf, bufoff + res);
157
+ storeu32le(RSTRING_PTR(p->destbuf) + bufoff - 8, res);
158
+ storeu32le(RSTRING_PTR(p->destbuf) + bufoff - 4, (uint32_t)len);
159
+
160
+ if (p->firstwrite) {
161
+ memcpy(RSTRING_PTR(p->destbuf), "BZ3v1", 5);
162
+ storeu32le(RSTRING_PTR(p->destbuf) + 5, p->blocksize);
163
+ p->firstwrite = 0;
164
+ }
165
+
166
+ rb_funcallv(p->outport, rb_intern("<<"), 1, &p->destbuf);
167
+ }
168
+
169
+ static VALUE
170
+ encoder_write(VALUE self, VALUE src)
171
+ {
172
+ struct encoder *p = get_encoder(self);
173
+
174
+ rb_check_type(src, RUBY_T_STRING);
175
+
176
+ size_t srclen = RSTRING_LEN(src);
177
+
178
+ if (srclen <= p->blocksize) {
179
+ if (rb_type_p(p->srcbuf, RUBY_T_STRING)) {
180
+ size_t srcbuflen = RSTRING_LEN(p->srcbuf);
181
+ size_t catlen = srclen + srcbuflen;
182
+
183
+ if (catlen >= p->blocksize) {
184
+ rb_str_cat(p->srcbuf, RSTRING_PTR(src), p->blocksize - srcbuflen);
185
+ encoder_write_encode(self, p, RSTRING_PTR(p->srcbuf), RSTRING_LEN(p->srcbuf));
186
+ rb_str_set_len(p->srcbuf, 0);
187
+ rb_str_cat(p->srcbuf, RSTRING_PTR(src) + p->blocksize - srcbuflen, srclen - (p->blocksize - srcbuflen));
188
+
189
+ return self;
190
+ }
191
+ } else {
192
+ p->srcbuf = rb_str_new(0, 0);
193
+ }
194
+
195
+ rb_str_cat(p->srcbuf, RSTRING_PTR(src), srclen);
196
+
197
+ return self;
198
+ } else {
199
+ size_t srcoff = 0;
200
+
201
+ if (rb_type_p(p->srcbuf, RUBY_T_STRING) && RSTRING_LEN(p->srcbuf) > 0) {
202
+ srcoff = p->blocksize - RSTRING_LEN(p->srcbuf);
203
+ rb_str_cat(p->srcbuf, RSTRING_PTR(src), srcoff);
204
+ encoder_write_encode(self, p, RSTRING_PTR(p->srcbuf), RSTRING_LEN(p->srcbuf));
205
+ rb_str_set_len(p->srcbuf, 0);
206
+ srclen = RSTRING_LEN(src); // maybe changed src with `outport << destbuf`
207
+ if (srclen < srcoff) {
208
+ return self;
209
+ }
210
+ }
211
+
212
+ while (srclen - srcoff > p->blocksize) {
213
+ encoder_write_encode(self, p, RSTRING_PTR(src) + srcoff, p->blocksize);
214
+ srcoff += p->blocksize;
215
+ srclen = RSTRING_LEN(src); // maybe changed src with `outport << destbuf`
216
+ if (srclen < srcoff) {
217
+ return self;
218
+ }
219
+ }
220
+
221
+ if (srcoff < srclen) {
222
+ if (!rb_type_p(p->srcbuf, RUBY_T_STRING)) {
223
+ p->srcbuf = rb_str_new(0, 0);
224
+ }
225
+
226
+ rb_str_cat(p->srcbuf, RSTRING_PTR(src), srclen - srcoff);
227
+ }
228
+
229
+ return self;
230
+ }
231
+ }
232
+
233
+ static VALUE
234
+ encoder_flush(VALUE self)
235
+ {
236
+ struct encoder *p = get_encoder(self);
237
+
238
+ if (rb_type_p(p->srcbuf, RUBY_T_STRING) && RSTRING_LEN(p->srcbuf) > 0) {
239
+ encoder_write_encode(self, p, RSTRING_PTR(p->srcbuf), RSTRING_LEN(p->srcbuf));
240
+ rb_str_set_len(p->srcbuf, 0);
241
+ }
242
+
243
+ return Qnil;
244
+ }
245
+
246
+ static VALUE
247
+ encoder_close(VALUE self)
248
+ {
249
+ struct encoder *p = get_encoder(self);
250
+
251
+ if (rb_type_p(p->srcbuf, RUBY_T_STRING) && RSTRING_LEN(p->srcbuf) > 0) {
252
+ encoder_write_encode(self, p, RSTRING_PTR(p->srcbuf), RSTRING_LEN(p->srcbuf));
253
+ rb_str_set_len(p->srcbuf, 0);
254
+ }
255
+
256
+ p->closed = 1;
257
+
258
+ return Qnil;
259
+ }
260
+
261
+ static VALUE
262
+ encoder_closed_p(VALUE self)
263
+ {
264
+ return get_encoder(self)->closed ? Qtrue : Qfalse;
265
+ }
266
+
267
+ /*
268
+ * @overload encode(src, maxdest = nil, dest = "", **opts)
269
+ * @overload encode(src, dest, **opts)
270
+ *
271
+ * @return [String]
272
+ * dest as decompression data
273
+ * @param [String] src
274
+ * @param [Integer] maxdest
275
+ * @param [String] dest
276
+ * @option opts [Integer] :blocksize ((16 << 20))
277
+ * @option opts :format (Bzip3::V1_FILE_FORMAT)
278
+ * Bzip3::V1_FILE_FORMAT, Bzip3::V1_FRAME_FORMAT
279
+ */
280
+ static VALUE
281
+ encoder_s_encode(int argc, VALUE argv[], VALUE mod)
282
+ {
283
+ size_t insize, outsize;
284
+ struct { VALUE src, maxdest, dest, opts; } args;
285
+ switch (rb_scan_args(argc, argv, "12:", &args.src, &args.maxdest, &args.dest, &args.opts)) {
286
+ case 1:
287
+ insize = RSTRING_LEN(args.src);
288
+ outsize = bz3_bound(insize);
289
+ args.dest = rb_str_buf_new(outsize);
290
+ break;
291
+ case 2:
292
+ insize = RSTRING_LEN(args.src);
293
+
294
+ if (rb_type_p(args.maxdest, RUBY_T_FIXNUM) || rb_type_p(args.maxdest, RUBY_T_BIGNUM)) {
295
+ outsize = NUM2SIZET(args.maxdest);
296
+ args.dest = rb_str_buf_new(outsize);
297
+ } else {
298
+ args.dest = args.maxdest;
299
+ outsize = bz3_bound(insize);
300
+ rb_str_modify(args.dest);
301
+ rb_str_set_len(args.dest, 0);
302
+ rb_str_modify_expand(args.dest, outsize);
303
+ }
304
+
305
+ break;
306
+ case 3:
307
+ insize = RSTRING_LEN(args.src);
308
+ outsize = NUM2SIZET(args.maxdest);
309
+ rb_str_modify(args.dest);
310
+ rb_str_set_len(args.dest, 0);
311
+ rb_str_modify_expand(args.dest, outsize);
312
+
313
+ break;
314
+ }
315
+
316
+ enum { numkw = 2 };
317
+ ID idtab[numkw] = { rb_intern("blocksize"), rb_intern("format") };
318
+ union { struct { VALUE blocksize, format; }; VALUE vect[numkw]; } opts;
319
+ rb_get_kwargs(args.opts, idtab, 0, numkw, opts.vect);
320
+
321
+ uint32_t blocksize = aux_conv_to_blocksize(opts.blocksize);
322
+ int status = aux_oneshot_encode(aux_conv_to_format(opts.format), blocksize,
323
+ RSTRING_PTR(args.src), RSTRING_PTR(args.dest),
324
+ insize, &outsize);
325
+ extbzip3_check_error(status);
326
+ rb_str_set_len(args.dest, outsize);
327
+
328
+ return args.dest;
329
+ }
330
+
331
+ void
332
+ extbzip3_init_encoder(VALUE bzip3_module)
333
+ {
334
+ VALUE encoder_class = rb_define_class_under(bzip3_module, "Encoder", rb_cObject);
335
+ rb_define_alloc_func(encoder_class, encoder_allocate);
336
+ rb_define_singleton_method(encoder_class, "encode", encoder_s_encode, -1);
337
+ rb_define_method(encoder_class, "initialize", encoder_initialize, -1);
338
+ rb_define_method(encoder_class, "outport", encoder_outport, 0);
339
+ rb_define_method(encoder_class, "write", encoder_write, 1);
340
+ rb_define_method(encoder_class, "flush", encoder_flush, 0);
341
+ rb_define_method(encoder_class, "close", encoder_close, 0);
342
+ rb_define_method(encoder_class, "closed?", encoder_closed_p, 0);
343
+ rb_define_alias(encoder_class, "<<", "write");
344
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,43 @@
1
+ #!ruby
2
+
3
+ require "mkmf"
4
+
5
+ using Module.new {
6
+ refine Object do
7
+ def has_function_modifier?(modifier_code)
8
+ try_compile(<<~CODE)
9
+ #{modifier_code}
10
+ void
11
+ func1(void) {
12
+ }
13
+ CODE
14
+ end
15
+ end
16
+ }
17
+
18
+ MakeMakefile::CONFIG["optflags"] = "-O0 -g3" if ENV["RUBY_EXTBZIP3_DEBUG"].to_i > 0
19
+
20
+ have_header("libbz3.h") or abort "need libbz3.h header file"
21
+ have_library("bzip3") or abort "need libbzip3 library"
22
+
23
+ if RbConfig::CONFIG["arch"] =~ /mingw/i
24
+ #$LDFLAGS << " -static-libgcc" if try_ldflags("-static-libgcc")
25
+ else
26
+ if try_compile(<<~"VISIBILITY")
27
+ __attribute__((visibility("hidden"))) int conftest(void) { return 0; }
28
+ VISIBILITY
29
+
30
+ if try_cflags("-fvisibility=hidden")
31
+ $CFLAGS << " -fvisibility=hidden"
32
+ $defs << %(-DEXTBZIP3_API='__attribute__((visibility("default")))')
33
+ end
34
+ end
35
+ end
36
+
37
+ mod = %w(__attribute__((__noreturn__)) __declspec(noreturn) [[noreturn]] _Noreturn).find { |m|
38
+ has_function_modifier?(m)
39
+ }
40
+ $defs << %(-DRBEXT_NORETURN='#{mod}')
41
+
42
+ create_header
43
+ create_makefile File.join(RUBY_VERSION.slice(/\d+\.\d+/), "extbzip3")
data/gemstub.rb ADDED
@@ -0,0 +1,17 @@
1
+ require_relative "lib/extbzip3/version"
2
+
3
+ GEMSTUB = Gem::Specification.new do |s|
4
+ s.name = "extbzip3"
5
+ s.version = Bzip3::VERSION
6
+ s.summary = "ruby bindings for bzip3 (bz3)"
7
+ s.description = <<~DESCRIPT
8
+ unoficial ruby bindings for bzip3 (bz3) <https://github.com/kspalaiologos/bzip3>.
9
+ DESCRIPT
10
+ s.homepage = "https://github.com/dearblue/ruby-extbzip3"
11
+ s.licenses = %w(BSD-2-Clause LGPL-3.0+ Apache-2.0)
12
+ s.author = "dearblue"
13
+ s.email = "dearblue@users.osdn.me"
14
+
15
+ #s.required_ruby_version = ">= 2.0"
16
+ s.add_development_dependency "rake", "~> 0"
17
+ end
@@ -0,0 +1,90 @@
1
+ module Bzip3
2
+ remove_const :Decoder rescue nil
3
+
4
+ class Decoder
5
+ def initialize(inport, blocksize = 16 << 20)
6
+ @bzip3 = BlockProcessor.new(blocksize)
7
+ @inport = inport
8
+ @readbuf = nil
9
+ @destbuf = nil
10
+ @closed = false
11
+ @eof = false
12
+
13
+ self
14
+ end
15
+
16
+ def read(size = nil, buf = "".b)
17
+ buf ||= "".b
18
+ buf[0..-1] = "".b
19
+
20
+ return buf if size == 0
21
+
22
+ size &&= 0 | Integer(0 + size)
23
+
24
+ @readbuf ||= "".b
25
+
26
+ while true
27
+ if @destbuf
28
+ if size && @destbuf.bytesize >= size
29
+ buf << @destbuf.byteslice(0, size)
30
+ @destbuf[0...size] = "".b
31
+ break
32
+ else
33
+ buf << @destbuf
34
+ size -= @destbuf.bytesize if size
35
+ @destbuf[0..-1] = "".b
36
+ end
37
+ else
38
+ @destbuf = "".b
39
+
40
+ (sig, bs) = @inport.read(9)&.unpack("a5V")
41
+ raise "意図しない EOF" unless bs
42
+ raise "シグネチャが違う" unless sig == "BZ3v1"
43
+ raise "おかしなブロックサイズ" unless ((65 << 10) .. (511 << 20)).include? bs
44
+ raise "ブロックサイズがでかすぎ" unless bs <= @bzip3.blocksize
45
+ end
46
+
47
+ unless b1 = @inport.read(8)
48
+ @eof = true
49
+ break
50
+ end
51
+ raise "意図しない EOF" if b1.bytesize < 8
52
+ if b1.byteslice(0, 5) == "BZ3v1"
53
+ b2 = @inport.read(1)
54
+ if b2 && b2.bytesize > 0
55
+ b1 << b2
56
+ bs = b1.unpack1("@5V")
57
+ raise "ブロックサイズがでかすぎ" unless bs <= @bzip3.blocksize
58
+ next
59
+ end
60
+ end
61
+ (packedsize, originsize) = b1.unpack("VV")
62
+ raise "元のデータがデカすぎ" unless originsize <= @bzip3.blocksize
63
+ raise "意図しない EOF" unless @inport.read(packedsize, @readbuf)
64
+ raise "大きさがあってない" unless @readbuf.bytesize == packedsize
65
+ @bzip3.decode(@readbuf, @destbuf, originsize)
66
+ end
67
+
68
+ buf.empty? ? nil : buf
69
+ end
70
+
71
+ def close
72
+ @closed = true
73
+ @bzip3 = nil
74
+ @readbuf = nil
75
+ @destbuf = nil
76
+
77
+ self
78
+ end
79
+
80
+ def closed?
81
+ @closed
82
+ end
83
+
84
+ def eof?
85
+ @eof
86
+ end
87
+
88
+ alias :eof :eof?
89
+ end
90
+ end
@@ -0,0 +1,38 @@
1
+ # This file is for additional documents
2
+
3
+ 0 / 0
4
+
5
+ #
6
+ # Bzip3 module.
7
+ #
8
+ module Bzip3
9
+ #
10
+ # Decoder class.
11
+ #
12
+ class Decoder
13
+ end
14
+
15
+ #
16
+ # Encoder class.
17
+ #
18
+ class Encoder
19
+ end
20
+ end
21
+
22
+ class BasicObject
23
+ # 自身を出力ストリームと見立てて bzip3 を行うエンコーダオブジェクトを生成します。
24
+ def to_bzip3
25
+ end
26
+
27
+ # 自身を入力ストリームと見立てて bunzip3 を行うデコーダオブジェクトを生成します。
28
+ def bunzip3
29
+ end
30
+ end
31
+
32
+ class String
33
+ def to_bzip3
34
+ end
35
+
36
+ def bunzip3
37
+ end
38
+ end
@@ -0,0 +1,8 @@
1
+ module Bzip3
2
+ verreg = /^\s*[\-\*]\s+version:\s*(\d+(?:\.\w+)+)\s*$/i
3
+ unless File.read("#{__dir__}/../../README.md", mode: "rt") =~ verreg
4
+ raise "``version'' is not defined or bad syntax in ``README.md''"
5
+ end
6
+
7
+ VERSION = String($1)
8
+ end
data/lib/extbzip3.rb ADDED
@@ -0,0 +1,65 @@
1
+ ver = RUBY_VERSION.slice(/\d+\.\d+/)
2
+ soname = File.basename(__FILE__, ".rb") << ".so"
3
+ require File.join(ver, soname)
4
+
5
+ module Bzip3
6
+ refine String do
7
+ def to_bzip3(*args, **opts)
8
+ Bzip3::Encoder.encode(self, *args, **opts)
9
+ end
10
+
11
+ def bunzip3(*args, **opts)
12
+ Bzip3::Decoder.decode(self, *args, **opts)
13
+ end
14
+ end
15
+
16
+ refine BasicObject do
17
+ def to_bzip3(*args, **opts, &block)
18
+ Bzip3::Encoder.open(self, *args, **opts, &block)
19
+ end
20
+
21
+ def bunzip3(*args, **opts, &block)
22
+ Bzip3::Decoder.open(self, *args, **opts, &block)
23
+ end
24
+ end
25
+
26
+ class << Bzip3
27
+ using Bzip3
28
+
29
+ def encode(src, *args, **opts, &block)
30
+ src.to_bzip3(*args, **opts, &block)
31
+ end
32
+
33
+ def decode(src, *args, **opts, &block)
34
+ src.bunzip3(*args, **opts, &block)
35
+ end
36
+ end
37
+
38
+ class << Decoder
39
+ def open(*args, **opts, &block)
40
+ bz3 = new(*args, **opts)
41
+ return bz3 unless block
42
+
43
+ begin
44
+ yield bz3
45
+ ensure
46
+ bz3.close unless bz3.closed?
47
+ end
48
+ end
49
+ end
50
+
51
+ class << Encoder
52
+ def open(*args, **opts, &block)
53
+ bz3 = new(*args, **opts)
54
+ return bz3 unless block
55
+
56
+ begin
57
+ yield bz3
58
+ ensure
59
+ bz3.close unless bz3.closed?
60
+ end
61
+ end
62
+ end
63
+
64
+ Bzip3 = self
65
+ end
@@ -0,0 +1,77 @@
1
+ #!ruby
2
+
3
+ require "test-unit"
4
+ require "extbzip3"
5
+
6
+ SAMPLES = File.join(__dir__, "../sampledata")
7
+
8
+ class << SAMPLES
9
+ def load_file(path)
10
+ File.binread File.join(self, path)
11
+ end
12
+
13
+ def open_file(path, *args, **opts, &block)
14
+ File.open File.join(self, path), *args, **opts, &block
15
+ end
16
+ end
17
+
18
+ SAMPLES.freeze
19
+
20
+ class TestBzip3 < Test::Unit::TestCase
21
+ def test_oneshot
22
+ assert_equal "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
23
+ Bzip3.decode(SAMPLES.load_file("single.bz3"))
24
+
25
+ assert_raise RuntimeError do
26
+ Bzip3.decode(SAMPLES.load_file("single.bz3-frame"))
27
+ end
28
+
29
+ assert_raise RuntimeError do
30
+ Bzip3.decode(SAMPLES.load_file("single.bz3-frame"), format: Bzip3::V1_FILE_FORMAT)
31
+ end
32
+
33
+ assert_equal "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\nZYXWVUTSRQPONMLKJIHGFEDCBA987654321\n",
34
+ Bzip3.decode(SAMPLES.load_file("double.bz3"))
35
+
36
+ assert_equal "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
37
+ Bzip3.decode(SAMPLES.load_file("double.bz3"), concat: false)
38
+
39
+ assert_raise RuntimeError do
40
+ Bzip3.decode(SAMPLES.load_file("single+junks.bz3"))
41
+ end
42
+ end
43
+
44
+ def test_oneshot_frame
45
+ assert_equal "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\n",
46
+ Bzip3.decode(SAMPLES.load_file("single.bz3-frame"), format: Bzip3::V1_FRAME_FORMAT)
47
+
48
+ assert_raise RuntimeError do
49
+ Bzip3.decode(SAMPLES.load_file("single.bz3"), format: Bzip3::V1_FRAME_FORMAT)
50
+ end
51
+ end
52
+
53
+ def test_stream
54
+ io = SAMPLES.open_file("single.bz3")
55
+ assert_kind_of Bzip3::Decoder, Bzip3.decode(io)
56
+ assert_equal "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", Bzip3.decode(io).read
57
+ io.rewind
58
+ assert_equal "OK",
59
+ Bzip3.decode(io) { |bz3|
60
+ assert_equal "", bz3.read(0, "")
61
+ assert_equal "12345", bz3.read(5, "")
62
+ assert_equal "6789AB", bz3.read(6)
63
+ assert_equal "", bz3.read(0)
64
+ assert_equal "CDEFGHIJKLMNOPQRSTUVWXYZ\n", bz3.read
65
+ assert_equal "", bz3.read(0)
66
+ assert_equal nil, bz3.read
67
+ "OK"
68
+ }
69
+
70
+ if defined? Ractor
71
+ assert_equal "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", Ractor.new {
72
+ io2 = SAMPLES.open_file("single.bz3")
73
+ Bzip3.decode(io2).read
74
+ }.take
75
+ end
76
+ end
77
+ end