if (byteBuffer.get() != BlockCompressedStreamConstants.GZIP_ID1 ||
byteBuffer.get() != (byte)BlockCompressedStreamConstants.GZIP_ID2 ||
byteBuffer.get() != BlockCompressedStreamConstants.GZIP_CM_DEFLATE ||
byteBuffer.get() != BlockCompressedStreamConstants.GZIP_FLG
) {
throw new SAMFormatException("Invalid GZIP header");
}
// Skip MTIME, XFL, OS fields
byteBuffer.position(byteBuffer.position() + 6);
if (byteBuffer.getShort() != BlockCompressedStreamConstants.GZIP_XLEN) {
throw new SAMFormatException("Invalid GZIP header");
}
// Skip blocksize subfield intro
byteBuffer.position(byteBuffer.position() + 4);
// Read ushort
final int totalBlockSize = (byteBuffer.getShort() & 0xffff) + 1;
if (totalBlockSize != compressedLength) {
throw new SAMFormatException("GZIP blocksize disagreement");
}
// Read expected size and CRD from end of GZIP block
final int deflatedSize = compressedLength - BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH - BlockCompressedStreamConstants.BLOCK_FOOTER_LENGTH;
byteBuffer.position(byteBuffer.position() + deflatedSize);
int expectedCrc = byteBuffer.getInt();
int uncompressedSize = byteBuffer.getInt();
inflater.reset();
// Decompress
inflater.setInput(compressedBlock, BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH, deflatedSize);
final int inflatedBytes = inflater.inflate(uncompressedBlock, 0, uncompressedSize);
if (inflatedBytes != uncompressedSize) {
throw new SAMFormatException("Did not inflate expected amount");
}
// Validate CRC
crc32.reset();
crc32.update(uncompressedBlock, 0, uncompressedSize);
final long crc = crc32.getValue();
if ((int)crc != expectedCrc) {
throw new SAMFormatException("CRC mismatch");
}
} catch (DataFormatException e) {
throw new RuntimeException(e);
}
}