archive-zip 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HACKING +25 -42
- data/NEWS +25 -0
- data/README +2 -2
- data/Rakefile +202 -0
- data/TODO +5 -0
- data/default.mspec +8 -0
- data/lib/archive/support/binary_stringio.rb +23 -0
- data/lib/archive/support/integer.rb +13 -0
- data/lib/archive/support/io-like.rb +3 -1
- data/lib/archive/support/ioextensions.rb +16 -0
- data/lib/archive/support/iowindow.rb +10 -18
- data/lib/archive/support/time.rb +2 -0
- data/lib/archive/support/zlib.rb +298 -71
- data/lib/archive/zip.rb +161 -139
- data/lib/archive/zip/codec.rb +2 -0
- data/lib/archive/zip/codec/deflate.rb +59 -11
- data/lib/archive/zip/codec/null_encryption.rb +75 -14
- data/lib/archive/zip/codec/store.rb +75 -26
- data/lib/archive/zip/codec/traditional_encryption.rb +146 -35
- data/lib/archive/zip/data_descriptor.rb +6 -4
- data/lib/archive/zip/entry.rb +184 -132
- data/lib/archive/zip/error.rb +2 -0
- data/lib/archive/zip/extra_field.rb +20 -6
- data/lib/archive/zip/extra_field/extended_timestamp.rb +141 -60
- data/lib/archive/zip/extra_field/raw.rb +70 -12
- data/lib/archive/zip/extra_field/unix.rb +58 -16
- data/lib/archive/zip/version.rb +6 -0
- data/spec/archive/zip/codec/deflate/compress/checksum_spec.rb +42 -0
- data/spec/archive/zip/codec/deflate/compress/close_spec.rb +44 -0
- data/spec/archive/zip/codec/deflate/compress/crc32_spec.rb +21 -0
- data/spec/archive/zip/codec/deflate/compress/data_descriptor_spec.rb +67 -0
- data/spec/archive/zip/codec/deflate/compress/new_spec.rb +37 -0
- data/spec/archive/zip/codec/deflate/compress/open_spec.rb +46 -0
- data/spec/archive/zip/codec/deflate/compress/write_spec.rb +109 -0
- data/spec/archive/zip/codec/deflate/decompress/checksum_spec.rb +18 -0
- data/spec/archive/zip/codec/deflate/decompress/close_spec.rb +33 -0
- data/spec/archive/zip/codec/deflate/decompress/crc32_spec.rb +18 -0
- data/spec/archive/zip/codec/deflate/decompress/data_descriptor_spec.rb +67 -0
- data/spec/archive/zip/codec/deflate/decompress/new_spec.rb +14 -0
- data/spec/archive/zip/codec/deflate/decompress/open_spec.rb +27 -0
- data/spec/archive/zip/codec/deflate/fixtures/classes.rb +25 -0
- data/spec/archive/zip/codec/deflate/fixtures/compressed_file.bin +1 -0
- data/spec/archive/zip/codec/deflate/fixtures/compressed_file_nocomp.bin +0 -0
- data/spec/archive/zip/codec/deflate/fixtures/raw_file.txt +10 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/close_spec.rb +33 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/new_spec.rb +14 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/open_spec.rb +27 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/read_spec.rb +24 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/rewind_spec.rb +25 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/seek_spec.rb +57 -0
- data/spec/archive/zip/codec/null_encryption/decrypt/tell_spec.rb +21 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/close_spec.rb +33 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/new_spec.rb +14 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/open_spec.rb +27 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/rewind_spec.rb +26 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/seek_spec.rb +50 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/tell_spec.rb +29 -0
- data/spec/archive/zip/codec/null_encryption/encrypt/write_spec.rb +29 -0
- data/spec/archive/zip/codec/null_encryption/fixtures/classes.rb +12 -0
- data/spec/archive/zip/codec/null_encryption/fixtures/raw_file.txt +10 -0
- data/spec/archive/zip/codec/store/compress/close_spec.rb +33 -0
- data/spec/archive/zip/codec/store/compress/data_descriptor_spec.rb +68 -0
- data/spec/archive/zip/codec/store/compress/new_spec.rb +14 -0
- data/spec/archive/zip/codec/store/compress/open_spec.rb +27 -0
- data/spec/archive/zip/codec/store/compress/rewind_spec.rb +26 -0
- data/spec/archive/zip/codec/store/compress/seek_spec.rb +50 -0
- data/spec/archive/zip/codec/store/compress/tell_spec.rb +29 -0
- data/spec/archive/zip/codec/store/compress/write_spec.rb +29 -0
- data/spec/archive/zip/codec/store/decompress/close_spec.rb +33 -0
- data/spec/archive/zip/codec/store/decompress/data_descriptor_spec.rb +68 -0
- data/spec/archive/zip/codec/store/decompress/new_spec.rb +14 -0
- data/spec/archive/zip/codec/store/decompress/open_spec.rb +27 -0
- data/spec/archive/zip/codec/store/decompress/read_spec.rb +24 -0
- data/spec/archive/zip/codec/store/decompress/rewind_spec.rb +25 -0
- data/spec/archive/zip/codec/store/decompress/seek_spec.rb +57 -0
- data/spec/archive/zip/codec/store/decompress/tell_spec.rb +21 -0
- data/spec/archive/zip/codec/store/fixtures/classes.rb +12 -0
- data/spec/archive/zip/codec/store/fixtures/raw_file.txt +10 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/close_spec.rb +64 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/new_spec.rb +18 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/open_spec.rb +39 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/read_spec.rb +126 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/rewind_spec.rb +38 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/seek_spec.rb +82 -0
- data/spec/archive/zip/codec/traditional_encryption/decrypt/tell_spec.rb +25 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/close_spec.rb +64 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/new_spec.rb +18 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/open_spec.rb +39 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/rewind_spec.rb +41 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/seek_spec.rb +75 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/tell_spec.rb +42 -0
- data/spec/archive/zip/codec/traditional_encryption/encrypt/write_spec.rb +127 -0
- data/spec/archive/zip/codec/traditional_encryption/fixtures/classes.rb +27 -0
- data/spec/archive/zip/codec/traditional_encryption/fixtures/encrypted_file.bin +0 -0
- data/spec/archive/zip/codec/traditional_encryption/fixtures/raw_file.txt +10 -0
- data/spec/binary_stringio/new_spec.rb +34 -0
- data/spec/binary_stringio/set_encoding_spec.rb +14 -0
- data/spec/ioextensions/read_exactly_spec.rb +50 -0
- data/spec/zlib/fixtures/classes.rb +65 -0
- data/spec/zlib/fixtures/compressed_file.bin +1 -0
- data/spec/zlib/fixtures/compressed_file_gzip.bin +0 -0
- data/spec/zlib/fixtures/compressed_file_huffman.bin +2 -0
- data/spec/zlib/fixtures/compressed_file_minmem.bin +0 -0
- data/spec/zlib/fixtures/compressed_file_minwin.bin +1 -0
- data/spec/zlib/fixtures/compressed_file_nocomp.bin +0 -0
- data/spec/zlib/fixtures/compressed_file_raw.bin +1 -0
- data/spec/zlib/fixtures/raw_file.txt +10 -0
- data/spec/zlib/zreader/checksum_spec.rb +40 -0
- data/spec/zlib/zreader/close_spec.rb +14 -0
- data/spec/zlib/zreader/compressed_size_spec.rb +18 -0
- data/spec/zlib/zreader/new_spec.rb +41 -0
- data/spec/zlib/zreader/open_spec.rb +49 -0
- data/spec/zlib/zreader/read_spec.rb +47 -0
- data/spec/zlib/zreader/rewind_spec.rb +23 -0
- data/spec/zlib/zreader/seek_spec.rb +55 -0
- data/spec/zlib/zreader/tell_spec.rb +21 -0
- data/spec/zlib/zreader/uncompressed_size_spec.rb +18 -0
- data/spec/zlib/zwriter/checksum_spec.rb +41 -0
- data/spec/zlib/zwriter/close_spec.rb +14 -0
- data/spec/zlib/zwriter/compressed_size_spec.rb +19 -0
- data/spec/zlib/zwriter/new_spec.rb +64 -0
- data/spec/zlib/zwriter/open_spec.rb +68 -0
- data/spec/zlib/zwriter/rewind_spec.rb +26 -0
- data/spec/zlib/zwriter/seek_spec.rb +54 -0
- data/spec/zlib/zwriter/tell_spec.rb +29 -0
- data/spec/zlib/zwriter/uncompressed_size_spec.rb +19 -0
- data/spec/zlib/zwriter/write_spec.rb +28 -0
- data/spec_helper.rb +49 -0
- metadata +296 -74
- data/MANIFEST +0 -27
- data/lib/archive/support/io.rb +0 -14
- data/lib/archive/support/stringio.rb +0 -22
data/lib/archive/support/time.rb
CHANGED
data/lib/archive/support/zlib.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
1
3
|
require 'zlib'
|
2
4
|
|
3
5
|
require 'archive/support/io-like'
|
@@ -7,6 +9,14 @@ module Zlib # :nodoc:
|
|
7
9
|
MAX_WBITS = Deflate::MAX_WBITS
|
8
10
|
end
|
9
11
|
|
12
|
+
# A deflate strategy which limits match distances to 1, also known as
|
13
|
+
# run-length encoding.
|
14
|
+
RLE = 3
|
15
|
+
|
16
|
+
# A deflate strategy which does not use dynamic Huffman codes, allowing for a
|
17
|
+
# simpler decoder to be used to inflate.
|
18
|
+
FIXED = 4
|
19
|
+
|
10
20
|
# Zlib::ZWriter is a writable, IO-like object (includes IO::Like) which wraps
|
11
21
|
# other writable, IO-like objects in order to facilitate writing data to those
|
12
22
|
# objects using the deflate method of compression.
|
@@ -18,8 +28,8 @@ module Zlib # :nodoc:
|
|
18
28
|
# guaranteed to be called after the block completes.
|
19
29
|
#
|
20
30
|
# Equivalent to #new if no block is given.
|
21
|
-
def self.open(
|
22
|
-
zw = new(
|
31
|
+
def self.open(delegate, level = nil, window_bits = nil, mem_level = nil, strategy = nil)
|
32
|
+
zw = new(delegate, level, window_bits, mem_level, strategy)
|
23
33
|
return zw unless block_given?
|
24
34
|
|
25
35
|
begin
|
@@ -29,28 +39,112 @@ module Zlib # :nodoc:
|
|
29
39
|
end
|
30
40
|
end
|
31
41
|
|
32
|
-
# Creates a new instance of this class.
|
33
|
-
# method as an instance of IO would. _level_, _window_bits_,
|
34
|
-
# and _strategy_ are all passed directly to
|
35
|
-
#
|
42
|
+
# Creates a new instance of this class. _delegate_ must respond to the
|
43
|
+
# _write_ method as an instance of IO would. _level_, _window_bits_,
|
44
|
+
# _mem_level_, and _strategy_ are all passed directly to
|
45
|
+
# Zlib::Deflate.new().
|
46
|
+
#
|
47
|
+
# <b>
|
48
|
+
# The following descriptions of _level_, _window_bits_, _mem_level_, and
|
49
|
+
# _strategy_ are based upon or pulled largely verbatim from descriptions
|
50
|
+
# found in zlib.h version 1.2.3 with changes made to account for different
|
51
|
+
# parameter names and to improve readability. Some of the statements
|
52
|
+
# concerning default settings or value ranges may not be accurate depending
|
53
|
+
# on the version of the zlib library used by a given Ruby interpreter.
|
54
|
+
# </b>
|
55
|
+
#
|
56
|
+
# The _level_ parameter must be +nil+, Zlib::DEFAULT_COMPRESSION, or between
|
57
|
+
# <tt>0</tt> and <tt>9</tt>: <tt>1</tt> gives best speed, <tt>9</tt> gives
|
58
|
+
# best compression, <tt>0</tt> gives no compression at all (the input data
|
59
|
+
# is simply copied a block at a time). Zlib::DEFAULT_COMPRESSION requests a
|
60
|
+
# default compromise between speed and compression (currently equivalent to
|
61
|
+
# level <tt>6</tt>). If unspecified or +nil+, _level_ defaults to
|
62
|
+
# Zlib::DEFAULT_COMPRESSION.
|
63
|
+
#
|
64
|
+
# The _window_bits_ parameter specifies the size of the history buffer, the
|
65
|
+
# format of the compressed stream, and the kind of checksum returned by the
|
66
|
+
# checksum method. The size of the history buffer is specified by setting
|
67
|
+
# the value of _window_bits_ in the range of <tt>8</tt>..<tt>15</tt>,
|
68
|
+
# inclusive. A value of <tt>8</tt> indicates a small window which reduces
|
69
|
+
# memory usage but lowers the compression ratio while a value of <tt>15</tt>
|
70
|
+
# indicates a larger window which increases memory usage but raises the
|
71
|
+
# compression ratio. Modification of this base value for _window_bits_ as
|
72
|
+
# noted below dictates what kind of compressed stream and checksum will be
|
73
|
+
# produced <b>while preserving the setting for the history buffer</b>.
|
74
|
+
#
|
75
|
+
# If nothing else is done to the base value of _window_bits_, a zlib stream
|
76
|
+
# is to be produced with an appropriate header and trailer. In this case
|
77
|
+
# the checksum method of this object will be an adler32.
|
78
|
+
#
|
79
|
+
# Adding <tt>16</tt> to the base value of _window_bits_ indicates that a
|
80
|
+
# gzip stream is to be produced with an appropriate header and trailer. The
|
81
|
+
# gzip header will have no file name, no extra data, no comment, no
|
82
|
+
# modification time (set to zero), no header crc, and the operating system
|
83
|
+
# will be set to <tt>255</tt> (unknown). In this case the checksum
|
84
|
+
# attribute of this object will be a crc32.
|
85
|
+
#
|
86
|
+
# Finally, negating the base value of _window_bits_ indicates that a raw
|
87
|
+
# zlib stream is to be produced without any header or trailer. In this case
|
88
|
+
# the checksum method of this object will always return <tt>1</tt>. This is
|
89
|
+
# for use with other formats that use the deflate compressed data format
|
90
|
+
# such as zip. Such formats should provide their own check values.
|
91
|
+
#
|
92
|
+
# If unspecified or +nil+, _window_bits_ defaults to <tt>15</tt>.
|
93
|
+
#
|
94
|
+
# The _mem_level_ parameter specifies how much memory should be allocated
|
95
|
+
# for the internal compression state. A value of <tt>1</tt> uses minimum
|
96
|
+
# memory but is slow and reduces compression ratio; a value of <tt>9</tt>
|
97
|
+
# uses maximum memory for optimal speed. The default value is <tt>8</tt> if
|
98
|
+
# unspecified or +nil+.
|
99
|
+
#
|
100
|
+
# The _strategy_ parameter is used to tune the compression algorithm. It
|
101
|
+
# only affects the compression ratio but not the correctness of the
|
102
|
+
# compressed output even if it is not set appropriately. The default value
|
103
|
+
# is Zlib::DEFAULT_STRATEGY if unspecified or +nil+.
|
104
|
+
#
|
105
|
+
# Use the value Zlib::DEFAULT_STRATEGY for normal data, Zlib::FILTERED for
|
106
|
+
# data produced by a filter (or predictor), Zlib::HUFFMAN_ONLY to force
|
107
|
+
# Huffman encoding only (no string match), Zlib::RLE to limit match
|
108
|
+
# distances to 1 (run-length encoding), or Zlib::FIXED to simplify decoder
|
109
|
+
# requirements.
|
110
|
+
#
|
111
|
+
# The effect of Zlib::FILTERED is to force more Huffman coding and less
|
112
|
+
# string matching; it is somewhat intermediate between
|
113
|
+
# Zlib::DEFAULT_STRATEGY and Zlib::HUFFMAN_ONLY. Filtered data consists
|
114
|
+
# mostly of small values with a somewhat random distribution. In this case,
|
115
|
+
# the compression algorithm is tuned to compress them better.
|
116
|
+
#
|
117
|
+
# Zlib::RLE is designed to be almost as fast as Zlib::HUFFMAN_ONLY, but give
|
118
|
+
# better compression for PNG image data.
|
119
|
+
#
|
120
|
+
# Zlib::FIXED prevents the use of dynamic Huffman codes, allowing for a
|
121
|
+
# simpler decoder for special applications.
|
122
|
+
#
|
123
|
+
# This class has extremely limited seek capabilities. It is possible to
|
124
|
+
# seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
|
125
|
+
# As a result, the _pos_ and _tell_ methods also work as expected.
|
126
|
+
#
|
127
|
+
# If _delegate_ also responds to _rewind_, then the _rewind_ method of this
|
128
|
+
# class can be used to reset the whole stream back to the beginning. Using
|
129
|
+
# _seek_ of this class to seek directly to offset <tt>0</tt> using
|
130
|
+
# <tt>IO::SEEK_SET</tt> for whence will also work in this case.
|
36
131
|
#
|
37
132
|
# <b>NOTE:</b> Due to limitations in Ruby's finalization capabilities, the
|
38
133
|
# #close method is _not_ automatically called when this object is garbage
|
39
134
|
# collected. Make sure to call #close when finished with this object.
|
40
|
-
def initialize(
|
41
|
-
@delegate =
|
42
|
-
@
|
135
|
+
def initialize(delegate, level = nil, window_bits = nil, mem_level = nil, strategy = nil)
|
136
|
+
@delegate = delegate
|
137
|
+
@level = level
|
138
|
+
@window_bits = window_bits
|
139
|
+
@mem_level = mem_level
|
140
|
+
@strategy = strategy
|
141
|
+
@deflater = Zlib::Deflate.new(@level, @window_bits, @mem_level, @strategy)
|
43
142
|
@deflate_buffer = ''
|
44
|
-
@
|
143
|
+
@checksum = nil
|
144
|
+
@compressed_size = nil
|
145
|
+
@uncompressed_size = nil
|
45
146
|
end
|
46
147
|
|
47
|
-
# The CRC32 checksum of the uncompressed data written using this object.
|
48
|
-
#
|
49
|
-
# <b>NOTE:</b> Anything still in the internal write buffer has not been
|
50
|
-
# processed, so calling #flush prior to examining this attribute may be
|
51
|
-
# necessary for an accurate computation.
|
52
|
-
attr_reader :crc32
|
53
|
-
|
54
148
|
protected
|
55
149
|
|
56
150
|
# The delegate object to which compressed data is written.
|
@@ -58,49 +152,100 @@ module Zlib # :nodoc:
|
|
58
152
|
|
59
153
|
public
|
60
154
|
|
155
|
+
# Returns the checksum computed over the data written to this stream so far.
|
156
|
+
#
|
157
|
+
# <b>NOTE:</b> Refer to the documentation of #new concerning _window_bits_
|
158
|
+
# to learn what kind of checksum will be returned.
|
159
|
+
#
|
160
|
+
# <b>NOTE:</b> Anything still in the internal write buffer has not been
|
161
|
+
# processed, so calling #flush prior to calling this method may be necessary
|
162
|
+
# for an accurate checksum.
|
163
|
+
def checksum
|
164
|
+
@deflater.closed? ? @checksum : @deflater.adler
|
165
|
+
end
|
166
|
+
|
61
167
|
# Closes the writer by finishing the compressed data and flushing it to the
|
62
168
|
# delegate.
|
63
169
|
#
|
64
170
|
# Raises IOError if called more than once.
|
65
171
|
def close
|
172
|
+
flush()
|
173
|
+
@deflate_buffer << @deflater.finish unless @deflater.finished?
|
174
|
+
begin
|
175
|
+
until @deflate_buffer.empty? do
|
176
|
+
@deflate_buffer.slice!(0, delegate.write(@deflate_buffer))
|
177
|
+
end
|
178
|
+
rescue Errno::EAGAIN, Errno::EINTR
|
179
|
+
retry if write_ready?
|
180
|
+
end
|
181
|
+
@checksum = @deflater.adler
|
182
|
+
@compressed_size = @deflater.total_out
|
183
|
+
@uncompressed_size = @deflater.total_in
|
184
|
+
@deflater.close
|
66
185
|
super()
|
67
|
-
delegate.write(@deflater.finish)
|
68
186
|
nil
|
69
187
|
end
|
70
188
|
|
71
189
|
# Returns the number of bytes of compressed data produced so far.
|
72
190
|
#
|
73
|
-
# <b>NOTE:</b>
|
74
|
-
#
|
75
|
-
#
|
191
|
+
# <b>NOTE:</b> This value is only updated when both the internal write
|
192
|
+
# buffer is flushed and there is enough data to produce a compressed block.
|
193
|
+
# It does not necessarily reflect the amount of data written to the
|
194
|
+
# delegate until this stream is closed however. Until then the only
|
195
|
+
# guarantee is that the value will be greater than or equal to <tt>0</tt>.
|
76
196
|
def compressed_size
|
77
|
-
@deflater.total_out
|
197
|
+
@deflater.closed? ? @compressed_size : @deflater.total_out
|
78
198
|
end
|
79
199
|
|
80
200
|
# Returns the number of bytes sent to be compressed so far.
|
81
201
|
#
|
82
|
-
# <b>NOTE:</b>
|
83
|
-
#
|
84
|
-
# for an accurate count.
|
202
|
+
# <b>NOTE:</b> This value is only updated when the internal write buffer is
|
203
|
+
# flushed.
|
85
204
|
def uncompressed_size
|
86
|
-
@deflater.total_in
|
205
|
+
@deflater.closed? ? @uncompressed_size : @deflater.total_in
|
87
206
|
end
|
88
207
|
|
89
208
|
private
|
90
209
|
|
210
|
+
# Allows resetting this object and the delegate object back to the beginning
|
211
|
+
# of the stream or reporting the current position in the stream.
|
212
|
+
#
|
213
|
+
# Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is either
|
214
|
+
# IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_ is
|
215
|
+
# IO::SEEK_SEK and the delegate object does not respond to the _rewind_
|
216
|
+
# method.
|
217
|
+
def unbuffered_seek(offset, whence = IO::SEEK_SET)
|
218
|
+
unless offset == 0 &&
|
219
|
+
((whence == IO::SEEK_SET && delegate.respond_to?(:rewind)) ||
|
220
|
+
whence == IO::SEEK_CUR) then
|
221
|
+
raise Errno::EINVAL
|
222
|
+
end
|
223
|
+
|
224
|
+
case whence
|
225
|
+
when IO::SEEK_SET
|
226
|
+
delegate.rewind
|
227
|
+
@deflater.finish
|
228
|
+
@deflater.close
|
229
|
+
@deflater = Zlib::Deflate.new(
|
230
|
+
@level, @window_bits, @mem_level, @strategy
|
231
|
+
)
|
232
|
+
@deflate_buffer = ''
|
233
|
+
0
|
234
|
+
when IO::SEEK_CUR
|
235
|
+
@deflater.total_in
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
91
239
|
def unbuffered_write(string)
|
240
|
+
# First try to write out the contents of the deflate buffer because if
|
241
|
+
# that raises a failure we can let that pass up the call stack without
|
242
|
+
# having polluted the deflater instance.
|
92
243
|
until @deflate_buffer.empty? do
|
93
244
|
@deflate_buffer.slice!(0, delegate.write(@deflate_buffer))
|
94
245
|
end
|
246
|
+
# At this point we can deflate the given string into a new buffer and
|
247
|
+
# behave as if it was written.
|
95
248
|
@deflate_buffer = @deflater.deflate(string)
|
96
|
-
|
97
|
-
begin
|
98
|
-
@deflate_buffer.slice!(0, delegate.write(@deflate_buffer))
|
99
|
-
rescue Errno::EINTR, Errno::EAGAIN
|
100
|
-
# Ignore this because everything is in the deflate buffer and will be
|
101
|
-
# attempted again the next time this method is called.
|
102
|
-
end
|
103
|
-
@crc32 = Zlib.crc32(string, @crc32)
|
104
249
|
string.length
|
105
250
|
end
|
106
251
|
end
|
@@ -120,8 +265,8 @@ module Zlib # :nodoc:
|
|
120
265
|
# guaranteed to be called after the block completes.
|
121
266
|
#
|
122
267
|
# Equivalent to #new if no block is given.
|
123
|
-
def self.open(
|
124
|
-
zr = new(
|
268
|
+
def self.open(delegate, window_bits = nil)
|
269
|
+
zr = new(delegate, window_bits)
|
125
270
|
return zr unless block_given?
|
126
271
|
|
127
272
|
begin
|
@@ -131,31 +276,82 @@ module Zlib # :nodoc:
|
|
131
276
|
end
|
132
277
|
end
|
133
278
|
|
134
|
-
# Creates a new instance of this class.
|
135
|
-
# method as an IO instance would. _window_bits_ is passed directly
|
136
|
-
# Zlib::Inflate.new().
|
137
|
-
#
|
138
|
-
#
|
279
|
+
# Creates a new instance of this class. _delegate_ must respond to the
|
280
|
+
# _read_ method as an IO instance would. _window_bits_ is passed directly
|
281
|
+
# to Zlib::Inflate.new().
|
282
|
+
#
|
283
|
+
# <b>
|
284
|
+
# The following description of _window_bits_ is based on the description
|
285
|
+
# found in zlib.h version 1.2.3. Some of the statements concerning default
|
286
|
+
# settings or value ranges may not be accurate depending on the version of
|
287
|
+
# the zlib library used by a given Ruby interpreter.
|
288
|
+
# </b>
|
289
|
+
#
|
290
|
+
# The _window_bits_ parameter specifies the size of the history buffer, the
|
291
|
+
# format of the compressed stream, and the kind of checksum returned by the
|
292
|
+
# checksum method. The size of the history buffer is specified by setting
|
293
|
+
# the value of _window_bits_ in the range of <tt>8</tt>..<tt>15</tt>,
|
294
|
+
# inclusive. It must be at least as large as the setting used to create the
|
295
|
+
# stream or a Zlib::DataError will be raised. Modification of this base
|
296
|
+
# value for _window_bits_ as noted below dictates what kind of compressed
|
297
|
+
# stream is expected and what kind of checksum will be produced <b>while
|
298
|
+
# preserving the setting for the history buffer</b>.
|
299
|
+
#
|
300
|
+
# If nothing else is done to the base value of _window_bits_, a zlib stream
|
301
|
+
# is expected with an appropriate header and trailer. In this case the
|
302
|
+
# checksum method of this object will be an adler32.
|
303
|
+
#
|
304
|
+
# Adding <tt>16</tt> to the base value of _window_bits_ indicates that a
|
305
|
+
# gzip stream is expected with an appropriate header and trailer. In this
|
306
|
+
# case the checksum method of this object will be a crc32.
|
307
|
+
#
|
308
|
+
# Adding <tt>32</tt> to the base value of _window_bits_ indicates that an
|
309
|
+
# automatic detection of the stream format should be made based on the
|
310
|
+
# header in the stream. In this case the checksum method of this object
|
311
|
+
# will depend on whether a zlib or a gzip stream is detected.
|
312
|
+
#
|
313
|
+
# Finally, negating the base value of _window_bits_ indicates that a raw
|
314
|
+
# zlib stream is expected without any header or trailer. In this case the
|
315
|
+
# checksum method of this object will always return <tt>1</tt>. This is for
|
316
|
+
# use with other formats that use the deflate compressed data format such as
|
317
|
+
# zip. Such formats should provide their own check values.
|
318
|
+
#
|
319
|
+
# If unspecified or +nil+, _window_bits_ defaults to <tt>15</tt>.
|
320
|
+
#
|
321
|
+
# In all cases, Zlib::DataError is raised if the wrong stream format is
|
322
|
+
# found <b>when reading</b>.
|
323
|
+
#
|
324
|
+
# This class has extremely limited seek capabilities. It is possible to
|
325
|
+
# seek with an offset of <tt>0</tt> and a whence of <tt>IO::SEEK_CUR</tt>.
|
326
|
+
# As a result, the _pos_ and _tell_ methods also work as expected.
|
327
|
+
#
|
328
|
+
# Due to certain optimizations within IO::Like#seek and if there is data in
|
329
|
+
# the read buffer, the _seek_ method can be used to seek forward from the
|
330
|
+
# current stream position up to the end of the buffer. Unless it is known
|
331
|
+
# definitively how much data is in the buffer, it is best to avoid relying
|
332
|
+
# on this behavior.
|
333
|
+
#
|
334
|
+
# If _delegate_ also responds to _rewind_, then the _rewind_ method of this
|
335
|
+
# class can be used to reset the whole stream back to the beginning. Using
|
336
|
+
# _seek_ of this class to seek directly to offset <tt>0</tt> using
|
337
|
+
# <tt>IO::SEEK_SET</tt> for whence will also work in this case.
|
338
|
+
#
|
339
|
+
# Any other seeking attempts, will raise Errno::EINVAL exceptions.
|
139
340
|
#
|
140
341
|
# <b>NOTE:</b> Due to limitations in Ruby's finalization capabilities, the
|
141
342
|
# #close method is _not_ automatically called when this object is garbage
|
142
343
|
# collected. Make sure to call #close when finished with this object.
|
143
|
-
def initialize(
|
144
|
-
@delegate =
|
344
|
+
def initialize(delegate, window_bits = nil)
|
345
|
+
@delegate = delegate
|
145
346
|
@delegate_read_size = DEFAULT_DELEGATE_READ_SIZE
|
146
347
|
@window_bits = window_bits
|
147
348
|
@inflater = Zlib::Inflate.new(@window_bits)
|
148
|
-
@
|
149
|
-
@
|
349
|
+
@inflate_buffer = ''
|
350
|
+
@checksum = nil
|
351
|
+
@compressed_size = nil
|
352
|
+
@uncompressed_size = nil
|
150
353
|
end
|
151
354
|
|
152
|
-
# The CRC32 checksum of the uncompressed data read using this object.
|
153
|
-
#
|
154
|
-
# <b>NOTE:</b> The contents of the internal read buffer are immediately
|
155
|
-
# processed any time the buffer is filled, so this count is only accurate if
|
156
|
-
# all data has been read out of this object.
|
157
|
-
attr_reader :crc32
|
158
|
-
|
159
355
|
# The number of bytes to read from the delegate object each time the
|
160
356
|
# internal read buffer is filled.
|
161
357
|
attr_accessor :delegate_read_size
|
@@ -167,57 +363,88 @@ module Zlib # :nodoc:
|
|
167
363
|
|
168
364
|
public
|
169
365
|
|
366
|
+
# Returns the checksum computed over the data read from this stream.
|
367
|
+
#
|
368
|
+
# <b>NOTE:</b> Refer to the documentation of #new concerning _window_bits_
|
369
|
+
# to learn what kind of checksum will be returned.
|
370
|
+
#
|
371
|
+
# <b>NOTE:</b> The contents of the internal read buffer are immediately
|
372
|
+
# processed any time the internal buffer is filled, so this checksum is only
|
373
|
+
# accurate if all data has been read out of this object.
|
374
|
+
def checksum
|
375
|
+
@inflater.closed? ? @checksum : @inflater.adler
|
376
|
+
end
|
377
|
+
|
170
378
|
# Closes the reader.
|
171
379
|
#
|
172
380
|
# Raises IOError if called more than once.
|
173
381
|
def close
|
174
382
|
super()
|
383
|
+
@checksum = @inflater.adler
|
384
|
+
@compressed_size = @inflater.total_in
|
385
|
+
@uncompressed_size = @inflater.total_out
|
175
386
|
@inflater.close
|
176
387
|
nil
|
177
388
|
end
|
178
389
|
|
179
|
-
# Returns the number of bytes sent to be
|
390
|
+
# Returns the number of bytes sent to be compressed so far.
|
391
|
+
#
|
392
|
+
# <b>NOTE:</b> This value is updated whenever the internal read buffer needs
|
393
|
+
# to be filled, not when data is read out of this stream.
|
180
394
|
def compressed_size
|
181
|
-
@inflater.total_in
|
395
|
+
@inflater.closed? ? @compressed_size : @inflater.total_in
|
182
396
|
end
|
183
397
|
|
184
398
|
# Returns the number of bytes of decompressed data produced so far.
|
399
|
+
#
|
400
|
+
# <b>NOTE:</b> This value is updated whenever the internal read buffer needs
|
401
|
+
# to be filled, not when data is read out of this stream.
|
185
402
|
def uncompressed_size
|
186
|
-
@inflater.total_out
|
403
|
+
@inflater.closed? ? @uncompressed_size : @inflater.total_out
|
187
404
|
end
|
188
405
|
|
189
406
|
private
|
190
407
|
|
191
408
|
def unbuffered_read(length)
|
192
|
-
if @
|
409
|
+
if @inflate_buffer.empty? && @inflater.finished? then
|
193
410
|
raise EOFError, 'end of file reached'
|
194
411
|
end
|
195
412
|
|
196
413
|
begin
|
197
|
-
while @
|
198
|
-
@
|
414
|
+
while @inflate_buffer.length < length && ! @inflater.finished? do
|
415
|
+
@inflate_buffer <<
|
199
416
|
@inflater.inflate(delegate.read(@delegate_read_size))
|
200
417
|
end
|
201
418
|
rescue Errno::EINTR, Errno::EAGAIN
|
202
|
-
raise if @
|
419
|
+
raise if @inflate_buffer.empty?
|
203
420
|
end
|
204
|
-
|
205
|
-
@crc32 = Zlib.crc32(buffer, @crc32)
|
206
|
-
buffer
|
421
|
+
@inflate_buffer.slice!(0, length)
|
207
422
|
end
|
208
423
|
|
424
|
+
# Allows resetting this object and the delegate object back to the beginning
|
425
|
+
# of the stream or reporting the current position in the stream.
|
426
|
+
#
|
427
|
+
# Raises Errno::EINVAL unless _offset_ is <tt>0</tt> and _whence_ is either
|
428
|
+
# IO::SEEK_SET or IO::SEEK_CUR. Raises Errno::EINVAL if _whence_ is
|
429
|
+
# IO::SEEK_SEK and the delegate object does not respond to the _rewind_
|
430
|
+
# method.
|
209
431
|
def unbuffered_seek(offset, whence = IO::SEEK_SET)
|
210
|
-
unless offset == 0 &&
|
211
|
-
|
432
|
+
unless offset == 0 &&
|
433
|
+
((whence == IO::SEEK_SET && delegate.respond_to?(:rewind)) ||
|
434
|
+
whence == IO::SEEK_CUR) then
|
435
|
+
raise Errno::EINVAL
|
212
436
|
end
|
213
|
-
|
214
|
-
|
437
|
+
|
438
|
+
case whence
|
439
|
+
when IO::SEEK_SET
|
440
|
+
delegate.rewind
|
441
|
+
@inflater.close
|
442
|
+
@inflater = Zlib::Inflate.new(@window_bits)
|
443
|
+
@inflate_buffer = ''
|
444
|
+
0
|
445
|
+
when IO::SEEK_CUR
|
446
|
+
@inflater.total_out - @inflate_buffer.length
|
215
447
|
end
|
216
|
-
delegate.rewind
|
217
|
-
@inflater.close
|
218
|
-
@inflater = Zlib::Inflate.new(@window_bits)
|
219
|
-
@crc32 = 0
|
220
|
-
@decompress_buffer = ''
|
221
448
|
end
|
222
449
|
end
|
223
450
|
end
|