package org.broad.igv.sam.lite;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
/**
* Created by jrobinso on 3/10/17.
*/
public class BGUnzip {
public static final int BGZIP_HEADER_LENGTH = 18;
// Uncompress data, assumed to be series of bgzipped blocks
public static byte[] blockUnzip(byte[] data) throws IOException {
Inflater inflater = new Inflater(true);
int ptr = 0;
int lim = data.length - BGZIP_HEADER_LENGTH;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
while (ptr < lim) {
int xlen = unpackInt16(data, ptr + 10);
int si1 = data[ptr + 12];
int si2 = data[ptr + 13];
int slen = unpackInt16(data, 14);
int bsize = unpackInt16(data, ptr + 16) + 1;
int start = BGZIP_HEADER_LENGTH + ptr; // Start of CDATA
int remainder = data.length - start;
if (remainder < (bsize + 8)) break;
int uncLength = unpackInt32(data, ptr + bsize - 4);
inflater.reset();
inflater.setInput(data, start, remainder);
byte [] output = new byte[uncLength];
final int inflatedBytes;
try {
inflatedBytes = inflater.inflate(output, 0, uncLength);
} catch (DataFormatException e) {
// Can happen near end of file;
break;
}
outputStream.write(output, 0, inflatedBytes);
ptr += bsize; // Advance to next block
}
return outputStream.toByteArray();
}
private static int unpackInt16(final byte[] buffer, final int offset) {
return ((buffer[offset] & 0xFF) |
((buffer[offset+1] & 0xFF) << 8));
}
private static int unpackInt32(final byte[] buffer, final int offset) {
return ((buffer[offset] & 0xFF) |
((buffer[offset + 1] & 0xFF) << 8) |
((buffer[offset + 2] & 0xFF) << 16) |
((buffer[offset + 3] & 0xFF) << 24));
}
}