bzip2-ruby 0.2.6 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.yardopts +1 -0
- data/CHANGELOG.rdoc +70 -1
- data/Gemfile +3 -0
- data/Gemfile.lock +26 -0
- data/README.rdoc +44 -3
- data/Rakefile +2 -19
- data/bzip2-ruby.gemspec +14 -48
- data/ext/bzip2.c +1012 -823
- data/ext/extconf.rb +4 -1
- data/lib/bzip2-ruby.rb +1 -0
- data/lib/bzip2.rb +10 -2
- data/lib/bzip2/internals.rb +13 -0
- data/lib/bzip2/reader.rb +27 -0
- data/lib/bzip2/version.rb +3 -0
- data/lib/bzip2/writer.rb +63 -0
- data/spec/reader_spec.rb +118 -214
- data/spec/spec_helper.rb +9 -1
- data/spec/writer_spec.rb +64 -74
- metadata +50 -17
- data/VERSION.yml +0 -4
- data/tasks/extconf.rake +0 -13
- data/tasks/extconf/bz2.rake +0 -43
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--no-private
|
data/CHANGELOG.rdoc
CHANGED
@@ -1,8 +1,28 @@
|
|
1
|
+
== 0.2.7 2010-11-16
|
2
|
+
|
3
|
+
* Add documentation for an overview of the Bzip2 module
|
4
|
+
* Document the class methods on Bzip2 and get them to show up in yarddoc
|
5
|
+
* Remove the ConfigError class because searching for it showed no instances of its usage
|
6
|
+
* Add a Usage section to the README and a bit about adding it to a Gemfile
|
7
|
+
* Improve the reader_spec.rb by making it more resilient in lots of places and a bit more descriptive/terse in
|
8
|
+
* Add a lot more documentation for the Reader class and also touch up the Writer class a bit
|
9
|
+
* Make the Writer specs more descriptive by giving them some doc strings.
|
10
|
+
* Wrap up documentation of the Bzip2::Writer class.
|
11
|
+
* Add lib/bzip2-ruby.rb so it's not always necessary to specify to require 'bzip2' in Gemfiles and such
|
12
|
+
* Start documenting the Bzip2::Writer class
|
13
|
+
* Fix a few compiler warnings
|
14
|
+
* Removed some dead code
|
15
|
+
* Fix for ruby 1.9 compatibility.
|
16
|
+
* Fix segfault when exiting in ruby 1.9
|
17
|
+
* Follow the newer conventions of rspec
|
18
|
+
* Migrate to using Bundler instead of Jeweler
|
19
|
+
* use malloc/free instead of ruby_xmalloc/ruby_xfree
|
20
|
+
|
1
21
|
== 0.2.6 2009-10-6
|
2
22
|
|
3
23
|
* Updated to support Ruby 1.8.5
|
4
24
|
|
5
|
-
== 0.2.5
|
25
|
+
== 0.2.5 2009-06-07
|
6
26
|
|
7
27
|
* initial conversion of original tests over to rspec
|
8
28
|
|
@@ -23,3 +43,52 @@
|
|
23
43
|
* 1 major enhancement:
|
24
44
|
* Gemify bz2 library from http://moulon.inra.fr/ruby/bz2.html
|
25
45
|
* All credit goes to Guy Decoux <ts@moulon.inra.fr>
|
46
|
+
|
47
|
+
=== 0.2.1
|
48
|
+
|
49
|
+
* replaced rb_proc_new() with bz_proc_new() for 1.6
|
50
|
+
(Thanks "Akinori MUSHA" <knu@iDaemons.org>)
|
51
|
+
|
52
|
+
=== 0.1.9
|
53
|
+
|
54
|
+
* corrected BZ_FINISH_OK (Thanks Rudi Cilibrasi <Rudi.Cilibrasi@cwi.nl>)
|
55
|
+
|
56
|
+
=== 0.1.6
|
57
|
+
|
58
|
+
* adapted for 1.8.0 (ihi)
|
59
|
+
* modified ::new
|
60
|
+
* BZ2::Writer#finish (same than #flush)
|
61
|
+
|
62
|
+
=== 0.1.5
|
63
|
+
|
64
|
+
* corrected extconf.rb
|
65
|
+
* added close!
|
66
|
+
* replaced close(false) by #finish
|
67
|
+
* corrected #flush
|
68
|
+
|
69
|
+
=== 0.1.4
|
70
|
+
|
71
|
+
* corrected bz_iv
|
72
|
+
* #to_io
|
73
|
+
* corrected ::Reader#close
|
74
|
+
|
75
|
+
=== 0.1.3
|
76
|
+
|
77
|
+
* corrected #lineno
|
78
|
+
* corrected ::Writer::new(nil)
|
79
|
+
* taint result
|
80
|
+
|
81
|
+
=== 0.1.2
|
82
|
+
|
83
|
+
* better (???) interface for #read
|
84
|
+
* finalize for objects which respond to #closed?
|
85
|
+
|
86
|
+
=== 0.1.1
|
87
|
+
|
88
|
+
* better interface for T_FILE
|
89
|
+
* corrected bug with gc (buf)
|
90
|
+
* Reader#lineno, Reader#lineno=, Reader#ungets
|
91
|
+
* corrected Reader#unused
|
92
|
+
* taint check in #initialize
|
93
|
+
* BZ2::bzip2, BZ2::bunzip2
|
94
|
+
* too many exceptions
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
bzip2-ruby (0.2.6)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.1.2)
|
10
|
+
rspec (2.0.0)
|
11
|
+
rspec-core (= 2.0.0)
|
12
|
+
rspec-expectations (= 2.0.0)
|
13
|
+
rspec-mocks (= 2.0.0)
|
14
|
+
rspec-core (2.0.0)
|
15
|
+
rspec-expectations (2.0.0)
|
16
|
+
diff-lcs (>= 1.1.2)
|
17
|
+
rspec-mocks (2.0.0)
|
18
|
+
rspec-core (= 2.0.0)
|
19
|
+
rspec-expectations (= 2.0.0)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
bzip2-ruby!
|
26
|
+
rspec (>= 2.0.0)
|
data/README.rdoc
CHANGED
@@ -2,14 +2,55 @@
|
|
2
2
|
|
3
3
|
== Installation
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
First make sure you’ve got Gemcutter in your sources list:
|
6
|
+
|
7
|
+
gem sources -a http://gemcutter.org
|
8
|
+
|
9
|
+
Then go ahead and install it as usual:
|
10
|
+
|
11
|
+
sudo gem install bzip2-ruby
|
12
|
+
|
7
13
|
You may need to specify:
|
8
14
|
|
9
15
|
--with-bz2-dir=<include file directory for libbzip2>
|
10
16
|
|
17
|
+
Or in a Gemfile
|
18
|
+
|
19
|
+
gem 'bzip2-ruby'
|
20
|
+
|
21
|
+
== Usage
|
22
|
+
|
23
|
+
The full documentation is hosted on {rdoc.info}[http://rdoc.info/github/brianmario/bzip2-ruby/master/frames].
|
24
|
+
|
25
|
+
Here's a quick overview, hower:
|
26
|
+
|
27
|
+
require 'bzip2'
|
28
|
+
|
29
|
+
# Quick shortcuts
|
30
|
+
data = Bzip2.compress 'string'
|
31
|
+
Bzip2.uncompress data
|
32
|
+
|
33
|
+
# Creating a bz2 compressed file
|
34
|
+
writer = Bzip2::Writer.new File.open('file')
|
35
|
+
writer << 'data1'
|
36
|
+
writer.puts 'data2'
|
37
|
+
writer.print 'data3'
|
38
|
+
writer.printf '%s', 'data4'
|
39
|
+
writer.close
|
40
|
+
|
41
|
+
Bzip2::Writer.open('file'){ |f| f << data }
|
42
|
+
|
43
|
+
# Reading a bz2 compressed file
|
44
|
+
reader = Bzip2::Reader.new File.open('file')
|
45
|
+
reader.gets # => "data1data2\n"
|
46
|
+
reader.read # => 'data3data4'
|
47
|
+
|
48
|
+
reader.readline # => raises Bzip2::EOZError
|
49
|
+
|
50
|
+
Bzip2::Reader.open('file'){ |f| puts f.read }
|
51
|
+
|
11
52
|
== Copying
|
12
|
-
|
53
|
+
|
13
54
|
This extension module is copyrighted free software by Guy Decoux
|
14
55
|
You can redistribute it and/or modify it under the same term as Ruby.
|
15
56
|
Guy Decoux <ts@moulon.inra.fr>
|
data/Rakefile
CHANGED
@@ -1,19 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'jeweler'
|
4
|
-
Jeweler::Tasks.new do |gem|
|
5
|
-
gem.name = "bzip2-ruby"
|
6
|
-
gem.summary = "Ruby C bindings to libbzip2."
|
7
|
-
gem.email = "seniorlopez@gmail.com"
|
8
|
-
gem.homepage = "http://github.com/brianmario/bzip2-ruby"
|
9
|
-
gem.authors = ["Guy Decoux", "Brian Lopez"]
|
10
|
-
gem.require_paths = ["lib", "ext"]
|
11
|
-
gem.extra_rdoc_files = `git ls-files *.rdoc`.split("\n")
|
12
|
-
gem.files = `git ls-files`.split("\n")
|
13
|
-
gem.extensions = ["ext/extconf.rb"]
|
14
|
-
gem.files.include %w(lib/jeweler/templates/.document lib/jeweler/templates/.gitignore)
|
15
|
-
# gem.rubyforge_project = "bzip2-ruby"
|
16
|
-
end
|
17
|
-
rescue LoadError
|
18
|
-
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
-
end
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
data/bzip2-ruby.gemspec
CHANGED
@@ -1,54 +1,20 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'bzip2/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |s|
|
7
|
-
s.name
|
8
|
-
s.version
|
6
|
+
s.name = 'bzip2-ruby'
|
7
|
+
s.version = Bzip2::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ['Guy Decoux', 'Brian Lopezs']
|
10
|
+
s.email = ['seniorlopez@gmail.com']
|
11
|
+
s.homepage = 'http://github.com/brianmario/bzip2-ruby'
|
12
|
+
s.summary = 'Ruby C bindings to libbzip2.'
|
9
13
|
|
10
|
-
s.
|
11
|
-
s.
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
s.extensions = ["ext/extconf.rb"]
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"CHANGELOG.rdoc",
|
17
|
-
"README.rdoc"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
"CHANGELOG.rdoc",
|
21
|
-
"README.rdoc",
|
22
|
-
"Rakefile",
|
23
|
-
"VERSION.yml",
|
24
|
-
"bzip2-ruby.gemspec",
|
25
|
-
"ext/bzip2.c",
|
26
|
-
"ext/extconf.rb",
|
27
|
-
"lib/bzip2.rb",
|
28
|
-
"spec/reader_spec.rb",
|
29
|
-
"spec/spec_helper.rb",
|
30
|
-
"spec/writer_spec.rb",
|
31
|
-
"tasks/extconf.rake",
|
32
|
-
"tasks/extconf/bz2.rake"
|
33
|
-
]
|
34
|
-
s.homepage = %q{http://github.com/brianmario/bzip2-ruby}
|
35
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
36
|
-
s.require_paths = ["lib", "ext"]
|
37
|
-
s.rubygems_version = %q{1.3.5}
|
38
|
-
s.summary = %q{Ruby C bindings to libbzip2.}
|
39
|
-
s.test_files = [
|
40
|
-
"spec/reader_spec.rb",
|
41
|
-
"spec/spec_helper.rb",
|
42
|
-
"spec/writer_spec.rb"
|
43
|
-
]
|
14
|
+
s.extensions = ['ext/extconf.rb']
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
17
|
+
s.require_paths = ['lib', 'ext']
|
44
18
|
|
45
|
-
|
46
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
|
-
s.specification_version = 3
|
48
|
-
|
49
|
-
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
50
|
-
else
|
51
|
-
end
|
52
|
-
else
|
53
|
-
end
|
19
|
+
s.add_development_dependency 'rspec', '>= 2.0.0'
|
54
20
|
end
|
data/ext/bzip2.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <bzlib.h>
|
3
|
+
#include <unistd.h>
|
3
4
|
#ifndef RUBY_19_COMPATIBILITY
|
4
5
|
#include <rubyio.h>
|
5
6
|
#include <version.h>
|
@@ -8,7 +9,7 @@
|
|
8
9
|
#endif
|
9
10
|
|
10
11
|
static VALUE bz_cWriter, bz_cReader, bz_cInternal;
|
11
|
-
static VALUE bz_eError,
|
12
|
+
static VALUE bz_eError, bz_eEOZError;
|
12
13
|
|
13
14
|
static VALUE bz_internal_ary;
|
14
15
|
|
@@ -36,7 +37,7 @@ struct bz_file {
|
|
36
37
|
bz_stream bzs;
|
37
38
|
VALUE in, io;
|
38
39
|
char *buf;
|
39
|
-
int buflen;
|
40
|
+
unsigned int buflen;
|
40
41
|
int blocks, work, small;
|
41
42
|
int flags, lineno, state;
|
42
43
|
};
|
@@ -51,150 +52,123 @@ struct bz_iv {
|
|
51
52
|
void (*finalize)();
|
52
53
|
};
|
53
54
|
|
54
|
-
#define Get_BZ2(obj, bzf)
|
55
|
-
rb_io_taint_check(obj);
|
55
|
+
#define Get_BZ2(obj, bzf) \
|
56
|
+
rb_io_taint_check(obj); \
|
56
57
|
Data_Get_Struct(obj, struct bz_file, bzf); \
|
57
|
-
if (!RTEST(bzf->io)) {
|
58
|
-
|
58
|
+
if (!RTEST(bzf->io)) { \
|
59
|
+
rb_raise(rb_eIOError, "closed IO"); \
|
59
60
|
}
|
60
61
|
|
61
|
-
static VALUE
|
62
|
-
bz_raise(error)
|
63
|
-
int error;
|
64
|
-
{
|
62
|
+
static VALUE bz_raise(int error) {
|
65
63
|
VALUE exc;
|
66
|
-
char *msg;
|
64
|
+
const char *msg;
|
67
65
|
|
68
66
|
exc = bz_eError;
|
69
67
|
switch (error) {
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
break;
|
99
|
-
default:
|
100
|
-
msg = "unknown error";
|
101
|
-
exc = bz_eError;
|
68
|
+
case BZ_SEQUENCE_ERROR:
|
69
|
+
msg = "incorrect sequence";
|
70
|
+
break;
|
71
|
+
case BZ_PARAM_ERROR:
|
72
|
+
msg = "parameter out of range";
|
73
|
+
break;
|
74
|
+
case BZ_MEM_ERROR:
|
75
|
+
msg = "not enough memory is available";
|
76
|
+
break;
|
77
|
+
case BZ_DATA_ERROR:
|
78
|
+
msg = "data integrity error is detected";
|
79
|
+
break;
|
80
|
+
case BZ_DATA_ERROR_MAGIC:
|
81
|
+
msg = "compressed stream does not start with the correct magic bytes";
|
82
|
+
break;
|
83
|
+
case BZ_IO_ERROR:
|
84
|
+
msg = "error reading or writing";
|
85
|
+
break;
|
86
|
+
case BZ_UNEXPECTED_EOF:
|
87
|
+
exc = bz_eEOZError;
|
88
|
+
msg = "compressed file finishes before the logical end of stream is detected";
|
89
|
+
break;
|
90
|
+
case BZ_OUTBUFF_FULL:
|
91
|
+
msg = "output buffer full";
|
92
|
+
break;
|
93
|
+
default:
|
94
|
+
msg = "unknown error";
|
95
|
+
exc = bz_eError;
|
102
96
|
}
|
103
|
-
rb_raise(exc, msg);
|
97
|
+
rb_raise(exc, "%s", msg);
|
104
98
|
}
|
105
|
-
|
106
|
-
static void
|
107
|
-
bz_str_mark(bzs)
|
108
|
-
struct bz_str *bzs;
|
109
|
-
{
|
99
|
+
|
100
|
+
static void bz_str_mark(struct bz_str *bzs) {
|
110
101
|
rb_gc_mark(bzs->str);
|
111
102
|
}
|
112
103
|
|
113
|
-
static void
|
114
|
-
bz_file_mark(bzf)
|
115
|
-
struct bz_file *bzf;
|
116
|
-
{
|
104
|
+
static void bz_file_mark(struct bz_file * bzf) {
|
117
105
|
rb_gc_mark(bzf->io);
|
118
106
|
rb_gc_mark(bzf->in);
|
119
107
|
}
|
120
108
|
|
121
|
-
static struct bz_iv *
|
122
|
-
bz_find_struct(obj, ptr, posp)
|
123
|
-
VALUE obj;
|
124
|
-
void *ptr;
|
125
|
-
int *posp;
|
126
|
-
{
|
109
|
+
static struct bz_iv * bz_find_struct(VALUE obj, void *ptr, int *posp) {
|
127
110
|
struct bz_iv *bziv;
|
128
111
|
int i;
|
129
112
|
|
130
113
|
for (i = 0; i < RARRAY_LEN(bz_internal_ary); i++) {
|
131
|
-
|
132
|
-
|
114
|
+
Data_Get_Struct(RARRAY_PTR(bz_internal_ary)[i], struct bz_iv, bziv);
|
115
|
+
if (ptr) {
|
133
116
|
#ifndef RUBY_19_COMPATIBILITY
|
134
|
-
|
117
|
+
if (TYPE(bziv->io) == T_FILE && RFILE(bziv->io)->fptr == (OpenFile *)ptr) {
|
135
118
|
#else
|
136
|
-
|
119
|
+
if (TYPE(bziv->io) == T_FILE && RFILE(bziv->io)->fptr == (rb_io_t *)ptr) {
|
137
120
|
#endif
|
121
|
+
if (posp) {
|
122
|
+
*posp = i;
|
123
|
+
}
|
124
|
+
return bziv;
|
125
|
+
} else if (TYPE(bziv->io) == T_DATA && DATA_PTR(bziv->io) == ptr) {
|
126
|
+
if (posp) *posp = i;
|
127
|
+
return bziv;
|
128
|
+
}
|
129
|
+
} else if (bziv->io == obj) {
|
138
130
|
if (posp) *posp = i;
|
139
131
|
return bziv;
|
140
132
|
}
|
141
|
-
else if (TYPE(bziv->io) == T_DATA && DATA_PTR(bziv->io) == ptr) {
|
142
|
-
if (posp) *posp = i;
|
143
|
-
return bziv;
|
144
|
-
}
|
145
|
-
}
|
146
|
-
else if (bziv->io == obj) {
|
147
|
-
if (posp) *posp = i;
|
148
|
-
return bziv;
|
149
|
-
}
|
150
133
|
}
|
151
134
|
if (posp) *posp = -1;
|
152
135
|
return 0;
|
153
136
|
}
|
154
137
|
|
155
|
-
static VALUE
|
156
|
-
bz_writer_internal_flush(bzf)
|
157
|
-
struct bz_file *bzf;
|
158
|
-
{
|
138
|
+
static VALUE bz_writer_internal_flush(struct bz_file *bzf) {
|
159
139
|
int closed = 1;
|
160
140
|
|
161
141
|
if (rb_respond_to(bzf->io, id_closed)) {
|
162
|
-
|
142
|
+
closed = RTEST(rb_funcall2(bzf->io, id_closed, 0, 0));
|
163
143
|
}
|
164
144
|
if (bzf->buf) {
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
145
|
+
if (!closed && bzf->state == BZ_OK) {
|
146
|
+
bzf->bzs.next_in = NULL;
|
147
|
+
bzf->bzs.avail_in = 0;
|
148
|
+
do {
|
149
|
+
bzf->bzs.next_out = bzf->buf;
|
150
|
+
bzf->bzs.avail_out = bzf->buflen;
|
151
|
+
bzf->state = BZ2_bzCompress(&(bzf->bzs), BZ_FINISH);
|
152
|
+
if (bzf->state != BZ_FINISH_OK && bzf->state != BZ_STREAM_END) {
|
153
|
+
break;
|
154
|
+
}
|
155
|
+
if (bzf->bzs.avail_out < bzf->buflen) {
|
156
|
+
rb_funcall(bzf->io, id_write, 1, rb_str_new(bzf->buf, bzf->buflen - bzf->bzs.avail_out));
|
157
|
+
}
|
158
|
+
} while (bzf->state != BZ_STREAM_END);
|
175
159
|
}
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
160
|
+
free(bzf->buf);
|
161
|
+
bzf->buf = 0;
|
162
|
+
BZ2_bzCompressEnd(&(bzf->bzs));
|
163
|
+
bzf->state = BZ_OK;
|
164
|
+
if (!closed && rb_respond_to(bzf->io, id_flush)) {
|
165
|
+
rb_funcall2(bzf->io, id_flush, 0, 0);
|
180
166
|
}
|
181
|
-
} while (bzf->state != BZ_STREAM_END);
|
182
|
-
}
|
183
|
-
free(bzf->buf);
|
184
|
-
bzf->buf = 0;
|
185
|
-
BZ2_bzCompressEnd(&(bzf->bzs));
|
186
|
-
bzf->state = BZ_OK;
|
187
|
-
if (!closed && rb_respond_to(bzf->io, id_flush)) {
|
188
|
-
rb_funcall2(bzf->io, id_flush, 0, 0);
|
189
|
-
}
|
190
167
|
}
|
191
168
|
return closed;
|
192
169
|
}
|
193
170
|
|
194
|
-
static VALUE
|
195
|
-
bz_writer_internal_close(bzf)
|
196
|
-
struct bz_file *bzf;
|
197
|
-
{
|
171
|
+
static VALUE bz_writer_internal_close(struct bz_file *bzf) {
|
198
172
|
struct bz_iv *bziv;
|
199
173
|
int pos, closed;
|
200
174
|
VALUE res;
|
@@ -202,82 +176,87 @@ bz_writer_internal_close(bzf)
|
|
202
176
|
closed = bz_writer_internal_flush(bzf);
|
203
177
|
bziv = bz_find_struct(bzf->io, 0, &pos);
|
204
178
|
if (bziv) {
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
rb_ary_delete_at(bz_internal_ary, pos);
|
179
|
+
if (TYPE(bzf->io) == T_FILE) {
|
180
|
+
RFILE(bzf->io)->fptr->finalize = bziv->finalize;
|
181
|
+
} else if (TYPE(bziv->io) == T_DATA) {
|
182
|
+
RDATA(bziv->io)->dfree = bziv->finalize;
|
183
|
+
}
|
184
|
+
RDATA(bziv->bz2)->dfree = free;
|
185
|
+
bziv->bz2 = 0;
|
186
|
+
rb_ary_delete_at(bz_internal_ary, pos);
|
214
187
|
}
|
215
188
|
if (bzf->flags & BZ2_RB_CLOSE) {
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
}
|
222
|
-
|
223
|
-
res = bzf->io;
|
189
|
+
bzf->flags &= ~BZ2_RB_CLOSE;
|
190
|
+
if (!closed && rb_respond_to(bzf->io, id_close)) {
|
191
|
+
rb_funcall2(bzf->io, id_close, 0, 0);
|
192
|
+
}
|
193
|
+
res = Qnil;
|
194
|
+
} else {
|
195
|
+
res = bzf->io;
|
224
196
|
}
|
225
197
|
bzf->io = Qnil;
|
226
198
|
return res;
|
227
199
|
}
|
228
200
|
|
229
|
-
static VALUE
|
230
|
-
bz_internal_finalize(ary, obj)
|
231
|
-
VALUE ary, obj;
|
232
|
-
{
|
201
|
+
static void bz_internal_finalize(VALUE data) {
|
233
202
|
VALUE elem;
|
234
203
|
int closed, i;
|
235
204
|
struct bz_iv *bziv;
|
236
205
|
struct bz_file *bzf;
|
237
206
|
|
238
207
|
for (i = 0; i < RARRAY_LEN(bz_internal_ary); i++) {
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
208
|
+
elem = RARRAY_PTR(bz_internal_ary)[i];
|
209
|
+
Data_Get_Struct(elem, struct bz_iv, bziv);
|
210
|
+
if (bziv->bz2) {
|
211
|
+
RDATA(bziv->bz2)->dfree = free;
|
212
|
+
if (TYPE(bziv->io) == T_FILE) {
|
213
|
+
RFILE(bziv->io)->fptr->finalize = bziv->finalize;
|
214
|
+
} else if (TYPE(bziv->io) == T_DATA) {
|
215
|
+
RDATA(bziv->io)->dfree = bziv->finalize;
|
216
|
+
}
|
217
|
+
Data_Get_Struct(bziv->bz2, struct bz_file, bzf);
|
218
|
+
closed = bz_writer_internal_flush(bzf);
|
219
|
+
if (bzf->flags & BZ2_RB_CLOSE) {
|
220
|
+
bzf->flags &= ~BZ2_RB_CLOSE;
|
221
|
+
if (!closed && rb_respond_to(bzf->io, id_close)) {
|
222
|
+
rb_funcall2(bzf->io, id_close, 0, 0);
|
223
|
+
}
|
224
|
+
}
|
256
225
|
}
|
257
226
|
}
|
258
|
-
}
|
259
|
-
return Qnil;
|
260
227
|
}
|
261
228
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
229
|
+
/*
|
230
|
+
* Closes this writer for further use. The remaining data is compressed and
|
231
|
+
* flushed.
|
232
|
+
*
|
233
|
+
* If the writer was constructed with an io object, that object is returned.
|
234
|
+
* Otherwise, the actual compressed data is returned
|
235
|
+
*
|
236
|
+
* writer = Bzip2::Writer.new File.open('path', 'w')
|
237
|
+
* writer << 'a'
|
238
|
+
* writer.close # => #<File:path>
|
239
|
+
*
|
240
|
+
* writer = Bzip2::Writer.new
|
241
|
+
* writer << 'a'
|
242
|
+
* writer.close # => "BZh91AY&SY...
|
243
|
+
*/
|
244
|
+
static VALUE bz_writer_close(VALUE obj) {
|
266
245
|
struct bz_file *bzf;
|
267
246
|
VALUE res;
|
268
247
|
|
269
248
|
Get_BZ2(obj, bzf);
|
270
249
|
res = bz_writer_internal_close(bzf);
|
271
250
|
if (!NIL_P(res) && (bzf->flags & BZ2_RB_INTERNAL)) {
|
272
|
-
|
251
|
+
RBASIC(res)->klass = rb_cString;
|
273
252
|
}
|
274
253
|
return res;
|
275
254
|
}
|
276
255
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
{
|
256
|
+
/*
|
257
|
+
* Calls Bzip2::Writer#close and then does some more stuff...
|
258
|
+
*/
|
259
|
+
static VALUE bz_writer_close_bang(VALUE obj) {
|
281
260
|
struct bz_file *bzf;
|
282
261
|
int closed;
|
283
262
|
|
@@ -285,28 +264,22 @@ bz_writer_close_bang(obj)
|
|
285
264
|
closed = bzf->flags & (BZ2_RB_INTERNAL|BZ2_RB_CLOSE);
|
286
265
|
bz_writer_close(obj);
|
287
266
|
if (!closed && rb_respond_to(bzf->io, id_close)) {
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
267
|
+
if (rb_respond_to(bzf->io, id_closed)) {
|
268
|
+
closed = RTEST(rb_funcall2(bzf->io, id_closed, 0, 0));
|
269
|
+
}
|
270
|
+
if (!closed) {
|
271
|
+
rb_funcall2(bzf->io, id_close, 0, 0);
|
272
|
+
}
|
294
273
|
}
|
295
274
|
return Qnil;
|
296
275
|
}
|
297
276
|
|
298
|
-
static void
|
299
|
-
bz_writer_free(bzf)
|
300
|
-
struct bz_file *bzf;
|
301
|
-
{
|
277
|
+
static void bz_writer_free(struct bz_file *bzf) {
|
302
278
|
bz_writer_internal_close(bzf);
|
303
|
-
|
279
|
+
free(bzf);
|
304
280
|
}
|
305
281
|
|
306
|
-
static void
|
307
|
-
bz_io_data_finalize(ptr)
|
308
|
-
void *ptr;
|
309
|
-
{
|
282
|
+
static void bz_io_data_finalize(void *ptr) {
|
310
283
|
struct bz_file *bzf;
|
311
284
|
struct bz_iv *bziv;
|
312
285
|
int pos;
|
@@ -315,8 +288,8 @@ bz_io_data_finalize(ptr)
|
|
315
288
|
if (bziv) {
|
316
289
|
rb_ary_delete_at(bz_internal_ary, pos);
|
317
290
|
Data_Get_Struct(bziv->bz2, struct bz_file, bzf);
|
318
|
-
rb_protect(bz_writer_internal_flush, (VALUE)bzf, 0);
|
319
|
-
RDATA(bziv->bz2)->dfree =
|
291
|
+
rb_protect((VALUE (*)(VALUE))bz_writer_internal_flush, (VALUE)bzf, 0);
|
292
|
+
RDATA(bziv->bz2)->dfree = free;
|
320
293
|
if (bziv->finalize) {
|
321
294
|
(*bziv->finalize)(ptr);
|
322
295
|
} else if (TYPE(bzf->io) == T_FILE) {
|
@@ -333,7 +306,8 @@ bz_io_data_finalize(ptr)
|
|
333
306
|
#else
|
334
307
|
rb_io_t *file = (rb_io_t *)ptr;
|
335
308
|
if (file->fd) {
|
336
|
-
|
309
|
+
close(file->fd);
|
310
|
+
|
337
311
|
file->fd = 0;
|
338
312
|
}
|
339
313
|
if (file->stdio_file) {
|
@@ -343,33 +317,27 @@ bz_io_data_finalize(ptr)
|
|
343
317
|
#endif
|
344
318
|
}
|
345
319
|
}
|
320
|
+
|
346
321
|
}
|
347
322
|
|
348
|
-
static void *
|
349
|
-
|
350
|
-
void *opaque;
|
351
|
-
int m, n;
|
352
|
-
{
|
353
|
-
return ruby_xmalloc(m * n);
|
323
|
+
static void * bz_malloc(void *opaque, int m, int n) {
|
324
|
+
return malloc(m * n);
|
354
325
|
}
|
355
326
|
|
356
|
-
static void
|
357
|
-
|
358
|
-
void *opaque, *p;
|
359
|
-
{
|
360
|
-
ruby_xfree(p);
|
327
|
+
static void bz_free(void *opaque, void *p) {
|
328
|
+
free(p);
|
361
329
|
}
|
362
330
|
|
363
331
|
#define DEFAULT_BLOCKS 9
|
364
332
|
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
333
|
+
/*
|
334
|
+
* Internally allocates information about a new writer
|
335
|
+
* @private
|
336
|
+
*/
|
337
|
+
static VALUE bz_writer_s_alloc(VALUE obj) {
|
369
338
|
struct bz_file *bzf;
|
370
339
|
VALUE res;
|
371
|
-
res = Data_Make_Struct(obj, struct bz_file, bz_file_mark,
|
372
|
-
bz_writer_free, bzf);
|
340
|
+
res = Data_Make_Struct(obj, struct bz_file, bz_file_mark, bz_writer_free, bzf);
|
373
341
|
bzf->bzs.bzalloc = bz_malloc;
|
374
342
|
bzf->bzs.bzfree = bz_free;
|
375
343
|
bzf->blocks = DEFAULT_BLOCKS;
|
@@ -377,139 +345,171 @@ bz_writer_s_alloc(obj)
|
|
377
345
|
return res;
|
378
346
|
}
|
379
347
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
348
|
+
/*
|
349
|
+
* Flushes all of the data in this stream to the underlying IO.
|
350
|
+
*
|
351
|
+
* If this writer was constructed with no underlying io object, the compressed
|
352
|
+
* data is returned as a string.
|
353
|
+
*
|
354
|
+
* @return [String, nil]
|
355
|
+
* @raise [IOError] if the stream has been closed
|
356
|
+
*/
|
357
|
+
static VALUE bz_writer_flush(VALUE obj) {
|
384
358
|
struct bz_file *bzf;
|
385
359
|
|
386
360
|
Get_BZ2(obj, bzf);
|
387
361
|
if (bzf->flags & BZ2_RB_INTERNAL) {
|
388
|
-
|
362
|
+
return bz_writer_close(obj);
|
389
363
|
}
|
390
364
|
bz_writer_internal_flush(bzf);
|
391
365
|
return Qnil;
|
392
366
|
}
|
393
367
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
368
|
+
/*
|
369
|
+
* call-seq:
|
370
|
+
* open(filename, mode='wb', &block=nil) -> Bzip2::Writer
|
371
|
+
*
|
372
|
+
* @param [String] filename the name of the file to write to
|
373
|
+
* @param [String] mode a mode string passed to Kernel#open
|
374
|
+
* @yieldparam [Bzip2::Writer] writer the Bzip2::Writer instance
|
375
|
+
*
|
376
|
+
* If a block is given, the created Bzip2::Writer instance is yielded to the
|
377
|
+
* block and will be closed when the block completes. It is guaranteed via
|
378
|
+
* +ensure+ that the writer is closed
|
379
|
+
*
|
380
|
+
* If a block is not given, a Bzip2::Writer instance will be returned
|
381
|
+
*
|
382
|
+
* Bzip2::Writer.open('file') { |f| f << data }
|
383
|
+
*
|
384
|
+
* writer = Bzip2::Writer.open('file')
|
385
|
+
* writer << data
|
386
|
+
* writer.close
|
387
|
+
*
|
388
|
+
* @return [Bzip2::Writer, nil]
|
389
|
+
*/
|
390
|
+
static VALUE bz_writer_s_open(int argc, VALUE *argv, VALUE obj) {
|
399
391
|
VALUE res;
|
400
392
|
struct bz_file *bzf;
|
401
393
|
|
402
394
|
if (argc < 1) {
|
403
|
-
|
395
|
+
rb_raise(rb_eArgError, "invalid number of arguments");
|
404
396
|
}
|
405
397
|
if (argc == 1) {
|
406
|
-
|
407
|
-
|
408
|
-
}
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
argc -= 1;
|
398
|
+
argv[0] = rb_funcall(rb_mKernel, id_open, 2, argv[0],
|
399
|
+
rb_str_new2("wb"));
|
400
|
+
} else {
|
401
|
+
argv[1] = rb_funcall2(rb_mKernel, id_open, 2, argv);
|
402
|
+
argv += 1;
|
403
|
+
argc -= 1;
|
413
404
|
}
|
414
405
|
res = rb_funcall2(obj, id_new, argc, argv);
|
415
406
|
Data_Get_Struct(res, struct bz_file, bzf);
|
416
407
|
bzf->flags |= BZ2_RB_CLOSE;
|
417
408
|
if (rb_block_given_p()) {
|
418
|
-
|
409
|
+
return rb_ensure(rb_yield, res, bz_writer_close, res);
|
419
410
|
}
|
420
411
|
return res;
|
421
412
|
}
|
422
413
|
|
423
|
-
static VALUE
|
424
|
-
bz_str_write(obj, str)
|
425
|
-
VALUE obj, str;
|
426
|
-
{
|
414
|
+
static VALUE bz_str_write(VALUE obj, VALUE str) {
|
427
415
|
if (TYPE(str) != T_STRING) {
|
428
|
-
|
416
|
+
rb_raise(rb_eArgError, "expected a String");
|
429
417
|
}
|
430
418
|
if (RSTRING_LEN(str)) {
|
431
|
-
|
419
|
+
rb_str_cat(obj, RSTRING_PTR(str), RSTRING_LEN(str));
|
432
420
|
}
|
433
421
|
return str;
|
434
422
|
}
|
435
423
|
|
436
|
-
static VALUE
|
437
|
-
bz_str_closed(obj)
|
438
|
-
VALUE obj;
|
439
|
-
{
|
424
|
+
static VALUE bz_str_closed(VALUE obj) {
|
440
425
|
return Qfalse;
|
441
426
|
}
|
442
427
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
428
|
+
/*
|
429
|
+
* call-seq:
|
430
|
+
* initialize(io = nil)
|
431
|
+
*
|
432
|
+
* @param [File] io the file which to write compressed data to
|
433
|
+
*
|
434
|
+
* Creates a new Bzip2::Writer for compressing a stream of data. An optional
|
435
|
+
* io object (something responding to +write+) can be supplied which data
|
436
|
+
* will be written to.
|
437
|
+
*
|
438
|
+
* If nothing is given, the Bzip2::Writer#flush method can be called to retrieve
|
439
|
+
* the compressed stream so far.
|
440
|
+
*
|
441
|
+
* writer = Bzip2::Writer.new File.open('files.bz2')
|
442
|
+
* writer << 'a'
|
443
|
+
* writer << 'b'
|
444
|
+
* writer.close
|
445
|
+
*
|
446
|
+
* writer = Bzip2::Writer.new
|
447
|
+
* writer << 'abcde'
|
448
|
+
* writer.flush # => 'abcde' compressed
|
449
|
+
*/
|
450
|
+
static VALUE bz_writer_init(int argc, VALUE *argv, VALUE obj) {
|
448
451
|
struct bz_file *bzf;
|
449
452
|
int blocks = DEFAULT_BLOCKS;
|
450
453
|
int work = 0;
|
451
454
|
VALUE a, b, c;
|
452
455
|
|
453
456
|
switch(rb_scan_args(argc, argv, "03", &a, &b, &c)) {
|
454
|
-
|
455
|
-
|
457
|
+
case 3:
|
458
|
+
work = NUM2INT(c);
|
456
459
|
/* ... */
|
457
|
-
|
458
|
-
|
460
|
+
case 2:
|
461
|
+
blocks = NUM2INT(b);
|
459
462
|
}
|
460
463
|
Data_Get_Struct(obj, struct bz_file, bzf);
|
461
464
|
if (NIL_P(a)) {
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
}
|
467
|
-
|
468
|
-
|
469
|
-
struct bz_iv *bziv;
|
465
|
+
a = rb_str_new(0, 0);
|
466
|
+
rb_define_method(rb_singleton_class(a), "write", bz_str_write, 1);
|
467
|
+
rb_define_method(rb_singleton_class(a), "closed?", bz_str_closed, 0);
|
468
|
+
bzf->flags |= BZ2_RB_INTERNAL;
|
469
|
+
} else {
|
470
|
+
VALUE iv;
|
471
|
+
struct bz_iv *bziv;
|
470
472
|
#ifndef RUBY_19_COMPATIBILITY
|
471
|
-
|
473
|
+
OpenFile *fptr;
|
472
474
|
#else
|
473
|
-
|
475
|
+
rb_io_t *fptr;
|
474
476
|
#endif
|
475
477
|
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
}
|
480
|
-
if (TYPE(a) == T_FILE) {
|
481
|
-
GetOpenFile(a, fptr);
|
482
|
-
rb_io_check_writable(fptr);
|
483
|
-
}
|
484
|
-
else if (rb_respond_to(a, id_closed)) {
|
485
|
-
iv = rb_funcall2(a, id_closed, 0, 0);
|
486
|
-
if (RTEST(iv)) {
|
487
|
-
rb_raise(rb_eArgError, "closed object");
|
478
|
+
rb_io_taint_check(a);
|
479
|
+
if (!rb_respond_to(a, id_write)) {
|
480
|
+
rb_raise(rb_eArgError, "first argument must respond to #write");
|
488
481
|
}
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
if (
|
493
|
-
|
482
|
+
if (TYPE(a) == T_FILE) {
|
483
|
+
GetOpenFile(a, fptr);
|
484
|
+
rb_io_check_writable(fptr);
|
485
|
+
} else if (rb_respond_to(a, id_closed)) {
|
486
|
+
iv = rb_funcall2(a, id_closed, 0, 0);
|
487
|
+
if (RTEST(iv)) {
|
488
|
+
rb_raise(rb_eArgError, "closed object");
|
489
|
+
}
|
490
|
+
}
|
491
|
+
bziv = bz_find_struct(a, 0, 0);
|
492
|
+
if (bziv) {
|
493
|
+
if (RTEST(bziv->bz2)) {
|
494
|
+
rb_raise(rb_eArgError, "invalid data type");
|
495
|
+
}
|
496
|
+
bziv->bz2 = obj;
|
497
|
+
} else {
|
498
|
+
iv = Data_Make_Struct(rb_cData, struct bz_iv, 0, free, bziv);
|
499
|
+
bziv->io = a;
|
500
|
+
bziv->bz2 = obj;
|
501
|
+
rb_ary_push(bz_internal_ary, iv);
|
502
|
+
}
|
503
|
+
switch (TYPE(a)) {
|
504
|
+
case T_FILE:
|
505
|
+
bziv->finalize = RFILE(a)->fptr->finalize;
|
506
|
+
RFILE(a)->fptr->finalize = (void (*)(struct rb_io_t *, int))bz_io_data_finalize;
|
507
|
+
break;
|
508
|
+
case T_DATA:
|
509
|
+
bziv->finalize = RDATA(a)->dfree;
|
510
|
+
RDATA(a)->dfree = bz_io_data_finalize;
|
511
|
+
break;
|
494
512
|
}
|
495
|
-
bziv->bz2 = obj;
|
496
|
-
}
|
497
|
-
else {
|
498
|
-
iv = Data_Make_Struct(rb_cData, struct bz_iv, 0, free, bziv);
|
499
|
-
bziv->io = a;
|
500
|
-
bziv->bz2 = obj;
|
501
|
-
rb_ary_push(bz_internal_ary, iv);
|
502
|
-
}
|
503
|
-
switch (TYPE(a)) {
|
504
|
-
case T_FILE:
|
505
|
-
bziv->finalize = RFILE(a)->fptr->finalize;
|
506
|
-
RFILE(a)->fptr->finalize = bz_io_data_finalize;
|
507
|
-
break;
|
508
|
-
case T_DATA:
|
509
|
-
bziv->finalize = RDATA(a)->dfree;
|
510
|
-
RDATA(a)->dfree = bz_io_data_finalize;
|
511
|
-
break;
|
512
|
-
}
|
513
513
|
}
|
514
514
|
bzf->io = a;
|
515
515
|
bzf->blocks = blocks;
|
@@ -519,86 +519,105 @@ bz_writer_init(argc, argv, obj)
|
|
519
519
|
|
520
520
|
#define BZ_RB_BLOCKSIZE 4096
|
521
521
|
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
522
|
+
/*
|
523
|
+
* call-seq:
|
524
|
+
* write(data)
|
525
|
+
* Actually writes some data into this stream.
|
526
|
+
*
|
527
|
+
* @param [String] data the data to write
|
528
|
+
* @return [Integer] the length of the data which was written (uncompressed)
|
529
|
+
* @raise [IOError] if the stream has been closed
|
530
|
+
*/
|
531
|
+
static VALUE bz_writer_write(VALUE obj, VALUE a) {
|
526
532
|
struct bz_file *bzf;
|
527
533
|
int n;
|
528
534
|
|
529
535
|
a = rb_obj_as_string(a);
|
530
536
|
Get_BZ2(obj, bzf);
|
531
537
|
if (!bzf->buf) {
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
538
|
+
if (bzf->state != BZ_OK) {
|
539
|
+
bz_raise(bzf->state);
|
540
|
+
}
|
541
|
+
bzf->state = BZ2_bzCompressInit(&(bzf->bzs), bzf->blocks,
|
542
|
+
0, bzf->work);
|
543
|
+
if (bzf->state != BZ_OK) {
|
544
|
+
bz_writer_internal_flush(bzf);
|
545
|
+
bz_raise(bzf->state);
|
546
|
+
}
|
547
|
+
bzf->buf = ALLOC_N(char, BZ_RB_BLOCKSIZE + 1);
|
548
|
+
bzf->buflen = BZ_RB_BLOCKSIZE;
|
549
|
+
bzf->buf[0] = bzf->buf[bzf->buflen] = '\0';
|
544
550
|
}
|
545
551
|
bzf->bzs.next_in = RSTRING_PTR(a);
|
546
552
|
bzf->bzs.avail_in = RSTRING_LEN(a);
|
547
553
|
while (bzf->bzs.avail_in) {
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
554
|
+
bzf->bzs.next_out = bzf->buf;
|
555
|
+
bzf->bzs.avail_out = bzf->buflen;
|
556
|
+
bzf->state = BZ2_bzCompress(&(bzf->bzs), BZ_RUN);
|
557
|
+
if (bzf->state == BZ_SEQUENCE_ERROR || bzf->state == BZ_PARAM_ERROR) {
|
558
|
+
bz_writer_internal_flush(bzf);
|
559
|
+
bz_raise(bzf->state);
|
560
|
+
}
|
561
|
+
bzf->state = BZ_OK;
|
562
|
+
if (bzf->bzs.avail_out < bzf->buflen) {
|
563
|
+
n = bzf->buflen - bzf->bzs.avail_out;
|
564
|
+
rb_funcall(bzf->io, id_write, 1, rb_str_new(bzf->buf, n));
|
565
|
+
}
|
560
566
|
}
|
561
567
|
return INT2NUM(RSTRING_LEN(a));
|
562
568
|
}
|
563
569
|
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
570
|
+
/*
|
571
|
+
* call-seq:
|
572
|
+
* putc(num)
|
573
|
+
*
|
574
|
+
* Write one byte into this stream.
|
575
|
+
* @param [Integer] num the number value of the character to write
|
576
|
+
* @return [Integer] always 1
|
577
|
+
* @raise [IOError] if the stream has been closed
|
578
|
+
*/
|
579
|
+
static VALUE bz_writer_putc(VALUE obj, VALUE a) {
|
568
580
|
char c = NUM2CHR(a);
|
569
581
|
return bz_writer_write(obj, rb_str_new(&c, 1));
|
570
582
|
}
|
571
583
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
584
|
+
/*
|
585
|
+
* call-seq:
|
586
|
+
* compress(str)
|
587
|
+
*
|
588
|
+
* Shortcut for compressing just a string.
|
589
|
+
*
|
590
|
+
* Bzip2.uncompress Bzip2.compress('data') # => 'data'
|
591
|
+
*
|
592
|
+
* @param [String] str the string to compress
|
593
|
+
* @return [String] +str+ compressed with bz2
|
594
|
+
*/
|
595
|
+
static VALUE bz_compress(int argc, VALUE *argv, VALUE obj) {
|
577
596
|
VALUE bz2, str;
|
578
597
|
|
579
598
|
if (!argc) {
|
580
|
-
|
599
|
+
rb_raise(rb_eArgError, "need a String to compress");
|
581
600
|
}
|
582
601
|
str = rb_str_to_str(argv[0]);
|
583
602
|
argv[0] = Qnil;
|
584
603
|
bz2 = rb_funcall2(bz_cWriter, id_new, argc, argv);
|
585
604
|
if (OBJ_TAINTED(str)) {
|
586
|
-
|
587
|
-
|
588
|
-
|
605
|
+
struct bz_file *bzf;
|
606
|
+
Data_Get_Struct(bz2, struct bz_file, bzf);
|
607
|
+
OBJ_TAINT(bzf->io);
|
589
608
|
}
|
590
609
|
bz_writer_write(bz2, str);
|
591
610
|
return bz_writer_close(bz2);
|
592
611
|
}
|
593
612
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
613
|
+
/*
|
614
|
+
* Internally allocates data for a new Reader
|
615
|
+
* @private
|
616
|
+
*/
|
617
|
+
static VALUE bz_reader_s_alloc(VALUE obj) {
|
598
618
|
struct bz_file *bzf;
|
599
619
|
VALUE res;
|
600
|
-
res = Data_Make_Struct(obj, struct bz_file, bz_file_mark,
|
601
|
-
ruby_xfree, bzf);
|
620
|
+
res = Data_Make_Struct(obj, struct bz_file, bz_file_mark, free, bzf);
|
602
621
|
bzf->bzs.bzalloc = bz_malloc;
|
603
622
|
bzf->bzs.bzfree = bz_free;
|
604
623
|
bzf->blocks = DEFAULT_BLOCKS;
|
@@ -608,79 +627,103 @@ bz_reader_s_alloc(obj)
|
|
608
627
|
|
609
628
|
static VALUE bz_reader_close __((VALUE));
|
610
629
|
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
630
|
+
/*
|
631
|
+
* call-seq:
|
632
|
+
* open(filename, &block=nil) -> Bzip2::Reader
|
633
|
+
*
|
634
|
+
* @param [String] filename the name of the file to read from
|
635
|
+
* @yieldparam [Bzip2::Reader] reader the Bzip2::Reader instance
|
636
|
+
*
|
637
|
+
* If a block is given, the created Bzip2::Reader instance is yielded to the
|
638
|
+
* block and will be closed when the block completes. It is guaranteed via
|
639
|
+
* +ensure+ that the reader is closed
|
640
|
+
*
|
641
|
+
* If a block is not given, a Bzip2::Reader instance will be returned
|
642
|
+
*
|
643
|
+
* Bzip2::Reader.open('file') { |f| puts f.gets }
|
644
|
+
*
|
645
|
+
* reader = Bzip2::Reader.open('file')
|
646
|
+
* puts reader.gets
|
647
|
+
* reader.close
|
648
|
+
*
|
649
|
+
* @return [Bzip2::Reader, nil]
|
650
|
+
*/
|
651
|
+
static VALUE bz_reader_s_open(int argc, VALUE *argv, VALUE obj) {
|
616
652
|
VALUE res;
|
617
653
|
struct bz_file *bzf;
|
618
654
|
|
619
655
|
if (argc < 1) {
|
620
|
-
|
656
|
+
rb_raise(rb_eArgError, "invalid number of arguments");
|
621
657
|
}
|
622
658
|
argv[0] = rb_funcall2(rb_mKernel, id_open, 1, argv);
|
623
|
-
if (NIL_P(argv[0]))
|
659
|
+
if (NIL_P(argv[0])) {
|
660
|
+
return Qnil;
|
661
|
+
}
|
624
662
|
res = rb_funcall2(obj, id_new, argc, argv);
|
625
663
|
Data_Get_Struct(res, struct bz_file, bzf);
|
626
664
|
bzf->flags |= BZ2_RB_CLOSE;
|
627
665
|
if (rb_block_given_p()) {
|
628
|
-
|
666
|
+
return rb_ensure(rb_yield, res, bz_reader_close, res);
|
629
667
|
}
|
630
668
|
return res;
|
631
669
|
}
|
632
670
|
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
671
|
+
/*
|
672
|
+
* call-seq:
|
673
|
+
* initialize(io)
|
674
|
+
*
|
675
|
+
* Creates a new stream for reading a bzip file or string
|
676
|
+
*
|
677
|
+
* @param [File, string, #read] io the source for input data. If the source is
|
678
|
+
* a file or something responding to #read, then data will be read via #read,
|
679
|
+
* otherwise if the input is a string it will be taken as the literal data
|
680
|
+
* to decompress
|
681
|
+
*/
|
682
|
+
static VALUE bz_reader_init(int argc, VALUE *argv, VALUE obj) {
|
638
683
|
struct bz_file *bzf;
|
639
684
|
int small = 0;
|
640
685
|
VALUE a, b;
|
641
686
|
int internal = 0;
|
642
687
|
|
643
688
|
if (rb_scan_args(argc, argv, "11", &a, &b) == 2) {
|
644
|
-
|
689
|
+
small = RTEST(b);
|
645
690
|
}
|
646
691
|
rb_io_taint_check(a);
|
647
692
|
if (OBJ_TAINTED(a)) {
|
648
|
-
|
693
|
+
OBJ_TAINT(obj);
|
649
694
|
}
|
650
695
|
if (rb_respond_to(a, id_read)) {
|
651
|
-
|
696
|
+
if (TYPE(a) == T_FILE) {
|
652
697
|
#ifndef RUBY_19_COMPATIBILITY
|
653
|
-
|
698
|
+
OpenFile *fptr;
|
654
699
|
#else
|
655
|
-
|
700
|
+
rb_io_t *fptr;
|
656
701
|
#endif
|
657
702
|
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
703
|
+
GetOpenFile(a, fptr);
|
704
|
+
rb_io_check_readable(fptr);
|
705
|
+
} else if (rb_respond_to(a, id_closed)) {
|
706
|
+
VALUE iv = rb_funcall2(a, id_closed, 0, 0);
|
707
|
+
if (RTEST(iv)) {
|
708
|
+
rb_raise(rb_eArgError, "closed object");
|
709
|
+
}
|
665
710
|
}
|
666
|
-
}
|
667
|
-
|
668
|
-
|
669
|
-
struct bz_str *bzs;
|
670
|
-
VALUE res;
|
711
|
+
} else {
|
712
|
+
struct bz_str *bzs;
|
713
|
+
VALUE res;
|
671
714
|
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
715
|
+
if (!rb_respond_to(a, id_str)) {
|
716
|
+
rb_raise(rb_eArgError, "first argument must respond to #read");
|
717
|
+
}
|
718
|
+
a = rb_funcall2(a, id_str, 0, 0);
|
719
|
+
if (TYPE(a) != T_STRING) {
|
720
|
+
rb_raise(rb_eArgError, "#to_str must return a String");
|
721
|
+
}
|
722
|
+
res = Data_Make_Struct(bz_cInternal, struct bz_str,
|
723
|
+
bz_str_mark, free, bzs);
|
724
|
+
bzs->str = a;
|
725
|
+
a = res;
|
726
|
+
internal = BZ2_RB_INTERNAL;
|
684
727
|
}
|
685
728
|
Data_Get_Struct(obj, struct bz_file, bzf);
|
686
729
|
bzf->io = a;
|
@@ -689,70 +732,63 @@ bz_reader_init(argc, argv, obj)
|
|
689
732
|
return obj;
|
690
733
|
}
|
691
734
|
|
692
|
-
static struct bz_file *
|
693
|
-
bz_get_bzf(obj)
|
694
|
-
VALUE obj;
|
695
|
-
{
|
735
|
+
static struct bz_file * bz_get_bzf(VALUE obj) {
|
696
736
|
struct bz_file *bzf;
|
697
737
|
|
698
738
|
Get_BZ2(obj, bzf);
|
699
739
|
if (!bzf->buf) {
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
740
|
+
if (bzf->state != BZ_OK) {
|
741
|
+
bz_raise(bzf->state);
|
742
|
+
}
|
743
|
+
bzf->state = BZ2_bzDecompressInit(&(bzf->bzs), 0, bzf->small);
|
744
|
+
if (bzf->state != BZ_OK) {
|
745
|
+
BZ2_bzDecompressEnd(&(bzf->bzs));
|
746
|
+
bz_raise(bzf->state);
|
747
|
+
}
|
748
|
+
bzf->buf = ALLOC_N(char, BZ_RB_BLOCKSIZE + 1);
|
749
|
+
bzf->buflen = BZ_RB_BLOCKSIZE;
|
750
|
+
bzf->buf[0] = bzf->buf[bzf->buflen] = '\0';
|
751
|
+
bzf->bzs.total_out_hi32 = bzf->bzs.total_out_lo32 = 0;
|
752
|
+
bzf->bzs.next_out = bzf->buf;
|
753
|
+
bzf->bzs.avail_out = 0;
|
714
754
|
}
|
715
755
|
if (bzf->state == BZ_STREAM_END && !bzf->bzs.avail_out) {
|
716
|
-
|
756
|
+
return 0;
|
717
757
|
}
|
718
758
|
return bzf;
|
719
759
|
}
|
720
760
|
|
721
|
-
static int
|
722
|
-
bz_next_available(bzf, in)
|
723
|
-
struct bz_file *bzf;
|
724
|
-
int in;
|
725
|
-
{
|
761
|
+
static int bz_next_available(struct bz_file *bzf, int in){
|
726
762
|
bzf->bzs.next_out = bzf->buf;
|
727
763
|
bzf->bzs.avail_out = 0;
|
728
764
|
if (bzf->state == BZ_STREAM_END) {
|
729
|
-
|
765
|
+
return BZ_STREAM_END;
|
730
766
|
}
|
731
767
|
if (!bzf->bzs.avail_in) {
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
768
|
+
bzf->in = rb_funcall(bzf->io, id_read, 1, INT2FIX(1024));
|
769
|
+
if (TYPE(bzf->in) != T_STRING || RSTRING_LEN(bzf->in) == 0) {
|
770
|
+
BZ2_bzDecompressEnd(&(bzf->bzs));
|
771
|
+
bzf->bzs.avail_out = 0;
|
772
|
+
bzf->state = BZ_UNEXPECTED_EOF;
|
773
|
+
bz_raise(bzf->state);
|
774
|
+
}
|
775
|
+
bzf->bzs.next_in = RSTRING_PTR(bzf->in);
|
776
|
+
bzf->bzs.avail_in = RSTRING_LEN(bzf->in);
|
741
777
|
}
|
742
778
|
if ((bzf->buflen - in) < (BZ_RB_BLOCKSIZE / 2)) {
|
743
|
-
|
744
|
-
|
745
|
-
|
779
|
+
bzf->buf = REALLOC_N(bzf->buf, char, bzf->buflen+BZ_RB_BLOCKSIZE+1);
|
780
|
+
bzf->buflen += BZ_RB_BLOCKSIZE;
|
781
|
+
bzf->buf[bzf->buflen] = '\0';
|
746
782
|
}
|
747
783
|
bzf->bzs.avail_out = bzf->buflen - in;
|
748
784
|
bzf->bzs.next_out = bzf->buf + in;
|
749
785
|
bzf->state = BZ2_bzDecompress(&(bzf->bzs));
|
750
786
|
if (bzf->state != BZ_OK) {
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
|
787
|
+
BZ2_bzDecompressEnd(&(bzf->bzs));
|
788
|
+
if (bzf->state != BZ_STREAM_END) {
|
789
|
+
bzf->bzs.avail_out = 0;
|
790
|
+
bz_raise(bzf->state);
|
791
|
+
}
|
756
792
|
}
|
757
793
|
bzf->bzs.avail_out = bzf->buflen - bzf->bzs.avail_out;
|
758
794
|
bzf->bzs.next_out = bzf->buf;
|
@@ -761,101 +797,99 @@ bz_next_available(bzf, in)
|
|
761
797
|
|
762
798
|
#define ASIZE (1 << CHAR_BIT)
|
763
799
|
|
764
|
-
static VALUE
|
765
|
-
bz_read_until(bzf, str, len, td1)
|
766
|
-
struct bz_file *bzf;
|
767
|
-
char *str;
|
768
|
-
int len;
|
769
|
-
int *td1;
|
770
|
-
{
|
800
|
+
static VALUE bz_read_until(struct bz_file *bzf, const char *str, int len, int *td1) {
|
771
801
|
VALUE res;
|
772
802
|
int total, i, nex = 0;
|
773
|
-
char *p, *t, *tx, *end, *pend = str + len;
|
803
|
+
char *p, *t, *tx, *end, *pend = ((char*) str) + len;
|
774
804
|
|
775
805
|
res = rb_str_new(0, 0);
|
776
806
|
while (1) {
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
785
|
-
|
786
|
-
|
787
|
-
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
}
|
808
|
-
}
|
809
|
-
}
|
810
|
-
nex = 0;
|
811
|
-
if (total) {
|
812
|
-
nex = len - 1;
|
813
|
-
res = rb_str_cat(res, bzf->bzs.next_out, total - nex);
|
814
|
-
if (nex) {
|
815
|
-
MEMMOVE(bzf->buf, bzf->bzs.next_out + total - nex, char, nex);
|
807
|
+
total = bzf->bzs.avail_out;
|
808
|
+
if (len == 1) {
|
809
|
+
tx = memchr(bzf->bzs.next_out, *str, bzf->bzs.avail_out);
|
810
|
+
if (tx) {
|
811
|
+
i = tx - bzf->bzs.next_out + len;
|
812
|
+
res = rb_str_cat(res, bzf->bzs.next_out, i);
|
813
|
+
bzf->bzs.next_out += i;
|
814
|
+
bzf->bzs.avail_out -= i;
|
815
|
+
return res;
|
816
|
+
}
|
817
|
+
} else {
|
818
|
+
tx = bzf->bzs.next_out;
|
819
|
+
end = bzf->bzs.next_out + bzf->bzs.avail_out;
|
820
|
+
while (tx + len <= end) {
|
821
|
+
for (p = (char*) str, t = tx; p != pend; ++p, ++t) {
|
822
|
+
if (*p != *t) break;
|
823
|
+
}
|
824
|
+
if (p == pend) {
|
825
|
+
i = tx - bzf->bzs.next_out + len;
|
826
|
+
res = rb_str_cat(res, bzf->bzs.next_out, i);
|
827
|
+
bzf->bzs.next_out += i;
|
828
|
+
bzf->bzs.avail_out -= i;
|
829
|
+
return res;
|
830
|
+
}
|
831
|
+
if (td1) {
|
832
|
+
tx += td1[(int)*(tx + len)];
|
833
|
+
} else {
|
834
|
+
tx += 1;
|
835
|
+
}
|
836
|
+
}
|
816
837
|
}
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
838
|
+
nex = 0;
|
839
|
+
if (total) {
|
840
|
+
nex = len - 1;
|
841
|
+
res = rb_str_cat(res, bzf->bzs.next_out, total - nex);
|
842
|
+
if (nex) {
|
843
|
+
MEMMOVE(bzf->buf, bzf->bzs.next_out + total - nex, char, nex);
|
844
|
+
}
|
821
845
|
}
|
822
|
-
if (
|
823
|
-
|
846
|
+
if (bz_next_available(bzf, nex) == BZ_STREAM_END) {
|
847
|
+
if (nex) {
|
848
|
+
res = rb_str_cat(res, bzf->buf, nex);
|
849
|
+
}
|
850
|
+
if (RSTRING_LEN(res)) {
|
851
|
+
return res;
|
852
|
+
}
|
853
|
+
return Qnil;
|
824
854
|
}
|
825
|
-
return Qnil;
|
826
|
-
}
|
827
855
|
}
|
828
856
|
return Qnil;
|
829
857
|
}
|
830
858
|
|
831
|
-
static int
|
832
|
-
bz_read_while(bzf, c)
|
833
|
-
struct bz_file *bzf;
|
834
|
-
char c;
|
835
|
-
{
|
859
|
+
static int bz_read_while(struct bz_file *bzf, char c) {
|
836
860
|
char *end;
|
837
861
|
|
838
862
|
while (1) {
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
863
|
+
end = bzf->bzs.next_out + bzf->bzs.avail_out;
|
864
|
+
while (bzf->bzs.next_out < end) {
|
865
|
+
if (c != *bzf->bzs.next_out) {
|
866
|
+
bzf->bzs.avail_out = end - bzf->bzs.next_out;
|
867
|
+
return *bzf->bzs.next_out;
|
868
|
+
}
|
869
|
+
++bzf->bzs.next_out;
|
870
|
+
}
|
871
|
+
if (bz_next_available(bzf, 0) == BZ_STREAM_END) {
|
872
|
+
return EOF;
|
844
873
|
}
|
845
|
-
++bzf->bzs.next_out;
|
846
|
-
}
|
847
|
-
if (bz_next_available(bzf, 0) == BZ_STREAM_END) {
|
848
|
-
return EOF;
|
849
|
-
}
|
850
874
|
}
|
851
875
|
return EOF;
|
852
876
|
}
|
853
877
|
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
878
|
+
/*
|
879
|
+
* call-seq:
|
880
|
+
* read(len = nil)
|
881
|
+
*
|
882
|
+
* Read decompressed data from the stream.
|
883
|
+
*
|
884
|
+
* Bzip2::Reader.new(Bzip2.compress('ab')).read # => "ab"
|
885
|
+
* Bzip2::Reader.new(Bzip2.compress('ab')).read(1) # => "a"
|
886
|
+
*
|
887
|
+
* @return [String, nil] the decompressed data read or +nil+ if eoz has been
|
888
|
+
* reached
|
889
|
+
* @param [Integer] len the number of decompressed bytes which should be read.
|
890
|
+
* If nothing is specified, the entire stream is read
|
891
|
+
*/
|
892
|
+
static VALUE bz_reader_read(int argc, VALUE *argv, VALUE obj) {
|
859
893
|
struct bz_file *bzf;
|
860
894
|
VALUE res, length;
|
861
895
|
int total;
|
@@ -863,449 +897,552 @@ bz_reader_read(argc, argv, obj)
|
|
863
897
|
|
864
898
|
rb_scan_args(argc, argv, "01", &length);
|
865
899
|
if (NIL_P(length)) {
|
866
|
-
|
867
|
-
}
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
}
|
900
|
+
n = -1;
|
901
|
+
} else {
|
902
|
+
n = NUM2INT(length);
|
903
|
+
if (n < 0) {
|
904
|
+
rb_raise(rb_eArgError, "negative length %d given", n);
|
905
|
+
}
|
873
906
|
}
|
874
907
|
bzf = bz_get_bzf(obj);
|
875
908
|
if (!bzf) {
|
876
|
-
|
909
|
+
return Qnil;
|
877
910
|
}
|
878
911
|
res = rb_str_new(0, 0);
|
879
912
|
if (OBJ_TAINTED(obj)) {
|
880
|
-
|
913
|
+
OBJ_TAINT(res);
|
881
914
|
}
|
882
915
|
if (n == 0) {
|
883
|
-
return res;
|
884
|
-
}
|
885
|
-
while (1) {
|
886
|
-
total = bzf->bzs.avail_out;
|
887
|
-
if (n != -1 && (RSTRING_LEN(res) + total) >= n) {
|
888
|
-
n -= RSTRING_LEN(res);
|
889
|
-
res = rb_str_cat(res, bzf->bzs.next_out, n);
|
890
|
-
bzf->bzs.next_out += n;
|
891
|
-
bzf->bzs.avail_out -= n;
|
892
|
-
return res;
|
893
|
-
}
|
894
|
-
if (total) {
|
895
|
-
res = rb_str_cat(res, bzf->bzs.next_out, total);
|
896
|
-
}
|
897
|
-
if (bz_next_available(bzf, 0) == BZ_STREAM_END) {
|
898
916
|
return res;
|
899
917
|
}
|
918
|
+
while (1) {
|
919
|
+
total = bzf->bzs.avail_out;
|
920
|
+
if (n != -1 && (RSTRING_LEN(res) + total) >= n) {
|
921
|
+
n -= RSTRING_LEN(res);
|
922
|
+
res = rb_str_cat(res, bzf->bzs.next_out, n);
|
923
|
+
bzf->bzs.next_out += n;
|
924
|
+
bzf->bzs.avail_out -= n;
|
925
|
+
return res;
|
926
|
+
}
|
927
|
+
if (total) {
|
928
|
+
res = rb_str_cat(res, bzf->bzs.next_out, total);
|
929
|
+
}
|
930
|
+
if (bz_next_available(bzf, 0) == BZ_STREAM_END) {
|
931
|
+
return res;
|
932
|
+
}
|
900
933
|
}
|
901
934
|
return Qnil;
|
902
935
|
}
|
903
936
|
|
904
|
-
static int
|
905
|
-
bz_getc(obj)
|
906
|
-
VALUE obj;
|
907
|
-
{
|
937
|
+
static int bz_getc(VALUE obj) {
|
908
938
|
VALUE length = INT2FIX(1);
|
909
939
|
VALUE res = bz_reader_read(1, &length, obj);
|
910
940
|
if (NIL_P(res) || RSTRING_LEN(res) == 0) {
|
911
|
-
|
941
|
+
return EOF;
|
912
942
|
}
|
913
943
|
return RSTRING_PTR(res)[0];
|
914
944
|
}
|
915
945
|
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
946
|
+
/*
|
947
|
+
* call-seq:
|
948
|
+
* ungetc(byte)
|
949
|
+
*
|
950
|
+
* "Ungets" a character/byte. This rewinds the stream by 1 character and inserts
|
951
|
+
* the given character into that position. The next read will return the given
|
952
|
+
* character as the first one read
|
953
|
+
*
|
954
|
+
* reader = Bzip2::Reader.new Bzip2.compress('abc')
|
955
|
+
* reader.getc # => 97
|
956
|
+
* reader.ungetc 97 # => nil
|
957
|
+
* reader.getc # => 97
|
958
|
+
* reader.ungetc 42 # => nil
|
959
|
+
* reader.getc # => 42
|
960
|
+
* reader.getc # => 98
|
961
|
+
* reader.getc # => 99
|
962
|
+
* reader.ungetc 100 # => nil
|
963
|
+
* reader.getc # => 100
|
964
|
+
*
|
965
|
+
* @param [Integer] byte the byte to 'unget'
|
966
|
+
* @return [nil] always
|
967
|
+
*/
|
968
|
+
static VALUE bz_reader_ungetc(VALUE obj, VALUE a) {
|
920
969
|
struct bz_file *bzf;
|
921
970
|
int c = NUM2INT(a);
|
922
971
|
|
923
972
|
Get_BZ2(obj, bzf);
|
924
973
|
if (!bzf->buf) {
|
925
|
-
|
974
|
+
bz_raise(BZ_SEQUENCE_ERROR);
|
926
975
|
}
|
927
976
|
if (bzf->bzs.avail_out < bzf->buflen) {
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
}
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
bzf->bzs.avail_out = bzf->buflen;
|
977
|
+
bzf->bzs.next_out -= 1;
|
978
|
+
bzf->bzs.next_out[0] = c;
|
979
|
+
bzf->bzs.avail_out += 1;
|
980
|
+
} else {
|
981
|
+
bzf->buf = REALLOC_N(bzf->buf, char, bzf->buflen + 2);
|
982
|
+
bzf->buf[bzf->buflen++] = c;
|
983
|
+
bzf->buf[bzf->buflen] = '\0';
|
984
|
+
bzf->bzs.next_out = bzf->buf;
|
985
|
+
bzf->bzs.avail_out = bzf->buflen;
|
938
986
|
}
|
939
987
|
return Qnil;
|
940
988
|
}
|
941
989
|
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
990
|
+
/*
|
991
|
+
* call-seq:
|
992
|
+
* ungets(str)
|
993
|
+
*
|
994
|
+
* Equivalently "unget" a string. When called on a string that was just read
|
995
|
+
* from the stream, this inserts the string back into the stream to br read
|
996
|
+
* again.
|
997
|
+
*
|
998
|
+
* When called with a string which hasn't been read from the stream, it does
|
999
|
+
* the same thing, and the next read line/data will start from the beginning
|
1000
|
+
* of the given data and the continue on with the rest of the stream.
|
1001
|
+
*
|
1002
|
+
* reader = Bzip2::Reader.new Bzip2.compress("a\nb")
|
1003
|
+
* reader.gets # => "a\n"
|
1004
|
+
* reader.ungets "a\n" # => nil
|
1005
|
+
* reader.gets # => "a\n"
|
1006
|
+
* reader.ungets "foo" # => nil
|
1007
|
+
* reader.gets # => "foob"
|
1008
|
+
*
|
1009
|
+
* @param [String] str the string to insert back into the stream
|
1010
|
+
* @return [nil] always
|
1011
|
+
*/
|
1012
|
+
static VALUE bz_reader_ungets(VALUE obj, VALUE a) {
|
946
1013
|
struct bz_file *bzf;
|
947
1014
|
|
948
1015
|
Check_Type(a, T_STRING);
|
949
1016
|
Get_BZ2(obj, bzf);
|
950
1017
|
if (!bzf->buf) {
|
951
|
-
|
1018
|
+
bz_raise(BZ_SEQUENCE_ERROR);
|
952
1019
|
}
|
953
1020
|
if ((bzf->bzs.avail_out + RSTRING_LEN(a)) < bzf->buflen) {
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
}
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
bzf->bzs.avail_out = bzf->buflen;
|
1021
|
+
bzf->bzs.next_out -= RSTRING_LEN(a);
|
1022
|
+
MEMCPY(bzf->bzs.next_out, RSTRING_PTR(a), char, RSTRING_LEN(a));
|
1023
|
+
bzf->bzs.avail_out += RSTRING_LEN(a);
|
1024
|
+
} else {
|
1025
|
+
bzf->buf = REALLOC_N(bzf->buf, char, bzf->buflen + RSTRING_LEN(a) + 1);
|
1026
|
+
MEMCPY(bzf->buf + bzf->buflen, RSTRING_PTR(a), char,RSTRING_LEN(a));
|
1027
|
+
bzf->buflen += RSTRING_LEN(a);
|
1028
|
+
bzf->buf[bzf->buflen] = '\0';
|
1029
|
+
bzf->bzs.next_out = bzf->buf;
|
1030
|
+
bzf->bzs.avail_out = bzf->buflen;
|
965
1031
|
}
|
966
1032
|
return Qnil;
|
967
1033
|
}
|
968
1034
|
|
969
|
-
VALUE
|
970
|
-
bz_reader_gets(obj)
|
971
|
-
VALUE obj;
|
972
|
-
{
|
1035
|
+
VALUE bz_reader_gets(VALUE obj) {
|
973
1036
|
struct bz_file *bzf;
|
974
1037
|
VALUE str = Qnil;
|
975
1038
|
|
976
1039
|
bzf = bz_get_bzf(obj);
|
977
1040
|
if (bzf) {
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
1041
|
+
str = bz_read_until(bzf, "\n", 1, 0);
|
1042
|
+
if (!NIL_P(str)) {
|
1043
|
+
bzf->lineno++;
|
1044
|
+
OBJ_TAINT(str);
|
1045
|
+
}
|
983
1046
|
}
|
984
1047
|
return str;
|
985
1048
|
}
|
986
1049
|
|
987
|
-
static VALUE
|
988
|
-
bz_reader_gets_internal(argc, argv, obj, td, init)
|
989
|
-
int argc;
|
990
|
-
VALUE obj, *argv;
|
991
|
-
int *td, init;
|
992
|
-
{
|
1050
|
+
static VALUE bz_reader_gets_internal(int argc, VALUE *argv, VALUE obj, int *td, int init) {
|
993
1051
|
struct bz_file *bzf;
|
994
1052
|
VALUE rs, res;
|
995
|
-
char *rsptr;
|
1053
|
+
const char *rsptr;
|
996
1054
|
int rslen, rspara, *td1;
|
997
1055
|
|
998
1056
|
rs = rb_rs;
|
999
1057
|
if (argc) {
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1058
|
+
rb_scan_args(argc, argv, "1", &rs);
|
1059
|
+
if (!NIL_P(rs)) {
|
1060
|
+
Check_Type(rs, T_STRING);
|
1061
|
+
}
|
1004
1062
|
}
|
1005
1063
|
if (NIL_P(rs)) {
|
1006
|
-
|
1064
|
+
return bz_reader_read(1, &rs, obj);
|
1007
1065
|
}
|
1008
1066
|
rslen = RSTRING_LEN(rs);
|
1009
1067
|
if (rs == rb_default_rs || (rslen == 1 && RSTRING_PTR(rs)[0] == '\n')) {
|
1010
|
-
|
1068
|
+
return bz_reader_gets(obj);
|
1011
1069
|
}
|
1012
1070
|
|
1013
1071
|
if (rslen == 0) {
|
1014
|
-
|
1015
|
-
|
1016
|
-
|
1017
|
-
}
|
1018
|
-
|
1019
|
-
|
1020
|
-
rspara = 0;
|
1072
|
+
rsptr = "\n\n";
|
1073
|
+
rslen = 2;
|
1074
|
+
rspara = 1;
|
1075
|
+
} else {
|
1076
|
+
rsptr = RSTRING_PTR(rs);
|
1077
|
+
rspara = 0;
|
1021
1078
|
}
|
1022
1079
|
|
1023
1080
|
bzf = bz_get_bzf(obj);
|
1024
1081
|
if (!bzf) {
|
1025
|
-
|
1082
|
+
return Qnil;
|
1026
1083
|
}
|
1027
1084
|
if (rspara) {
|
1028
|
-
|
1085
|
+
bz_read_while(bzf, '\n');
|
1029
1086
|
}
|
1030
1087
|
td1 = 0;
|
1031
1088
|
if (rslen != 1) {
|
1032
|
-
|
1033
|
-
|
1089
|
+
if (init) {
|
1090
|
+
int i;
|
1034
1091
|
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1092
|
+
for (i = 0; i < ASIZE; i++) {
|
1093
|
+
td[i] = rslen + 1;
|
1094
|
+
}
|
1095
|
+
for (i = 0; i < rslen; i++) {
|
1096
|
+
td[(int)*(rsptr + i)] = rslen - i;
|
1097
|
+
}
|
1040
1098
|
}
|
1041
|
-
|
1042
|
-
td1 = td;
|
1099
|
+
td1 = td;
|
1043
1100
|
}
|
1044
1101
|
|
1045
1102
|
res = bz_read_until(bzf, rsptr, rslen, td1);
|
1046
1103
|
if (rspara) {
|
1047
|
-
|
1104
|
+
bz_read_while(bzf, '\n');
|
1048
1105
|
}
|
1049
1106
|
|
1050
1107
|
if (!NIL_P(res)) {
|
1051
|
-
|
1052
|
-
|
1108
|
+
bzf->lineno++;
|
1109
|
+
OBJ_TAINT(res);
|
1053
1110
|
}
|
1054
1111
|
return res;
|
1055
1112
|
}
|
1056
1113
|
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1114
|
+
/*
|
1115
|
+
* Specs were missing for this method originally and playing around with it
|
1116
|
+
* gave some very odd results, so unless you know what you're doing, I wouldn't
|
1117
|
+
* mess around with this...
|
1118
|
+
*/
|
1119
|
+
static VALUE bz_reader_set_unused(VALUE obj, VALUE a) {
|
1061
1120
|
struct bz_file *bzf;
|
1062
1121
|
|
1063
1122
|
Check_Type(a, T_STRING);
|
1064
1123
|
Get_BZ2(obj, bzf);
|
1065
1124
|
if (!bzf->in) {
|
1066
|
-
|
1067
|
-
}
|
1068
|
-
|
1069
|
-
bzf->in = rb_str_cat(bzf->in, RSTRING_PTR(a), RSTRING_LEN(a));
|
1125
|
+
bzf->in = rb_str_new(RSTRING_PTR(a), RSTRING_LEN(a));
|
1126
|
+
} else {
|
1127
|
+
bzf->in = rb_str_cat(bzf->in, RSTRING_PTR(a), RSTRING_LEN(a));
|
1070
1128
|
}
|
1071
1129
|
bzf->bzs.next_in = RSTRING_PTR(bzf->in);
|
1072
1130
|
bzf->bzs.avail_in = RSTRING_LEN(bzf->in);
|
1073
1131
|
return Qnil;
|
1074
1132
|
}
|
1075
1133
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1134
|
+
/*
|
1135
|
+
* Reads one character from the stream, returning the byte read.
|
1136
|
+
*
|
1137
|
+
* reader = Bzip2::Reader.new Bzip2.compress('ab')
|
1138
|
+
* reader.getc # => 97
|
1139
|
+
* reader.getc # => 98
|
1140
|
+
* reader.getc # => nil
|
1141
|
+
*
|
1142
|
+
* @return [Integer, nil] the byte value of the character read or +nil+ if eoz
|
1143
|
+
* has been reached
|
1144
|
+
*/
|
1145
|
+
static VALUE bz_reader_getc(VALUE obj) {
|
1080
1146
|
VALUE str;
|
1081
1147
|
VALUE len = INT2FIX(1);
|
1082
1148
|
|
1083
1149
|
str = bz_reader_read(1, &len, obj);
|
1084
1150
|
if (NIL_P(str) || RSTRING_LEN(str) == 0) {
|
1085
|
-
|
1151
|
+
return Qnil;
|
1086
1152
|
}
|
1087
1153
|
return INT2FIX(RSTRING_PTR(str)[0] & 0xff);
|
1088
1154
|
}
|
1089
1155
|
|
1090
|
-
static void
|
1091
|
-
bz_eoz_error()
|
1092
|
-
{
|
1156
|
+
static void bz_eoz_error() {
|
1093
1157
|
rb_raise(bz_eEOZError, "End of Zip component reached");
|
1094
1158
|
}
|
1095
1159
|
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1160
|
+
/*
|
1161
|
+
* Performs the same as Bzip2::Reader#getc except Bzip2::EOZError is raised if
|
1162
|
+
* eoz has been readhed
|
1163
|
+
*
|
1164
|
+
* @raise [Bzip2::EOZError] if eoz has been reached
|
1165
|
+
*/
|
1166
|
+
static VALUE bz_reader_readchar(VALUE obj) {
|
1100
1167
|
VALUE res = bz_reader_getc(obj);
|
1101
1168
|
|
1102
1169
|
if (NIL_P(res)) {
|
1103
|
-
|
1170
|
+
bz_eoz_error();
|
1104
1171
|
}
|
1105
1172
|
return res;
|
1106
1173
|
}
|
1107
1174
|
|
1108
|
-
|
1109
|
-
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1175
|
+
/*
|
1176
|
+
* call-seq:
|
1177
|
+
* gets(sep = "\n")
|
1178
|
+
*
|
1179
|
+
* Reads a line from the stream until the separator is reached. This does not
|
1180
|
+
* throw an exception, but rather returns nil if an eoz/eof error occurs
|
1181
|
+
*
|
1182
|
+
* reader = Bzip2::Reader.new Bzip2.compress("a\nb")
|
1183
|
+
* reader.gets # => "a\n"
|
1184
|
+
* reader.gets # => "b"
|
1185
|
+
* reader.gets # => nil
|
1186
|
+
*
|
1187
|
+
* @return [String, nil] the read data or nil if eoz has been reached
|
1188
|
+
* @see Bzip2::Reader#readline
|
1189
|
+
*/
|
1190
|
+
static VALUE bz_reader_gets_m(int argc, VALUE *argv, VALUE obj) {
|
1113
1191
|
int td[ASIZE];
|
1114
1192
|
VALUE str = bz_reader_gets_internal(argc, argv, obj, td, Qtrue);
|
1115
1193
|
|
1116
1194
|
if (!NIL_P(str)) {
|
1117
|
-
|
1195
|
+
rb_lastline_set(str);
|
1118
1196
|
}
|
1119
1197
|
return str;
|
1120
1198
|
}
|
1121
1199
|
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1200
|
+
/*
|
1201
|
+
* call-seq:
|
1202
|
+
* readline(sep = "\n")
|
1203
|
+
*
|
1204
|
+
* Reads one line from the stream and returns it (including the separator)
|
1205
|
+
*
|
1206
|
+
* reader = Bzip2::Reader.new Bzip2.compress("a\nb")
|
1207
|
+
* reader.readline # => "a\n"
|
1208
|
+
* reader.readline # => "b"
|
1209
|
+
* reader.readline # => raises Bzip2::EOZError
|
1210
|
+
*
|
1211
|
+
*
|
1212
|
+
* @param [String] sep the newline separator character
|
1213
|
+
* @return [String] the read line
|
1214
|
+
* @see Bzip2::Reader.readlines
|
1215
|
+
* @raise [Bzip2::EOZError] if the stream has reached its end
|
1216
|
+
*/
|
1217
|
+
static VALUE bz_reader_readline(int argc, VALUE *argv, VALUE obj) {
|
1127
1218
|
VALUE res = bz_reader_gets_m(argc, argv, obj);
|
1128
1219
|
|
1129
1220
|
if (NIL_P(res)) {
|
1130
|
-
|
1221
|
+
bz_eoz_error();
|
1131
1222
|
}
|
1132
1223
|
return res;
|
1133
1224
|
}
|
1134
1225
|
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1226
|
+
/*
|
1227
|
+
* call-seq:
|
1228
|
+
* readlines(sep = "\n")
|
1229
|
+
*
|
1230
|
+
* Reads the lines of the files and returns the result as an array.
|
1231
|
+
*
|
1232
|
+
* If the stream has reached eoz, then an empty array is returned
|
1233
|
+
*
|
1234
|
+
* @param [String] sep the newline separator character
|
1235
|
+
* @return [Array] an array of lines read
|
1236
|
+
* @see Bzip2::Reader.readlines
|
1237
|
+
*/
|
1238
|
+
static VALUE bz_reader_readlines(int argc, VALUE *argv, VALUE obj) {
|
1140
1239
|
VALUE line, ary;
|
1141
1240
|
int td[ASIZE], in;
|
1142
1241
|
|
1143
1242
|
in = Qtrue;
|
1144
1243
|
ary = rb_ary_new();
|
1145
1244
|
while (!NIL_P(line = bz_reader_gets_internal(argc, argv, obj, td, in))) {
|
1146
|
-
|
1147
|
-
|
1245
|
+
in = Qfalse;
|
1246
|
+
rb_ary_push(ary, line);
|
1148
1247
|
}
|
1149
1248
|
return ary;
|
1150
1249
|
}
|
1151
1250
|
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1251
|
+
/*
|
1252
|
+
* call-seq:
|
1253
|
+
* each(sep = "\n", &block)
|
1254
|
+
*
|
1255
|
+
* Iterates over the lines of the stream.
|
1256
|
+
*
|
1257
|
+
* @param [String] sep the byte which separates lines
|
1258
|
+
* @yieldparam [String] line the next line of the file (including the separator
|
1259
|
+
* character)
|
1260
|
+
* @see Bzip2::Reader.foreach
|
1261
|
+
*/
|
1262
|
+
static VALUE bz_reader_each_line(int argc, VALUE *argv, VALUE obj) {
|
1157
1263
|
VALUE line;
|
1158
1264
|
int td[ASIZE], in;
|
1159
1265
|
|
1160
1266
|
in = Qtrue;
|
1161
1267
|
while (!NIL_P(line = bz_reader_gets_internal(argc, argv, obj, td, in))) {
|
1162
|
-
|
1163
|
-
|
1268
|
+
in = Qfalse;
|
1269
|
+
rb_yield(line);
|
1164
1270
|
}
|
1165
1271
|
return obj;
|
1166
1272
|
}
|
1167
1273
|
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1274
|
+
/*
|
1275
|
+
* call-seq:
|
1276
|
+
* each_byte(&block)
|
1277
|
+
*
|
1278
|
+
* Iterates over the decompressed bytes of the file.
|
1279
|
+
*
|
1280
|
+
* Bzip2::Writer.open('file'){ |f| f << 'asdf' }
|
1281
|
+
* reader = Bzip2::Reader.new File.open('file')
|
1282
|
+
* reader.each_byte{ |b| puts "#{b} #{b.chr}" }
|
1283
|
+
*
|
1284
|
+
* # Output:
|
1285
|
+
* # 97 a
|
1286
|
+
* # 115 s
|
1287
|
+
* # 100 d
|
1288
|
+
* # 102 f
|
1289
|
+
*
|
1290
|
+
* @yieldparam [Integer] byte the decompressed bytes of the file
|
1291
|
+
*/
|
1292
|
+
static VALUE bz_reader_each_byte(VALUE obj) {
|
1172
1293
|
int c;
|
1173
1294
|
|
1174
1295
|
while ((c = bz_getc(obj)) != EOF) {
|
1175
|
-
|
1296
|
+
rb_yield(INT2FIX(c & 0xff));
|
1176
1297
|
}
|
1177
1298
|
return obj;
|
1178
1299
|
}
|
1179
1300
|
|
1180
|
-
|
1181
|
-
|
1182
|
-
|
1183
|
-
|
1301
|
+
/*
|
1302
|
+
* Specs were missing for this method originally and playing around with it
|
1303
|
+
* gave some very odd results, so unless you know what you're doing, I wouldn't
|
1304
|
+
* mess around with this...
|
1305
|
+
*/
|
1306
|
+
static VALUE bz_reader_unused(VALUE obj) {
|
1184
1307
|
struct bz_file *bzf;
|
1185
1308
|
VALUE res;
|
1186
1309
|
|
1187
1310
|
Get_BZ2(obj, bzf);
|
1188
1311
|
if (!bzf->in || bzf->state != BZ_STREAM_END) {
|
1189
|
-
|
1312
|
+
return Qnil;
|
1190
1313
|
}
|
1191
1314
|
if (bzf->bzs.avail_in) {
|
1192
|
-
|
1193
|
-
|
1194
|
-
}
|
1195
|
-
|
1196
|
-
res = rb_tainted_str_new(0, 0);
|
1315
|
+
res = rb_tainted_str_new(bzf->bzs.next_in, bzf->bzs.avail_in);
|
1316
|
+
bzf->bzs.avail_in = 0;
|
1317
|
+
} else {
|
1318
|
+
res = rb_tainted_str_new(0, 0);
|
1197
1319
|
}
|
1198
1320
|
return res;
|
1199
1321
|
}
|
1200
1322
|
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1323
|
+
/*
|
1324
|
+
* Test whether the end of the bzip stream has been reached
|
1325
|
+
*
|
1326
|
+
* @return [Boolean] +true+ if the reader is at the end of the bz stream or
|
1327
|
+
* +false+ otherwise
|
1328
|
+
*/
|
1329
|
+
static VALUE bz_reader_eoz(VALUE obj) {
|
1205
1330
|
struct bz_file *bzf;
|
1206
1331
|
|
1207
1332
|
Get_BZ2(obj, bzf);
|
1208
1333
|
if (!bzf->in || !bzf->buf) {
|
1209
|
-
|
1334
|
+
return Qnil;
|
1210
1335
|
}
|
1211
1336
|
if (bzf->state == BZ_STREAM_END && !bzf->bzs.avail_out) {
|
1212
|
-
|
1337
|
+
return Qtrue;
|
1213
1338
|
}
|
1214
1339
|
return Qfalse;
|
1215
1340
|
}
|
1216
1341
|
|
1217
|
-
|
1218
|
-
|
1219
|
-
|
1220
|
-
|
1342
|
+
/*
|
1343
|
+
* Test whether the bzip stream has reached its end (see Bzip2::Reader#eoz?)
|
1344
|
+
* and then tests that the undlerying IO has also reached an eof
|
1345
|
+
*
|
1346
|
+
* @return [Boolean] +true+ if the stream has reached or +false+ otherwise.
|
1347
|
+
*/
|
1348
|
+
static VALUE bz_reader_eof(VALUE obj) {
|
1221
1349
|
struct bz_file *bzf;
|
1222
1350
|
VALUE res;
|
1223
1351
|
|
1224
1352
|
res = bz_reader_eoz(obj);
|
1225
1353
|
if (RTEST(res)) {
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
res = Qfalse;
|
1354
|
+
Get_BZ2(obj, bzf);
|
1355
|
+
if (bzf->bzs.avail_in) {
|
1356
|
+
res = Qfalse;
|
1357
|
+
} else {
|
1358
|
+
res = bz_reader_getc(obj);
|
1359
|
+
if (NIL_P(res)) {
|
1360
|
+
res = Qtrue;
|
1361
|
+
} else {
|
1362
|
+
bz_reader_ungetc(obj, res);
|
1363
|
+
res = Qfalse;
|
1364
|
+
}
|
1238
1365
|
}
|
1239
1366
|
}
|
1240
|
-
}
|
1241
1367
|
return res;
|
1242
1368
|
}
|
1243
1369
|
|
1244
|
-
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1370
|
+
/*
|
1371
|
+
* Tests whether this reader has be closed.
|
1372
|
+
*
|
1373
|
+
* @return [Boolean] +true+ if it is or +false+ otherwise.
|
1374
|
+
*/
|
1375
|
+
static VALUE bz_reader_closed(VALUE obj) {
|
1248
1376
|
struct bz_file *bzf;
|
1249
1377
|
|
1250
1378
|
Data_Get_Struct(obj, struct bz_file, bzf);
|
1251
1379
|
return RTEST(bzf->io)?Qfalse:Qtrue;
|
1252
1380
|
}
|
1253
1381
|
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
-
|
1382
|
+
/*
|
1383
|
+
* Closes this reader to disallow further reads.
|
1384
|
+
*
|
1385
|
+
* reader = Bzip2::Reader.new File.open('file')
|
1386
|
+
* reader.close
|
1387
|
+
*
|
1388
|
+
* reader.closed? # => true
|
1389
|
+
*
|
1390
|
+
* @return [File] the io with which the reader was created.
|
1391
|
+
* @raise [IOError] if the stream has already been closed
|
1392
|
+
*/
|
1393
|
+
static VALUE bz_reader_close(VALUE obj) {
|
1258
1394
|
struct bz_file *bzf;
|
1259
1395
|
VALUE res;
|
1260
1396
|
|
1261
1397
|
Get_BZ2(obj, bzf);
|
1262
1398
|
if (bzf->buf) {
|
1263
|
-
|
1264
|
-
|
1399
|
+
free(bzf->buf);
|
1400
|
+
bzf->buf = 0;
|
1265
1401
|
}
|
1266
1402
|
if (bzf->state == BZ_OK) {
|
1267
|
-
|
1403
|
+
BZ2_bzDecompressEnd(&(bzf->bzs));
|
1268
1404
|
}
|
1269
1405
|
if (bzf->flags & BZ2_RB_CLOSE) {
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1406
|
+
int closed = 0;
|
1407
|
+
if (rb_respond_to(bzf->io, id_closed)) {
|
1408
|
+
VALUE iv = rb_funcall2(bzf->io, id_closed, 0, 0);
|
1409
|
+
closed = RTEST(iv);
|
1410
|
+
}
|
1411
|
+
if (!closed && rb_respond_to(bzf->io, id_close)) {
|
1412
|
+
rb_funcall2(bzf->io, id_close, 0, 0);
|
1413
|
+
}
|
1278
1414
|
}
|
1279
1415
|
if (bzf->flags & (BZ2_RB_CLOSE|BZ2_RB_INTERNAL)) {
|
1280
|
-
|
1281
|
-
}
|
1282
|
-
|
1283
|
-
res = bzf->io;
|
1416
|
+
res = Qnil;
|
1417
|
+
} else {
|
1418
|
+
res = bzf->io;
|
1284
1419
|
}
|
1285
1420
|
bzf->io = 0;
|
1286
1421
|
return res;
|
1287
1422
|
}
|
1288
1423
|
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1424
|
+
/*
|
1425
|
+
* Originally undocument and had no sepcs. Appears to call Bzip2::Reader#read
|
1426
|
+
* and then mark the stream as finished, but this didn't work for me...
|
1427
|
+
*/
|
1428
|
+
static VALUE bz_reader_finish(VALUE obj) {
|
1293
1429
|
struct bz_file *bzf;
|
1294
1430
|
|
1295
1431
|
Get_BZ2(obj, bzf);
|
1296
1432
|
if (bzf->buf) {
|
1297
|
-
|
1298
|
-
|
1433
|
+
rb_funcall2(obj, id_read, 0, 0);
|
1434
|
+
free(bzf->buf);
|
1299
1435
|
}
|
1300
1436
|
bzf->buf = 0;
|
1301
1437
|
bzf->state = BZ_OK;
|
1302
1438
|
return Qnil;
|
1303
1439
|
}
|
1304
1440
|
|
1305
|
-
|
1306
|
-
|
1307
|
-
|
1308
|
-
|
1441
|
+
/*
|
1442
|
+
* Originally undocument and had no sepcs. Appears to work nearly the same
|
1443
|
+
* as Bzip2::Reader#close...
|
1444
|
+
*/
|
1445
|
+
static VALUE bz_reader_close_bang(VALUE obj) {
|
1309
1446
|
struct bz_file *bzf;
|
1310
1447
|
int closed;
|
1311
1448
|
|
@@ -1313,12 +1450,12 @@ bz_reader_close_bang(obj)
|
|
1313
1450
|
closed = bzf->flags & (BZ2_RB_CLOSE|BZ2_RB_INTERNAL);
|
1314
1451
|
bz_reader_close(obj);
|
1315
1452
|
if (!closed && rb_respond_to(bzf->io, id_close)) {
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1453
|
+
if (rb_respond_to(bzf->io, id_closed)) {
|
1454
|
+
closed = RTEST(rb_funcall2(bzf->io, id_closed, 0, 0));
|
1455
|
+
}
|
1456
|
+
if (!closed) {
|
1457
|
+
rb_funcall2(bzf->io, id_close, 0, 0);
|
1458
|
+
}
|
1322
1459
|
}
|
1323
1460
|
return Qnil;
|
1324
1461
|
}
|
@@ -1329,98 +1466,158 @@ struct foreach_arg {
|
|
1329
1466
|
VALUE obj;
|
1330
1467
|
};
|
1331
1468
|
|
1332
|
-
static VALUE
|
1333
|
-
bz_reader_foreach_line(arg)
|
1334
|
-
struct foreach_arg *arg;
|
1335
|
-
{
|
1469
|
+
static VALUE bz_reader_foreach_line(struct foreach_arg *arg) {
|
1336
1470
|
VALUE str;
|
1337
1471
|
int td[ASIZE], in;
|
1338
1472
|
|
1339
1473
|
in = Qtrue;
|
1340
|
-
while (!NIL_P(str = bz_reader_gets_internal(arg->argc, &arg->sep,
|
1341
|
-
|
1342
|
-
|
1343
|
-
rb_yield(str);
|
1474
|
+
while (!NIL_P(str = bz_reader_gets_internal(arg->argc, &arg->sep, arg->obj, td, in))) {
|
1475
|
+
in = Qfalse;
|
1476
|
+
rb_yield(str);
|
1344
1477
|
}
|
1345
1478
|
return Qnil;
|
1346
1479
|
}
|
1347
1480
|
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1481
|
+
/*
|
1482
|
+
* call-seq:
|
1483
|
+
* foreach(filename, &block)
|
1484
|
+
*
|
1485
|
+
* Reads a bz2 compressed file and yields each line to the block
|
1486
|
+
*
|
1487
|
+
* Bzip2::Writer.open('file'){ |f| f << "a\n" << "b\n" << "c\n\nd" }
|
1488
|
+
* Bzip2::Reader.foreach('file'){ |l| p l }
|
1489
|
+
*
|
1490
|
+
* # Output:
|
1491
|
+
* # "a\n"
|
1492
|
+
* # "b\n"
|
1493
|
+
* # "c\n"
|
1494
|
+
* # "\n"
|
1495
|
+
* # "d"
|
1496
|
+
*
|
1497
|
+
* @param [String] filename the path to the file to open
|
1498
|
+
* @yieldparam [String] each line of the file
|
1499
|
+
*/
|
1500
|
+
static VALUE bz_reader_s_foreach(int argc, VALUE *argv, VALUE obj) {
|
1353
1501
|
VALUE fname, sep;
|
1354
1502
|
struct foreach_arg arg;
|
1355
1503
|
struct bz_file *bzf;
|
1356
1504
|
|
1357
1505
|
if (!rb_block_given_p()) {
|
1358
|
-
|
1506
|
+
rb_raise(rb_eArgError, "call out of a block");
|
1359
1507
|
}
|
1360
1508
|
rb_scan_args(argc, argv, "11", &fname, &sep);
|
1509
|
+
#ifdef SafeStringValue
|
1510
|
+
SafeStringValue(fname);
|
1511
|
+
#else
|
1361
1512
|
Check_SafeStr(fname);
|
1513
|
+
#endif
|
1362
1514
|
arg.argc = argc - 1;
|
1363
1515
|
arg.sep = sep;
|
1364
1516
|
arg.obj = rb_funcall2(rb_mKernel, id_open, 1, &fname);
|
1365
|
-
if (NIL_P(arg.obj))
|
1517
|
+
if (NIL_P(arg.obj)) {
|
1518
|
+
return Qnil;
|
1519
|
+
}
|
1366
1520
|
arg.obj = rb_funcall2(obj, id_new, 1, &arg.obj);
|
1367
1521
|
Data_Get_Struct(arg.obj, struct bz_file, bzf);
|
1368
1522
|
bzf->flags |= BZ2_RB_CLOSE;
|
1369
1523
|
return rb_ensure(bz_reader_foreach_line, (VALUE)&arg, bz_reader_close, arg.obj);
|
1370
1524
|
}
|
1371
1525
|
|
1372
|
-
static VALUE
|
1373
|
-
bz_reader_i_readlines(arg)
|
1374
|
-
struct foreach_arg *arg;
|
1375
|
-
{
|
1526
|
+
static VALUE bz_reader_i_readlines(struct foreach_arg *arg) {
|
1376
1527
|
VALUE str, res;
|
1377
1528
|
int td[ASIZE], in;
|
1378
1529
|
|
1379
1530
|
in = Qtrue;
|
1380
1531
|
res = rb_ary_new();
|
1381
|
-
while (!NIL_P(str = bz_reader_gets_internal(arg->argc, &arg->sep,
|
1382
|
-
|
1383
|
-
|
1384
|
-
rb_ary_push(res, str);
|
1532
|
+
while (!NIL_P(str = bz_reader_gets_internal(arg->argc, &arg->sep, arg->obj, td, in))) {
|
1533
|
+
in = Qfalse;
|
1534
|
+
rb_ary_push(res, str);
|
1385
1535
|
}
|
1386
1536
|
return res;
|
1387
1537
|
}
|
1388
1538
|
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
|
1393
|
-
|
1539
|
+
/*
|
1540
|
+
* call-seq:
|
1541
|
+
* readlines(filename, separator="\n")
|
1542
|
+
*
|
1543
|
+
* Opens the given bz2 compressed file for reading and decompresses the file,
|
1544
|
+
* returning an array of the lines of the file. A line is denoted by the
|
1545
|
+
* separator argument.
|
1546
|
+
*
|
1547
|
+
* Bzip2::Writer.open('file'){ |f| f << "a\n" << "b\n" << "c\n\nd" }
|
1548
|
+
*
|
1549
|
+
* Bzip2::Reader.readlines('file') # => ["a\n", "b\n", "c\n", "\n", "d"]
|
1550
|
+
* Bzip2::Reader.readlines('file', 'c') # => ["a\nb\nc", "\n\nd"]
|
1551
|
+
*
|
1552
|
+
* @param [String] filename the path to the file to read
|
1553
|
+
* @param [String] separator the character to denote a newline in the file
|
1554
|
+
* @see Bzip2::Reader#readlines
|
1555
|
+
* @return [Array] an array of lines for the file
|
1556
|
+
* @raise [Bzip2::Error] if the file is not a valid bz2 compressed file
|
1557
|
+
*/
|
1558
|
+
static VALUE bz_reader_s_readlines(int argc, VALUE *argv, VALUE obj) {
|
1394
1559
|
VALUE fname, sep;
|
1395
1560
|
struct foreach_arg arg;
|
1396
1561
|
struct bz_file *bzf;
|
1397
1562
|
|
1398
1563
|
rb_scan_args(argc, argv, "11", &fname, &sep);
|
1564
|
+
#ifdef SafeStringValue
|
1565
|
+
SafeStringValue(fname);
|
1566
|
+
#else
|
1399
1567
|
Check_SafeStr(fname);
|
1568
|
+
#endif
|
1400
1569
|
arg.argc = argc - 1;
|
1401
1570
|
arg.sep = sep;
|
1402
1571
|
arg.obj = rb_funcall2(rb_mKernel, id_open, 1, &fname);
|
1403
|
-
if (NIL_P(arg.obj))
|
1572
|
+
if (NIL_P(arg.obj)) {
|
1573
|
+
return Qnil;
|
1574
|
+
}
|
1404
1575
|
arg.obj = rb_funcall2(obj, id_new, 1, &arg.obj);
|
1405
1576
|
Data_Get_Struct(arg.obj, struct bz_file, bzf);
|
1406
1577
|
bzf->flags |= BZ2_RB_CLOSE;
|
1407
1578
|
return rb_ensure(bz_reader_i_readlines, (VALUE)&arg, bz_reader_close, arg.obj);
|
1408
1579
|
}
|
1409
1580
|
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1581
|
+
/*
|
1582
|
+
* Returns the current line number that the stream is at. This number is based
|
1583
|
+
* on the newline separator being "\n"
|
1584
|
+
*
|
1585
|
+
* reader = Bzip2::Reader.new Bzip2.compress("a\nb")
|
1586
|
+
* reader.lineno # => 0
|
1587
|
+
* reader.readline # => "a\n"
|
1588
|
+
* reader.lineno # => 1
|
1589
|
+
* reader.readline # => "b"
|
1590
|
+
* reader.lineno # => 2
|
1591
|
+
|
1592
|
+
* @return [Integer] the current line number
|
1593
|
+
*/
|
1594
|
+
static VALUE bz_reader_lineno(VALUE obj) {
|
1414
1595
|
struct bz_file *bzf;
|
1415
1596
|
|
1416
1597
|
Get_BZ2(obj, bzf);
|
1417
1598
|
return INT2NUM(bzf->lineno);
|
1418
1599
|
}
|
1419
1600
|
|
1420
|
-
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1601
|
+
/*
|
1602
|
+
* call-seq:
|
1603
|
+
* lineno=(num)
|
1604
|
+
*
|
1605
|
+
* Sets the internal line number count that this stream should be set at
|
1606
|
+
*
|
1607
|
+
* reader = Bzip2::Reader.new Bzip2.compress("a\nb")
|
1608
|
+
* reader.lineno # => 0
|
1609
|
+
* reader.readline # => "a\n"
|
1610
|
+
* reader.lineno # => 1
|
1611
|
+
* reader.lineno = 0
|
1612
|
+
* reader.readline # => "b"
|
1613
|
+
* reader.lineno # => 1
|
1614
|
+
*
|
1615
|
+
* @note This does not actually rewind or move the stream forward
|
1616
|
+
* @param [Integer] lineno the line number which the stream should consider
|
1617
|
+
* being set at
|
1618
|
+
* @return [Integer] the line number provided
|
1619
|
+
*/
|
1620
|
+
static VALUE bz_reader_set_lineno(VALUE obj, VALUE lineno) {
|
1424
1621
|
struct bz_file *bzf;
|
1425
1622
|
|
1426
1623
|
Get_BZ2(obj, bzf);
|
@@ -1428,121 +1625,111 @@ bz_reader_set_lineno(obj, lineno)
|
|
1428
1625
|
return lineno;
|
1429
1626
|
}
|
1430
1627
|
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1434
|
-
|
1628
|
+
/*
|
1629
|
+
* Returns the io stream underlying this stream. If the strem was constructed
|
1630
|
+
* with a file, that is returned. Otherwise, an empty string is returned.
|
1631
|
+
*
|
1632
|
+
* @return [File, String] similar to whatever the stream was constructed with
|
1633
|
+
* @raise [IOError] if the stream has been closed
|
1634
|
+
*/
|
1635
|
+
static VALUE bz_to_io(VALUE obj) {
|
1435
1636
|
struct bz_file *bzf;
|
1436
1637
|
|
1437
1638
|
Get_BZ2(obj, bzf);
|
1438
1639
|
return bzf->io;
|
1439
1640
|
}
|
1440
1641
|
|
1441
|
-
static VALUE
|
1442
|
-
bz_str_read(argc, argv, obj)
|
1443
|
-
int argc;
|
1444
|
-
VALUE obj, *argv;
|
1445
|
-
{
|
1642
|
+
static VALUE bz_str_read(int argc, VALUE *argv, VALUE obj) {
|
1446
1643
|
struct bz_str *bzs;
|
1447
1644
|
VALUE res, len;
|
1448
1645
|
int count;
|
1449
|
-
|
1646
|
+
|
1450
1647
|
Data_Get_Struct(obj, struct bz_str, bzs);
|
1451
1648
|
rb_scan_args(argc, argv, "01", &len);
|
1452
1649
|
if (NIL_P(len)) {
|
1453
|
-
|
1454
|
-
}
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
}
|
1650
|
+
count = RSTRING_LEN(bzs->str);
|
1651
|
+
} else {
|
1652
|
+
count = NUM2INT(len);
|
1653
|
+
if (count < 0) {
|
1654
|
+
rb_raise(rb_eArgError, "negative length %d given", count);
|
1655
|
+
}
|
1460
1656
|
}
|
1461
1657
|
if (!count || bzs->pos == -1) {
|
1462
|
-
|
1658
|
+
return Qnil;
|
1463
1659
|
}
|
1464
1660
|
if ((bzs->pos + count) >= RSTRING_LEN(bzs->str)) {
|
1465
|
-
|
1466
|
-
|
1467
|
-
|
1468
|
-
}
|
1469
|
-
|
1470
|
-
|
1471
|
-
bzs->pos += count;
|
1661
|
+
res = rb_str_new(RSTRING_PTR(bzs->str) + bzs->pos,
|
1662
|
+
RSTRING_LEN(bzs->str) - bzs->pos);
|
1663
|
+
bzs->pos = -1;
|
1664
|
+
} else {
|
1665
|
+
res = rb_str_new(RSTRING_PTR(bzs->str) + bzs->pos, count);
|
1666
|
+
bzs->pos += count;
|
1472
1667
|
}
|
1473
1668
|
return res;
|
1474
1669
|
}
|
1475
1670
|
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1671
|
+
/*
|
1672
|
+
* call-seq:
|
1673
|
+
* uncompress(data)
|
1674
|
+
* Decompress a string of bz2 compressed data.
|
1675
|
+
*
|
1676
|
+
* Bzip2.uncompress Bzip2.compress('asdf') # => 'asdf'
|
1677
|
+
*
|
1678
|
+
* @param [String] data bz2 compressed data
|
1679
|
+
* @return [String] +data+ as uncompressed bz2 data
|
1680
|
+
* @raise [Bzip2::Error] if +data+ is not valid bz2 data
|
1681
|
+
*/
|
1682
|
+
static VALUE bz_uncompress(int argc, VALUE *argv, VALUE obj) {
|
1481
1683
|
VALUE bz2, nilv = Qnil;
|
1482
1684
|
|
1483
1685
|
if (!argc) {
|
1484
|
-
|
1686
|
+
rb_raise(rb_eArgError, "need a String to Uncompress");
|
1485
1687
|
}
|
1486
1688
|
argv[0] = rb_str_to_str(argv[0]);
|
1487
1689
|
bz2 = rb_funcall2(bz_cReader, id_new, argc, argv);
|
1488
1690
|
return bz_reader_read(1, &nilv, bz2);
|
1489
1691
|
}
|
1490
1692
|
|
1491
|
-
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1693
|
+
/*
|
1694
|
+
* Internally allocates data,
|
1695
|
+
*
|
1696
|
+
* @see Bzip2::Writer#initialize
|
1697
|
+
* @see Bzip2::Reader#initialize
|
1698
|
+
* @private
|
1699
|
+
*/
|
1700
|
+
static VALUE bz_s_new(int argc, VALUE *argv, VALUE obj) {
|
1496
1701
|
VALUE res = rb_funcall2(obj, rb_intern("allocate"), 0, 0);
|
1497
1702
|
rb_obj_call_init(res, argc, argv);
|
1498
1703
|
return res;
|
1499
1704
|
}
|
1500
1705
|
|
1501
|
-
|
1502
|
-
bz_proc_new(func, val)
|
1503
|
-
VALUE (*func)(ANYARGS);
|
1504
|
-
VALUE val;
|
1505
|
-
{
|
1506
|
-
VALUE tmp = Data_Wrap_Struct(rb_cData, 0, 0, 0);
|
1507
|
-
rb_define_singleton_method(tmp, "tmp_proc", func, 1);
|
1508
|
-
return rb_funcall2(rb_funcall(tmp, rb_intern("method"), 1,
|
1509
|
-
ID2SYM(rb_intern("tmp_proc"))),
|
1510
|
-
rb_intern("to_proc"), 0, 0);
|
1511
|
-
}
|
1512
|
-
|
1513
|
-
void Init_bzip2_ext()
|
1514
|
-
{
|
1706
|
+
void Init_bzip2_ext() {
|
1515
1707
|
VALUE bz_mBzip2;
|
1516
1708
|
|
1517
|
-
if (rb_const_defined_at(rb_cObject, rb_intern("Bzip2"))) {
|
1518
|
-
rb_raise(rb_eNameError, "module already defined");
|
1519
|
-
}
|
1520
|
-
|
1521
1709
|
bz_internal_ary = rb_ary_new();
|
1522
1710
|
rb_global_variable(&bz_internal_ary);
|
1523
|
-
|
1524
|
-
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
id_read = rb_intern("read");
|
1532
|
-
id_close = rb_intern("close");
|
1711
|
+
rb_set_end_proc(bz_internal_finalize, Qnil);
|
1712
|
+
|
1713
|
+
id_new = rb_intern("new");
|
1714
|
+
id_write = rb_intern("write");
|
1715
|
+
id_open = rb_intern("open");
|
1716
|
+
id_flush = rb_intern("flush");
|
1717
|
+
id_read = rb_intern("read");
|
1718
|
+
id_close = rb_intern("close");
|
1533
1719
|
id_closed = rb_intern("closed?");
|
1534
|
-
id_str
|
1535
|
-
|
1536
|
-
bz_mBzip2
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
1720
|
+
id_str = rb_intern("to_str");
|
1721
|
+
|
1722
|
+
bz_mBzip2 = rb_define_module("Bzip2");
|
1723
|
+
bz_eError = rb_define_class_under(bz_mBzip2, "Error", rb_eIOError);
|
1724
|
+
bz_eEOZError = rb_define_class_under(bz_mBzip2, "EOZError", bz_eError);
|
1725
|
+
|
1726
|
+
VALUE bz_mBzip2Singleton = rb_singleton_class(bz_mBzip2);
|
1727
|
+
rb_define_singleton_method(bz_mBzip2, "compress", bz_compress, -1);
|
1728
|
+
rb_define_singleton_method(bz_mBzip2, "uncompress", bz_uncompress, -1);
|
1729
|
+
rb_define_alias(bz_mBzip2Singleton, "bzip2", "compress");
|
1730
|
+
rb_define_alias(bz_mBzip2Singleton, "decompress", "uncompress");
|
1731
|
+
rb_define_alias(bz_mBzip2Singleton, "bunzip2", "uncompress");
|
1732
|
+
|
1546
1733
|
/*
|
1547
1734
|
Writer
|
1548
1735
|
*/
|
@@ -1551,7 +1738,7 @@ void Init_bzip2_ext()
|
|
1551
1738
|
rb_define_alloc_func(bz_cWriter, bz_writer_s_alloc);
|
1552
1739
|
#else
|
1553
1740
|
rb_define_singleton_method(bz_cWriter, "allocate", bz_writer_s_alloc, 0);
|
1554
|
-
#endif
|
1741
|
+
#endif
|
1555
1742
|
rb_define_singleton_method(bz_cWriter, "new", bz_s_new, -1);
|
1556
1743
|
rb_define_singleton_method(bz_cWriter, "open", bz_writer_s_open, -1);
|
1557
1744
|
rb_define_method(bz_cWriter, "initialize", bz_writer_init, -1);
|
@@ -1562,10 +1749,11 @@ void Init_bzip2_ext()
|
|
1562
1749
|
rb_define_method(bz_cWriter, "printf", rb_io_printf, -1);
|
1563
1750
|
rb_define_method(bz_cWriter, "<<", rb_io_addstr, 1);
|
1564
1751
|
rb_define_method(bz_cWriter, "flush", bz_writer_flush, 0);
|
1565
|
-
rb_define_method(bz_cWriter, "finish", bz_writer_flush, 0);
|
1566
1752
|
rb_define_method(bz_cWriter, "close", bz_writer_close, 0);
|
1567
1753
|
rb_define_method(bz_cWriter, "close!", bz_writer_close_bang, 0);
|
1568
1754
|
rb_define_method(bz_cWriter, "to_io", bz_to_io, 0);
|
1755
|
+
rb_define_alias(bz_cWriter, "finish", "flush");
|
1756
|
+
|
1569
1757
|
/*
|
1570
1758
|
Reader
|
1571
1759
|
*/
|
@@ -1592,20 +1780,21 @@ void Init_bzip2_ext()
|
|
1592
1780
|
rb_define_method(bz_cReader, "readline", bz_reader_readline, -1);
|
1593
1781
|
rb_define_method(bz_cReader, "readlines", bz_reader_readlines, -1);
|
1594
1782
|
rb_define_method(bz_cReader, "each", bz_reader_each_line, -1);
|
1595
|
-
rb_define_method(bz_cReader, "each_line", bz_reader_each_line, -1);
|
1596
1783
|
rb_define_method(bz_cReader, "each_byte", bz_reader_each_byte, 0);
|
1597
1784
|
rb_define_method(bz_cReader, "close", bz_reader_close, 0);
|
1598
1785
|
rb_define_method(bz_cReader, "close!", bz_reader_close_bang, 0);
|
1599
1786
|
rb_define_method(bz_cReader, "finish", bz_reader_finish, 0);
|
1600
|
-
rb_define_method(bz_cReader, "closed", bz_reader_closed, 0);
|
1601
1787
|
rb_define_method(bz_cReader, "closed?", bz_reader_closed, 0);
|
1602
1788
|
rb_define_method(bz_cReader, "eoz?", bz_reader_eoz, 0);
|
1603
|
-
rb_define_method(bz_cReader, "eoz", bz_reader_eoz, 0);
|
1604
1789
|
rb_define_method(bz_cReader, "eof?", bz_reader_eof, 0);
|
1605
|
-
rb_define_method(bz_cReader, "eof", bz_reader_eof, 0);
|
1606
1790
|
rb_define_method(bz_cReader, "lineno", bz_reader_lineno, 0);
|
1607
1791
|
rb_define_method(bz_cReader, "lineno=", bz_reader_set_lineno, 1);
|
1608
1792
|
rb_define_method(bz_cReader, "to_io", bz_to_io, 0);
|
1793
|
+
rb_define_alias(bz_cReader, "each_line", "each");
|
1794
|
+
rb_define_alias(bz_cReader, "closed", "closed?");
|
1795
|
+
rb_define_alias(bz_cReader, "eoz", "eoz?");
|
1796
|
+
rb_define_alias(bz_cReader, "eof", "eof?");
|
1797
|
+
|
1609
1798
|
/*
|
1610
1799
|
Internal
|
1611
1800
|
*/
|