public abstract class AbstractLZ77CompressorInputStream extends CompressorInputStream implements InputStreamStatistics
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:
readOneByte()
to access the underlying stream
directly.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
.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
.-1
as this class' methods will never do so themselves.readOneByte()
and readLiteral(byte[], int, int)
update the counter
for bytes read.
Modifier and Type | Field and Description |
---|---|
private int |
backReferenceOffset
Offset of the current back-reference.
|
private byte[] |
buf
Buffer to write decompressed bytes to for back-references, will
be three times windowSize big.
|
private long |
bytesRemaining
Number of bytes still to be read from the current literal or back-reference.
|
private CountingInputStream |
in
The underlying stream to read compressed data from
|
private byte[] |
oneByte |
private int |
readIndex
Index of the next byte to be read.
|
private int |
size
uncompressed size
|
protected ByteUtils.ByteSupplier |
supplier
Supplier that delegates to
readOneByte() . |
private int |
windowSize
Size of the window - must be bigger than the biggest offset expected.
|
private int |
writeIndex
One behind the index of the last byte in the buffer that was written, i.e.
|
Constructor and Description |
---|
AbstractLZ77CompressorInputStream(java.io.InputStream is,
int windowSize)
Creates a new LZ77 input stream.
|
Modifier and Type | Method and Description |
---|---|
int |
available() |
void |
close() |
long |
getCompressedCount() |
int |
getSize()
Get the uncompressed size of the stream
|
protected 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 int |
readBackReference(byte[] b,
int off,
int len)
Reads data from the current back-reference.
|
private int |
readFromBuffer(byte[] b,
int off,
int len) |
protected int |
readLiteral(byte[] b,
int off,
int len)
Reads data from the current literal block.
|
protected int |
readOneByte()
Reads a single byte from the real input stream and ensures the data is accounted for.
|
private void |
slideBuffer() |
protected void |
startBackReference(int offset,
long length)
Used by subclasses to signal the next block contains a back-reference with the given coordinates.
|
protected void |
startLiteral(long length)
Used by subclasses to signal the next block contains the given
amount of literal data.
|
private void |
tryToCopy(int bytesToCopy) |
private void |
tryToReadLiteral(int bytesToRead) |
count, count, getBytesRead, getCount, getUncompressedCount, pushedBackBytes
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
getUncompressedCount
private final int windowSize
private final byte[] buf
Three times so we can slide the whole buffer a windowSize to the left once we've read twice windowSize and still have enough data inside of it to satisfy back-references.
private int writeIndex
private int readIndex
private final CountingInputStream in
private long bytesRemaining
private int backReferenceOffset
private int size
private final byte[] oneByte
protected final ByteUtils.ByteSupplier supplier
readOneByte()
.public AbstractLZ77CompressorInputStream(java.io.InputStream is, int windowSize) throws java.io.IOException
is
- An InputStream to read compressed data fromwindowSize
- Size of the window kept for back-references, must be bigger than the biggest offset expected.java.io.IOException
- if reading failspublic int read() throws java.io.IOException
read
in class java.io.InputStream
java.io.IOException
public void close() throws java.io.IOException
close
in interface java.io.Closeable
close
in interface java.lang.AutoCloseable
close
in class java.io.InputStream
java.io.IOException
public int available()
available
in class java.io.InputStream
public int getSize()
public void prefill(byte[] data)
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.
data
- the data to fill the window with.java.lang.IllegalStateException
- if the stream has already started to read datapublic long getCompressedCount()
getCompressedCount
in interface InputStreamStatistics
protected final void startLiteral(long length)
length
- the length of the blockprotected final boolean hasMoreDataInBlock()
protected final int readLiteral(byte[] b, int off, int len) throws java.io.IOException
b
- buffer to write data tooff
- offset to start writing tolen
- maximum amount of data to readjava.io.IOException
- if the underlying stream throws or signals
an EOF before the amount of data promised for the block have
been readprivate void tryToReadLiteral(int bytesToRead) throws java.io.IOException
java.io.IOException
private int readFromBuffer(byte[] b, int off, int len)
private void slideBuffer()
protected final void startBackReference(int offset, long length)
offset
- the offset of the back-referencelength
- the length of the back-referenceprotected final int readBackReference(byte[] b, int off, int len)
b
- buffer to write data tooff
- offset to start writing tolen
- maximum amount of data to readprivate void tryToCopy(int bytesToCopy)
protected final int readOneByte() throws java.io.IOException
java.io.IOException
- if the underlying stream throws