]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.lz4/src/net/jpountz/lz4/LZ4SafeUtils.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.lz4 / src / net / jpountz / lz4 / LZ4SafeUtils.java
1 package net.jpountz.lz4;
2
3 /*
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 import static net.jpountz.lz4.LZ4Constants.LAST_LITERALS;
18 import static net.jpountz.lz4.LZ4Constants.ML_BITS;
19 import static net.jpountz.lz4.LZ4Constants.ML_MASK;
20 import static net.jpountz.lz4.LZ4Constants.RUN_MASK;
21 import net.jpountz.util.SafeUtils;
22
23 enum LZ4SafeUtils {
24   ;
25
26   static int hash(byte[] buf, int i) {
27     return LZ4Utils.hash(SafeUtils.readInt(buf, i));
28   }
29
30   static int hash64k(byte[] buf, int i) {
31     return LZ4Utils.hash64k(SafeUtils.readInt(buf, i));
32   }
33
34   static boolean readIntEquals(byte[] buf, int i, int j) {
35     return buf[i] == buf[j] && buf[i+1] == buf[j+1] && buf[i+2] == buf[j+2] && buf[i+3] == buf[j+3];
36   }
37
38   static void safeIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchLen) {
39     for (int i = 0; i < matchLen; ++i) {
40       dest[dOff + i] = dest[matchOff + i];
41     }
42   }
43
44   static void wildIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchCopyEnd) {
45     do {
46       copy8Bytes(dest, matchOff, dest, dOff);
47       matchOff += 8;
48       dOff += 8;
49     } while (dOff < matchCopyEnd);
50   }
51
52   static void copy8Bytes(byte[] src, int sOff, byte[] dest, int dOff) {
53     for (int i = 0; i < 8; ++i) {
54       dest[dOff + i] = src[sOff + i];
55     }
56   }
57
58   static int commonBytes(byte[] b, int o1, int o2, int limit) {
59     int count = 0;
60     while (o2 < limit && b[o1++] == b[o2++]) {
61       ++count;
62     }
63     return count;
64   }
65
66   static int commonBytesBackward(byte[] b, int o1, int o2, int l1, int l2) {
67     int count = 0;
68     while (o1 > l1 && o2 > l2 && b[--o1] == b[--o2]) {
69       ++count;
70     }
71     return count;
72   }
73
74   static void safeArraycopy(byte[] src, int sOff, byte[] dest, int dOff, int len) {
75     System.arraycopy(src, sOff, dest, dOff, len);
76   }
77
78   static void wildArraycopy(byte[] src, int sOff, byte[] dest, int dOff, int len) {
79     try {
80       for (int i = 0; i < len; i += 8) {
81         copy8Bytes(src, sOff + i, dest, dOff + i);
82       }
83     } catch (ArrayIndexOutOfBoundsException e) {
84       throw new LZ4Exception("Malformed input at offset " + sOff);
85     }
86   }
87
88   static int encodeSequence(byte[] src, int anchor, int matchOff, int matchRef, int matchLen, byte[] dest, int dOff, int destEnd) {
89     final int runLen = matchOff - anchor;
90     final int tokenOff = dOff++;
91
92     if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
93       throw new LZ4Exception("maxDestLen is too small");
94     }
95
96     int token;
97     if (runLen >= RUN_MASK) {
98       token = (byte) (RUN_MASK << ML_BITS);
99       dOff = writeLen(runLen - RUN_MASK, dest, dOff);
100     } else {
101       token = runLen << ML_BITS;
102     }
103
104     // copy literals
105     wildArraycopy(src, anchor, dest, dOff, runLen);
106     dOff += runLen;
107
108     // encode offset
109     final int matchDec = matchOff - matchRef;
110     dest[dOff++] = (byte) matchDec;
111     dest[dOff++] = (byte) (matchDec >>> 8);
112
113     // encode match len
114     matchLen -= 4;
115     if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
116       throw new LZ4Exception("maxDestLen is too small");
117     }
118     if (matchLen >= ML_MASK) {
119       token |= ML_MASK;
120       dOff = writeLen(matchLen - RUN_MASK, dest, dOff);
121     } else {
122       token |= matchLen;
123     }
124
125     dest[tokenOff] = (byte) token;
126
127     return dOff;
128   }
129
130   static int lastLiterals(byte[] src, int sOff, int srcLen, byte[] dest, int dOff, int destEnd) {
131     final int runLen = srcLen;
132
133     if (dOff + runLen + 1 + (runLen + 255 - RUN_MASK) / 255 > destEnd) {
134       throw new LZ4Exception();
135     }
136
137     if (runLen >= RUN_MASK) {
138       dest[dOff++] = (byte) (RUN_MASK << ML_BITS);
139       dOff = writeLen(runLen - RUN_MASK, dest, dOff);
140     } else {
141       dest[dOff++] = (byte) (runLen << ML_BITS);
142     }
143     // copy literals
144     System.arraycopy(src, sOff, dest, dOff, runLen);
145     dOff += runLen;
146
147     return dOff;
148   }
149
150   static int writeLen(int len, byte[] dest, int dOff) {
151     while (len >= 0xFF) {
152       dest[dOff++] = (byte) 0xFF;
153       len -= 0xFF;
154     }
155     dest[dOff++] = (byte) len;
156     return dOff;
157   }
158
159   static class Match {
160     int start, ref, len;
161
162     void fix(int correction) {
163       start += correction;
164       ref += correction;
165       len -= correction;
166     }
167
168     int end() {
169       return start + len;
170     }
171   }
172
173   static void copyTo(Match m1, Match m2) {
174     m2.len = m1.len;
175     m2.start = m1.start;
176     m2.ref = m1.ref;
177   }
178
179 }