package yuku.alkitab.yes2.compress;
import yuku.snappy.codec.Snappy;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class SnappyOutputStream extends FilterOutputStream {
public final String TAG = SnappyOutputStream.class.getSimpleName();
private final Snappy snappy;
private final int block_size;
private byte[] uncompressed_buf;
private byte[] compressed_buf;
private int uncompressed_offset;
private int[] compressed_block_sizes = new int[100];
private int compressed_block_sizes_length = 0;
public SnappyOutputStream(OutputStream out, int block_size) {
super(out);
this.snappy = new Snappy.Factory().newInstance();
this.block_size = block_size;
this.uncompressed_buf = new byte[block_size];
this.compressed_buf = new byte[snappy.maxCompressedLength(uncompressed_buf.length)];
}
@Override public void write(int b) throws IOException {
if (uncompressed_offset >= block_size) {
dump();
}
uncompressed_buf[uncompressed_offset++] = (byte) b;
}
@Override public void write(byte[] b, int off, int len) throws IOException {
int remaining = len;
int src_off = off;
while (remaining > 0) {
int can_write = block_size - uncompressed_offset;
int will_write = Math.min(remaining, can_write);
System.arraycopy(b, src_off, uncompressed_buf, uncompressed_offset, will_write);
uncompressed_offset += will_write;
src_off += will_write;
remaining -= will_write;
if (uncompressed_offset >= block_size) {
dump();
}
}
assert src_off == off + len;
}
private void dump() throws IOException {
if (uncompressed_offset > 0) {
int compressed_len = snappy.compress(uncompressed_buf, 0, compressed_buf, 0, uncompressed_offset);
out.write(compressed_buf, 0, compressed_len);
// check for need of expanding compressed_block_sizes array
while (compressed_block_sizes_length >= compressed_block_sizes.length) {
final int[] newArray = new int[compressed_block_sizes.length << 1];
System.arraycopy(compressed_block_sizes, 0, newArray, 0, compressed_block_sizes_length);
compressed_block_sizes = newArray;
}
compressed_block_sizes[compressed_block_sizes_length] = compressed_len;
compressed_block_sizes_length++;
uncompressed_offset = 0;
}
}
@Override public void flush() throws IOException {
dump();
out.flush();
}
public int[] getCompressedBlockSizes() {
int[] res = new int[compressed_block_sizes_length];
System.arraycopy(compressed_block_sizes, 0, res, 0, compressed_block_sizes_length);
return res;
}
}