1 package net.jpountz.lz4;
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 import static net.jpountz.lz4.LZ4Constants.COPY_LENGTH;
18 import static net.jpountz.lz4.LZ4Constants.LAST_LITERALS;
19 import static net.jpountz.lz4.LZ4Constants.ML_BITS;
20 import static net.jpountz.lz4.LZ4Constants.ML_MASK;
21 import static net.jpountz.lz4.LZ4Constants.RUN_MASK;
22 import static net.jpountz.util.ByteBufferUtils.readByte;
23 import static net.jpountz.util.ByteBufferUtils.readInt;
24 import static net.jpountz.util.ByteBufferUtils.readLong;
25 import static net.jpountz.util.ByteBufferUtils.writeByte;
26 import static net.jpountz.util.ByteBufferUtils.writeInt;
27 import static net.jpountz.util.ByteBufferUtils.writeLong;
29 import java.nio.ByteBuffer;
30 import java.nio.ByteOrder;
32 enum LZ4ByteBufferUtils {
34 static int hash(ByteBuffer buf, int i) {
35 return LZ4Utils.hash(readInt(buf, i));
38 static int hash64k(ByteBuffer buf, int i) {
39 return LZ4Utils.hash64k(readInt(buf, i));
42 static boolean readIntEquals(ByteBuffer buf, int i, int j) {
43 return buf.getInt(i) == buf.getInt(j);
46 static void safeIncrementalCopy(ByteBuffer dest, int matchOff, int dOff, int matchLen) {
47 for (int i = 0; i < matchLen; ++i) {
48 dest.put(dOff + i, dest.get(matchOff + i));
52 static void wildIncrementalCopy(ByteBuffer dest, int matchOff, int dOff, int matchCopyEnd) {
53 if (dOff - matchOff < 4) {
54 for (int i = 0; i < 4; ++i) {
55 writeByte(dest, dOff+i, readByte(dest, matchOff+i));
60 assert dOff >= matchOff && dOff - matchOff < 8;
61 switch (dOff - matchOff) {
84 writeInt(dest, dOff, readInt(dest, matchOff));
87 } else if (dOff - matchOff < COPY_LENGTH) {
88 writeLong(dest, dOff, readLong(dest, matchOff));
89 dOff += dOff - matchOff;
91 while (dOff < matchCopyEnd) {
92 writeLong(dest, dOff, readLong(dest, matchOff));
98 static int commonBytes(ByteBuffer src, int ref, int sOff, int srcLimit) {
100 while (sOff <= srcLimit - 8) {
101 if (readLong(src, sOff) == readLong(src, ref)) {
107 if (src.order() == ByteOrder.BIG_ENDIAN) {
108 zeroBits = Long.numberOfLeadingZeros(readLong(src, sOff) ^ readLong(src, ref));
110 zeroBits = Long.numberOfTrailingZeros(readLong(src, sOff) ^ readLong(src, ref));
112 return matchLen + (zeroBits >>> 3);
115 while (sOff < srcLimit && readByte(src, ref++) == readByte(src, sOff++)) {
121 static int commonBytesBackward(ByteBuffer b, int o1, int o2, int l1, int l2) {
123 while (o1 > l1 && o2 > l2 && b.get(--o1) == b.get(--o2)) {
129 static void safeArraycopy(ByteBuffer src, int sOff, ByteBuffer dest, int dOff, int len) {
130 for (int i = 0; i < len; ++i) {
131 dest.put(dOff + i, src.get(sOff + i));
135 static void wildArraycopy(ByteBuffer src, int sOff, ByteBuffer dest, int dOff, int len) {
136 assert src.order().equals(dest.order());
138 for (int i = 0; i < len; i += 8) {
139 dest.putLong(dOff + i, src.getLong(sOff + i));
141 } catch (IndexOutOfBoundsException e) {
142 throw new LZ4Exception("Malformed input at offset " + sOff);
146 static int encodeSequence(ByteBuffer src, int anchor, int matchOff, int matchRef, int matchLen, ByteBuffer dest, int dOff, int destEnd) {
147 final int runLen = matchOff - anchor;
148 final int tokenOff = dOff++;
150 if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
151 throw new LZ4Exception("maxDestLen is too small");
155 if (runLen >= RUN_MASK) {
156 token = (byte) (RUN_MASK << ML_BITS);
157 dOff = writeLen(runLen - RUN_MASK, dest, dOff);
159 token = runLen << ML_BITS;
163 wildArraycopy(src, anchor, dest, dOff, runLen);
167 final int matchDec = matchOff - matchRef;
168 dest.put(dOff++, (byte) matchDec);
169 dest.put(dOff++, (byte) (matchDec >>> 8));
173 if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
174 throw new LZ4Exception("maxDestLen is too small");
176 if (matchLen >= ML_MASK) {
178 dOff = writeLen(matchLen - RUN_MASK, dest, dOff);
183 dest.put(tokenOff, (byte) token);
188 static int lastLiterals(ByteBuffer src, int sOff, int srcLen, ByteBuffer dest, int dOff, int destEnd) {
189 final int runLen = srcLen;
191 if (dOff + runLen + 1 + (runLen + 255 - RUN_MASK) / 255 > destEnd) {
192 throw new LZ4Exception();
195 if (runLen >= RUN_MASK) {
196 dest.put(dOff++, (byte) (RUN_MASK << ML_BITS));
197 dOff = writeLen(runLen - RUN_MASK, dest, dOff);
199 dest.put(dOff++, (byte) (runLen << ML_BITS));
202 safeArraycopy(src, sOff, dest, dOff, runLen);
208 static int writeLen(int len, ByteBuffer dest, int dOff) {
209 while (len >= 0xFF) {
210 dest.put(dOff++, (byte) 0xFF);
213 dest.put(dOff++, (byte) len);
220 void fix(int correction) {
231 static void copyTo(Match m1, Match m2) {