InsertOldDist(uint Distance)1 _forceinline void Unpack::InsertOldDist(uint Distance)
2 {
3   OldDist[3]=OldDist[2];
4   OldDist[2]=OldDist[1];
5   OldDist[1]=OldDist[0];
6   OldDist[0]=Distance;
7 }
8 
9 #ifdef _MSC_VER
10 #define FAST_MEMCPY
11 #endif
12 
CopyString(uint Length,uint Distance)13 _forceinline void Unpack::CopyString(uint Length,uint Distance)
14 {
15   size_t SrcPtr=UnpPtr-Distance;
16   if (SrcPtr<MaxWinSize-MAX_INC_LZ_MATCH && UnpPtr<MaxWinSize-MAX_INC_LZ_MATCH)
17   {
18     // If we are not close to end of window, we do not need to waste time
19     // to "& MaxWinMask" pointer protection.
20 
21     byte *Src=Window+SrcPtr;
22     byte *Dest=Window+UnpPtr;
23     UnpPtr+=Length;
24 
25 #ifdef FAST_MEMCPY
26     if (Distance<Length) // Overlapping strings
27 #endif
28       while (Length>=8)
29       {
30         Dest[0]=Src[0];
31         Dest[1]=Src[1];
32         Dest[2]=Src[2];
33         Dest[3]=Src[3];
34         Dest[4]=Src[4];
35         Dest[5]=Src[5];
36         Dest[6]=Src[6];
37         Dest[7]=Src[7];
38 
39         Src+=8;
40         Dest+=8;
41         Length-=8;
42       }
43 #ifdef FAST_MEMCPY
44     else
45       while (Length>=8)
46       {
47         // In theory we still could overlap here.
48         // Supposing Distance == MaxWinSize - 1 we have memcpy(Src, Src + 1, 8).
49         // But for real RAR archives Distance <= MaxWinSize - MAX_INC_LZ_MATCH
50         // always, so overlap here is impossible.
51 
52         // This memcpy expanded inline by MSVC. We could also use uint64
53         // assignment, which seems to provide about the same speed.
54         memcpy(Dest,Src,8);
55 
56         Src+=8;
57         Dest+=8;
58         Length-=8;
59       }
60 #endif
61 
62     // Unroll the loop for 0 - 7 bytes left. Note that we use nested "if"s.
63     if (Length>0) { Dest[0]=Src[0];
64     if (Length>1) { Dest[1]=Src[1];
65     if (Length>2) { Dest[2]=Src[2];
66     if (Length>3) { Dest[3]=Src[3];
67     if (Length>4) { Dest[4]=Src[4];
68     if (Length>5) { Dest[5]=Src[5];
69     if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s.
70   }
71   else
72     while (Length-- > 0) // Slow copying with all possible precautions.
73     {
74       Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask];
75       // We need to have masked UnpPtr after quit from loop, so it must not
76       // be replaced with 'Window[UnpPtr++ & MaxWinMask]'
77       UnpPtr=(UnpPtr+1) & MaxWinMask;
78     }
79 }
80 
81 
DecodeNumber(BitInput & Inp,DecodeTable * Dec)82 _forceinline uint Unpack::DecodeNumber(BitInput &Inp,DecodeTable *Dec)
83 {
84   // Left aligned 15 bit length raw bit field.
85   uint BitField=Inp.getbits() & 0xfffe;
86 
87   if (BitField<Dec->DecodeLen[Dec->QuickBits])
88   {
89     uint Code=BitField>>(16-Dec->QuickBits);
90     Inp.addbits(Dec->QuickLen[Code]);
91     return Dec->QuickNum[Code];
92   }
93 
94   // Detect the real bit length for current code.
95   uint Bits=15;
96   for (uint I=Dec->QuickBits+1;I<15;I++)
97     if (BitField<Dec->DecodeLen[I])
98     {
99       Bits=I;
100       break;
101     }
102 
103   Inp.addbits(Bits);
104 
105   // Calculate the distance from the start code for current bit length.
106   uint Dist=BitField-Dec->DecodeLen[Bits-1];
107 
108   // Start codes are left aligned, but we need the normal right aligned
109   // number. So we shift the distance to the right.
110   Dist>>=(16-Bits);
111 
112   // Now we can calculate the position in the code list. It is the sum
113   // of first position for current bit length and right aligned distance
114   // between our bit field and start code for current bit length.
115   uint Pos=Dec->DecodePos[Bits]+Dist;
116 
117   // Out of bounds safety check required for damaged archives.
118   if (Pos>=Dec->MaxNum)
119     Pos=0;
120 
121   // Convert the position in the code list to position in alphabet
122   // and return it.
123   return Dec->DecodeNum[Pos];
124 }
125 
126 
SlotToLength(BitInput & Inp,uint Slot)127 _forceinline uint Unpack::SlotToLength(BitInput &Inp,uint Slot)
128 {
129   uint LBits,Length=2;
130   if (Slot<8)
131   {
132     LBits=0;
133     Length+=Slot;
134   }
135   else
136   {
137     LBits=Slot/4-1;
138     Length+=(4 | (Slot & 3)) << LBits;
139   }
140 
141   if (LBits>0)
142   {
143     Length+=Inp.getbits()>>(16-LBits);
144     Inp.addbits(LBits);
145   }
146   return Length;
147 }
148