]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/org/simantics/db/procore/cluster/FastLZ.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / FastLZ.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.db.exception.InternalException;\r
18 \r
19 public class FastLZ {\r
20     static private final int InLength = 1<<20;\r
21     \r
22         public static class DecompressStruct {\r
23                 public long[] longs;\r
24                 public int[] ints;\r
25                 public byte[] bytes;\r
26         }\r
27         static class SourceData {\r
28                 SourceData(byte[] data) {\r
29                         this.data = data;\r
30                         this.offset = 0;\r
31                 }\r
32                 int left() {\r
33                         return data.length - offset;\r
34                 }\r
35                 int readInt() {\r
36                     int inLength = 4; // sizeof(int)\r
37                     assert(left() >= inLength); // must have data for input\r
38                         ByteBuffer buffer = ByteBuffer.wrap(data, offset, inLength);\r
39                         buffer.order(ByteOrder.LITTLE_ENDIAN); // argh!\r
40                         int t = buffer.getInt();\r
41                         offset += inLength;\r
42                         return t;\r
43                 }\r
44                 void readBytes(byte[] bytes, int aOffset, int inLength) {\r
45                     assert(left() >= inLength); // must have data for input\r
46                         System.arraycopy(data, offset, bytes, aOffset, inLength);\r
47                         offset += inLength;\r
48                 }\r
49                 byte[] data;\r
50                 int offset;\r
51         }\r
52         public static DecompressStruct decompress(byte[] data) throws InternalException {\r
53                 assert(data.length > 12); // 3*(table size)\r
54                 SourceData sourceData = new SourceData(data);\r
55                 DecompressStruct struct = new DecompressStruct();\r
56                 int longSize = sourceData.readInt();\r
57                 int intSize = sourceData.readInt();\r
58                 int byteSize = sourceData.readInt();\r
59                 struct.longs = new long[longSize]; \r
60                 try {\r
61                         decompress(sourceData, struct.longs);\r
62                         struct.ints = new int[intSize]; \r
63                         decompress(sourceData, struct.ints);\r
64                         struct.bytes = new byte[byteSize];\r
65                         decompress(sourceData, struct.bytes);\r
66                 } catch (CompressionException e) {\r
67                         throw new InternalException("Failed to decompress.", e);\r
68                 }\r
69                 return struct;\r
70         }\r
71         private static void decompress(SourceData sourceData, long[] longs) throws CompressionException {\r
72                 int length = longs.length * 8;\r
73                 ByteBuffer bytes = ByteBuffer.allocate(length);\r
74                 int size = decompressRaw(sourceData, bytes.array());\r
75                 assert(size == length);\r
76                 bytes.order(ByteOrder.LITTLE_ENDIAN); // argh\r
77                 for (int i=0; i<longs.length; ++i)\r
78                         longs[i] = bytes.getLong();\r
79         }\r
80         private static void decompress(SourceData sourceData, int[] ints) throws CompressionException {\r
81                 int length = ints.length * 4;\r
82                 ByteBuffer bytes = ByteBuffer.allocate(length);\r
83                 int size = decompressRaw(sourceData, bytes.array());\r
84                 assert(size == length);\r
85                 bytes.order(ByteOrder.LITTLE_ENDIAN); // argh\r
86                 for (int i=0; i<ints.length; ++i)\r
87                         ints[i] = bytes.getInt();\r
88         }\r
89         private static void decompress(SourceData sourceData, byte[] bytes) throws CompressionException {\r
90                 int size = decompressRaw(sourceData, bytes);\r
91                 assert(size == bytes.length);\r
92         }\r
93         private static int decompressRaw(SourceData sourceData, byte[] bytes) throws CompressionException {\r
94                 int aDstSize = bytes.length;\r
95                 if (aDstSize < 1)\r
96                         return aDstSize;\r
97                 int dstOffset = 0;\r
98                 for (int dstSize = 0;;) {\r
99                         int dataLength = sourceData.readInt(); \r
100                         assert(dataLength <= InLength); // data is written in blocks\r
101                         if (0 == dataLength) // EOF\r
102                                 return dstSize;\r
103                         dstSize += dataLength;\r
104                 int inLength = sourceData.readInt();\r
105 \r
106                         assert(aDstSize >= dstSize); // must have space for data\r
107                         assert(sourceData.left() >= inLength); // must have data for input\r
108                         assert(inLength > 0); // no data no block\r
109                         assert(inLength <= InLength); // input size is block size or less\r
110                         assert(inLength <= dataLength); // input size is never bigger than data size\r
111 \r
112                         if (inLength < dataLength) {// block was actually compressed\r
113                                 decompress(sourceData.data, sourceData.offset, inLength, bytes, dstOffset, dataLength);\r
114                                 sourceData.offset += inLength;\r
115                                 dstOffset += dataLength;\r
116                 } else {\r
117                         sourceData.readBytes(bytes, dstOffset, inLength);\r
118                         dstOffset += inLength;\r
119                 }\r
120             }\r
121         }\r
122         private static void decompress(byte[] in, int inOffset, int inLength, byte[] out, int outOffset, int outLength) throws CompressionException {\r
123             ByteBuffer inBuffer = ByteBuffer.allocateDirect(inLength);\r
124                 inBuffer.put(in, inOffset, inLength);\r
125                 inBuffer.flip();\r
126                 ByteBuffer outBuffer = ByteBuffer.allocateDirect(outLength);\r
127                 int inflateSize = org.simantics.fastlz.FastLZ.decompressBuffer(inBuffer, 0, inLength, outBuffer, 0, outLength);\r
128                 if (inflateSize != outLength)\r
129                         throw new RuntimeException("Decompression error.");\r
130                 //outBuffer.flip();\r
131                 outBuffer.get(out, outOffset, outLength);\r
132         }\r
133 }\r