]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.server/src/org/simantics/db/server/internal/ClusterDecompressor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.server / src / org / simantics / db / server / internal / ClusterDecompressor.java
1 package org.simantics.db.server.internal;\r
2 \r
3 import java.nio.ByteBuffer;\r
4 import java.util.Arrays;\r
5 \r
6 import org.simantics.fastlz.FastLZ;\r
7 import org.simantics.fastlz.FastLZJava;\r
8 \r
9 \r
10 /**\r
11  * @author Tuukka Lehtonen\r
12  */\r
13 public class ClusterDecompressor {\r
14 \r
15     private byte[] inflateBuffer;\r
16 \r
17     public Object[] inflateCluster(int inflateSize, ByteBuffer deflatedCluster)\r
18             throws CompressionException {\r
19         int deflatedSize = deflatedCluster.limit();\r
20         Object[] arrays = new Object[3];\r
21         int inflated = decompressCluster(deflatedCluster, deflatedSize, inflateSize, arrays);\r
22         if (inflated != inflateSize)\r
23             throw new CompressionException("decompression error, inflated "\r
24                     + inflated + " bytes when " + inflateSize + " expected.");\r
25         return arrays;\r
26     }\r
27 \r
28     /**\r
29      * Wrapper for the old native direct byte buffer version of cluster\r
30      * decompression.\r
31      *\r
32      * @param deflated\r
33      * @param deflatedSize\r
34      * @param inflatedSize\r
35      * @param arrays\r
36      *            expects an array of 3 elements. The decompression result will\r
37      *            be stored in here. [0] = cluster long array (long[]), [1] =\r
38      *            cluster int array (int[]), [2] = cluster byte array (byte[]).\r
39      * @return the amount of bytes inflated from the deflated cluster. Matches\r
40      *         inflatedSize when successful.\r
41      *\r
42      * @see FastLZ#decompressCluster(ByteBuffer, int, int, Object[])\r
43      */\r
44     public int decompressCluster(ByteBuffer deflated, int deflatedSize, int inflatedSize, Object[] arrays) {\r
45         if (deflated.isDirect()) {\r
46             if (FastLZ.isNativeInitialized()) {\r
47                 FastLZ.decompressCluster(deflated, deflatedSize, inflatedSize, arrays);\r
48                 return inflatedSize;\r
49             }\r
50             // REALLY SLOW FALLBACK: java code for direct byte buffers\r
51         }\r
52         byte[] array = null;\r
53         if (deflated.hasArray()) {\r
54             array = deflated.array();\r
55         } else {\r
56             // SLOW FALLBACK: read-only heap byte buffer\r
57             array = new byte[deflatedSize];\r
58             int pos = deflated.position();\r
59             deflated.position(0);\r
60             deflated.get(array, 0, deflatedSize);\r
61             deflated.position(pos);\r
62         }\r
63         return decompressCluster(array, deflatedSize, inflatedSize, arrays);\r
64     }\r
65 \r
66     /**\r
67      * @param deflated\r
68      * @param deflatedSize\r
69      * @param inflatedSize\r
70      * @param arrays\r
71      * @return\r
72      */\r
73     public synchronized int decompressCluster(byte[] deflated, int deflatedSize, int inflatedSize, Object[] arrays) {\r
74         if (inflateBuffer == null) {\r
75             inflateBuffer = new byte[inflatedSize];\r
76         } else if (inflateBuffer.length < inflatedSize) {\r
77             inflateBuffer = new byte[inflatedSize];\r
78         }\r
79         return decompressCluster(deflated, deflatedSize, inflateBuffer, inflatedSize, arrays);\r
80     }\r
81 \r
82     /**\r
83      * @param deflated\r
84      * @param deflatedSize\r
85      * @param inflated\r
86      * @param inflatedSize\r
87      * @param arrays\r
88      * @return amount of bytes inflated from the original deflated buffer.\r
89      *         Should match inflatedSize if everything went ok, otherwise will\r
90      *         not.\r
91      */\r
92     public static int decompressCluster(byte[] deflated, int deflatedSize, byte[] inflated, int inflatedSize, Object[] arrays) {\r
93         if (inflated.length < inflatedSize)\r
94             throw new IllegalArgumentException("inflate buffer size (" + inflated.length + ") is smaller than inflated size (" + inflatedSize + ")");\r
95 \r
96         int decompressedBytes = FastLZJava.decompress(deflated, 0, deflatedSize, inflated, 0, inflatedSize);\r
97         if (decompressedBytes != inflatedSize)\r
98             return decompressedBytes;\r
99 \r
100         int offset = 0;\r
101 \r
102         int longCount = readInt(inflated, offset);\r
103         long[] longs = new long[longCount];\r
104         copyLongs(inflated, offset + 4, longs);\r
105         offset += 4 + 8*longCount;\r
106 \r
107         int intCount = readInt(inflated, offset);\r
108         int[] ints = new int[intCount];\r
109         copyInts(inflated, offset + 4, ints);\r
110         offset += 4 + 4*intCount;\r
111 \r
112         int byteCount = readInt(inflated, offset);\r
113         byte[] bytes = Arrays.copyOfRange(inflated, offset + 4, offset + 4 + byteCount);\r
114 \r
115         arrays[0] = longs;\r
116         arrays[1] = ints;\r
117         arrays[2] = bytes;\r
118 \r
119         return decompressedBytes;\r
120     }\r
121 \r
122     private static void copyInts(byte[] bytes, int i, int[] ints) {\r
123         int offset = i;\r
124         int count = ints.length;\r
125         for (int a = 0; a < count; ++a, offset += 4) {\r
126             int value = (((int) bytes[offset] & 0xff)) |\r
127                     (((int) bytes[offset+1] & 0xff) << 8) |\r
128                     (((int) bytes[offset+2] & 0xff) << 16) |\r
129                     (((int) bytes[offset+3] & 0xff) << 24);\r
130             ints[a] = value;\r
131         }\r
132     }\r
133 \r
134     private static void copyLongs(byte[] bytes, int i, long[] longs) {\r
135         int offset = i;\r
136         int count = longs.length;\r
137         for (int a = 0; a < count; ++a, offset += 8) {\r
138             long value = (((long) bytes[offset] & 0xff)) |\r
139                     (((long) bytes[offset+1] & 0xff) << 8) |\r
140                     (((long) bytes[offset+2] & 0xff) << 16) |\r
141                     (((long) bytes[offset+3] & 0xff) << 24) |\r
142                     (((long) bytes[offset+4] & 0xff) << 32) |\r
143                     (((long) bytes[offset+5] & 0xff) << 40) |\r
144                     (((long) bytes[offset+6] & 0xff) << 48) |\r
145                     (((long) bytes[offset+7] & 0xff) << 56);\r
146             longs[a] = value;\r
147         }\r
148     }\r
149 \r
150     private static int readInt(byte[] array, int offset) {\r
151         return (((int) array[offset] & 0xff)) |\r
152                 (((int) array[offset+1] & 0xff) << 8) |\r
153                 (((int) array[offset+2] & 0xff) << 16) |\r
154                 (((int) array[offset+3] & 0xff) << 24);\r
155     }\r
156 \r
157 }\r