[ruby/zlib] Add Zlib::GzipReader.zcat for handling multiple gzip streams in gz file
Most gzip tools support concatenated gz streams in a gz file. This offers a way to handle such gz files in Ruby. Fixes [Bug #9790] Fixes [Bug #11180] Fixes [Bug #14804] https://github.com/ruby/zlib/commit/e2ce56de7d
This commit is contained in:
parent
f1d32010e6
commit
d52dffd817
@ -3723,6 +3723,60 @@ rb_gzreader_s_open(int argc, VALUE *argv, VALUE klass)
|
|||||||
return gzfile_s_open(argc, argv, klass, "rb");
|
return gzfile_s_open(argc, argv, klass, "rb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Document-method: Zlib::GzipReader.zcat
|
||||||
|
*
|
||||||
|
* call-seq:
|
||||||
|
* Zlib::GzipReader.zcat(io, options = {}, &block) => nil
|
||||||
|
* Zlib::GzipReader.zcat(io, options = {}) => string
|
||||||
|
*
|
||||||
|
* Decompresses all gzip data in the +io+, handling multiple gzip
|
||||||
|
* streams until the end of the +io+. There should not be any non-gzip
|
||||||
|
* data after the gzip streams.
|
||||||
|
*
|
||||||
|
* If a block is given, it is yielded strings of uncompressed data,
|
||||||
|
* and the method returns +nil+.
|
||||||
|
* If a block is not given, the method returns the concatenation of
|
||||||
|
* all uncompressed data in all gzip streams.
|
||||||
|
*/
|
||||||
|
static VALUE
|
||||||
|
rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass)
|
||||||
|
{
|
||||||
|
VALUE io, unused, obj, buf=0, tmpbuf;
|
||||||
|
long pos;
|
||||||
|
|
||||||
|
rb_check_arity(argc, 1, 2);
|
||||||
|
io = argv[0];
|
||||||
|
|
||||||
|
do {
|
||||||
|
obj = rb_funcallv(klass, rb_intern("new"), argc, argv);
|
||||||
|
if (rb_block_given_p()) {
|
||||||
|
rb_gzreader_each(0, 0, obj);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!buf) {
|
||||||
|
buf = rb_str_new(0, 0);
|
||||||
|
}
|
||||||
|
tmpbuf = gzfile_read_all(get_gzfile(obj));
|
||||||
|
rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf));
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_gzreader_read(0, 0, obj);
|
||||||
|
pos = NUM2LONG(rb_funcall(io, rb_intern("pos"), 0));
|
||||||
|
unused = rb_gzreader_unused(obj);
|
||||||
|
rb_gzfile_finish(obj);
|
||||||
|
if (!NIL_P(unused)) {
|
||||||
|
pos -= NUM2LONG(rb_funcall(unused, rb_intern("length"), 0));
|
||||||
|
rb_funcall(io, rb_intern("pos="), 1, LONG2NUM(pos));
|
||||||
|
}
|
||||||
|
} while (pos < NUM2LONG(rb_funcall(io, rb_intern("size"), 0)));
|
||||||
|
|
||||||
|
if (rb_block_given_p()) {
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Document-method: Zlib::GzipReader.new
|
* Document-method: Zlib::GzipReader.new
|
||||||
*
|
*
|
||||||
@ -4696,6 +4750,7 @@ Init_zlib(void)
|
|||||||
rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
|
rb_define_method(cGzipWriter, "puts", rb_gzwriter_puts, -1);
|
||||||
|
|
||||||
rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
|
rb_define_singleton_method(cGzipReader, "open", rb_gzreader_s_open,-1);
|
||||||
|
rb_define_singleton_method(cGzipReader, "zcat", rb_gzreader_s_zcat, -1);
|
||||||
rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
|
rb_define_alloc_func(cGzipReader, rb_gzreader_s_allocate);
|
||||||
rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
|
rb_define_method(cGzipReader, "initialize", rb_gzreader_initialize, -1);
|
||||||
rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
|
rb_define_method(cGzipReader, "rewind", rb_gzreader_rewind, 0);
|
||||||
|
@ -446,6 +446,30 @@ if defined? Zlib
|
|||||||
end
|
end
|
||||||
|
|
||||||
class TestZlibGzipFile < Test::Unit::TestCase
|
class TestZlibGzipFile < Test::Unit::TestCase
|
||||||
|
def test_gzip_reader_zcat
|
||||||
|
Tempfile.create("test_zlib_gzip_file_to_io") {|t|
|
||||||
|
gz = Zlib::GzipWriter.new(t)
|
||||||
|
gz.print("foo")
|
||||||
|
gz.close
|
||||||
|
t = File.open(t.path, 'ab')
|
||||||
|
gz = Zlib::GzipWriter.new(t)
|
||||||
|
gz.print("bar")
|
||||||
|
gz.close
|
||||||
|
|
||||||
|
results = []
|
||||||
|
t = File.open(t.path)
|
||||||
|
Zlib::GzipReader.zcat(t) do |str|
|
||||||
|
results << str
|
||||||
|
end
|
||||||
|
assert_equal(["foo", "bar"], results)
|
||||||
|
t.close
|
||||||
|
|
||||||
|
t = File.open(t.path)
|
||||||
|
assert_equal("foobar", Zlib::GzipReader.zcat(t))
|
||||||
|
t.close
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def test_to_io
|
def test_to_io
|
||||||
Tempfile.create("test_zlib_gzip_file_to_io") {|t|
|
Tempfile.create("test_zlib_gzip_file_to_io") {|t|
|
||||||
t.close
|
t.close
|
||||||
|
Loading…
x
Reference in New Issue
Block a user