Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.
*/package io.airlift.compress.v2.lz4;
import io.airlift.compress.v2.MalformedInputException;
importstatic io.airlift.compress.v2.lz4.Lz4Constants.LAST_LITERAL_SIZE;
importstatic io.airlift.compress.v2.lz4.Lz4Constants.MIN_MATCH;
importstatic io.airlift.compress.v2.lz4.Lz4Constants.SIZE_OF_INT;
importstatic io.airlift.compress.v2.lz4.Lz4Constants.SIZE_OF_LONG;
importstatic io.airlift.compress.v2.lz4.Lz4Constants.SIZE_OF_SHORT;
importstatic io.airlift.compress.v2.lz4.UnsafeUtil.UNSAFE;
finalclassLz4RawDecompressor{
privatestaticfinalint[] DEC_32_TABLE = {4, 1, 2, 1, 4, 4, 4, 4};
privatestaticfinalint[] DEC_64_TABLE = {0, 0, 0, -1, 0, 1, 2, 3};
privatestaticfinalint OFFSET_SIZE = 2;
privatestaticfinalint TOKEN_SIZE = 1;
privateLz4RawDecompressor(){}
publicstaticintdecompress(
final Object inputBase,
finallong inputAddress,
finallong inputLimit,
final Object outputBase,
finallong outputAddress,
finallong outputLimit){
finallong fastOutputLimit = outputLimit - SIZE_OF_LONG; // maximum offset in output buffer to which it's safe to write long-at-a-timelong input = inputAddress;
long output = outputAddress;
if (inputAddress == inputLimit) {
thrownew MalformedInputException(0, "input is empty");
}
if (outputAddress == outputLimit) {
if (inputLimit - inputAddress == 1 && UNSAFE.getByte(inputBase, inputAddress) == 0) {
return0;
}
return -1;
}
while (input < inputLimit) {
finalint token = UNSAFE.getByte(inputBase, input++) & 0xFF;
// decode literal lengthint literalLength = token >>> 4; // top-most 4 bits of tokenif (literalLength == 0xF) {
if (input >= inputLimit) {
thrownew MalformedInputException(input - inputAddress);
}
int value;
do {
value = UNSAFE.getByte(inputBase, input++) & 0xFF;
literalLength += value;
}
while (value == 255 && input < inputLimit - 15);
}
if (literalLength < 0) {
thrownew MalformedInputException(input - inputAddress);
}
// copy literallong literalEnd = input + literalLength;
long literalOutputLimit = output + literalLength;
if (literalOutputLimit > (fastOutputLimit - MIN_MATCH) || literalEnd > inputLimit - (OFFSET_SIZE + TOKEN_SIZE + LAST_LITERAL_SIZE)) {
// copy the last literal and finishif (literalOutputLimit > outputLimit) {
thrownew MalformedInputException(input - inputAddress, "attempt to write last literal outside of destination buffer");
}
if (literalEnd != inputLimit) {
thrownew MalformedInputException(input - inputAddress, "all input must be consumed");
}
// slow, precise copy
UNSAFE.copyMemory(inputBase, input, outputBase, output, literalLength);
output += literalLength;
break;
}
// fast copy. We may overcopy but there's enough room in input and output to not overrun themint index = 0;
do {
UNSAFE.putLong(outputBase, output, UNSAFE.getLong(inputBase, input));
output += SIZE_OF_LONG;
input += SIZE_OF_LONG;
index += SIZE_OF_LONG;
}
while (index < literalLength);
output = literalOutputLimit;
input = literalEnd;
// get offset// we know we can read two bytes because of the bounds check performed before copying the literal aboveint offset = UNSAFE.getShort(inputBase, input) & 0xFFFF;
input += SIZE_OF_SHORT;
long matchAddress = output - offset;
if (matchAddress < outputAddress) {
thrownew MalformedInputException(input - inputAddress, "offset outside destination buffer");
}
// compute match lengthint matchLength = token & 0xF; // bottom-most 4 bits of tokenif (matchLength == 0xF) {
int value;
do {
if (input > inputLimit - LAST_LITERAL_SIZE) {
thrownew MalformedInputException(input - inputAddress);
}
value = UNSAFE.getByte(inputBase, input++) & 0xFF;
matchLength += value;
}
while (value == 255);
}
matchLength += MIN_MATCH; // implicit length from initial 4-byte match in encoderif (matchLength < 0) {
thrownew MalformedInputException(input - inputAddress);
}
long matchOutputLimit = output + matchLength;
// at this point we have at least 12 bytes of space in the output buffer// due to the fastLimit check before copying a literal, so no need to check again// copy repeated sequenceif (offset < SIZE_OF_LONG) {
// 8 bytes apart so that we can copy long-at-a-time belowint increment32 = DEC_32_TABLE[offset];
int decrement64 = DEC_64_TABLE[offset];
UNSAFE.putByte(outputBase, output, UNSAFE.getByte(outputBase, matchAddress));
UNSAFE.putByte(outputBase, output + 1, UNSAFE.getByte(outputBase, matchAddress + 1));
UNSAFE.putByte(outputBase, output + 2, UNSAFE.getByte(outputBase, matchAddress + 2));
UNSAFE.putByte(outputBase, output + 3, UNSAFE.getByte(outputBase, matchAddress + 3));
output += SIZE_OF_INT;
matchAddress += increment32;
UNSAFE.putInt(outputBase, output, UNSAFE.getInt(outputBase, matchAddress));
output += SIZE_OF_INT;
matchAddress -= decrement64;
}
else {
UNSAFE.putLong(outputBase, output, UNSAFE.getLong(outputBase, matchAddress));
matchAddress += SIZE_OF_LONG;
output += SIZE_OF_LONG;
}
if (matchOutputLimit > fastOutputLimit - MIN_MATCH) {
if (matchOutputLimit > outputLimit - LAST_LITERAL_SIZE) {
thrownew MalformedInputException(input - inputAddress, String.format("last %s bytes must be literals", LAST_LITERAL_SIZE));
}
while (output < fastOutputLimit) {
UNSAFE.putLong(outputBase, output, UNSAFE.getLong(outputBase, matchAddress));
matchAddress += SIZE_OF_LONG;
output += SIZE_OF_LONG;
}
while (output < matchOutputLimit) {
UNSAFE.putByte(outputBase, output++, UNSAFE.getByte(outputBase, matchAddress++));
}
}
else {
int i = 0;
do {
UNSAFE.putLong(outputBase, output, UNSAFE.getLong(outputBase, matchAddress));
output += SIZE_OF_LONG;
matchAddress += SIZE_OF_LONG;
i += SIZE_OF_LONG;
}
while (i < matchLength - SIZE_OF_LONG); // first long copied previously
}
output = matchOutputLimit; // correction in case we overcopied
}
return (int) (output - outputAddress);
}
}