geforkt von Mirrors/FastAsyncWorldEdit
Removed unused classes
Dieser Commit ist enthalten in:
Ursprung
fb0bb62180
Commit
83197dba0c
@ -1,553 +0,0 @@
|
||||
// Auto-generated: DO NOT EDIT
|
||||
|
||||
package net.jpountz.lz4;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import net.jpountz.lz4.LZ4Utils.Match;
|
||||
import net.jpountz.util.ByteBufferUtils;
|
||||
import net.jpountz.util.UnsafeUtils;
|
||||
|
||||
|
||||
import static net.jpountz.lz4.LZ4Constants.*;
|
||||
import static net.jpountz.lz4.LZ4Utils.copyTo;
|
||||
import static net.jpountz.lz4.LZ4Utils.hashHC;
|
||||
|
||||
/**
|
||||
* High compression compressor.
|
||||
*/
|
||||
final class LZ4HCJavaUnsafeCompressor extends LZ4Compressor {
|
||||
|
||||
public static final LZ4Compressor INSTANCE = new LZ4HCJavaUnsafeCompressor();
|
||||
|
||||
private final int maxAttempts;
|
||||
final int compressionLevel;
|
||||
|
||||
LZ4HCJavaUnsafeCompressor() {
|
||||
this(DEFAULT_COMPRESSION_LEVEL);
|
||||
}
|
||||
|
||||
LZ4HCJavaUnsafeCompressor(int compressionLevel) {
|
||||
this.maxAttempts = 1 << (compressionLevel - 1);
|
||||
this.compressionLevel = compressionLevel;
|
||||
}
|
||||
|
||||
private class HashTable {
|
||||
static final int MASK = MAX_DISTANCE - 1;
|
||||
int nextToUpdate;
|
||||
private final int base;
|
||||
private final int[] hashTable;
|
||||
private final short[] chainTable;
|
||||
|
||||
HashTable(int base) {
|
||||
this.base = base;
|
||||
nextToUpdate = base;
|
||||
hashTable = new int[HASH_TABLE_SIZE_HC];
|
||||
Arrays.fill(hashTable, -1);
|
||||
chainTable = new short[MAX_DISTANCE];
|
||||
}
|
||||
|
||||
private int hashPointer(byte[] bytes, int off) {
|
||||
final int v = UnsafeUtils.readInt(bytes, off);
|
||||
return hashPointer(v);
|
||||
}
|
||||
|
||||
private int hashPointer(ByteBuffer bytes, int off) {
|
||||
final int v = ByteBufferUtils.readInt(bytes, off);
|
||||
return hashPointer(v);
|
||||
}
|
||||
|
||||
private int hashPointer(int v) {
|
||||
final int h = hashHC(v);
|
||||
return hashTable[h];
|
||||
}
|
||||
|
||||
private int next(int off) {
|
||||
return off - (chainTable[off & MASK] & 0xFFFF);
|
||||
}
|
||||
|
||||
private void addHash(byte[] bytes, int off) {
|
||||
final int v = UnsafeUtils.readInt(bytes, off);
|
||||
addHash(v, off);
|
||||
}
|
||||
|
||||
private void addHash(ByteBuffer bytes, int off) {
|
||||
final int v = ByteBufferUtils.readInt(bytes, off);
|
||||
addHash(v, off);
|
||||
}
|
||||
|
||||
private void addHash(int v, int off) {
|
||||
final int h = hashHC(v);
|
||||
int delta = off - hashTable[h];
|
||||
assert delta > 0 : delta;
|
||||
if (delta >= MAX_DISTANCE) {
|
||||
delta = MAX_DISTANCE - 1;
|
||||
}
|
||||
chainTable[off & MASK] = (short) delta;
|
||||
hashTable[h] = off;
|
||||
}
|
||||
|
||||
void insert(int off, byte[] bytes) {
|
||||
for (; nextToUpdate < off; ++nextToUpdate) {
|
||||
addHash(bytes, nextToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
void insert(int off, ByteBuffer bytes) {
|
||||
for (; nextToUpdate < off; ++nextToUpdate) {
|
||||
addHash(bytes, nextToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean insertAndFindBestMatch(byte[] buf, int off, int matchLimit, Match match) {
|
||||
match.start = off;
|
||||
match.len = 0;
|
||||
int delta = 0;
|
||||
int repl = 0;
|
||||
|
||||
insert(off, buf);
|
||||
|
||||
int ref = hashPointer(buf, off);
|
||||
|
||||
if (ref >= off - 4 && ref <= off && ref >= base) { // potential repetition
|
||||
if (LZ4UnsafeUtils.readIntEquals(buf, ref, off)) { // confirmed
|
||||
delta = off - ref;
|
||||
repl = match.len = MIN_MATCH + LZ4UnsafeUtils.commonBytes(buf, ref + MIN_MATCH, off + MIN_MATCH, matchLimit);
|
||||
match.ref = ref;
|
||||
}
|
||||
ref = next(ref);
|
||||
}
|
||||
|
||||
for (int i = 0; i < maxAttempts; ++i) {
|
||||
if (ref < Math.max(base, off - MAX_DISTANCE + 1) || ref > off) {
|
||||
break;
|
||||
}
|
||||
if (LZ4UnsafeUtils.readIntEquals(buf, ref, off)) {
|
||||
final int matchLen = MIN_MATCH + LZ4UnsafeUtils.commonBytes(buf, ref + MIN_MATCH, off + MIN_MATCH, matchLimit);
|
||||
if (matchLen > match.len) {
|
||||
match.ref = ref;
|
||||
match.len = matchLen;
|
||||
}
|
||||
}
|
||||
ref = next(ref);
|
||||
}
|
||||
|
||||
if (repl != 0) {
|
||||
int ptr = off;
|
||||
final int end = off + repl - (MIN_MATCH - 1);
|
||||
while (ptr < end - delta) {
|
||||
chainTable[ptr & MASK] = (short) delta; // pre load
|
||||
++ptr;
|
||||
}
|
||||
do {
|
||||
chainTable[ptr & MASK] = (short) delta;
|
||||
hashTable[hashHC(UnsafeUtils.readInt(buf, ptr))] = ptr;
|
||||
++ptr;
|
||||
} while (ptr < end);
|
||||
nextToUpdate = end;
|
||||
}
|
||||
|
||||
return match.len != 0;
|
||||
}
|
||||
|
||||
boolean insertAndFindWiderMatch(byte[] buf, int off, int startLimit, int matchLimit, int minLen, Match match) {
|
||||
match.len = minLen;
|
||||
|
||||
insert(off, buf);
|
||||
|
||||
final int delta = off - startLimit;
|
||||
int ref = hashPointer(buf, off);
|
||||
for (int i = 0; i < maxAttempts; ++i) {
|
||||
if (ref < Math.max(base, off - MAX_DISTANCE + 1) || ref > off) {
|
||||
break;
|
||||
}
|
||||
if (LZ4UnsafeUtils.readIntEquals(buf, ref, off)) {
|
||||
final int matchLenForward = MIN_MATCH + LZ4UnsafeUtils.commonBytes(buf, ref + MIN_MATCH, off + MIN_MATCH, matchLimit);
|
||||
final int matchLenBackward = LZ4UnsafeUtils.commonBytesBackward(buf, ref, off, base, startLimit);
|
||||
final int matchLen = matchLenBackward + matchLenForward;
|
||||
if (matchLen > match.len) {
|
||||
match.len = matchLen;
|
||||
match.ref = ref - matchLenBackward;
|
||||
match.start = off - matchLenBackward;
|
||||
}
|
||||
}
|
||||
ref = next(ref);
|
||||
}
|
||||
|
||||
return match.len > minLen;
|
||||
}
|
||||
|
||||
|
||||
boolean insertAndFindBestMatch(ByteBuffer buf, int off, int matchLimit, Match match) {
|
||||
match.start = off;
|
||||
match.len = 0;
|
||||
int delta = 0;
|
||||
int repl = 0;
|
||||
|
||||
insert(off, buf);
|
||||
|
||||
int ref = hashPointer(buf, off);
|
||||
|
||||
if (ref >= off - 4 && ref <= off && ref >= base) { // potential repetition
|
||||
if (LZ4ByteBufferUtils.readIntEquals(buf, ref, off)) { // confirmed
|
||||
delta = off - ref;
|
||||
repl = match.len = MIN_MATCH + LZ4ByteBufferUtils.commonBytes(buf, ref + MIN_MATCH, off + MIN_MATCH, matchLimit);
|
||||
match.ref = ref;
|
||||
}
|
||||
ref = next(ref);
|
||||
}
|
||||
|
||||
for (int i = 0; i < maxAttempts; ++i) {
|
||||
if (ref < Math.max(base, off - MAX_DISTANCE + 1) || ref > off) {
|
||||
break;
|
||||
}
|
||||
if (LZ4ByteBufferUtils.readIntEquals(buf, ref, off)) {
|
||||
final int matchLen = MIN_MATCH + LZ4ByteBufferUtils.commonBytes(buf, ref + MIN_MATCH, off + MIN_MATCH, matchLimit);
|
||||
if (matchLen > match.len) {
|
||||
match.ref = ref;
|
||||
match.len = matchLen;
|
||||
}
|
||||
}
|
||||
ref = next(ref);
|
||||
}
|
||||
|
||||
if (repl != 0) {
|
||||
int ptr = off;
|
||||
final int end = off + repl - (MIN_MATCH - 1);
|
||||
while (ptr < end - delta) {
|
||||
chainTable[ptr & MASK] = (short) delta; // pre load
|
||||
++ptr;
|
||||
}
|
||||
do {
|
||||
chainTable[ptr & MASK] = (short) delta;
|
||||
hashTable[hashHC(ByteBufferUtils.readInt(buf, ptr))] = ptr;
|
||||
++ptr;
|
||||
} while (ptr < end);
|
||||
nextToUpdate = end;
|
||||
}
|
||||
|
||||
return match.len != 0;
|
||||
}
|
||||
|
||||
boolean insertAndFindWiderMatch(ByteBuffer buf, int off, int startLimit, int matchLimit, int minLen, Match match) {
|
||||
match.len = minLen;
|
||||
|
||||
insert(off, buf);
|
||||
|
||||
final int delta = off - startLimit;
|
||||
int ref = hashPointer(buf, off);
|
||||
for (int i = 0; i < maxAttempts; ++i) {
|
||||
if (ref < Math.max(base, off - MAX_DISTANCE + 1) || ref > off) {
|
||||
break;
|
||||
}
|
||||
if (LZ4ByteBufferUtils.readIntEquals(buf, ref, off)) {
|
||||
final int matchLenForward = MIN_MATCH + LZ4ByteBufferUtils.commonBytes(buf, ref + MIN_MATCH, off + MIN_MATCH, matchLimit);
|
||||
final int matchLenBackward = LZ4ByteBufferUtils.commonBytesBackward(buf, ref, off, base, startLimit);
|
||||
final int matchLen = matchLenBackward + matchLenForward;
|
||||
if (matchLen > match.len) {
|
||||
match.len = matchLen;
|
||||
match.ref = ref - matchLenBackward;
|
||||
match.start = off - matchLenBackward;
|
||||
}
|
||||
}
|
||||
ref = next(ref);
|
||||
}
|
||||
|
||||
return match.len > minLen;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compress(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int maxDestLen) {
|
||||
|
||||
UnsafeUtils.checkRange(src, srcOff, srcLen);
|
||||
UnsafeUtils.checkRange(dest, destOff, maxDestLen);
|
||||
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
final int destEnd = destOff + maxDestLen;
|
||||
final int mfLimit = srcEnd - MF_LIMIT;
|
||||
final int matchLimit = srcEnd - LAST_LITERALS;
|
||||
|
||||
int sOff = srcOff;
|
||||
int dOff = destOff;
|
||||
int anchor = sOff++;
|
||||
|
||||
final HashTable ht = new HashTable(srcOff);
|
||||
final Match match0 = new Match();
|
||||
final Match match1 = new Match();
|
||||
final Match match2 = new Match();
|
||||
final Match match3 = new Match();
|
||||
|
||||
main:
|
||||
while (sOff < mfLimit) {
|
||||
if (!ht.insertAndFindBestMatch(src, sOff, matchLimit, match1)) {
|
||||
++sOff;
|
||||
continue;
|
||||
}
|
||||
|
||||
// saved, in case we would skip too much
|
||||
copyTo(match1, match0);
|
||||
|
||||
search2:
|
||||
while (true) {
|
||||
assert match1.start >= anchor;
|
||||
if (match1.end() >= mfLimit
|
||||
|| !ht.insertAndFindWiderMatch(src, match1.end() - 2, match1.start + 1, matchLimit, match1.len, match2)) {
|
||||
// no better match
|
||||
dOff = LZ4UnsafeUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
continue main;
|
||||
}
|
||||
|
||||
if (match0.start < match1.start) {
|
||||
if (match2.start < match1.start + match0.len) { // empirical
|
||||
copyTo(match0, match1);
|
||||
}
|
||||
}
|
||||
assert match2.start > match1.start;
|
||||
|
||||
if (match2.start - match1.start < 3) { // First Match too small : removed
|
||||
copyTo(match2, match1);
|
||||
continue search2;
|
||||
}
|
||||
|
||||
search3:
|
||||
while (true) {
|
||||
if (match2.start - match1.start < OPTIMAL_ML) {
|
||||
int newMatchLen = match1.len;
|
||||
if (newMatchLen > OPTIMAL_ML) {
|
||||
newMatchLen = OPTIMAL_ML;
|
||||
}
|
||||
if (match1.start + newMatchLen > match2.end() - MIN_MATCH) {
|
||||
newMatchLen = match2.start - match1.start + match2.len - MIN_MATCH;
|
||||
}
|
||||
final int correction = newMatchLen - (match2.start - match1.start);
|
||||
if (correction > 0) {
|
||||
match2.fix(correction);
|
||||
}
|
||||
}
|
||||
|
||||
if (match2.start + match2.len >= mfLimit
|
||||
|| !ht.insertAndFindWiderMatch(src, match2.end() - 3, match2.start, matchLimit, match2.len, match3)) {
|
||||
// no better match -> 2 sequences to encode
|
||||
if (match2.start < match1.end()) {
|
||||
match1.len = match2.start - match1.start;
|
||||
}
|
||||
// encode seq 1
|
||||
dOff = LZ4UnsafeUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
// encode seq 2
|
||||
dOff = LZ4UnsafeUtils.encodeSequence(src, anchor, match2.start, match2.ref, match2.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match2.end();
|
||||
continue main;
|
||||
}
|
||||
|
||||
if (match3.start < match1.end() + 3) { // Not enough space for match 2 : remove it
|
||||
if (match3.start >= match1.end()) { // // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
|
||||
if (match2.start < match1.end()) {
|
||||
final int correction = match1.end() - match2.start;
|
||||
match2.fix(correction);
|
||||
if (match2.len < MIN_MATCH) {
|
||||
copyTo(match3, match2);
|
||||
}
|
||||
}
|
||||
|
||||
dOff = LZ4UnsafeUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
|
||||
copyTo(match3, match1);
|
||||
copyTo(match2, match0);
|
||||
|
||||
continue search2;
|
||||
}
|
||||
|
||||
copyTo(match3, match2);
|
||||
continue search3;
|
||||
}
|
||||
|
||||
// OK, now we have 3 ascending matches; let's write at least the first one
|
||||
if (match2.start < match1.end()) {
|
||||
if (match2.start - match1.start < ML_MASK) {
|
||||
if (match1.len > OPTIMAL_ML) {
|
||||
match1.len = OPTIMAL_ML;
|
||||
}
|
||||
if (match1.end() > match2.end() - MIN_MATCH) {
|
||||
match1.len = match2.end() - match1.start - MIN_MATCH;
|
||||
}
|
||||
final int correction = match1.end() - match2.start;
|
||||
match2.fix(correction);
|
||||
} else {
|
||||
match1.len = match2.start - match1.start;
|
||||
}
|
||||
}
|
||||
|
||||
dOff = LZ4UnsafeUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
|
||||
copyTo(match2, match1);
|
||||
copyTo(match3, match2);
|
||||
|
||||
continue search3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dOff = LZ4UnsafeUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
|
||||
return dOff - destOff;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compress(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int maxDestLen) {
|
||||
|
||||
if (src.hasArray() && dest.hasArray()) {
|
||||
return compress(src.array(), srcOff + src.arrayOffset(), srcLen, dest.array(), destOff + dest.arrayOffset(), maxDestLen);
|
||||
}
|
||||
src = ByteBufferUtils.inNativeByteOrder(src);
|
||||
dest = ByteBufferUtils.inNativeByteOrder(dest);
|
||||
|
||||
ByteBufferUtils.checkRange(src, srcOff, srcLen);
|
||||
ByteBufferUtils.checkRange(dest, destOff, maxDestLen);
|
||||
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
final int destEnd = destOff + maxDestLen;
|
||||
final int mfLimit = srcEnd - MF_LIMIT;
|
||||
final int matchLimit = srcEnd - LAST_LITERALS;
|
||||
|
||||
int sOff = srcOff;
|
||||
int dOff = destOff;
|
||||
int anchor = sOff++;
|
||||
|
||||
final HashTable ht = new HashTable(srcOff);
|
||||
final Match match0 = new Match();
|
||||
final Match match1 = new Match();
|
||||
final Match match2 = new Match();
|
||||
final Match match3 = new Match();
|
||||
|
||||
main:
|
||||
while (sOff < mfLimit) {
|
||||
if (!ht.insertAndFindBestMatch(src, sOff, matchLimit, match1)) {
|
||||
++sOff;
|
||||
continue;
|
||||
}
|
||||
|
||||
// saved, in case we would skip too much
|
||||
copyTo(match1, match0);
|
||||
|
||||
search2:
|
||||
while (true) {
|
||||
assert match1.start >= anchor;
|
||||
if (match1.end() >= mfLimit
|
||||
|| !ht.insertAndFindWiderMatch(src, match1.end() - 2, match1.start + 1, matchLimit, match1.len, match2)) {
|
||||
// no better match
|
||||
dOff = LZ4ByteBufferUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
continue main;
|
||||
}
|
||||
|
||||
if (match0.start < match1.start) {
|
||||
if (match2.start < match1.start + match0.len) { // empirical
|
||||
copyTo(match0, match1);
|
||||
}
|
||||
}
|
||||
assert match2.start > match1.start;
|
||||
|
||||
if (match2.start - match1.start < 3) { // First Match too small : removed
|
||||
copyTo(match2, match1);
|
||||
continue search2;
|
||||
}
|
||||
|
||||
search3:
|
||||
while (true) {
|
||||
if (match2.start - match1.start < OPTIMAL_ML) {
|
||||
int newMatchLen = match1.len;
|
||||
if (newMatchLen > OPTIMAL_ML) {
|
||||
newMatchLen = OPTIMAL_ML;
|
||||
}
|
||||
if (match1.start + newMatchLen > match2.end() - MIN_MATCH) {
|
||||
newMatchLen = match2.start - match1.start + match2.len - MIN_MATCH;
|
||||
}
|
||||
final int correction = newMatchLen - (match2.start - match1.start);
|
||||
if (correction > 0) {
|
||||
match2.fix(correction);
|
||||
}
|
||||
}
|
||||
|
||||
if (match2.start + match2.len >= mfLimit
|
||||
|| !ht.insertAndFindWiderMatch(src, match2.end() - 3, match2.start, matchLimit, match2.len, match3)) {
|
||||
// no better match -> 2 sequences to encode
|
||||
if (match2.start < match1.end()) {
|
||||
match1.len = match2.start - match1.start;
|
||||
}
|
||||
// encode seq 1
|
||||
dOff = LZ4ByteBufferUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
// encode seq 2
|
||||
dOff = LZ4ByteBufferUtils.encodeSequence(src, anchor, match2.start, match2.ref, match2.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match2.end();
|
||||
continue main;
|
||||
}
|
||||
|
||||
if (match3.start < match1.end() + 3) { // Not enough space for match 2 : remove it
|
||||
if (match3.start >= match1.end()) { // // can write Seq1 immediately ==> Seq2 is removed, so Seq3 becomes Seq1
|
||||
if (match2.start < match1.end()) {
|
||||
final int correction = match1.end() - match2.start;
|
||||
match2.fix(correction);
|
||||
if (match2.len < MIN_MATCH) {
|
||||
copyTo(match3, match2);
|
||||
}
|
||||
}
|
||||
|
||||
dOff = LZ4ByteBufferUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
|
||||
copyTo(match3, match1);
|
||||
copyTo(match2, match0);
|
||||
|
||||
continue search2;
|
||||
}
|
||||
|
||||
copyTo(match3, match2);
|
||||
continue search3;
|
||||
}
|
||||
|
||||
// OK, now we have 3 ascending matches; let's write at least the first one
|
||||
if (match2.start < match1.end()) {
|
||||
if (match2.start - match1.start < ML_MASK) {
|
||||
if (match1.len > OPTIMAL_ML) {
|
||||
match1.len = OPTIMAL_ML;
|
||||
}
|
||||
if (match1.end() > match2.end() - MIN_MATCH) {
|
||||
match1.len = match2.end() - match1.start - MIN_MATCH;
|
||||
}
|
||||
final int correction = match1.end() - match2.start;
|
||||
match2.fix(correction);
|
||||
} else {
|
||||
match1.len = match2.start - match1.start;
|
||||
}
|
||||
}
|
||||
|
||||
dOff = LZ4ByteBufferUtils.encodeSequence(src, anchor, match1.start, match1.ref, match1.len, dest, dOff, destEnd);
|
||||
anchor = sOff = match1.end();
|
||||
|
||||
copyTo(match2, match1);
|
||||
copyTo(match3, match2);
|
||||
|
||||
continue search3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dOff = LZ4ByteBufferUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
|
||||
return dOff - destOff;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,512 +0,0 @@
|
||||
// Auto-generated: DO NOT EDIT
|
||||
|
||||
package net.jpountz.lz4;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import net.jpountz.util.ByteBufferUtils;
|
||||
import net.jpountz.util.UnsafeUtils;
|
||||
|
||||
|
||||
import static net.jpountz.lz4.LZ4Constants.*;
|
||||
import static net.jpountz.lz4.LZ4Utils.hash;
|
||||
import static net.jpountz.lz4.LZ4Utils.hash64k;
|
||||
|
||||
/**
|
||||
* Compressor.
|
||||
*/
|
||||
final class LZ4JavaUnsafeCompressor extends LZ4Compressor {
|
||||
|
||||
public static final LZ4Compressor INSTANCE = new LZ4JavaUnsafeCompressor();
|
||||
|
||||
static int compress64k(byte[] src, int srcOff, int srcLen, byte[] dest, int destOff, int destEnd) {
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
final int srcLimit = srcEnd - LAST_LITERALS;
|
||||
final int mflimit = srcEnd - MF_LIMIT;
|
||||
|
||||
int sOff = srcOff, dOff = destOff;
|
||||
|
||||
int anchor = sOff;
|
||||
|
||||
if (srcLen >= MIN_LENGTH) {
|
||||
|
||||
final short[] hashTable = new short[HASH_TABLE_SIZE_64K];
|
||||
|
||||
++sOff;
|
||||
|
||||
main:
|
||||
while (true) {
|
||||
|
||||
// find a match
|
||||
int forwardOff = sOff;
|
||||
|
||||
int ref;
|
||||
int step = 1;
|
||||
int searchMatchNb = 1 << SKIP_STRENGTH;
|
||||
do {
|
||||
sOff = forwardOff;
|
||||
forwardOff += step;
|
||||
step = searchMatchNb++ >>> SKIP_STRENGTH;
|
||||
|
||||
if (forwardOff > mflimit) {
|
||||
break main;
|
||||
}
|
||||
|
||||
final int h = hash64k(UnsafeUtils.readInt(src, sOff));
|
||||
ref = srcOff + UnsafeUtils.readShort(hashTable, h);
|
||||
UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
|
||||
} while (!LZ4UnsafeUtils.readIntEquals(src, ref, sOff));
|
||||
|
||||
// catch up
|
||||
final int excess = LZ4UnsafeUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
|
||||
sOff -= excess;
|
||||
ref -= excess;
|
||||
|
||||
// sequence == refsequence
|
||||
final int runLen = sOff - anchor;
|
||||
|
||||
// encode literal length
|
||||
int tokenOff = dOff++;
|
||||
|
||||
if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
|
||||
if (runLen >= RUN_MASK) {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
|
||||
dOff = LZ4UnsafeUtils.writeLen(runLen - RUN_MASK, dest, dOff);
|
||||
} else {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
|
||||
}
|
||||
|
||||
// copy literals
|
||||
LZ4UnsafeUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
|
||||
dOff += runLen;
|
||||
|
||||
while (true) {
|
||||
// encode offset
|
||||
UnsafeUtils.writeShortLE(dest, dOff, (short) (sOff - ref));
|
||||
dOff += 2;
|
||||
|
||||
// count nb matches
|
||||
sOff += MIN_MATCH;
|
||||
ref += MIN_MATCH;
|
||||
final int matchLen = LZ4UnsafeUtils.commonBytes(src, ref, sOff, srcLimit);
|
||||
if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
sOff += matchLen;
|
||||
|
||||
// encode match len
|
||||
if (matchLen >= ML_MASK) {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | ML_MASK);
|
||||
dOff = LZ4UnsafeUtils.writeLen(matchLen - ML_MASK, dest, dOff);
|
||||
} else {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | matchLen);
|
||||
}
|
||||
|
||||
// test end of chunk
|
||||
if (sOff > mflimit) {
|
||||
anchor = sOff;
|
||||
break main;
|
||||
}
|
||||
|
||||
// fill table
|
||||
UnsafeUtils.writeShort(hashTable, hash64k(UnsafeUtils.readInt(src, sOff - 2)), sOff - 2 - srcOff);
|
||||
|
||||
// test next position
|
||||
final int h = hash64k(UnsafeUtils.readInt(src, sOff));
|
||||
ref = srcOff + UnsafeUtils.readShort(hashTable, h);
|
||||
UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
|
||||
|
||||
if (!LZ4UnsafeUtils.readIntEquals(src, sOff, ref)) {
|
||||
break;
|
||||
}
|
||||
|
||||
tokenOff = dOff++;
|
||||
UnsafeUtils.writeByte(dest, tokenOff, 0);
|
||||
}
|
||||
|
||||
// prepare next loop
|
||||
anchor = sOff++;
|
||||
}
|
||||
}
|
||||
|
||||
dOff = LZ4UnsafeUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
|
||||
return dOff - destOff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compress(byte[] src, final int srcOff, int srcLen, byte[] dest, final int destOff, int maxDestLen) {
|
||||
|
||||
UnsafeUtils.checkRange(src, srcOff, srcLen);
|
||||
UnsafeUtils.checkRange(dest, destOff, maxDestLen);
|
||||
final int destEnd = destOff + maxDestLen;
|
||||
|
||||
if (srcLen < LZ4_64K_LIMIT) {
|
||||
return compress64k(src, srcOff, srcLen, dest, destOff, destEnd);
|
||||
}
|
||||
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
final int srcLimit = srcEnd - LAST_LITERALS;
|
||||
final int mflimit = srcEnd - MF_LIMIT;
|
||||
|
||||
int sOff = srcOff, dOff = destOff;
|
||||
int anchor = sOff++;
|
||||
|
||||
final int[] hashTable = new int[HASH_TABLE_SIZE];
|
||||
Arrays.fill(hashTable, anchor);
|
||||
|
||||
main:
|
||||
while (true) {
|
||||
|
||||
// find a match
|
||||
int forwardOff = sOff;
|
||||
|
||||
int ref;
|
||||
int step = 1;
|
||||
int searchMatchNb = 1 << SKIP_STRENGTH;
|
||||
int back;
|
||||
do {
|
||||
sOff = forwardOff;
|
||||
forwardOff += step;
|
||||
step = searchMatchNb++ >>> SKIP_STRENGTH;
|
||||
|
||||
if (forwardOff > mflimit) {
|
||||
break main;
|
||||
}
|
||||
|
||||
final int h = hash(UnsafeUtils.readInt(src, sOff));
|
||||
ref = UnsafeUtils.readInt(hashTable, h);
|
||||
back = sOff - ref;
|
||||
UnsafeUtils.writeInt(hashTable, h, sOff);
|
||||
} while (back >= MAX_DISTANCE || !LZ4UnsafeUtils.readIntEquals(src, ref, sOff));
|
||||
|
||||
|
||||
final int excess = LZ4UnsafeUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
|
||||
sOff -= excess;
|
||||
ref -= excess;
|
||||
|
||||
// sequence == refsequence
|
||||
final int runLen = sOff - anchor;
|
||||
|
||||
// encode literal length
|
||||
int tokenOff = dOff++;
|
||||
|
||||
if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
|
||||
if (runLen >= RUN_MASK) {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
|
||||
dOff = LZ4UnsafeUtils.writeLen(runLen - RUN_MASK, dest, dOff);
|
||||
} else {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
|
||||
}
|
||||
|
||||
// copy literals
|
||||
LZ4UnsafeUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
|
||||
dOff += runLen;
|
||||
|
||||
while (true) {
|
||||
// encode offset
|
||||
UnsafeUtils.writeShortLE(dest, dOff, back);
|
||||
dOff += 2;
|
||||
|
||||
// count nb matches
|
||||
sOff += MIN_MATCH;
|
||||
final int matchLen = LZ4UnsafeUtils.commonBytes(src, ref + MIN_MATCH, sOff, srcLimit);
|
||||
if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
sOff += matchLen;
|
||||
|
||||
// encode match len
|
||||
if (matchLen >= ML_MASK) {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | ML_MASK);
|
||||
dOff = LZ4UnsafeUtils.writeLen(matchLen - ML_MASK, dest, dOff);
|
||||
} else {
|
||||
UnsafeUtils.writeByte(dest, tokenOff, UnsafeUtils.readByte(dest, tokenOff) | matchLen);
|
||||
}
|
||||
|
||||
// test end of chunk
|
||||
if (sOff > mflimit) {
|
||||
anchor = sOff;
|
||||
break main;
|
||||
}
|
||||
|
||||
// fill table
|
||||
UnsafeUtils.writeInt(hashTable, hash(UnsafeUtils.readInt(src, sOff - 2)), sOff - 2);
|
||||
|
||||
// test next position
|
||||
final int h = hash(UnsafeUtils.readInt(src, sOff));
|
||||
ref = UnsafeUtils.readInt(hashTable, h);
|
||||
UnsafeUtils.writeInt(hashTable, h, sOff);
|
||||
back = sOff - ref;
|
||||
|
||||
if (back >= MAX_DISTANCE || !LZ4UnsafeUtils.readIntEquals(src, ref, sOff)) {
|
||||
break;
|
||||
}
|
||||
|
||||
tokenOff = dOff++;
|
||||
UnsafeUtils.writeByte(dest, tokenOff, 0);
|
||||
}
|
||||
|
||||
// prepare next loop
|
||||
anchor = sOff++;
|
||||
}
|
||||
|
||||
dOff = LZ4UnsafeUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
|
||||
return dOff - destOff;
|
||||
}
|
||||
|
||||
|
||||
static int compress64k(ByteBuffer src, int srcOff, int srcLen, ByteBuffer dest, int destOff, int destEnd) {
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
final int srcLimit = srcEnd - LAST_LITERALS;
|
||||
final int mflimit = srcEnd - MF_LIMIT;
|
||||
|
||||
int sOff = srcOff, dOff = destOff;
|
||||
|
||||
int anchor = sOff;
|
||||
|
||||
if (srcLen >= MIN_LENGTH) {
|
||||
|
||||
final short[] hashTable = new short[HASH_TABLE_SIZE_64K];
|
||||
|
||||
++sOff;
|
||||
|
||||
main:
|
||||
while (true) {
|
||||
|
||||
// find a match
|
||||
int forwardOff = sOff;
|
||||
|
||||
int ref;
|
||||
int step = 1;
|
||||
int searchMatchNb = 1 << SKIP_STRENGTH;
|
||||
do {
|
||||
sOff = forwardOff;
|
||||
forwardOff += step;
|
||||
step = searchMatchNb++ >>> SKIP_STRENGTH;
|
||||
|
||||
if (forwardOff > mflimit) {
|
||||
break main;
|
||||
}
|
||||
|
||||
final int h = hash64k(ByteBufferUtils.readInt(src, sOff));
|
||||
ref = srcOff + UnsafeUtils.readShort(hashTable, h);
|
||||
UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
|
||||
} while (!LZ4ByteBufferUtils.readIntEquals(src, ref, sOff));
|
||||
|
||||
// catch up
|
||||
final int excess = LZ4ByteBufferUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
|
||||
sOff -= excess;
|
||||
ref -= excess;
|
||||
|
||||
// sequence == refsequence
|
||||
final int runLen = sOff - anchor;
|
||||
|
||||
// encode literal length
|
||||
int tokenOff = dOff++;
|
||||
|
||||
if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
|
||||
if (runLen >= RUN_MASK) {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
|
||||
dOff = LZ4ByteBufferUtils.writeLen(runLen - RUN_MASK, dest, dOff);
|
||||
} else {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
|
||||
}
|
||||
|
||||
// copy literals
|
||||
LZ4ByteBufferUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
|
||||
dOff += runLen;
|
||||
|
||||
while (true) {
|
||||
// encode offset
|
||||
ByteBufferUtils.writeShortLE(dest, dOff, (short) (sOff - ref));
|
||||
dOff += 2;
|
||||
|
||||
// count nb matches
|
||||
sOff += MIN_MATCH;
|
||||
ref += MIN_MATCH;
|
||||
final int matchLen = LZ4ByteBufferUtils.commonBytes(src, ref, sOff, srcLimit);
|
||||
if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
sOff += matchLen;
|
||||
|
||||
// encode match len
|
||||
if (matchLen >= ML_MASK) {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | ML_MASK);
|
||||
dOff = LZ4ByteBufferUtils.writeLen(matchLen - ML_MASK, dest, dOff);
|
||||
} else {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | matchLen);
|
||||
}
|
||||
|
||||
// test end of chunk
|
||||
if (sOff > mflimit) {
|
||||
anchor = sOff;
|
||||
break main;
|
||||
}
|
||||
|
||||
// fill table
|
||||
UnsafeUtils.writeShort(hashTable, hash64k(ByteBufferUtils.readInt(src, sOff - 2)), sOff - 2 - srcOff);
|
||||
|
||||
// test next position
|
||||
final int h = hash64k(ByteBufferUtils.readInt(src, sOff));
|
||||
ref = srcOff + UnsafeUtils.readShort(hashTable, h);
|
||||
UnsafeUtils.writeShort(hashTable, h, sOff - srcOff);
|
||||
|
||||
if (!LZ4ByteBufferUtils.readIntEquals(src, sOff, ref)) {
|
||||
break;
|
||||
}
|
||||
|
||||
tokenOff = dOff++;
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, 0);
|
||||
}
|
||||
|
||||
// prepare next loop
|
||||
anchor = sOff++;
|
||||
}
|
||||
}
|
||||
|
||||
dOff = LZ4ByteBufferUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
|
||||
return dOff - destOff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compress(ByteBuffer src, final int srcOff, int srcLen, ByteBuffer dest, final int destOff, int maxDestLen) {
|
||||
|
||||
if (src.hasArray() && dest.hasArray()) {
|
||||
return compress(src.array(), srcOff + src.arrayOffset(), srcLen, dest.array(), destOff + dest.arrayOffset(), maxDestLen);
|
||||
}
|
||||
src = ByteBufferUtils.inNativeByteOrder(src);
|
||||
dest = ByteBufferUtils.inNativeByteOrder(dest);
|
||||
|
||||
ByteBufferUtils.checkRange(src, srcOff, srcLen);
|
||||
ByteBufferUtils.checkRange(dest, destOff, maxDestLen);
|
||||
final int destEnd = destOff + maxDestLen;
|
||||
|
||||
if (srcLen < LZ4_64K_LIMIT) {
|
||||
return compress64k(src, srcOff, srcLen, dest, destOff, destEnd);
|
||||
}
|
||||
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
final int srcLimit = srcEnd - LAST_LITERALS;
|
||||
final int mflimit = srcEnd - MF_LIMIT;
|
||||
|
||||
int sOff = srcOff, dOff = destOff;
|
||||
int anchor = sOff++;
|
||||
|
||||
final int[] hashTable = new int[HASH_TABLE_SIZE];
|
||||
Arrays.fill(hashTable, anchor);
|
||||
|
||||
main:
|
||||
while (true) {
|
||||
|
||||
// find a match
|
||||
int forwardOff = sOff;
|
||||
|
||||
int ref;
|
||||
int step = 1;
|
||||
int searchMatchNb = 1 << SKIP_STRENGTH;
|
||||
int back;
|
||||
do {
|
||||
sOff = forwardOff;
|
||||
forwardOff += step;
|
||||
step = searchMatchNb++ >>> SKIP_STRENGTH;
|
||||
|
||||
if (forwardOff > mflimit) {
|
||||
break main;
|
||||
}
|
||||
|
||||
final int h = hash(ByteBufferUtils.readInt(src, sOff));
|
||||
ref = UnsafeUtils.readInt(hashTable, h);
|
||||
back = sOff - ref;
|
||||
UnsafeUtils.writeInt(hashTable, h, sOff);
|
||||
} while (back >= MAX_DISTANCE || !LZ4ByteBufferUtils.readIntEquals(src, ref, sOff));
|
||||
|
||||
|
||||
final int excess = LZ4ByteBufferUtils.commonBytesBackward(src, ref, sOff, srcOff, anchor);
|
||||
sOff -= excess;
|
||||
ref -= excess;
|
||||
|
||||
// sequence == refsequence
|
||||
final int runLen = sOff - anchor;
|
||||
|
||||
// encode literal length
|
||||
int tokenOff = dOff++;
|
||||
|
||||
if (dOff + runLen + (2 + 1 + LAST_LITERALS) + (runLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
|
||||
if (runLen >= RUN_MASK) {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, RUN_MASK << ML_BITS);
|
||||
dOff = LZ4ByteBufferUtils.writeLen(runLen - RUN_MASK, dest, dOff);
|
||||
} else {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, runLen << ML_BITS);
|
||||
}
|
||||
|
||||
// copy literals
|
||||
LZ4ByteBufferUtils.wildArraycopy(src, anchor, dest, dOff, runLen);
|
||||
dOff += runLen;
|
||||
|
||||
while (true) {
|
||||
// encode offset
|
||||
ByteBufferUtils.writeShortLE(dest, dOff, back);
|
||||
dOff += 2;
|
||||
|
||||
// count nb matches
|
||||
sOff += MIN_MATCH;
|
||||
final int matchLen = LZ4ByteBufferUtils.commonBytes(src, ref + MIN_MATCH, sOff, srcLimit);
|
||||
if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
sOff += matchLen;
|
||||
|
||||
// encode match len
|
||||
if (matchLen >= ML_MASK) {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | ML_MASK);
|
||||
dOff = LZ4ByteBufferUtils.writeLen(matchLen - ML_MASK, dest, dOff);
|
||||
} else {
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, ByteBufferUtils.readByte(dest, tokenOff) | matchLen);
|
||||
}
|
||||
|
||||
// test end of chunk
|
||||
if (sOff > mflimit) {
|
||||
anchor = sOff;
|
||||
break main;
|
||||
}
|
||||
|
||||
// fill table
|
||||
UnsafeUtils.writeInt(hashTable, hash(ByteBufferUtils.readInt(src, sOff - 2)), sOff - 2);
|
||||
|
||||
// test next position
|
||||
final int h = hash(ByteBufferUtils.readInt(src, sOff));
|
||||
ref = UnsafeUtils.readInt(hashTable, h);
|
||||
UnsafeUtils.writeInt(hashTable, h, sOff);
|
||||
back = sOff - ref;
|
||||
|
||||
if (back >= MAX_DISTANCE || !LZ4ByteBufferUtils.readIntEquals(src, ref, sOff)) {
|
||||
break;
|
||||
}
|
||||
|
||||
tokenOff = dOff++;
|
||||
ByteBufferUtils.writeByte(dest, tokenOff, 0);
|
||||
}
|
||||
|
||||
// prepare next loop
|
||||
anchor = sOff++;
|
||||
}
|
||||
|
||||
dOff = LZ4ByteBufferUtils.lastLiterals(src, anchor, srcEnd - anchor, dest, dOff, destEnd);
|
||||
return dOff - destOff;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,205 +0,0 @@
|
||||
// Auto-generated: DO NOT EDIT
|
||||
|
||||
package net.jpountz.lz4;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import net.jpountz.util.ByteBufferUtils;
|
||||
import net.jpountz.util.UnsafeUtils;
|
||||
|
||||
|
||||
import static net.jpountz.lz4.LZ4Constants.*;
|
||||
|
||||
/**
|
||||
* Decompressor.
|
||||
*/
|
||||
final class LZ4JavaUnsafeFastDecompressor extends LZ4FastDecompressor {
|
||||
|
||||
public static final LZ4FastDecompressor INSTANCE = new LZ4JavaUnsafeFastDecompressor();
|
||||
|
||||
@Override
|
||||
public int decompress(byte[] src, final int srcOff, byte[] dest, final int destOff, int destLen) {
|
||||
|
||||
|
||||
UnsafeUtils.checkRange(src, srcOff);
|
||||
UnsafeUtils.checkRange(dest, destOff, destLen);
|
||||
|
||||
if (destLen == 0) {
|
||||
if (UnsafeUtils.readByte(src, srcOff) != 0) {
|
||||
throw new LZ4Exception("Malformed input at " + srcOff);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
final int destEnd = destOff + destLen;
|
||||
|
||||
int sOff = srcOff;
|
||||
int dOff = destOff;
|
||||
|
||||
while (true) {
|
||||
final int token = UnsafeUtils.readByte(src, sOff) & 0xFF;
|
||||
++sOff;
|
||||
|
||||
// literals
|
||||
int literalLen = token >>> ML_BITS;
|
||||
if (literalLen == RUN_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while ((len = UnsafeUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
literalLen += 0xFF;
|
||||
}
|
||||
literalLen += len & 0xFF;
|
||||
}
|
||||
|
||||
final int literalCopyEnd = dOff + literalLen;
|
||||
|
||||
if (literalCopyEnd > destEnd - COPY_LENGTH) {
|
||||
if (literalCopyEnd != destEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
|
||||
} else {
|
||||
LZ4UnsafeUtils.safeArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
break; // EOF
|
||||
}
|
||||
}
|
||||
|
||||
LZ4UnsafeUtils.wildArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
|
||||
// matchs
|
||||
final int matchDec = UnsafeUtils.readShortLE(src, sOff);
|
||||
sOff += 2;
|
||||
int matchOff = dOff - matchDec;
|
||||
|
||||
if (matchOff < destOff) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
|
||||
int matchLen = token & ML_MASK;
|
||||
if (matchLen == ML_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while ((len = UnsafeUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
matchLen += 0xFF;
|
||||
}
|
||||
matchLen += len & 0xFF;
|
||||
}
|
||||
matchLen += MIN_MATCH;
|
||||
|
||||
final int matchCopyEnd = dOff + matchLen;
|
||||
|
||||
if (matchCopyEnd > destEnd - COPY_LENGTH) {
|
||||
if (matchCopyEnd > destEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
LZ4UnsafeUtils.safeIncrementalCopy(dest, matchOff, dOff, matchLen);
|
||||
} else {
|
||||
LZ4UnsafeUtils.wildIncrementalCopy(dest, matchOff, dOff, matchCopyEnd);
|
||||
}
|
||||
dOff = matchCopyEnd;
|
||||
}
|
||||
|
||||
|
||||
return sOff - srcOff;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decompress(ByteBuffer src, final int srcOff, ByteBuffer dest, final int destOff, int destLen) {
|
||||
|
||||
if (src.hasArray() && dest.hasArray()) {
|
||||
return decompress(src.array(), srcOff + src.arrayOffset(), dest.array(), destOff + dest.arrayOffset(), destLen);
|
||||
}
|
||||
src = ByteBufferUtils.inNativeByteOrder(src);
|
||||
dest = ByteBufferUtils.inNativeByteOrder(dest);
|
||||
|
||||
|
||||
ByteBufferUtils.checkRange(src, srcOff);
|
||||
ByteBufferUtils.checkRange(dest, destOff, destLen);
|
||||
|
||||
if (destLen == 0) {
|
||||
if (ByteBufferUtils.readByte(src, srcOff) != 0) {
|
||||
throw new LZ4Exception("Malformed input at " + srcOff);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
final int destEnd = destOff + destLen;
|
||||
|
||||
int sOff = srcOff;
|
||||
int dOff = destOff;
|
||||
|
||||
while (true) {
|
||||
final int token = ByteBufferUtils.readByte(src, sOff) & 0xFF;
|
||||
++sOff;
|
||||
|
||||
// literals
|
||||
int literalLen = token >>> ML_BITS;
|
||||
if (literalLen == RUN_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while ((len = ByteBufferUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
literalLen += 0xFF;
|
||||
}
|
||||
literalLen += len & 0xFF;
|
||||
}
|
||||
|
||||
final int literalCopyEnd = dOff + literalLen;
|
||||
|
||||
if (literalCopyEnd > destEnd - COPY_LENGTH) {
|
||||
if (literalCopyEnd != destEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
|
||||
} else {
|
||||
LZ4ByteBufferUtils.safeArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
break; // EOF
|
||||
}
|
||||
}
|
||||
|
||||
LZ4ByteBufferUtils.wildArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
|
||||
// matchs
|
||||
final int matchDec = ByteBufferUtils.readShortLE(src, sOff);
|
||||
sOff += 2;
|
||||
int matchOff = dOff - matchDec;
|
||||
|
||||
if (matchOff < destOff) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
|
||||
int matchLen = token & ML_MASK;
|
||||
if (matchLen == ML_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while ((len = ByteBufferUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
matchLen += 0xFF;
|
||||
}
|
||||
matchLen += len & 0xFF;
|
||||
}
|
||||
matchLen += MIN_MATCH;
|
||||
|
||||
final int matchCopyEnd = dOff + matchLen;
|
||||
|
||||
if (matchCopyEnd > destEnd - COPY_LENGTH) {
|
||||
if (matchCopyEnd > destEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
LZ4ByteBufferUtils.safeIncrementalCopy(dest, matchOff, dOff, matchLen);
|
||||
} else {
|
||||
LZ4ByteBufferUtils.wildIncrementalCopy(dest, matchOff, dOff, matchCopyEnd);
|
||||
}
|
||||
dOff = matchCopyEnd;
|
||||
}
|
||||
|
||||
|
||||
return sOff - srcOff;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,213 +0,0 @@
|
||||
// Auto-generated: DO NOT EDIT
|
||||
|
||||
package net.jpountz.lz4;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import net.jpountz.util.ByteBufferUtils;
|
||||
import net.jpountz.util.UnsafeUtils;
|
||||
|
||||
|
||||
import static net.jpountz.lz4.LZ4Constants.*;
|
||||
|
||||
/**
|
||||
* Decompressor.
|
||||
*/
|
||||
final class LZ4JavaUnsafeSafeDecompressor extends LZ4SafeDecompressor {
|
||||
|
||||
public static final LZ4SafeDecompressor INSTANCE = new LZ4JavaUnsafeSafeDecompressor();
|
||||
|
||||
@Override
|
||||
public int decompress(byte[] src, final int srcOff, final int srcLen, byte[] dest, final int destOff, int destLen) {
|
||||
|
||||
|
||||
UnsafeUtils.checkRange(src, srcOff, srcLen);
|
||||
UnsafeUtils.checkRange(dest, destOff, destLen);
|
||||
|
||||
if (destLen == 0) {
|
||||
if (srcLen != 1 || UnsafeUtils.readByte(src, srcOff) != 0) {
|
||||
throw new LZ4Exception("Output buffer too small");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
|
||||
|
||||
final int destEnd = destOff + destLen;
|
||||
|
||||
int sOff = srcOff;
|
||||
int dOff = destOff;
|
||||
|
||||
while (true) {
|
||||
final int token = UnsafeUtils.readByte(src, sOff) & 0xFF;
|
||||
++sOff;
|
||||
|
||||
// literals
|
||||
int literalLen = token >>> ML_BITS;
|
||||
if (literalLen == RUN_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while (sOff < srcEnd && (len = UnsafeUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
literalLen += 0xFF;
|
||||
}
|
||||
literalLen += len & 0xFF;
|
||||
}
|
||||
|
||||
final int literalCopyEnd = dOff + literalLen;
|
||||
|
||||
if (literalCopyEnd > destEnd - COPY_LENGTH || sOff + literalLen > srcEnd - COPY_LENGTH) {
|
||||
if (literalCopyEnd > destEnd) {
|
||||
throw new LZ4Exception();
|
||||
} else if (sOff + literalLen != srcEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
|
||||
} else {
|
||||
LZ4UnsafeUtils.safeArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
break; // EOF
|
||||
}
|
||||
}
|
||||
|
||||
LZ4UnsafeUtils.wildArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
|
||||
// matchs
|
||||
final int matchDec = UnsafeUtils.readShortLE(src, sOff);
|
||||
sOff += 2;
|
||||
int matchOff = dOff - matchDec;
|
||||
|
||||
if (matchOff < destOff) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
|
||||
int matchLen = token & ML_MASK;
|
||||
if (matchLen == ML_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while (sOff < srcEnd && (len = UnsafeUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
matchLen += 0xFF;
|
||||
}
|
||||
matchLen += len & 0xFF;
|
||||
}
|
||||
matchLen += MIN_MATCH;
|
||||
|
||||
final int matchCopyEnd = dOff + matchLen;
|
||||
|
||||
if (matchCopyEnd > destEnd - COPY_LENGTH) {
|
||||
if (matchCopyEnd > destEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
LZ4UnsafeUtils.safeIncrementalCopy(dest, matchOff, dOff, matchLen);
|
||||
} else {
|
||||
LZ4UnsafeUtils.wildIncrementalCopy(dest, matchOff, dOff, matchCopyEnd);
|
||||
}
|
||||
dOff = matchCopyEnd;
|
||||
}
|
||||
|
||||
|
||||
return dOff - destOff;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decompress(ByteBuffer src, final int srcOff, final int srcLen, ByteBuffer dest, final int destOff, int destLen) {
|
||||
|
||||
if (src.hasArray() && dest.hasArray()) {
|
||||
return decompress(src.array(), srcOff + src.arrayOffset(), srcLen, dest.array(), destOff + dest.arrayOffset(), destLen);
|
||||
}
|
||||
src = ByteBufferUtils.inNativeByteOrder(src);
|
||||
dest = ByteBufferUtils.inNativeByteOrder(dest);
|
||||
|
||||
|
||||
ByteBufferUtils.checkRange(src, srcOff, srcLen);
|
||||
ByteBufferUtils.checkRange(dest, destOff, destLen);
|
||||
|
||||
if (destLen == 0) {
|
||||
if (srcLen != 1 || ByteBufferUtils.readByte(src, srcOff) != 0) {
|
||||
throw new LZ4Exception("Output buffer too small");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
final int srcEnd = srcOff + srcLen;
|
||||
|
||||
|
||||
final int destEnd = destOff + destLen;
|
||||
|
||||
int sOff = srcOff;
|
||||
int dOff = destOff;
|
||||
|
||||
while (true) {
|
||||
final int token = ByteBufferUtils.readByte(src, sOff) & 0xFF;
|
||||
++sOff;
|
||||
|
||||
// literals
|
||||
int literalLen = token >>> ML_BITS;
|
||||
if (literalLen == RUN_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while (sOff < srcEnd && (len = ByteBufferUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
literalLen += 0xFF;
|
||||
}
|
||||
literalLen += len & 0xFF;
|
||||
}
|
||||
|
||||
final int literalCopyEnd = dOff + literalLen;
|
||||
|
||||
if (literalCopyEnd > destEnd - COPY_LENGTH || sOff + literalLen > srcEnd - COPY_LENGTH) {
|
||||
if (literalCopyEnd > destEnd) {
|
||||
throw new LZ4Exception();
|
||||
} else if (sOff + literalLen != srcEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
|
||||
} else {
|
||||
LZ4ByteBufferUtils.safeArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
break; // EOF
|
||||
}
|
||||
}
|
||||
|
||||
LZ4ByteBufferUtils.wildArraycopy(src, sOff, dest, dOff, literalLen);
|
||||
sOff += literalLen;
|
||||
dOff = literalCopyEnd;
|
||||
|
||||
// matchs
|
||||
final int matchDec = ByteBufferUtils.readShortLE(src, sOff);
|
||||
sOff += 2;
|
||||
int matchOff = dOff - matchDec;
|
||||
|
||||
if (matchOff < destOff) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
|
||||
int matchLen = token & ML_MASK;
|
||||
if (matchLen == ML_MASK) {
|
||||
byte len = (byte) 0xFF;
|
||||
while (sOff < srcEnd && (len = ByteBufferUtils.readByte(src, sOff++)) == (byte) 0xFF) {
|
||||
matchLen += 0xFF;
|
||||
}
|
||||
matchLen += len & 0xFF;
|
||||
}
|
||||
matchLen += MIN_MATCH;
|
||||
|
||||
final int matchCopyEnd = dOff + matchLen;
|
||||
|
||||
if (matchCopyEnd > destEnd - COPY_LENGTH) {
|
||||
if (matchCopyEnd > destEnd) {
|
||||
throw new LZ4Exception("Malformed input at " + sOff);
|
||||
}
|
||||
LZ4ByteBufferUtils.safeIncrementalCopy(dest, matchOff, dOff, matchLen);
|
||||
} else {
|
||||
LZ4ByteBufferUtils.wildIncrementalCopy(dest, matchOff, dOff, matchCopyEnd);
|
||||
}
|
||||
dOff = matchCopyEnd;
|
||||
}
|
||||
|
||||
|
||||
return dOff - destOff;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,196 +0,0 @@
|
||||
package net.jpountz.lz4;
|
||||
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
|
||||
import static net.jpountz.lz4.LZ4Constants.*;
|
||||
import static net.jpountz.util.UnsafeUtils.*;
|
||||
import static net.jpountz.util.Utils.NATIVE_BYTE_ORDER;
|
||||
|
||||
enum LZ4UnsafeUtils {
|
||||
;
|
||||
|
||||
static void safeArraycopy(byte[] src, int srcOff, byte[] dest, int destOff, int len) {
|
||||
final int fastLen = len & 0xFFFFFFF8;
|
||||
wildArraycopy(src, srcOff, dest, destOff, fastLen);
|
||||
for (int i = 0, slowLen = len & 0x7; i < slowLen; i += 1) {
|
||||
writeByte(dest, destOff + fastLen + i, readByte(src, srcOff + fastLen + i));
|
||||
}
|
||||
}
|
||||
|
||||
static void wildArraycopy(byte[] src, int srcOff, byte[] dest, int destOff, int len) {
|
||||
for (int i = 0; i < len; i += 8) {
|
||||
writeLong(dest, destOff + i, readLong(src, srcOff + i));
|
||||
}
|
||||
}
|
||||
|
||||
static void wildIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchCopyEnd) {
|
||||
if (dOff - matchOff < 4) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
writeByte(dest, dOff + i, readByte(dest, matchOff + i));
|
||||
}
|
||||
dOff += 4;
|
||||
matchOff += 4;
|
||||
int dec = 0;
|
||||
assert dOff >= matchOff && dOff - matchOff < 8;
|
||||
switch (dOff - matchOff) {
|
||||
case 1:
|
||||
matchOff -= 3;
|
||||
break;
|
||||
case 2:
|
||||
matchOff -= 2;
|
||||
break;
|
||||
case 3:
|
||||
matchOff -= 3;
|
||||
dec = -1;
|
||||
break;
|
||||
case 5:
|
||||
dec = 1;
|
||||
break;
|
||||
case 6:
|
||||
dec = 2;
|
||||
break;
|
||||
case 7:
|
||||
dec = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
writeInt(dest, dOff, readInt(dest, matchOff));
|
||||
dOff += 4;
|
||||
matchOff -= dec;
|
||||
} else if (dOff - matchOff < COPY_LENGTH) {
|
||||
writeLong(dest, dOff, readLong(dest, matchOff));
|
||||
dOff += dOff - matchOff;
|
||||
}
|
||||
while (dOff < matchCopyEnd) {
|
||||
writeLong(dest, dOff, readLong(dest, matchOff));
|
||||
dOff += 8;
|
||||
matchOff += 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void safeIncrementalCopy(byte[] dest, int matchOff, int dOff, int matchLen) {
|
||||
for (int i = 0; i < matchLen; ++i) {
|
||||
dest[dOff + i] = dest[matchOff + i];
|
||||
writeByte(dest, dOff + i, readByte(dest, matchOff + i));
|
||||
}
|
||||
}
|
||||
|
||||
static int readShortLittleEndian(byte[] src, int srcOff) {
|
||||
short s = readShort(src, srcOff);
|
||||
if (NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) {
|
||||
s = Short.reverseBytes(s);
|
||||
}
|
||||
return s & 0xFFFF;
|
||||
}
|
||||
|
||||
static void writeShortLittleEndian(byte[] dest, int destOff, int value) {
|
||||
short s = (short) value;
|
||||
if (NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) {
|
||||
s = Short.reverseBytes(s);
|
||||
}
|
||||
writeShort(dest, destOff, s);
|
||||
}
|
||||
|
||||
static boolean readIntEquals(byte[] src, int ref, int sOff) {
|
||||
return readInt(src, ref) == readInt(src, sOff);
|
||||
}
|
||||
|
||||
static int commonBytes(byte[] src, int ref, int sOff, int srcLimit) {
|
||||
int matchLen = 0;
|
||||
while (sOff <= srcLimit - 8) {
|
||||
if (readLong(src, sOff) == readLong(src, ref)) {
|
||||
matchLen += 8;
|
||||
ref += 8;
|
||||
sOff += 8;
|
||||
} else {
|
||||
final int zeroBits;
|
||||
if (NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) {
|
||||
zeroBits = Long.numberOfLeadingZeros(readLong(src, sOff) ^ readLong(src, ref));
|
||||
} else {
|
||||
zeroBits = Long.numberOfTrailingZeros(readLong(src, sOff) ^ readLong(src, ref));
|
||||
}
|
||||
return matchLen + (zeroBits >>> 3);
|
||||
}
|
||||
}
|
||||
while (sOff < srcLimit && readByte(src, ref++) == readByte(src, sOff++)) {
|
||||
++matchLen;
|
||||
}
|
||||
return matchLen;
|
||||
}
|
||||
|
||||
static int writeLen(int len, byte[] dest, int dOff) {
|
||||
while (len >= 0xFF) {
|
||||
writeByte(dest, dOff++, 0xFF);
|
||||
len -= 0xFF;
|
||||
}
|
||||
writeByte(dest, dOff++, len);
|
||||
return dOff;
|
||||
}
|
||||
|
||||
static int encodeSequence(byte[] src, int anchor, int matchOff, int matchRef, int matchLen, byte[] dest, int dOff, int destEnd) {
|
||||
final int runLen = matchOff - anchor;
|
||||
final int tokenOff = dOff++;
|
||||
int token;
|
||||
|
||||
if (runLen >= RUN_MASK) {
|
||||
token = (byte) (RUN_MASK << ML_BITS);
|
||||
dOff = writeLen(runLen - RUN_MASK, dest, dOff);
|
||||
} else {
|
||||
token = runLen << ML_BITS;
|
||||
}
|
||||
|
||||
// copy literals
|
||||
wildArraycopy(src, anchor, dest, dOff, runLen);
|
||||
dOff += runLen;
|
||||
|
||||
// encode offset
|
||||
final int matchDec = matchOff - matchRef;
|
||||
dest[dOff++] = (byte) matchDec;
|
||||
dest[dOff++] = (byte) (matchDec >>> 8);
|
||||
|
||||
// encode match len
|
||||
matchLen -= 4;
|
||||
if (dOff + (1 + LAST_LITERALS) + (matchLen >>> 8) > destEnd) {
|
||||
throw new LZ4Exception("maxDestLen is too small");
|
||||
}
|
||||
if (matchLen >= ML_MASK) {
|
||||
token |= ML_MASK;
|
||||
dOff = writeLen(matchLen - RUN_MASK, dest, dOff);
|
||||
} else {
|
||||
token |= matchLen;
|
||||
}
|
||||
|
||||
dest[tokenOff] = (byte) token;
|
||||
|
||||
return dOff;
|
||||
}
|
||||
|
||||
static int commonBytesBackward(byte[] b, int o1, int o2, int l1, int l2) {
|
||||
int count = 0;
|
||||
while (o1 > l1 && o2 > l2 && readByte(b, --o1) == readByte(b, --o2)) {
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int lastLiterals(byte[] src, int sOff, int srcLen, byte[] dest, int dOff, int destEnd) {
|
||||
return LZ4SafeUtils.lastLiterals(src, sOff, srcLen, dest, dOff, destEnd);
|
||||
}
|
||||
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
package net.jpountz.util;
|
||||
|
||||
/*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.ByteOrder;
|
||||
import sun.misc.Unsafe;
|
||||
|
||||
|
||||
import static net.jpountz.util.Utils.NATIVE_BYTE_ORDER;
|
||||
|
||||
public enum UnsafeUtils {
|
||||
;
|
||||
|
||||
private static final Unsafe UNSAFE;
|
||||
private static final long BYTE_ARRAY_OFFSET;
|
||||
private static final int BYTE_ARRAY_SCALE;
|
||||
private static final long INT_ARRAY_OFFSET;
|
||||
private static final int INT_ARRAY_SCALE;
|
||||
private static final long SHORT_ARRAY_OFFSET;
|
||||
private static final int SHORT_ARRAY_SCALE;
|
||||
|
||||
static {
|
||||
try {
|
||||
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
theUnsafe.setAccessible(true);
|
||||
UNSAFE = (Unsafe) theUnsafe.get(null);
|
||||
BYTE_ARRAY_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);
|
||||
BYTE_ARRAY_SCALE = UNSAFE.arrayIndexScale(byte[].class);
|
||||
INT_ARRAY_OFFSET = UNSAFE.arrayBaseOffset(int[].class);
|
||||
INT_ARRAY_SCALE = UNSAFE.arrayIndexScale(int[].class);
|
||||
SHORT_ARRAY_OFFSET = UNSAFE.arrayBaseOffset(short[].class);
|
||||
SHORT_ARRAY_SCALE = UNSAFE.arrayIndexScale(short[].class);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new ExceptionInInitializerError("Cannot access Unsafe");
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new ExceptionInInitializerError("Cannot access Unsafe");
|
||||
} catch (SecurityException e) {
|
||||
throw new ExceptionInInitializerError("Cannot access Unsafe");
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkRange(byte[] buf, int off) {
|
||||
SafeUtils.checkRange(buf, off);
|
||||
}
|
||||
|
||||
public static void checkRange(byte[] buf, int off, int len) {
|
||||
SafeUtils.checkRange(buf, off, len);
|
||||
}
|
||||
|
||||
public static void checkLength(int len) {
|
||||
SafeUtils.checkLength(len);
|
||||
}
|
||||
|
||||
public static byte readByte(byte[] src, int srcOff) {
|
||||
return UNSAFE.getByte(src, BYTE_ARRAY_OFFSET + BYTE_ARRAY_SCALE * srcOff);
|
||||
}
|
||||
|
||||
public static void writeByte(byte[] src, int srcOff, byte value) {
|
||||
UNSAFE.putByte(src, BYTE_ARRAY_OFFSET + BYTE_ARRAY_SCALE * srcOff, (byte) value);
|
||||
}
|
||||
|
||||
public static void writeByte(byte[] src, int srcOff, int value) {
|
||||
writeByte(src, srcOff, (byte) value);
|
||||
}
|
||||
|
||||
public static long readLong(byte[] src, int srcOff) {
|
||||
return UNSAFE.getLong(src, BYTE_ARRAY_OFFSET + srcOff);
|
||||
}
|
||||
|
||||
public static long readLongLE(byte[] src, int srcOff) {
|
||||
long i = readLong(src, srcOff);
|
||||
if (NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) {
|
||||
i = Long.reverseBytes(i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static void writeLong(byte[] dest, int destOff, long value) {
|
||||
UNSAFE.putLong(dest, BYTE_ARRAY_OFFSET + destOff, value);
|
||||
}
|
||||
|
||||
public static int readInt(byte[] src, int srcOff) {
|
||||
return UNSAFE.getInt(src, BYTE_ARRAY_OFFSET + srcOff);
|
||||
}
|
||||
|
||||
public static int readIntLE(byte[] src, int srcOff) {
|
||||
int i = readInt(src, srcOff);
|
||||
if (NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) {
|
||||
i = Integer.reverseBytes(i);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public static void writeInt(byte[] dest, int destOff, int value) {
|
||||
UNSAFE.putInt(dest, BYTE_ARRAY_OFFSET + destOff, value);
|
||||
}
|
||||
|
||||
public static short readShort(byte[] src, int srcOff) {
|
||||
return UNSAFE.getShort(src, BYTE_ARRAY_OFFSET + srcOff);
|
||||
}
|
||||
|
||||
public static int readShortLE(byte[] src, int srcOff) {
|
||||
short s = readShort(src, srcOff);
|
||||
if (NATIVE_BYTE_ORDER == ByteOrder.BIG_ENDIAN) {
|
||||
s = Short.reverseBytes(s);
|
||||
}
|
||||
return s & 0xFFFF;
|
||||
}
|
||||
|
||||
public static void writeShort(byte[] dest, int destOff, short value) {
|
||||
UNSAFE.putShort(dest, BYTE_ARRAY_OFFSET + destOff, value);
|
||||
}
|
||||
|
||||
public static void writeShortLE(byte[] buf, int off, int v) {
|
||||
writeByte(buf, off, (byte) v);
|
||||
writeByte(buf, off + 1, (byte) (v >>> 8));
|
||||
}
|
||||
|
||||
public static int readInt(int[] src, int srcOff) {
|
||||
return UNSAFE.getInt(src, INT_ARRAY_OFFSET + INT_ARRAY_SCALE * srcOff);
|
||||
}
|
||||
|
||||
public static void writeInt(int[] dest, int destOff, int value) {
|
||||
UNSAFE.putInt(dest, INT_ARRAY_OFFSET + INT_ARRAY_SCALE * destOff, value);
|
||||
}
|
||||
|
||||
public static int readShort(short[] src, int srcOff) {
|
||||
return UNSAFE.getShort(src, SHORT_ARRAY_OFFSET + SHORT_ARRAY_SCALE * srcOff) & 0xFFFF;
|
||||
}
|
||||
|
||||
public static void writeShort(short[] dest, int destOff, int value) {
|
||||
UNSAFE.putShort(dest, SHORT_ARRAY_OFFSET + SHORT_ARRAY_SCALE * destOff, (short) value);
|
||||
}
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren