1 package org.simantics.db.server.internal;
3 import java.nio.ByteBuffer;
4 import java.util.Arrays;
6 import org.simantics.fastlz.FastLZ;
7 import org.simantics.fastlz.FastLZJava;
11 * @author Tuukka Lehtonen
13 public class ClusterDecompressor {
15 private byte[] inflateBuffer;
17 public Object[] inflateCluster(int inflateSize, ByteBuffer deflatedCluster)
18 throws CompressionException {
19 int deflatedSize = deflatedCluster.limit();
20 Object[] arrays = new Object[3];
21 int inflated = decompressCluster(deflatedCluster, deflatedSize, inflateSize, arrays);
22 if (inflated != inflateSize)
23 throw new CompressionException("decompression error, inflated "
24 + inflated + " bytes when " + inflateSize + " expected.");
29 * Wrapper for the old native direct byte buffer version of cluster
36 * expects an array of 3 elements. The decompression result will
37 * be stored in here. [0] = cluster long array (long[]), [1] =
38 * cluster int array (int[]), [2] = cluster byte array (byte[]).
39 * @return the amount of bytes inflated from the deflated cluster. Matches
40 * inflatedSize when successful.
42 * @see FastLZ#decompressCluster(ByteBuffer, int, int, Object[])
44 public int decompressCluster(ByteBuffer deflated, int deflatedSize, int inflatedSize, Object[] arrays) {
45 if (deflated.isDirect()) {
46 if (FastLZ.isNativeInitialized()) {
47 FastLZ.decompressCluster(deflated, deflatedSize, inflatedSize, arrays);
50 // REALLY SLOW FALLBACK: java code for direct byte buffers
53 if (deflated.hasArray()) {
54 array = deflated.array();
56 // SLOW FALLBACK: read-only heap byte buffer
57 array = new byte[deflatedSize];
58 int pos = deflated.position();
60 deflated.get(array, 0, deflatedSize);
61 deflated.position(pos);
63 return decompressCluster(array, deflatedSize, inflatedSize, arrays);
73 public synchronized int decompressCluster(byte[] deflated, int deflatedSize, int inflatedSize, Object[] arrays) {
74 if (inflateBuffer == null) {
75 inflateBuffer = new byte[inflatedSize];
76 } else if (inflateBuffer.length < inflatedSize) {
77 inflateBuffer = new byte[inflatedSize];
79 return decompressCluster(deflated, deflatedSize, inflateBuffer, inflatedSize, arrays);
88 * @return amount of bytes inflated from the original deflated buffer.
89 * Should match inflatedSize if everything went ok, otherwise will
92 public static int decompressCluster(byte[] deflated, int deflatedSize, byte[] inflated, int inflatedSize, Object[] arrays) {
93 if (inflated.length < inflatedSize)
94 throw new IllegalArgumentException("inflate buffer size (" + inflated.length + ") is smaller than inflated size (" + inflatedSize + ")");
96 int decompressedBytes = FastLZJava.decompress(deflated, 0, deflatedSize, inflated, 0, inflatedSize);
97 if (decompressedBytes != inflatedSize)
98 return decompressedBytes;
102 int longCount = readInt(inflated, offset);
103 long[] longs = new long[longCount];
104 copyLongs(inflated, offset + 4, longs);
105 offset += 4 + 8*longCount;
107 int intCount = readInt(inflated, offset);
108 int[] ints = new int[intCount];
109 copyInts(inflated, offset + 4, ints);
110 offset += 4 + 4*intCount;
112 int byteCount = readInt(inflated, offset);
113 byte[] bytes = Arrays.copyOfRange(inflated, offset + 4, offset + 4 + byteCount);
119 return decompressedBytes;
122 private static void copyInts(byte[] bytes, int i, int[] ints) {
124 int count = ints.length;
125 for (int a = 0; a < count; ++a, offset += 4) {
126 int value = (((int) bytes[offset] & 0xff)) |
127 (((int) bytes[offset+1] & 0xff) << 8) |
128 (((int) bytes[offset+2] & 0xff) << 16) |
129 (((int) bytes[offset+3] & 0xff) << 24);
134 private static void copyLongs(byte[] bytes, int i, long[] longs) {
136 int count = longs.length;
137 for (int a = 0; a < count; ++a, offset += 8) {
138 long value = (((long) bytes[offset] & 0xff)) |
139 (((long) bytes[offset+1] & 0xff) << 8) |
140 (((long) bytes[offset+2] & 0xff) << 16) |
141 (((long) bytes[offset+3] & 0xff) << 24) |
142 (((long) bytes[offset+4] & 0xff) << 32) |
143 (((long) bytes[offset+5] & 0xff) << 40) |
144 (((long) bytes[offset+6] & 0xff) << 48) |
145 (((long) bytes[offset+7] & 0xff) << 56);
150 private static int readInt(byte[] array, int offset) {
151 return (((int) array[offset] & 0xff)) |
152 (((int) array[offset+1] & 0xff) << 8) |
153 (((int) array[offset+2] & 0xff) << 16) |
154 (((int) array[offset+3] & 0xff) << 24);