tikhomirov@534: /* tikhomirov@534: * Copyright (c) 2013 TMate Software Ltd tikhomirov@534: * tikhomirov@534: * This program is free software; you can redistribute it and/or modify tikhomirov@534: * it under the terms of the GNU General Public License as published by tikhomirov@534: * the Free Software Foundation; version 2 of the License. tikhomirov@534: * tikhomirov@534: * This program is distributed in the hope that it will be useful, tikhomirov@534: * but WITHOUT ANY WARRANTY; without even the implied warranty of tikhomirov@534: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the tikhomirov@534: * GNU General Public License for more details. tikhomirov@534: * tikhomirov@534: * For information on how to redistribute this software under tikhomirov@534: * the terms of a license other than GNU General Public License tikhomirov@534: * contact TMate Software at support@hg4j.com tikhomirov@534: */ tikhomirov@534: package org.tmatesoft.hg.internal; tikhomirov@534: tikhomirov@534: import java.io.IOException; tikhomirov@534: import java.util.zip.Deflater; tikhomirov@534: import java.util.zip.DeflaterOutputStream; tikhomirov@534: tikhomirov@534: /** tikhomirov@534: * {@link DeflaterOutputStream} counterpart for {@link DataSerializer} API tikhomirov@534: * tikhomirov@534: * @author Artem Tikhomirov tikhomirov@534: * @author TMate Software Ltd. tikhomirov@534: */ tikhomirov@534: class DeflaterDataSerializer extends DataSerializer { tikhomirov@534: tikhomirov@534: private static final int AUX_BUFFER_CAPACITY = 5; // room for 5 ints tikhomirov@534: tikhomirov@534: private final DataSerializer delegate; tikhomirov@534: private final Deflater deflater; tikhomirov@534: private final byte[] deflateOutBuffer; tikhomirov@534: private final byte[] auxBuffer; tikhomirov@534: tikhomirov@534: public DeflaterDataSerializer(DataSerializer delegateSerializer, Deflater def, int bufferSizeHint) { tikhomirov@534: delegate = delegateSerializer; tikhomirov@534: deflater = def; tikhomirov@534: deflateOutBuffer = new byte[bufferSizeHint <= 0 ? 2048 : bufferSizeHint]; tikhomirov@534: auxBuffer = new byte[4 * AUX_BUFFER_CAPACITY]; // sizeof(int) * capacity tikhomirov@534: } tikhomirov@534: tikhomirov@534: @Override tikhomirov@534: public void writeInt(int... values) throws IOException { tikhomirov@534: for (int i = 0; i < values.length; i+= AUX_BUFFER_CAPACITY) { tikhomirov@534: int idx = 0; tikhomirov@534: for (int j = i, x = Math.min(values.length, i + AUX_BUFFER_CAPACITY); j < x; j++) { tikhomirov@534: int v = values[j]; tikhomirov@534: auxBuffer[idx++] = (byte) ((v >>> 24) & 0x0ff); tikhomirov@534: auxBuffer[idx++] = (byte) ((v >>> 16) & 0x0ff); tikhomirov@534: auxBuffer[idx++] = (byte) ((v >>> 8) & 0x0ff); tikhomirov@534: auxBuffer[idx++] = (byte) (v & 0x0ff); tikhomirov@534: } tikhomirov@534: internalWrite(auxBuffer, 0, idx); tikhomirov@534: } tikhomirov@534: } tikhomirov@534: tikhomirov@534: @Override tikhomirov@534: public void write(byte[] data, int offset, int length) throws IOException { tikhomirov@534: // @see DeflaterOutputStream#write(byte[], int, int) tikhomirov@534: int stride = deflateOutBuffer.length; tikhomirov@534: for (int i = 0; i < length; i += stride) { tikhomirov@534: internalWrite(data, offset + i, Math.min(stride, length - i)); tikhomirov@534: } tikhomirov@534: } tikhomirov@534: tikhomirov@534: private void internalWrite(byte[] data, int offset, int length) throws IOException { tikhomirov@534: deflater.setInput(data, offset, length); tikhomirov@534: while (!deflater.needsInput()) { tikhomirov@534: deflate(); tikhomirov@534: } tikhomirov@534: } tikhomirov@534: tikhomirov@534: @Override tikhomirov@534: public void done() { tikhomirov@534: delegate.done(); tikhomirov@534: } tikhomirov@534: tikhomirov@534: public void finish() throws IOException { tikhomirov@534: if (!deflater.finished()) { tikhomirov@534: deflater.finish(); tikhomirov@534: while (!deflater.finished()) { tikhomirov@534: deflate(); tikhomirov@534: } tikhomirov@534: } tikhomirov@534: } tikhomirov@534: tikhomirov@534: protected void deflate() throws IOException { tikhomirov@534: int len = deflater.deflate(deflateOutBuffer, 0, deflateOutBuffer.length); tikhomirov@534: if (len > 0) { tikhomirov@534: delegate.write(deflateOutBuffer, 0, len); tikhomirov@534: } tikhomirov@534: } tikhomirov@534: }