Class: Zlib::ZReader

Inherits:
Object
  • Object
show all
Includes:
IO::Like
Defined in:
lib/archive/support/zlib.rb

Overview

Zlib::ZReader is a readable, IO-like object (includes IO::Like) which wraps other readable, IO-like objects in order to facilitate reading data from those objects using the inflate method of decompression.

Constant Summary collapse

DEFAULT_DELEGATE_READ_SIZE =

The number of bytes to read from the delegate object each time the internal read buffer is filled.

4096

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(delegate, window_bits = nil) ⇒ ZReader

Creates a new instance of this class. delegate must respond to the read method as an IO instance would. window_bits is passed directly to Zlib::Inflate.new().

The following description of window_bits is based on the description found in zlib.h version 1.2.3. Some of the statements concerning default settings or value ranges may not be accurate depending on the version of the zlib library used by a given Ruby interpreter.

The window_bits parameter specifies the size of the history buffer, the format of the compressed stream, and the kind of checksum returned by the checksum method. The size of the history buffer is specified by setting the value of window_bits in the range of 8..15, inclusive. It must be at least as large as the setting used to create the stream or a Zlib::DataError will be raised. Modification of this base value for window_bits as noted below dictates what kind of compressed stream is expected and what kind of checksum will be produced while preserving the setting for the history buffer.

If nothing else is done to the base value of window_bits, a zlib stream is expected with an appropriate header and trailer. In this case the checksum method of this object will be an adler32.

Adding 16 to the base value of window_bits indicates that a gzip stream is expected with an appropriate header and trailer. In this case the checksum method of this object will be a crc32.

Adding 32 to the base value of window_bits indicates that an automatic detection of the stream format should be made based on the header in the stream. In this case the checksum method of this object will depend on whether a zlib or a gzip stream is detected.

Finally, negating the base value of window_bits indicates that a raw zlib stream is expected without any header or trailer. In this case the checksum method of this object will always return 1. This is for use with other formats that use the deflate compressed data format such as zip. Such formats should provide their own check values.

If unspecified or nil, window_bits defaults to 15.

In all cases, Zlib::DataError is raised if the wrong stream format is found when reading.

This class has extremely limited seek capabilities. It is possible to seek with an offset of 0 and a whence of IO::SEEK_CUR. As a result, the pos and tell methods also work as expected.

Due to certain optimizations within IO::Like#seek and if there is data in the read buffer, the seek method can be used to seek forward from the current stream position up to the end of the buffer. Unless it is known definitively how much data is in the buffer, it is best to avoid relying on this behavior.

If delegate also responds to rewind, then the rewind method of this class can be used to reset the whole stream back to the beginning. Using seek of this class to seek directly to offset 0 using IO::SEEK_SET for whence will also work in this case.

Any other seeking attempts, will raise Errno::EINVAL exceptions.

NOTE: Due to limitations in Ruby's finalization capabilities, the #close method is not automatically called when this object is garbage collected. Make sure to call #close when finished with this object.


344
345
346
347
348
349
350
351
352
353
# File 'lib/archive/support/zlib.rb', line 344

def initialize(delegate, window_bits = nil)
  @delegate = delegate
  @delegate_read_size = DEFAULT_DELEGATE_READ_SIZE
  @window_bits = window_bits
  @inflater = Zlib::Inflate.new(@window_bits)
  @inflate_buffer = ''
  @checksum = nil
  @compressed_size = nil
  @uncompressed_size = nil
end

Instance Attribute Details

#delegate_read_sizeObject

The number of bytes to read from the delegate object each time the internal read buffer is filled.


357
358
359
# File 'lib/archive/support/zlib.rb', line 357

def delegate_read_size
  @delegate_read_size
end

Class Method Details

.open(delegate, window_bits = nil) ⇒ Object

Creates a new instance of this class with the given arguments using #new and then passes the instance to the given block. The #close method is guaranteed to be called after the block completes.

Equivalent to #new if no block is given.


268
269
270
271
272
273
274
275
276
277
# File 'lib/archive/support/zlib.rb', line 268

def self.open(delegate, window_bits = nil)
  zr = new(delegate, window_bits)
  return zr unless block_given?

  begin
    yield(zr)
  ensure
    zr.close unless zr.closed?
  end
end

Instance Method Details

#checksumObject

Returns the checksum computed over the data read from this stream.

NOTE: Refer to the documentation of #new concerning window_bits to learn what kind of checksum will be returned.

NOTE: The contents of the internal read buffer are immediately processed any time the internal buffer is filled, so this checksum is only accurate if all data has been read out of this object.


374
375
376
# File 'lib/archive/support/zlib.rb', line 374

def checksum
  @inflater.closed? ? @checksum : @inflater.adler
end

#closeObject

Closes the reader.

Raises IOError if called more than once.


381
382
383
384
385
386
387
388
# File 'lib/archive/support/zlib.rb', line 381

def close
  super()
  @checksum = @inflater.adler
  @compressed_size = @inflater.total_in
  @uncompressed_size = @inflater.total_out
  @inflater.close
  nil
end

#compressed_sizeObject

Returns the number of bytes sent to be compressed so far.

NOTE: This value is updated whenever the internal read buffer needs to be filled, not when data is read out of this stream.


394
395
396
# File 'lib/archive/support/zlib.rb', line 394

def compressed_size
  @inflater.closed? ? @compressed_size : @inflater.total_in
end

#uncompressed_sizeObject

Returns the number of bytes of decompressed data produced so far.

NOTE: This value is updated whenever the internal read buffer needs to be filled, not when data is read out of this stream.


402
403
404
# File 'lib/archive/support/zlib.rb', line 402

def uncompressed_size
  @inflater.closed? ? @uncompressed_size : @inflater.total_out
end