in src/main/java/org/apache/commons/compress/compressors/snappy/SnappyCompressorInputStream.java [88:188]
private void fill() throws IOException {
if (uncompressedBytesRemaining == 0) {
endReached = true;
return;
}
int b = readOneByte();
if (b == -1) {
throw new IOException("Premature end of stream reading block start");
}
int length = 0;
int offset = 0;
switch (b & TAG_MASK) {
case 0x00:
length = readLiteralLength(b);
if (length < 0) {
throw new IOException("Illegal block with a negative literal size found");
}
uncompressedBytesRemaining -= length;
startLiteral(length);
state = State.IN_LITERAL;
break;
case 0x01:
/*
* These elements can encode lengths between [4..11] bytes and offsets between [0..2047] bytes. (len-4) occupies three bits and is stored in bits
* [2..4] of the tag byte. The offset occupies 11 bits, of which the upper three are stored in the upper three bits ([5..7]) of the tag byte, and
* the lower eight are stored in a byte following the tag byte.
*/
length = 4 + (b >> 2 & 0x07);
uncompressedBytesRemaining -= length;
offset = (b & 0xE0) << 3;
b = readOneByte();
if (b == -1) {
throw new IOException("Premature end of stream reading back-reference length");
}
offset |= b;
try {
startBackReference(offset, length);
} catch (final IllegalArgumentException ex) {
throw new IOException("Illegal block with bad offset found", ex);
}
state = State.IN_BACK_REFERENCE;
break;
case 0x02:
/*
* These elements can encode lengths between [1..64] and offsets from [0..65535]. (len-1) occupies six bits and is stored in the upper six bits
* ([2..7]) of the tag byte. The offset is stored as a little-endian 16-bit integer in the two bytes following the tag byte.
*/
length = (b >> 2) + 1;
if (length < 0) {
throw new IOException("Illegal block with a negative match length found");
}
uncompressedBytesRemaining -= length;
offset = (int) ByteUtils.fromLittleEndian(supplier, 2);
try {
startBackReference(offset, length);
} catch (final IllegalArgumentException ex) {
throw new IOException("Illegal block with bad offset found", ex);
}
state = State.IN_BACK_REFERENCE;
break;
case 0x03:
/*
* These are like the copies with 2-byte offsets (see previous subsection), except that the offset is stored as a 32-bit integer instead of a 16-bit
* integer (and thus will occupy four bytes).
*/
length = (b >> 2) + 1;
if (length < 0) {
throw new IOException("Illegal block with a negative match length found");
}
uncompressedBytesRemaining -= length;
offset = (int) ByteUtils.fromLittleEndian(supplier, 4) & 0x7fffffff;
try {
startBackReference(offset, length);
} catch (final IllegalArgumentException ex) {
throw new IOException("Illegal block with bad offset found", ex);
}
state = State.IN_BACK_REFERENCE;
break;
default:
// impossible as TAG_MASK is two bits and all four possible cases have been covered
break;
}
}