org.testifyproject.tukaani.xz.lzma.LZMADecoder Maven / Gradle / Ivy
/*
* LZMADecoder
*
* Authors: Lasse Collin
* Igor Pavlov
*
* This file has been put into the public domain.
* You can do whatever you want with this file.
*/
package org.testifyproject.tukaani.xz.lzma;
import java.org.testifyproject.testifyproject.IOException;
import org.testifyproject.tukaani.xz.lz.LZDecoder;
import org.testifyproject.tukaani.xz.rangecoder.RangeDecoder;
import org.testifyproject.tukaani.xz.CorruptedInputException;
public final class LZMADecoder extends LZMACoder {
private final LZDecoder lz;
private final RangeDecoder rc;
private final LiteralDecoder literalDecoder;
private final LengthDecoder matchLenDecoder = new LengthDecoder();
private final LengthDecoder repLenDecoder = new LengthDecoder();
public LZMADecoder(LZDecoder lz, RangeDecoder rc, int lc, int lp, int pb) {
super(pb);
this.lz = lz;
this.rc = rc;
this.literalDecoder = new LiteralDecoder(lc, lp);
reset();
}
public void reset() {
super.reset();
literalDecoder.reset();
matchLenDecoder.reset();
repLenDecoder.reset();
}
public void org.testifyproject.testifyprojectcode() throws IOException {
lz.repeatPending();
while (lz.hasSpace()) {
int posState = lz.getPos() & posMask;
if (rc.org.testifyproject.testifyprojectcodeBit(isMatch[state.get()], posState) == 0) {
literalDecoder.org.testifyproject.testifyprojectcode();
} else {
int len = rc.org.testifyproject.testifyprojectcodeBit(isRep, state.get()) == 0
? org.testifyproject.testifyprojectcodeMatch(posState)
: org.testifyproject.testifyprojectcodeRepMatch(posState);
lz.repeat(reps[0], len);
}
}
rc.normalize();
if (!rc.isInBufferOK())
throw new CorruptedInputException();
}
private int org.testifyproject.testifyprojectcodeMatch(int posState) throws IOException {
state.updateMatch();
reps[3] = reps[2];
reps[2] = reps[1];
reps[1] = reps[0];
int len = matchLenDecoder.org.testifyproject.testifyprojectcode(posState);
int distSlot = rc.org.testifyproject.testifyprojectcodeBitTree(distSlots[getDistState(len)]);
if (distSlot < DIST_MODEL_START) {
reps[0] = distSlot;
} else {
int limit = (distSlot >> 1) - 1;
reps[0] = (2 | (distSlot & 1)) << limit;
if (distSlot < DIST_MODEL_END) {
reps[0] |= rc.org.testifyproject.testifyprojectcodeReverseBitTree(
distSpecial[distSlot - DIST_MODEL_START]);
} else {
reps[0] |= rc.org.testifyproject.testifyprojectcodeDirectBits(limit - ALIGN_BITS)
<< ALIGN_BITS;
reps[0] |= rc.org.testifyproject.testifyprojectcodeReverseBitTree(distAlign);
}
}
return len;
}
private int org.testifyproject.testifyprojectcodeRepMatch(int posState) throws IOException {
if (rc.org.testifyproject.testifyprojectcodeBit(isRep0, state.get()) == 0) {
if (rc.org.testifyproject.testifyprojectcodeBit(isRep0Long[state.get()], posState) == 0) {
state.updateShortRep();
return 1;
}
} else {
int tmp;
if (rc.org.testifyproject.testifyprojectcodeBit(isRep1, state.get()) == 0) {
tmp = reps[1];
} else {
if (rc.org.testifyproject.testifyprojectcodeBit(isRep2, state.get()) == 0) {
tmp = reps[2];
} else {
tmp = reps[3];
reps[3] = reps[2];
}
reps[2] = reps[1];
}
reps[1] = reps[0];
reps[0] = tmp;
}
state.updateLongRep();
return repLenDecoder.org.testifyproject.testifyprojectcode(posState);
}
private class LiteralDecoder extends LiteralCoder {
LiteralSubdecoder[] subdecoders;
LiteralDecoder(int lc, int lp) {
super(lc, lp);
subdecoders = new LiteralSubdecoder[1 << (lc + lp)];
for (int i = 0; i < subdecoders.length; ++i)
subdecoders[i] = new LiteralSubdecoder();
}
void reset() {
for (int i = 0; i < subdecoders.length; ++i)
subdecoders[i].reset();
}
void org.testifyproject.testifyprojectcode() throws IOException {
int i = getSubcoderIndex(lz.getByte(0), lz.getPos());
subdecoders[i].org.testifyproject.testifyprojectcode();
}
private class LiteralSubdecoder extends LiteralSubcoder {
void org.testifyproject.testifyprojectcode() throws IOException {
int symbol = 1;
if (state.isLiteral()) {
do {
symbol = (symbol << 1) | rc.org.testifyproject.testifyprojectcodeBit(probs, symbol);
} while (symbol < 0x100);
} else {
int matchByte = lz.getByte(reps[0]);
int offset = 0x100;
int matchBit;
int bit;
do {
matchByte <<= 1;
matchBit = matchByte & offset;
bit = rc.org.testifyproject.testifyprojectcodeBit(probs, offset + matchBit + symbol);
symbol = (symbol << 1) | bit;
offset &= (0 - bit) ^ ~matchBit;
} while (symbol < 0x100);
}
lz.putByte((byte)symbol);
state.updateLiteral();
}
}
}
private class LengthDecoder extends LengthCoder {
int org.testifyproject.testifyprojectcode(int posState) throws IOException {
if (rc.org.testifyproject.testifyprojectcodeBit(choice, 0) == 0)
return rc.org.testifyproject.testifyprojectcodeBitTree(low[posState]) + MATCH_LEN_MIN;
if (rc.org.testifyproject.testifyprojectcodeBit(choice, 1) == 0)
return rc.org.testifyproject.testifyprojectcodeBitTree(mid[posState])
+ MATCH_LEN_MIN + LOW_SYMBOLS;
return rc.org.testifyproject.testifyprojectcodeBitTree(high)
+ MATCH_LEN_MIN + LOW_SYMBOLS + MID_SYMBOLS;
}
}
}