package LZMA;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
public class LzmaInputStream extends FilterInputStream {
boolean isClosed;
CRangeDecoder RangeDecoder;
byte[] dictionary;
int dictionarySize;
int dictionaryPos;
int GlobalPos;
int rep0;
int rep1;
int rep2;
int rep3;
int lc;
int lp;
int pb;
int State;
boolean PreviousIsMatch;
int RemainLen;
int[] probs;
byte[] uncompressed_buffer;
int uncompressed_size;
int uncompressed_offset;
long GlobalNowPos;
long GlobalOutSize;
static final int LZMA_BASE_SIZE = 1846;
static final int LZMA_LIT_SIZE = 768;
static final int kBlockSize = 65536;
static final int kNumStates = 12;
static final int kStartPosModelIndex = 4;
static final int kEndPosModelIndex = 14;
static final int kNumFullDistances = 128;
static final int kNumPosSlotBits = 6;
static final int kNumLenToPosStates = 4;
static final int kNumAlignBits = 4;
static final int kAlignTableSize = 16;
static final int kMatchMinLen = 2;
static final int IsMatch = 0;
static final int IsRep = 192;
static final int IsRepG0 = 204;
static final int IsRepG1 = 216;
static final int IsRepG2 = 228;
static final int IsRep0Long = 240;
static final int PosSlot = 432;
static final int SpecPos = 688;
static final int Align = 802;
static final int LenCoder = 818;
static final int RepLenCoder = 1332;
static final int Literal = 1846;
public LzmaInputStream(InputStream paramInputStream)
throws IOException {
super(paramInputStream);
isClosed = false;
readHeader();
fill_buffer();
}
private void LzmaDecode(int paramInt) throws IOException {
int j = (1 << pb) - 1;
int k = (1 << lp) - 1;
uncompressed_size = 0;
if (RemainLen == -1)
return;
int m;
while ((RemainLen > 0) && (uncompressed_size < paramInt)) {
m = dictionaryPos - rep0;
if (m < 0)
m += dictionarySize;
byte tmp103_102 = dictionary[m];
dictionary[dictionaryPos] = tmp103_102;
uncompressed_buffer[(uncompressed_size++)] = tmp103_102;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
RemainLen -= 1;
}
int i;
if (dictionaryPos == 0)
i = dictionary[(dictionarySize - 1)];
else {
i = dictionary[(dictionaryPos - 1)];
}
while (uncompressed_size < paramInt) {
m = uncompressed_size + GlobalPos & j;
int n;
int i1;
if (RangeDecoder.BitDecode(probs, 0 + (State << 4) + m) == 0) {
n = 1846 + 768 * (((uncompressed_size + GlobalPos & k) << lc) + ((i & 0xFF) >> 8 - lc));
if (State < 4)
State = 0;
else if (State < 10)
State -= 3;
else
State -= 6;
if (PreviousIsMatch) {
i1 = dictionaryPos - rep0;
if (i1 < 0)
i1 += dictionarySize;
byte b = dictionary[i1];
i = RangeDecoder.LzmaLiteralDecodeMatch(probs, n, b);
PreviousIsMatch = false;
} else {
i = RangeDecoder.LzmaLiteralDecode(probs, n);
}
uncompressed_buffer[(uncompressed_size++)] = (byte) i;
dictionary[dictionaryPos] = (byte) i;
if (++dictionaryPos == dictionarySize)
dictionaryPos = 0;
} else {
PreviousIsMatch = true;
if (RangeDecoder.BitDecode(probs, 192 + State) == 1) {
if (RangeDecoder.BitDecode(probs, 204 + State) == 0) {
if (RangeDecoder.BitDecode(probs, 240 + (State << 4) + m) == 0) {
if (uncompressed_size + GlobalPos == 0) {
throw new LzmaException("LZMA : Data Error");
}
State = (State < 7 ? 9 : 11);
n = dictionaryPos - rep0;
if (n < 0)
n += dictionarySize;
i = dictionary[n];
dictionary[dictionaryPos] = (byte) i;
if (++dictionaryPos == dictionarySize) {
dictionaryPos = 0;
}
uncompressed_buffer[(uncompressed_size++)] = (byte) i;
continue;
}
} else {
if (RangeDecoder.BitDecode(probs, 216 + State) == 0) {
n = rep1;
} else {
if (RangeDecoder.BitDecode(probs, 228 + State) == 0) {
n = rep2;
} else {
n = rep3;
rep3 = rep2;
}
rep2 = rep1;
}
rep1 = rep0;
rep0 = n;
}
RemainLen = RangeDecoder.LzmaLenDecode(probs, 1332, m);
State = (State < 7 ? 8 : 11);
} else {
rep3 = rep2;
rep2 = rep1;
rep1 = rep0;
State = (State < 7 ? 7 : 10);
RemainLen = RangeDecoder.LzmaLenDecode(probs, 818, m);
n = RangeDecoder.BitTreeDecode(probs, 432 + ((RemainLen < 4 ? RemainLen : 3) << 6), 6);
if (n >= 4) {
i1 = (n >> 1) - 1;
rep0 = ((0x2 | n & 0x1) << i1);
if (n < 14) {
rep0 += RangeDecoder.ReverseBitTreeDecode(probs, 688 + rep0 - n - 1, i1);
} else {
rep0 += (RangeDecoder.DecodeDirectBits(i1 - 4) << 4);
rep0 += RangeDecoder.ReverseBitTreeDecode(probs, 802, 4);
}
} else {
rep0 = n;
}
rep0 += 1;
}
if (rep0 == 0) {
RemainLen = -1;
break;
}
if (rep0 > uncompressed_size + GlobalPos) {
throw new LzmaException("LZMA : Data Error");
}
RemainLen += 2;
do {
n = dictionaryPos - rep0;
if (n < 0)
n += dictionarySize;
i = dictionary[n];
dictionary[dictionaryPos] = (byte) i;
if (++dictionaryPos == dictionarySize) {
dictionaryPos = 0;
}
uncompressed_buffer[(uncompressed_size++)] = (byte) i;
RemainLen -= 1;
} while ((RemainLen > 0) && (uncompressed_size < paramInt));
}
}
GlobalPos += uncompressed_size;
}
private void fill_buffer() throws IOException {
if (GlobalNowPos < GlobalOutSize) {
uncompressed_offset = 0;
long l = GlobalOutSize - GlobalNowPos;
int i;
if (l > 65536L)
i = 65536;
else {
i = (int) l;
}
LzmaDecode(i);
if (uncompressed_size == 0)
GlobalOutSize = GlobalNowPos;
else
GlobalNowPos += uncompressed_size;
}
}
private void readHeader() throws IOException {
byte[] arrayOfByte = new byte[5];
if (5 != in.read(arrayOfByte)) {
throw new LzmaException("LZMA header corrupted : Properties error");
}
GlobalOutSize = 0L;
for (int i = 0; i < 8; i++) {
int j = in.read();
if (j == -1)
throw new LzmaException("LZMA header corrupted : Size error");
GlobalOutSize += (j << i * 8);
}
if (GlobalOutSize == -1L) GlobalOutSize = 9223372036854775807L;
int i = arrayOfByte[0] & 0xFF;
if (i >= 225) {
throw new LzmaException("LZMA header corrupted : Properties error");
}
for (pb = 0; i >= 45; i -= 45) pb += 1;
for (lp = 0; i >= 9; i -= 9) lp += 1;
lc = i;
int j = 1846 + (768 << lc + lp);
probs = new int[j];
dictionarySize = 0;
for (int k = 0; k < 4; k++)
dictionarySize += ((arrayOfByte[(1 + k)] & 0xFF) << k * 8);
dictionary = new byte[dictionarySize];
if (dictionary == null) {
throw new LzmaException("LZMA : can't allocate");
}
int k = 1846 + (768 << lc + lp);
RangeDecoder = new CRangeDecoder(in);
dictionaryPos = 0;
GlobalPos = 0;
rep0 = (this.rep1 = this.rep2 = this.rep3 = 1);
State = 0;
PreviousIsMatch = false;
RemainLen = 0;
dictionary[(dictionarySize - 1)] = 0;
for (int m = 0; m < k; m++) {
probs[m] = 1024;
}
uncompressed_buffer = new byte[65536];
uncompressed_size = 0;
uncompressed_offset = 0;
GlobalNowPos = 0L;
}
public int read(byte[] paramArrayOfByte, int paramInt1, int paramInt2) throws IOException {
if (isClosed) {
throw new IOException("stream closed");
}
if ((paramInt1 | paramInt2 | paramInt1 + paramInt2 | paramArrayOfByte.length - (paramInt1 + paramInt2)) < 0) {
throw new IndexOutOfBoundsException();
}
if (paramInt2 == 0) {
return 0;
}
if (uncompressed_offset == uncompressed_size)
fill_buffer();
if (uncompressed_offset == uncompressed_size) {
return -1;
}
int i = Math.min(paramInt2, uncompressed_size - uncompressed_offset);
System.arraycopy(uncompressed_buffer, uncompressed_offset, paramArrayOfByte, paramInt1, i);
uncompressed_offset += i;
return i;
}
public void close() throws IOException {
isClosed = true;
super.close();
}
}