148 lines
3.7 KiB
C++
148 lines
3.7 KiB
C++
|
_forceinline void Unpack::InsertOldDist(uint Distance)
|
||
|
{
|
||
|
OldDist[3]=OldDist[2];
|
||
|
OldDist[2]=OldDist[1];
|
||
|
OldDist[1]=OldDist[0];
|
||
|
OldDist[0]=Distance;
|
||
|
}
|
||
|
|
||
|
#ifdef _MSC_VER
|
||
|
#define FAST_MEMCPY
|
||
|
#endif
|
||
|
|
||
|
_forceinline void Unpack::CopyString(uint Length,uint Distance)
|
||
|
{
|
||
|
size_t SrcPtr=UnpPtr-Distance;
|
||
|
if (SrcPtr<MaxWinSize-MAX_INC_LZ_MATCH && UnpPtr<MaxWinSize-MAX_INC_LZ_MATCH)
|
||
|
{
|
||
|
// If we are not close to end of window, we do not need to waste time
|
||
|
// to "& MaxWinMask" pointer protection.
|
||
|
|
||
|
byte *Src=Window+SrcPtr;
|
||
|
byte *Dest=Window+UnpPtr;
|
||
|
UnpPtr+=Length;
|
||
|
|
||
|
#ifdef FAST_MEMCPY
|
||
|
if (Distance<Length) // Overlapping strings
|
||
|
#endif
|
||
|
while (Length>=8)
|
||
|
{
|
||
|
Dest[0]=Src[0];
|
||
|
Dest[1]=Src[1];
|
||
|
Dest[2]=Src[2];
|
||
|
Dest[3]=Src[3];
|
||
|
Dest[4]=Src[4];
|
||
|
Dest[5]=Src[5];
|
||
|
Dest[6]=Src[6];
|
||
|
Dest[7]=Src[7];
|
||
|
|
||
|
Src+=8;
|
||
|
Dest+=8;
|
||
|
Length-=8;
|
||
|
}
|
||
|
#ifdef FAST_MEMCPY
|
||
|
else
|
||
|
while (Length>=8)
|
||
|
{
|
||
|
// In theory we still could overlap here.
|
||
|
// Supposing Distance == MaxWinSize - 1 we have memcpy(Src, Src + 1, 8).
|
||
|
// But for real RAR archives Distance <= MaxWinSize - MAX_INC_LZ_MATCH
|
||
|
// always, so overlap here is impossible.
|
||
|
|
||
|
// This memcpy expanded inline by MSVC. We could also use uint64
|
||
|
// assignment, which seems to provide about the same speed.
|
||
|
memcpy(Dest,Src,8);
|
||
|
|
||
|
Src+=8;
|
||
|
Dest+=8;
|
||
|
Length-=8;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
// Unroll the loop for 0 - 7 bytes left. Note that we use nested "if"s.
|
||
|
if (Length>0) { Dest[0]=Src[0];
|
||
|
if (Length>1) { Dest[1]=Src[1];
|
||
|
if (Length>2) { Dest[2]=Src[2];
|
||
|
if (Length>3) { Dest[3]=Src[3];
|
||
|
if (Length>4) { Dest[4]=Src[4];
|
||
|
if (Length>5) { Dest[5]=Src[5];
|
||
|
if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s.
|
||
|
}
|
||
|
else
|
||
|
while (Length-- > 0) // Slow copying with all possible precautions.
|
||
|
{
|
||
|
Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask];
|
||
|
// We need to have masked UnpPtr after quit from loop, so it must not
|
||
|
// be replaced with 'Window[UnpPtr++ & MaxWinMask]'
|
||
|
UnpPtr=(UnpPtr+1) & MaxWinMask;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
_forceinline uint Unpack::DecodeNumber(BitInput &Inp,DecodeTable *Dec)
|
||
|
{
|
||
|
// Left aligned 15 bit length raw bit field.
|
||
|
uint BitField=Inp.getbits() & 0xfffe;
|
||
|
|
||
|
if (BitField<Dec->DecodeLen[Dec->QuickBits])
|
||
|
{
|
||
|
uint Code=BitField>>(16-Dec->QuickBits);
|
||
|
Inp.addbits(Dec->QuickLen[Code]);
|
||
|
return Dec->QuickNum[Code];
|
||
|
}
|
||
|
|
||
|
// Detect the real bit length for current code.
|
||
|
uint Bits=15;
|
||
|
for (uint I=Dec->QuickBits+1;I<15;I++)
|
||
|
if (BitField<Dec->DecodeLen[I])
|
||
|
{
|
||
|
Bits=I;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Inp.addbits(Bits);
|
||
|
|
||
|
// Calculate the distance from the start code for current bit length.
|
||
|
uint Dist=BitField-Dec->DecodeLen[Bits-1];
|
||
|
|
||
|
// Start codes are left aligned, but we need the normal right aligned
|
||
|
// number. So we shift the distance to the right.
|
||
|
Dist>>=(16-Bits);
|
||
|
|
||
|
// Now we can calculate the position in the code list. It is the sum
|
||
|
// of first position for current bit length and right aligned distance
|
||
|
// between our bit field and start code for current bit length.
|
||
|
uint Pos=Dec->DecodePos[Bits]+Dist;
|
||
|
|
||
|
// Out of bounds safety check required for damaged archives.
|
||
|
if (Pos>=Dec->MaxNum)
|
||
|
Pos=0;
|
||
|
|
||
|
// Convert the position in the code list to position in alphabet
|
||
|
// and return it.
|
||
|
return Dec->DecodeNum[Pos];
|
||
|
}
|
||
|
|
||
|
|
||
|
_forceinline uint Unpack::SlotToLength(BitInput &Inp,uint Slot)
|
||
|
{
|
||
|
uint LBits,Length=2;
|
||
|
if (Slot<8)
|
||
|
{
|
||
|
LBits=0;
|
||
|
Length+=Slot;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
LBits=Slot/4-1;
|
||
|
Length+=(4 | (Slot & 3)) << LBits;
|
||
|
}
|
||
|
|
||
|
if (LBits>0)
|
||
|
{
|
||
|
Length+=Inp.getbits()>>(16-LBits);
|
||
|
Inp.addbits(LBits);
|
||
|
}
|
||
|
return Length;
|
||
|
}
|