com.github.junrar.unpack.Unpack15 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of junrar Show documentation
Show all versions of junrar Show documentation
rar decompression library in plain java
/*
* Copyright (c) 2007 innoSysTec (R) GmbH, Germany. All rights reserved.
* Original author: Edmund Wagner
* Creation date: 21.06.2007
*
* Source: $HeadURL$
* Last changed: $LastChangedDate$
*
* the unrar licence applies to all junrar source and binary distributions
* you are not allowed to use this source to re-create the RAR compression algorithm
*
* Here some html entities which can be used for escaping javadoc tags:
* "&": "&" or "&"
* "<": "<" or "<"
* ">": ">" or ">"
* "@": "@"
*/
package com.github.junrar.unpack;
import java.io.IOException;
import java.util.Arrays;
import com.github.junrar.exception.RarException;
import com.github.junrar.unpack.decode.Compress;
import com.github.junrar.unpack.vm.BitInput;
/**
* DOCUMENT ME
*
* @author $LastChangedBy$
* @version $LastChangedRevision$
*/
public abstract class Unpack15 extends BitInput
{
protected int readBorder;
protected boolean suspended;
protected boolean unpAllBuf;
protected ComprDataIO unpIO;
protected boolean unpSomeRead;
protected int readTop;
protected long destUnpSize;
protected byte[] window;
protected int[] oldDist = new int[4];
protected int unpPtr, wrPtr;
protected int oldDistPtr;
protected int[] ChSet = new int[256], ChSetA = new int[256],
ChSetB = new int[256], ChSetC = new int[256];
protected int[] Place = new int[256], PlaceA = new int[256],
PlaceB = new int[256], PlaceC = new int[256];
protected int[] NToPl = new int[256], NToPlB = new int[256],
NToPlC = new int[256];
protected int FlagBuf, AvrPlc, AvrPlcB, AvrLn1, AvrLn2, AvrLn3;
protected int Buf60, NumHuf, StMode, LCount, FlagsCnt;
protected int Nhfb, Nlzb, MaxDist3;
protected int lastDist, lastLength;
private static final int STARTL1 = 2;
private static int DecL1[] = { 0x8000, 0xa000, 0xc000, 0xd000, 0xe000,
0xea00, 0xee00, 0xf000, 0xf200, 0xf200, 0xffff };
private static int PosL1[] = { 0, 0, 0, 2, 3, 5, 7, 11, 16, 20, 24, 32, 32 };
private static final int STARTL2 = 3;
private static int DecL2[] = { 0xa000, 0xc000, 0xd000, 0xe000, 0xea00,
0xee00, 0xf000, 0xf200, 0xf240, 0xffff };
private static int PosL2[] = { 0, 0, 0, 0, 5, 7, 9, 13, 18, 22, 26, 34, 36 };
private static final int STARTHF0 = 4;
private static int DecHf0[] = { 0x8000, 0xc000, 0xe000, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xffff };
private static int PosHf0[] = { 0, 0, 0, 0, 0, 8, 16, 24, 33, 33, 33, 33,
33 };
private static final int STARTHF1 = 5;
private static int DecHf1[] = { 0x2000, 0xc000, 0xe000, 0xf000, 0xf200,
0xf200, 0xf7e0, 0xffff };
private static int PosHf1[] = { 0, 0, 0, 0, 0, 0, 4, 44, 60, 76, 80, 80,
127 };
private static final int STARTHF2 = 5;
private static int DecHf2[] = { 0x1000, 0x2400, 0x8000, 0xc000, 0xfa00,
0xffff, 0xffff, 0xffff };
private static int PosHf2[] = { 0, 0, 0, 0, 0, 0, 2, 7, 53, 117, 233, 0, 0 };
private static final int STARTHF3 = 6;
private static int DecHf3[] = { 0x800, 0x2400, 0xee00, 0xfe80, 0xffff,
0xffff, 0xffff };
private static int PosHf3[] = { 0, 0, 0, 0, 0, 0, 0, 2, 16, 218, 251, 0, 0 };
private static final int STARTHF4 = 8;
private static int DecHf4[] = { 0xff00, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff };
private static int PosHf4[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 0, 0 };
static int ShortLen1[] = { 1, 3, 4, 4, 5, 6, 7, 8, 8, 4, 4, 5, 6, 6, 4, 0 };
static int ShortXor1[] = { 0, 0xa0, 0xd0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe,
0xff, 0xc0, 0x80, 0x90, 0x98, 0x9c, 0xb0 };
static int ShortLen2[] = { 2, 3, 3, 3, 4, 4, 5, 6, 6, 4, 4, 5, 6, 6, 4, 0 };
static int ShortXor2[] = { 0, 0x40, 0x60, 0xa0, 0xd0, 0xe0, 0xf0, 0xf8,
0xfc, 0xc0, 0x80, 0x90, 0x98, 0x9c, 0xb0 };
protected abstract void unpInitData(boolean solid);
protected void unpack15(boolean solid) throws IOException, RarException
{
if (suspended) {
unpPtr = wrPtr;
} else {
unpInitData(solid);
oldUnpInitData(solid);
unpReadBuf();
if (!solid) {
initHuff();
unpPtr = 0;
} else {
unpPtr = wrPtr;
}
--destUnpSize;
}
if (destUnpSize >= 0) {
getFlagsBuf();
FlagsCnt = 8;
}
while (destUnpSize >= 0) {
unpPtr &= Compress.MAXWINMASK;
if (inAddr > readTop - 30 && !unpReadBuf()) {
break;
}
if (((wrPtr - unpPtr) & Compress.MAXWINMASK) < 270
&& wrPtr != unpPtr) {
oldUnpWriteBuf();
if (suspended) {
return;
}
}
if (StMode != 0) {
huffDecode();
continue;
}
if (--FlagsCnt < 0) {
getFlagsBuf();
FlagsCnt = 7;
}
if ((FlagBuf & 0x80) != 0) {
FlagBuf <<= 1;
if (Nlzb > Nhfb) {
longLZ();
} else {
huffDecode();
}
} else {
FlagBuf <<= 1;
if (--FlagsCnt < 0) {
getFlagsBuf();
FlagsCnt = 7;
}
if ((FlagBuf & 0x80) != 0) {
FlagBuf <<= 1;
if (Nlzb > Nhfb) {
huffDecode();
} else {
longLZ();
}
} else {
FlagBuf <<= 1;
shortLZ();
}
}
}
oldUnpWriteBuf();
}
protected boolean unpReadBuf() throws IOException, RarException
{
int dataSize=readTop-inAddr;
if (dataSize<0){
return(false);
}
if (inAddr>BitInput.MAX_SIZE/2) {
if (dataSize>0){
//memmove(InBuf,InBuf+InAddr,DataSize);
// for (int i = 0; i < dataSize; i++) {
// inBuf[i] = inBuf[inAddr + i];
// }
System.arraycopy(inBuf, inAddr, inBuf, 0, dataSize);
}
inAddr=0;
readTop=dataSize;
}
else{
dataSize=readTop;
}
//int readCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf);
int readCode=unpIO.unpRead(inBuf, dataSize, (BitInput.MAX_SIZE-dataSize)&~0xf);
if (readCode>0){
readTop+=readCode;
}
readBorder=readTop-30;
return(readCode!=-1);
}
private int getShortLen1(int pos)
{
return pos == 1 ? Buf60 + 3 : ShortLen1[pos];
}
private int getShortLen2(int pos)
{
return pos == 3 ? Buf60 + 3 : ShortLen2[pos];
}
protected void shortLZ()
{
int Length, SaveLength;
int LastDistance;
int Distance;
int DistancePlace;
NumHuf = 0;
int BitField = fgetbits();
if (LCount == 2) {
faddbits(1);
if (BitField >= 0x8000) {
oldCopyString(lastDist, lastLength);
return;
}
BitField <<= 1;
LCount = 0;
}
BitField >>>= 8;
if (AvrLn1 < 37) {
for (Length = 0;; Length++) {
if (((BitField ^ ShortXor1[Length]) & (~(0xff >>> getShortLen1(Length)))) == 0) {
break;
}
}
faddbits(getShortLen1(Length));
} else {
for (Length = 0;; Length++) {
if (((BitField ^ ShortXor2[Length]) & (~(0xff >> getShortLen2(Length)))) == 0) {
break;
}
}
faddbits(getShortLen2(Length));
}
if (Length >= 9) {
if (Length == 9) {
LCount++;
oldCopyString(lastDist, lastLength);
return;
}
if (Length == 14) {
LCount = 0;
Length = decodeNum(fgetbits(), STARTL2, DecL2, PosL2) + 5;
Distance = (fgetbits() >> 1) | 0x8000;
faddbits(15);
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
return;
}
LCount = 0;
SaveLength = Length;
Distance = oldDist[(oldDistPtr - (Length - 9)) & 3];
Length = decodeNum(fgetbits(), STARTL1, DecL1, PosL1) + 2;
if (Length == 0x101 && SaveLength == 10) {
Buf60 ^= 1;
return;
}
if (Distance > 256)
Length++;
if (Distance >= MaxDist3)
Length++;
oldDist[oldDistPtr++] = Distance;
oldDistPtr = oldDistPtr & 3;
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
return;
}
LCount = 0;
AvrLn1 += Length;
AvrLn1 -= AvrLn1 >> 4;
DistancePlace = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2) & 0xff;
Distance = ChSetA[DistancePlace];
if (--DistancePlace != -1) {
PlaceA[Distance]--;
LastDistance = ChSetA[DistancePlace];
PlaceA[LastDistance]++;
ChSetA[DistancePlace + 1] = LastDistance;
ChSetA[DistancePlace] = Distance;
}
Length += 2;
oldDist[oldDistPtr++] = ++Distance;
oldDistPtr = oldDistPtr & 3;
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
}
protected void longLZ()
{
int Length;
int Distance;
int DistancePlace, NewDistancePlace;
int OldAvr2, OldAvr3;
NumHuf = 0;
Nlzb += 16;
if (Nlzb > 0xff) {
Nlzb = 0x90;
Nhfb >>>= 1;
}
OldAvr2 = AvrLn2;
int BitField = fgetbits();
if (AvrLn2 >= 122) {
Length = decodeNum(BitField, STARTL2, DecL2, PosL2);
} else {
if (AvrLn2 >= 64) {
Length = decodeNum(BitField, STARTL1, DecL1, PosL1);
} else {
if (BitField < 0x100) {
Length = BitField;
faddbits(16);
} else {
for (Length = 0; ((BitField << Length) & 0x8000) == 0; Length++) {
;
}
faddbits(Length + 1);
}
}
}
AvrLn2 += Length;
AvrLn2 -= AvrLn2 >>> 5;
BitField = fgetbits();
if (AvrPlcB > 0x28ff) {
DistancePlace = decodeNum(BitField, STARTHF2, DecHf2, PosHf2);
} else {
if (AvrPlcB > 0x6ff) {
DistancePlace = decodeNum(BitField, STARTHF1, DecHf1, PosHf1);
} else {
DistancePlace = decodeNum(BitField, STARTHF0, DecHf0, PosHf0);
}
}
AvrPlcB += DistancePlace;
AvrPlcB -= AvrPlcB >> 8;
while (true) {
Distance = ChSetB[DistancePlace & 0xff];
NewDistancePlace = NToPlB[Distance++ & 0xff]++;
if ((Distance & 0xff) == 0) {
corrHuff(ChSetB, NToPlB);
} else {
break;
}
}
ChSetB[DistancePlace] = ChSetB[NewDistancePlace];
ChSetB[NewDistancePlace] = Distance;
Distance = ((Distance & 0xff00) | (fgetbits() >>> 8)) >>> 1;
faddbits(7);
OldAvr3 = AvrLn3;
if (Length != 1 && Length != 4) {
if (Length == 0 && Distance <= MaxDist3) {
AvrLn3++;
AvrLn3 -= AvrLn3 >> 8;
} else {
if (AvrLn3 > 0) {
AvrLn3--;
}
}
}
Length += 3;
if (Distance >= MaxDist3) {
Length++;
}
if (Distance <= 256) {
Length += 8;
}
if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40) {
MaxDist3 = 0x7f00;
} else {
MaxDist3 = 0x2001;
}
oldDist[oldDistPtr++] = Distance;
oldDistPtr = oldDistPtr & 3;
lastLength = Length;
lastDist = Distance;
oldCopyString(Distance, Length);
}
protected void huffDecode()
{
int CurByte, NewBytePlace;
int Length;
int Distance;
int BytePlace;
int BitField = fgetbits();
if (AvrPlc > 0x75ff) {
BytePlace = decodeNum(BitField, STARTHF4, DecHf4, PosHf4);
} else {
if (AvrPlc > 0x5dff) {
BytePlace = decodeNum(BitField, STARTHF3, DecHf3, PosHf3);
} else {
if (AvrPlc > 0x35ff) {
BytePlace = decodeNum(BitField, STARTHF2, DecHf2, PosHf2);
} else {
if (AvrPlc > 0x0dff) {
BytePlace = decodeNum(BitField, STARTHF1, DecHf1,
PosHf1);
} else {
BytePlace = decodeNum(BitField, STARTHF0, DecHf0,
PosHf0);
}
}
}
}
BytePlace &= 0xff;
if (StMode != 0) {
if (BytePlace == 0 && BitField > 0xfff) {
BytePlace = 0x100;
}
if (--BytePlace == -1) {
BitField = fgetbits();
faddbits(1);
if ((BitField & 0x8000) != 0) {
NumHuf = StMode = 0;
return;
} else {
Length = (BitField & 0x4000) != 0 ? 4 : 3;
faddbits(1);
Distance = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2);
Distance = (Distance << 5) | (fgetbits() >>> 11);
faddbits(5);
oldCopyString(Distance, Length);
return;
}
}
} else {
if (NumHuf++ >= 16 && FlagsCnt == 0) {
StMode = 1;
}
}
AvrPlc += BytePlace;
AvrPlc -= AvrPlc >>> 8;
Nhfb += 16;
if (Nhfb > 0xff) {
Nhfb = 0x90;
Nlzb >>>= 1;
}
window[unpPtr++] = (byte) (ChSet[BytePlace] >>> 8);
--destUnpSize;
while (true) {
CurByte = ChSet[BytePlace];
NewBytePlace = NToPl[CurByte++ & 0xff]++;
if ((CurByte & 0xff) > 0xa1) {
corrHuff(ChSet, NToPl);
} else {
break;
}
}
ChSet[BytePlace] = ChSet[NewBytePlace];
ChSet[NewBytePlace] = CurByte;
}
protected void getFlagsBuf()
{
int Flags, NewFlagsPlace;
int FlagsPlace = decodeNum(fgetbits(), STARTHF2, DecHf2, PosHf2);
while (true) {
Flags = ChSetC[FlagsPlace];
FlagBuf = Flags >>> 8;
NewFlagsPlace = NToPlC[Flags++ & 0xff]++;
if ((Flags & 0xff) != 0) {
break;
}
corrHuff(ChSetC, NToPlC);
}
ChSetC[FlagsPlace] = ChSetC[NewFlagsPlace];
ChSetC[NewFlagsPlace] = Flags;
}
protected void oldUnpInitData(boolean Solid)
{
if (!Solid ) {
AvrPlcB = AvrLn1 = AvrLn2 = AvrLn3 = NumHuf = Buf60 = 0;
AvrPlc = 0x3500;
MaxDist3 = 0x2001;
Nhfb = Nlzb = 0x80;
}
FlagsCnt = 0;
FlagBuf = 0;
StMode = 0;
LCount = 0;
readTop = 0;
}
protected void initHuff()
{
for (int I = 0; I < 256; I++) {
Place[I] = PlaceA[I] = PlaceB[I] = I;
PlaceC[I] = (~I + 1) & 0xff;
ChSet[I] = ChSetB[I] = I << 8;
ChSetA[I] = I;
ChSetC[I] = ((~I + 1) & 0xff) << 8;
}
Arrays.fill(NToPl, 0);// memset(NToPl,0,sizeof(NToPl));
Arrays.fill(NToPlB, 0); // memset(NToPlB,0,sizeof(NToPlB));
Arrays.fill(NToPlC, 0); // memset(NToPlC,0,sizeof(NToPlC));
corrHuff(ChSetB, NToPlB);
}
protected void corrHuff(int[] CharSet, int[] NumToPlace)
{
int I, J, pos = 0;
for (I = 7; I >= 0; I--) {
for (J = 0; J < 32; J++, pos++) {
CharSet[pos] = ((CharSet[pos] & ~0xff) | I);// *CharSet=(*CharSet
// & ~0xff) | I;
}
}
Arrays.fill(NumToPlace, 0);// memset(NumToPlace,0,sizeof(NToPl));
for (I = 6; I >= 0; I--) {
NumToPlace[I] = (7 - I) * 32;
}
}
protected void oldCopyString(int Distance, int Length)
{
destUnpSize -= Length;
while ((Length--) != 0) {
window[unpPtr] = window[(unpPtr - Distance) & Compress.MAXWINMASK];
unpPtr = (unpPtr + 1) & Compress.MAXWINMASK;
}
}
protected int decodeNum(int Num, int StartPos, int[] DecTab, int[] PosTab)
{
int I;
for (Num &= 0xfff0, I = 0; DecTab[I] <= Num; I++) {
StartPos++;
}
faddbits(StartPos);
return (((Num - (I != 0 ? DecTab[I - 1] : 0)) >>> (16 - StartPos)) + PosTab[StartPos]);
}
protected void oldUnpWriteBuf() throws IOException
{
if (unpPtr != wrPtr) {
unpSomeRead = true;
}
if (unpPtr < wrPtr) {
unpIO.unpWrite(window, wrPtr, -wrPtr & Compress.MAXWINMASK);
unpIO.unpWrite(window, 0, unpPtr);
unpAllBuf = true;
} else {
unpIO.unpWrite(window, wrPtr, unpPtr - wrPtr);
}
wrPtr = unpPtr;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy