]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/LZ4.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / LZ4.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.db.procore.cluster;\r
13 \r
14 import java.nio.ByteBuffer;\r
15 import java.nio.ByteOrder;\r
16 \r
17 import org.simantics.compressions.Compressions;\r
18 import org.simantics.db.exception.InternalException;\r
19 \r
20 public class LZ4 {\r
21     static private final int InLength = 1<<20;\r
22     \r
23     public static class DecompressStruct {\r
24         public long[] longs;\r
25         public int[] ints;\r
26         public byte[] bytes;\r
27     }\r
28     static class SourceData {\r
29         SourceData(byte[] data) {\r
30             this.data = data;\r
31             this.offset = 0;\r
32         }\r
33         int left() {\r
34             return data.length - offset;\r
35         }\r
36         int readInt() {\r
37             int inLength = 4; // sizeof(int)\r
38             assert(left() >= inLength); // must have data for input\r
39             ByteBuffer buffer = ByteBuffer.wrap(data, offset, inLength);\r
40             buffer.order(ByteOrder.LITTLE_ENDIAN); // argh!\r
41             int t = buffer.getInt();\r
42             offset += inLength;\r
43             return t;\r
44         }\r
45         void readBytes(byte[] bytes, int aOffset, int inLength) {\r
46             assert(left() >= inLength); // must have data for input\r
47             System.arraycopy(data, offset, bytes, aOffset, inLength);\r
48             offset += inLength;\r
49         }\r
50         byte[] data;\r
51         int offset;\r
52     }\r
53     public static DecompressStruct decompress(byte[] data) throws InternalException {\r
54         assert(data.length > 12); // 3*(table size)\r
55         SourceData sourceData = new SourceData(data);\r
56         DecompressStruct struct = new DecompressStruct();\r
57         int longSize = sourceData.readInt();\r
58         int intSize = sourceData.readInt();\r
59         int byteSize = sourceData.readInt();\r
60         struct.longs = new long[longSize]; \r
61         try {\r
62             decompress(sourceData, struct.longs);\r
63             struct.ints = new int[intSize]; \r
64             decompress(sourceData, struct.ints);\r
65             struct.bytes = new byte[byteSize];\r
66             decompress(sourceData, struct.bytes);\r
67         } catch (CompressionException e) {\r
68             throw new InternalException("Failed to decompress.", e);\r
69         }\r
70         return struct;\r
71     }\r
72     private static void decompress(SourceData sourceData, long[] longs) throws CompressionException {\r
73         int length = longs.length * 8;\r
74         ByteBuffer bytes = ByteBuffer.allocate(length);\r
75         int size = decompressRaw(sourceData, bytes.array());\r
76         assert(size == length);\r
77         bytes.order(ByteOrder.LITTLE_ENDIAN); // argh\r
78         for (int i=0; i<longs.length; ++i)\r
79             longs[i] = bytes.getLong();\r
80     }\r
81     private static void decompress(SourceData sourceData, int[] ints) throws CompressionException {\r
82         int length = ints.length * 4;\r
83         ByteBuffer bytes = ByteBuffer.allocate(length);\r
84         int size = decompressRaw(sourceData, bytes.array());\r
85         assert(size == length);\r
86         bytes.order(ByteOrder.LITTLE_ENDIAN); // argh\r
87         for (int i=0; i<ints.length; ++i)\r
88             ints[i] = bytes.getInt();\r
89     }\r
90     private static void decompress(SourceData sourceData, byte[] bytes) throws CompressionException {\r
91         int size = decompressRaw(sourceData, bytes);\r
92         assert(size == bytes.length);\r
93     }\r
94     private static int decompressRaw(SourceData sourceData, byte[] bytes) throws CompressionException {\r
95         int aDstSize = bytes.length;\r
96         if (aDstSize < 1)\r
97             return aDstSize;\r
98         int dstOffset = 0;\r
99         for (int dstSize = 0;;) {\r
100             int dataLength = sourceData.readInt(); \r
101             assert(dataLength <= InLength); // data is written in blocks\r
102             if (0 == dataLength) // EOF\r
103                 return dstSize;\r
104             dstSize += dataLength;\r
105             int inLength = sourceData.readInt();\r
106 \r
107             assert(aDstSize >= dstSize); // must have space for data\r
108             assert(sourceData.left() >= inLength); // must have data for input\r
109             assert(inLength > 0); // no data no block\r
110             assert(inLength <= InLength); // input size is block size or less\r
111             assert(inLength <= dataLength); // input size is never bigger than data size\r
112 \r
113             if (inLength < dataLength) {// block was actually compressed\r
114                 decompress(sourceData.data, sourceData.offset, inLength, bytes, dstOffset, dataLength);\r
115                 sourceData.offset += inLength;\r
116                 dstOffset += dataLength;\r
117             } else {\r
118                 sourceData.readBytes(bytes, dstOffset, inLength);\r
119                 dstOffset += inLength;\r
120             }\r
121         }\r
122     }\r
123     private static void decompress(byte[] in, int inOffset, int inLength, byte[] out, int outOffset, int outLength) throws CompressionException {\r
124         ByteBuffer inBuffer = ByteBuffer.allocateDirect(inLength);\r
125         inBuffer.put(in, inOffset, inLength);\r
126         inBuffer.flip();\r
127         ByteBuffer outBuffer = ByteBuffer.allocateDirect(outLength);\r
128         int inflateSize = Compressions.get(Compressions.LZ4).decompressBuffer(inBuffer, 0, inLength, outBuffer, 0, outLength);\r
129 //        int inflateSize = org.simantics.fastlz.FastLZ.decompressBuffer(inBuffer, 0, inLength, outBuffer, 0, outLength);\r
130         if (inflateSize != outLength)\r
131             throw new RuntimeException("Decompression error.");\r
132         //outBuffer.flip();\r
133         outBuffer.get(out, outOffset, outLength);\r
134     }\r
135 }\r