/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.db.procore.cluster; import java.nio.ByteBuffer; import java.nio.ByteOrder; import org.simantics.compressions.Compressions; import org.simantics.db.exception.InternalException; public class LZ4 { static private final int InLength = 1<<20; public static class DecompressStruct { public long[] longs; public int[] ints; public byte[] bytes; } static class SourceData { SourceData(byte[] data) { this.data = data; this.offset = 0; } int left() { return data.length - offset; } int readInt() { int inLength = 4; // sizeof(int) assert(left() >= inLength); // must have data for input ByteBuffer buffer = ByteBuffer.wrap(data, offset, inLength); buffer.order(ByteOrder.LITTLE_ENDIAN); // argh! int t = buffer.getInt(); offset += inLength; return t; } void readBytes(byte[] bytes, int aOffset, int inLength) { assert(left() >= inLength); // must have data for input System.arraycopy(data, offset, bytes, aOffset, inLength); offset += inLength; } byte[] data; int offset; } public static DecompressStruct decompress(byte[] data) throws InternalException { assert(data.length > 12); // 3*(table size) SourceData sourceData = new SourceData(data); DecompressStruct struct = new DecompressStruct(); int longSize = sourceData.readInt(); int intSize = sourceData.readInt(); int byteSize = sourceData.readInt(); struct.longs = new long[longSize]; try { decompress(sourceData, struct.longs); struct.ints = new int[intSize]; decompress(sourceData, struct.ints); struct.bytes = new byte[byteSize]; decompress(sourceData, struct.bytes); } catch (CompressionException e) { throw new InternalException("Failed to decompress.", e); } return struct; } private static void decompress(SourceData sourceData, long[] longs) throws CompressionException { int length = longs.length * 8; ByteBuffer bytes = ByteBuffer.allocate(length); int size = decompressRaw(sourceData, bytes.array()); assert(size == length); bytes.order(ByteOrder.LITTLE_ENDIAN); // argh for (int i=0; i= dstSize); // must have space for data assert(sourceData.left() >= inLength); // must have data for input assert(inLength > 0); // no data no block assert(inLength <= InLength); // input size is block size or less assert(inLength <= dataLength); // input size is never bigger than data size if (inLength < dataLength) {// block was actually compressed decompress(sourceData.data, sourceData.offset, inLength, bytes, dstOffset, dataLength); sourceData.offset += inLength; dstOffset += dataLength; } else { sourceData.readBytes(bytes, dstOffset, inLength); dstOffset += inLength; } } } private static void decompress(byte[] in, int inOffset, int inLength, byte[] out, int outOffset, int outLength) throws CompressionException { ByteBuffer inBuffer = ByteBuffer.allocateDirect(inLength); inBuffer.put(in, inOffset, inLength); inBuffer.flip(); ByteBuffer outBuffer = ByteBuffer.allocateDirect(outLength); int inflateSize = Compressions.get(Compressions.LZ4).decompressBuffer(inBuffer, 0, inLength, outBuffer, 0, outLength); // int inflateSize = org.simantics.fastlz.FastLZ.decompressBuffer(inBuffer, 0, inLength, outBuffer, 0, outLength); if (inflateSize != outLength) throw new RuntimeException("Decompression error."); //outBuffer.flip(); outBuffer.get(out, outOffset, outLength); } }