archive-zip 0.3.0 → 0.4.0
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/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
|