Package org.apache.commons.compress.compressors.lz77support

# Class AbstractLZ77CompressorInputStream

java.lang.Object
java.io.InputStream
org.apache.commons.compress.compressors.CompressorInputStream
org.apache.commons.compress.compressors.lz77support.AbstractLZ77CompressorInputStream

All Implemented Interfaces:
  `Closeable`, `AutoCloseable`, `InputStreamStatistics`

Direct Known Subclasses:
  `BlockLZ4CompressorInputStream`, `SnappyCompressorInputStream`

public abstract class AbstractLZ77CompressorInputStream extends CompressorInputStream implements InputStreamStatistics
Encapsulates code common to LZ77 decompressors.

Assumes the stream consists of blocks of literal data and back-references (called copies) in any order. Of course the first block must be a literal block for the scheme to work - unless the `prefill` method has been used to provide initial data that is never returned by `read` but only used for back-references.

Subclasses must override the three-arg `read` method as the no-arg version delegates to it and the default implementation delegates to the no-arg version, leading to infinite mutual recursion and a `StackOverflowError` otherwise.

The contract for subclasses' `read` implementation is:

- keep track of the current state of the stream. Is it inside a literal block or a back-reference or in-between blocks?
- Use `readOneByte()` to access the underlying stream directly.
- If a new literal block starts, use `startLiteral(long)` to tell this class about it and read the literal data using `readLiteral(byte[], int, int)` until it returns `0`. `hasMoreDataInBlock()` will return `false` before the next call to `readLiteral(byte[], int, int)` would return `0`.
- If a new back-reference starts, use `startBackReference(int, long)` to tell this class about it and read the literal data using `readBackReference(byte[], int, int)` until it returns `0`. `hasMoreDataInBlock()` will return `false` before the next call to `readBackReference(byte[], int, int)` would return `0`.
- If the end of the stream has been reached, return `-1` as this class' methods will never do so themselves.

`readOneByte()` and `readLiteral(byte[], int, int)` update the counter for bytes read.

Since:
  1.14

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final ByteUtils.ByteSupplier`
  `supplier`
  Supplier that delegates to `readOneByte()`.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `AbstractLZ77CompressorInputStream(InputStream is, int windowSize)`
  Creates a new LZ77 input stream.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `int`
  `available()`
  `void`
  `close()`
  `long`
  `getCompressedCount()`
  `int`
  `getSize()`
  Get the uncompressed size of the stream
  `protected final boolean`
  `hasMoreDataInBlock()`
  Is there still data remaining inside the current block?
  `void`
  `prefill(byte[] data)`
  Adds some initial data to fill the window with.
  `int`
  `read()`
  `protected final int`
  `readBackReference(byte[] b, int off, int len)`
  Reads data from the current back-reference.
  `protected final int`
  `readLiteral(byte[] b, int off, int len)`
  Reads data from the current literal block.
  `protected final int`
  `readOneByte()`
  Reads a single byte from the real input stream and ensures the data is accounted for.
  `protected final void`
  `startBackReference(int offset, long length)`
  Used by subclasses to signal the next block contains a back-reference with the given coordinates.
  `protected final void`
  `startLiteral(long length)`
  Used by subclasses to signal the next block contains the given amount of literal data.

  ### Methods inherited from class org.apache.commons.compress.compressors.CompressorInputStream

  `count, count, getBytesRead, getCount, getUncompressedCount, pushedBackBytes`

  ### Methods inherited from class java.io.InputStream

  `mark, markSupported, read, read, reset, skip`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

  ### Methods inherited from interface org.apache.commons.compress.utils.InputStreamStatistics

  `getUncompressedCount`

- ## Field Details

  - ### supplier

    protected final ByteUtils.ByteSupplier supplier
    Supplier that delegates to `readOneByte()`.

- ## Constructor Details

  - ### AbstractLZ77CompressorInputStream

    public AbstractLZ77CompressorInputStream(InputStream is, int windowSize)
    Creates a new LZ77 input stream.
    Parameters:
      `is` - An InputStream to read compressed data from
      `windowSize` - Size of the window kept for back-references, must be bigger than the biggest offset expected.
    Throws:
      `IllegalArgumentException` - if windowSize is not bigger than 0

- ## Method Details

  - ### available

    public int available()
    Overrides:
      `available` in class `InputStream`

  - ### close

    public void close() throws IOException
    Specified by:
      `close` in interface `AutoCloseable`
    Specified by:
      `close` in interface `Closeable`
    Overrides:
      `close` in class `InputStream`
    Throws:
      `IOException`

  - ### getCompressedCount

    public long getCompressedCount()
    Specified by:
      `getCompressedCount` in interface `InputStreamStatistics`
    Returns:
      the amount of raw or compressed bytes read by the stream
    Since:
      1.17

  - ### getSize

    public int getSize()
    Get the uncompressed size of the stream
    Returns:
      the uncompressed size

  - ### hasMoreDataInBlock

    protected final boolean hasMoreDataInBlock()
    Is there still data remaining inside the current block?
    Returns:
      true if there is still data remaining inside the current block.

  - ### prefill

    public void prefill(byte[] data)
    Adds some initial data to fill the window with.

    This is used if the stream has been cut into blocks and back-references of one block may refer to data of the previous block(s). One such example is the LZ4 frame format using block dependency.

    Parameters:
      `data` - the data to fill the window with.
    Throws:
      `IllegalStateException` - if the stream has already started to read data

  - ### read

    public int read() throws IOException
    Specified by:
      `read` in class `InputStream`
    Throws:
      `IOException`

  - ### readBackReference

    protected final int readBackReference(byte[] b, int off, int len)
    Reads data from the current back-reference.
    Parameters:
      `b` - buffer to write data to
      `off` - offset to start writing to
      `len` - maximum amount of data to read
    Returns:
      number of bytes read, may be 0. Will never return -1 as EOF-detection is the responsibility of the subclass
    Throws:
      `NullPointerException` - if `b` is null
      `IndexOutOfBoundsException` - if `off` is negative, `len` is negative, or `len` is greater than `b.length - off`

  - ### readLiteral

    protected final int readLiteral(byte[] b, int off, int len) throws IOException
    Reads data from the current literal block.
    Parameters:
      `b` - buffer to write data to
      `off` - offset to start writing to
      `len` - maximum amount of data to read
    Returns:
      number of bytes read, may be 0. Will never return -1 as EOF-detection is the responsibility of the subclass
    Throws:
      `IOException` - if the underlying stream throws or signals an EOF before the amount of data promised for the block have been read
      `NullPointerException` - if `b` is null
      `IndexOutOfBoundsException` - if `off` is negative, `len` is negative, or `len` is greater than `b.length - off`

  - ### readOneByte

    protected final int readOneByte() throws IOException
    Reads a single byte from the real input stream and ensures the data is accounted for.
    Returns:
      the byte read as value between 0 and 255 or -1 if EOF has been reached.
    Throws:
      `IOException` - if the underlying stream throws

  - ### startBackReference

    protected final void startBackReference(int offset, long length)
    Used by subclasses to signal the next block contains a back-reference with the given coordinates.
    Parameters:
      `offset` - the offset of the back-reference
      `length` - the length of the back-reference
    Throws:
      `IllegalArgumentException` - if offset not bigger than 0 or bigger than the number of bytes available for back-references or if length is negative

  - ### startLiteral

    protected final void startLiteral(long length)
    Used by subclasses to signal the next block contains the given amount of literal data.
    Parameters:
      `length` - the length of the block
    Throws:
      `IllegalArgumentException` - if length is negative