_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=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 (BitFieldDecodeLen[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 (BitFieldDecodeLen[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; }