bzip2-ffi 1.0.0 → 1.1.1
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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/CHANGES.md +33 -2
- data/Gemfile +43 -2
- data/LICENSE +13 -13
- data/README.md +92 -62
- data/Rakefile +24 -0
- data/bzip2-ffi.gemspec +10 -1
- data/lib/bzip2/ffi/error.rb +5 -2
- data/lib/bzip2/ffi/io.rb +59 -47
- data/lib/bzip2/ffi/libbz2.rb +7 -3
- data/lib/bzip2/ffi/reader.rb +210 -104
- data/lib/bzip2/ffi/version.rb +4 -1
- data/lib/bzip2/ffi/writer.rb +81 -62
- data/lib/bzip2/ffi.rb +9 -6
- data/test/error_test.rb +19 -20
- data/test/fixtures/lorem-4096-bytes-compressed.txt.bz2 +0 -0
- data/test/fixtures/lorem-first-structure-4096-bytes.txt.bz2 +0 -0
- data/test/fixtures/two_structures.bz2 +0 -0
- data/test/io_test.rb +34 -32
- data/test/reader_test.rb +339 -111
- data/test/test_helper.rb +45 -8
- data/test/version_test.rb +4 -1
- data/test/writer_test.rb +99 -73
- data.tar.gz.sig +0 -0
- metadata +33 -26
- metadata.gz.sig +2 -1
- /data/test/fixtures/{bzipped → compressed.bz2} +0 -0
data/lib/bzip2/ffi/io.rb
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
module Bzip2
|
2
5
|
module FFI
|
3
|
-
#
|
6
|
+
# {IO} is a base class providing common functionality for the {Reader} and
|
4
7
|
# {Writer} subclasses.
|
5
8
|
#
|
6
|
-
#
|
7
|
-
#
|
9
|
+
# Holds a reference to an underlying IO-like stream representing the bzip2
|
10
|
+
# compressed data to be read from or written to.
|
8
11
|
class IO
|
9
12
|
class << self
|
10
13
|
protected :new
|
11
14
|
|
12
15
|
protected
|
13
16
|
|
14
|
-
# If no block is provided, returns a new
|
15
|
-
# a new
|
16
|
-
# executed, the
|
17
|
+
# If no block is provided, returns a new {IO}. If a block is provided,
|
18
|
+
# a new {IO} is created and yielded to the block. After the block has
|
19
|
+
# executed, the {IO} is closed and the result of the block is returned.
|
17
20
|
#
|
18
21
|
# If `io_or_proc` is a `Proc`, it is called to obtain an IO-like
|
19
22
|
# instance to pass to `new`. Otherwise `io_or_proc` is passed directly
|
@@ -22,6 +25,11 @@ module Bzip2
|
|
22
25
|
# @param io_or_proc [Object] An IO-like object or a `Proc` that returns
|
23
26
|
# an IO-like object when called.
|
24
27
|
# @param options [Hash] Options to pass to `new`.
|
28
|
+
# @yield [io] If a block is given, it is yielded to.
|
29
|
+
# @yieldparam io [IO] The new {IO} instance.
|
30
|
+
# @yieldresult [Object] A result to be returned as the result of {open}.
|
31
|
+
# @return [Object] The result of the block if a block is given,
|
32
|
+
# otherwise the new {IO} instance.
|
25
33
|
def open(io_or_proc, options = {})
|
26
34
|
if io_or_proc.kind_of?(Proc)
|
27
35
|
io = io_or_proc.call
|
@@ -36,7 +44,7 @@ module Bzip2
|
|
36
44
|
end
|
37
45
|
|
38
46
|
if block_given?
|
39
|
-
begin
|
47
|
+
begin
|
40
48
|
yield bz_io
|
41
49
|
ensure
|
42
50
|
bz_io.close unless bz_io.closed?
|
@@ -46,7 +54,7 @@ module Bzip2
|
|
46
54
|
end
|
47
55
|
end
|
48
56
|
|
49
|
-
# Opens and returns a bzip
|
57
|
+
# Opens and returns a bzip file using the specified mode. The system
|
50
58
|
# is advised that the file will be accessed once sequentially.
|
51
59
|
#
|
52
60
|
# @param path [String] The path to open.
|
@@ -67,9 +75,9 @@ module Bzip2
|
|
67
75
|
|
68
76
|
private
|
69
77
|
|
70
|
-
# Advises the system that an
|
78
|
+
# Advises the system that an `::IO` will be accessed once sequentially.
|
71
79
|
#
|
72
|
-
# @param io [IO] An
|
80
|
+
# @param io [::IO] An `::IO` instance to advise.
|
73
81
|
def after_open_file(io)
|
74
82
|
# JRuby 1.7.18 doesn't have a File#advise method (in any mode).
|
75
83
|
if io.respond_to?(:advise)
|
@@ -79,67 +87,69 @@ module Bzip2
|
|
79
87
|
end
|
80
88
|
end
|
81
89
|
|
82
|
-
# Returns `true` if the underlying compressed
|
83
|
-
# when {#close} is called, otherwise `false`.
|
90
|
+
# Returns `true` if the underlying compressed IO-like instance will be
|
91
|
+
# closed when {#close} is called, otherwise `false`.
|
84
92
|
#
|
85
|
-
# @return [Boolean] `true` if the underlying compressed IO instance
|
86
|
-
# be closed when {#close} is closed, otherwise
|
87
|
-
#
|
93
|
+
# @return [Boolean] `true` if the underlying compressed IO-like instance
|
94
|
+
# will be closed when {#close} is closed, otherwise
|
95
|
+
# `false`.
|
96
|
+
# @raise [IOError] If the {IO} instance has been closed.
|
88
97
|
def autoclose?
|
89
98
|
check_closed
|
90
99
|
@autoclose
|
91
100
|
end
|
92
101
|
|
93
|
-
# Sets whether the underlying compressed
|
102
|
+
# Sets whether the underlying compressed IO-like instance should be closed
|
94
103
|
# when {#close} is called (`true`) or left open (`false`).
|
95
104
|
#
|
96
105
|
# @param autoclose [Boolean] `true` if the underlying compressed `IO`
|
97
106
|
# instance should be closed when {#close} is
|
98
107
|
# called, or `false` if it should be left open.
|
99
|
-
# @raise [IOError] If the instance has been closed.
|
108
|
+
# @raise [IOError] If the {IO} instance has been closed.
|
100
109
|
def autoclose=(autoclose)
|
101
110
|
check_closed
|
102
111
|
@autoclose = !!autoclose
|
103
112
|
end
|
104
113
|
|
105
|
-
# Returns `true` to indicate that the
|
106
|
-
# (as is always the case).
|
114
|
+
# Returns `true` to indicate that the {IO} instance is operating in binary
|
115
|
+
# mode (as is always the case).
|
107
116
|
#
|
108
117
|
# @return [Boolean] `true`.
|
109
|
-
# @raise [IOError] If the
|
118
|
+
# @raise [IOError] If the {IO} instance has been closed.
|
110
119
|
def binmode?
|
111
120
|
check_closed
|
112
121
|
true
|
113
122
|
end
|
114
123
|
|
115
|
-
# Puts the
|
124
|
+
# Puts the {IO} instance into binary mode.
|
116
125
|
#
|
117
|
-
# Note that
|
118
|
-
#
|
126
|
+
# Note that {IO} and subclasses always operate in binary mode, so calling
|
127
|
+
# `binmode` has no effect.
|
119
128
|
#
|
120
129
|
# @return [IO] `self`.
|
121
|
-
# @raise [IOError] If the
|
130
|
+
# @raise [IOError] If the {IO} instance has been closed.
|
122
131
|
def binmode
|
123
132
|
check_closed
|
124
133
|
self
|
125
134
|
end
|
126
135
|
|
127
|
-
# Closes the
|
136
|
+
# Closes the {IO} instance.
|
128
137
|
#
|
129
|
-
# If {#autoclose?} is true and the underlying compressed
|
130
|
-
# `close`, it will also be closed.
|
138
|
+
# If {#autoclose?} is true and the underlying compressed IO-like instance
|
139
|
+
# responds to `close`, it will also be closed.
|
131
140
|
#
|
132
141
|
# @return [NilClass] `nil`.
|
133
|
-
# @raise [IOError] If the
|
142
|
+
# @raise [IOError] If the {IO} instance has already been closed.
|
134
143
|
def close
|
135
144
|
check_closed
|
136
145
|
@io.close if autoclose? && @io.respond_to?(:close)
|
137
146
|
@stream = nil
|
138
147
|
end
|
139
148
|
|
140
|
-
# Indicates whether the
|
149
|
+
# Indicates whether the {IO} instance has been closed by calling {#close}.
|
141
150
|
#
|
142
|
-
# @return [Boolean] `true` if the
|
151
|
+
# @return [Boolean] `true` if the {IO} instance has been closed, otherwise
|
152
|
+
# `false`.
|
143
153
|
def closed?
|
144
154
|
!@stream
|
145
155
|
end
|
@@ -151,7 +161,7 @@ module Bzip2
|
|
151
161
|
# returns `Encoding::ASCII_8BIT` (also known as `Encoding::BINARY`).
|
152
162
|
#
|
153
163
|
# @return [Encoding] `Encoding::ASCII_8BIT`.
|
154
|
-
# @raise [IOError] If the
|
164
|
+
# @raise [IOError] If the {IO} instance has been closed.
|
155
165
|
def external_encoding
|
156
166
|
check_closed
|
157
167
|
Encoding::ASCII_8BIT
|
@@ -168,32 +178,33 @@ module Bzip2
|
|
168
178
|
check_closed
|
169
179
|
Encoding::ASCII_8BIT
|
170
180
|
end
|
171
|
-
|
181
|
+
|
172
182
|
protected
|
173
183
|
|
174
|
-
# The underlying compressed
|
184
|
+
# The underlying compressed IO-like instance.
|
175
185
|
attr_reader :io
|
176
186
|
|
177
|
-
# Initializes a new {
|
178
|
-
#
|
187
|
+
# Initializes a new {IO} instance with an underlying compressed IO-like
|
188
|
+
# instance and `options` `Hash`.
|
179
189
|
#
|
180
190
|
# `binmode` is called on `io` if `io` responds to `binmode`.
|
181
191
|
#
|
182
|
-
# A single `:autoclose` option is supported. Set `:autoclose` to true
|
183
|
-
#
|
192
|
+
# A single `:autoclose` option is supported. Set `:autoclose` to true to
|
193
|
+
# close the underlying compressed IO-like instance when {#close} is
|
184
194
|
# called.
|
185
195
|
#
|
186
|
-
# @param io [
|
196
|
+
# @param io [Object] An IO-like object that represents the compressed
|
197
|
+
# data.
|
187
198
|
# @param options [Hash] Optional parameters (:autoclose).
|
188
199
|
# @raise [ArgumentError] If `io` is nil.
|
189
200
|
def initialize(io, options = {})
|
190
201
|
raise ArgumentError, 'io is required' unless io
|
191
|
-
|
202
|
+
|
192
203
|
@io = io
|
193
|
-
@io.binmode if @io.respond_to?(:binmode)
|
204
|
+
@io.binmode if @io.respond_to?(:binmode)
|
194
205
|
|
195
206
|
@autoclose = !!options[:autoclose]
|
196
|
-
|
207
|
+
|
197
208
|
@stream = Libbz2::BzStream.new
|
198
209
|
end
|
199
210
|
|
@@ -202,22 +213,23 @@ module Bzip2
|
|
202
213
|
#
|
203
214
|
# @return [Libbz2::BzStream] The {Libbz2::BzStream} instance being used
|
204
215
|
# to interface with libbz2.
|
205
|
-
# @raise [IOError] If the
|
216
|
+
# @raise [IOError] If the {IO} instance has been closed.
|
206
217
|
def stream
|
207
218
|
check_closed
|
208
219
|
@stream
|
209
|
-
end
|
220
|
+
end
|
210
221
|
|
211
|
-
# Raises an `IOError` if {#close} has been called to close the {IO}
|
222
|
+
# Raises an `IOError` if {#close} has been called to close the {IO}
|
223
|
+
# instance.
|
212
224
|
#
|
213
|
-
# @raise [IOError] If the
|
225
|
+
# @raise [IOError] If the {IO} instance has been closed.
|
214
226
|
def check_closed
|
215
227
|
raise IOError, 'closed stream' if closed?
|
216
228
|
end
|
217
229
|
|
218
230
|
# Checks a return code from a libbz2 function. If it is greater than or
|
219
231
|
# equal to 0 (success), the return code is returned. If it is less than
|
220
|
-
# zero (an error), the appropriate {
|
232
|
+
# zero (an error), the appropriate {Error::Bzip2Error} sub-class is
|
221
233
|
# raised.
|
222
234
|
#
|
223
235
|
# @param res [Integer] The result of a call to a libbz2 function.
|
@@ -244,7 +256,7 @@ module Bzip2
|
|
244
256
|
end
|
245
257
|
|
246
258
|
raise error_class.new
|
247
|
-
end
|
259
|
+
end
|
248
260
|
end
|
249
261
|
end
|
250
262
|
end
|
data/lib/bzip2/ffi/libbz2.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
1
4
|
require 'ffi'
|
2
5
|
|
3
6
|
module Bzip2
|
4
7
|
module FFI
|
5
8
|
# FFI bindings for the libbz2 low-level interface.
|
6
9
|
#
|
7
|
-
# See bzlib.h and
|
10
|
+
# See bzlib.h and https://sourceware.org/bzip2/docs.html.
|
8
11
|
#
|
9
12
|
# @private
|
10
13
|
module Libbz2 #:nodoc:
|
@@ -50,7 +53,7 @@ module Bzip2
|
|
50
53
|
|
51
54
|
:bzalloc, :bzalloc,
|
52
55
|
:bzfree, :bzfree,
|
53
|
-
:opaque, :pointer
|
56
|
+
:opaque, :pointer
|
54
57
|
end
|
55
58
|
|
56
59
|
# int BZ2_bzCompressInt(bz_stream* strm, int blockSize100k, int verbosity, int workFactor);
|
@@ -61,7 +64,7 @@ module Bzip2
|
|
61
64
|
|
62
65
|
# int BZ2_bzCompressEnd (bz_stream* strm);
|
63
66
|
attach_function :BZ2_bzCompressEnd, [BzStream.by_ref], :int
|
64
|
-
|
67
|
+
|
65
68
|
# int BZ2_bzDecompressInit (bz_stream *strm, int verbosity, int small);
|
66
69
|
attach_function :BZ2_bzDecompressInit, [BzStream.by_ref, :int, :int], :int
|
67
70
|
|
@@ -71,5 +74,6 @@ module Bzip2
|
|
71
74
|
# int BZ2_bzDecompressEnd (bz_stream *strm);
|
72
75
|
attach_function :BZ2_bzDecompressEnd, [BzStream.by_ref], :int
|
73
76
|
end
|
77
|
+
private_constant :Libbz2
|
74
78
|
end
|
75
79
|
end
|