Mercurial > hg4j
diff src/org/tmatesoft/hg/internal/DeflaterDataSerializer.java @ 534:243202f1bda5
Commit: refactor revision creation code from clone command to work separately, fit into existing library structure
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Mon, 04 Feb 2013 18:00:55 +0100 |
parents | |
children | 7c0d2ce340b8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/tmatesoft/hg/internal/DeflaterDataSerializer.java Mon Feb 04 18:00:55 2013 +0100 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@hg4j.com + */ +package org.tmatesoft.hg.internal; + +import java.io.IOException; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + +/** + * {@link DeflaterOutputStream} counterpart for {@link DataSerializer} API + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +class DeflaterDataSerializer extends DataSerializer { + + private static final int AUX_BUFFER_CAPACITY = 5; // room for 5 ints + + private final DataSerializer delegate; + private final Deflater deflater; + private final byte[] deflateOutBuffer; + private final byte[] auxBuffer; + + public DeflaterDataSerializer(DataSerializer delegateSerializer, Deflater def, int bufferSizeHint) { + delegate = delegateSerializer; + deflater = def; + deflateOutBuffer = new byte[bufferSizeHint <= 0 ? 2048 : bufferSizeHint]; + auxBuffer = new byte[4 * AUX_BUFFER_CAPACITY]; // sizeof(int) * capacity + } + + @Override + public void writeInt(int... values) throws IOException { + for (int i = 0; i < values.length; i+= AUX_BUFFER_CAPACITY) { + int idx = 0; + for (int j = i, x = Math.min(values.length, i + AUX_BUFFER_CAPACITY); j < x; j++) { + int v = values[j]; + auxBuffer[idx++] = (byte) ((v >>> 24) & 0x0ff); + auxBuffer[idx++] = (byte) ((v >>> 16) & 0x0ff); + auxBuffer[idx++] = (byte) ((v >>> 8) & 0x0ff); + auxBuffer[idx++] = (byte) (v & 0x0ff); + } + internalWrite(auxBuffer, 0, idx); + } + } + + @Override + public void write(byte[] data, int offset, int length) throws IOException { + // @see DeflaterOutputStream#write(byte[], int, int) + int stride = deflateOutBuffer.length; + for (int i = 0; i < length; i += stride) { + internalWrite(data, offset + i, Math.min(stride, length - i)); + } + } + + private void internalWrite(byte[] data, int offset, int length) throws IOException { + deflater.setInput(data, offset, length); + while (!deflater.needsInput()) { + deflate(); + } + } + + @Override + public void done() { + delegate.done(); + } + + public void finish() throws IOException { + if (!deflater.finished()) { + deflater.finish(); + while (!deflater.finished()) { + deflate(); + } + } + } + + protected void deflate() throws IOException { + int len = deflater.deflate(deflateOutBuffer, 0, deflateOutBuffer.length); + if (len > 0) { + delegate.write(deflateOutBuffer, 0, len); + } + } +}