bzip2-ruby 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
*/
|