/src/unrar/unpackinline.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | _forceinline void Unpack::InsertOldDist(uint Distance) |
2 | 0 | { |
3 | 0 | OldDist[3]=OldDist[2]; |
4 | 0 | OldDist[2]=OldDist[1]; |
5 | 0 | OldDist[1]=OldDist[0]; |
6 | 0 | OldDist[0]=Distance; |
7 | 0 | } |
8 | | |
9 | | #ifdef _MSC_VER |
10 | | #define FAST_MEMCPY |
11 | | #endif |
12 | | |
13 | | _forceinline void Unpack::CopyString(uint Length,uint Distance) |
14 | 0 | { |
15 | 0 | size_t SrcPtr=UnpPtr-Distance; |
16 | 0 | if (SrcPtr<MaxWinSize-MAX_INC_LZ_MATCH && UnpPtr<MaxWinSize-MAX_INC_LZ_MATCH) |
17 | 0 | { |
18 | | // If we are not close to end of window, we do not need to waste time |
19 | | // to "& MaxWinMask" pointer protection. |
20 | |
|
21 | 0 | byte *Src=Window+SrcPtr; |
22 | 0 | byte *Dest=Window+UnpPtr; |
23 | 0 | UnpPtr+=Length; |
24 | |
|
25 | | #ifdef FAST_MEMCPY |
26 | | if (Distance<Length) // Overlapping strings |
27 | | #endif |
28 | 0 | while (Length>=8) |
29 | 0 | { |
30 | 0 | Dest[0]=Src[0]; |
31 | 0 | Dest[1]=Src[1]; |
32 | 0 | Dest[2]=Src[2]; |
33 | 0 | Dest[3]=Src[3]; |
34 | 0 | Dest[4]=Src[4]; |
35 | 0 | Dest[5]=Src[5]; |
36 | 0 | Dest[6]=Src[6]; |
37 | 0 | Dest[7]=Src[7]; |
38 | |
|
39 | 0 | Src+=8; |
40 | 0 | Dest+=8; |
41 | 0 | Length-=8; |
42 | 0 | } |
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 | 0 | if (Length>0) { Dest[0]=Src[0]; |
64 | 0 | if (Length>1) { Dest[1]=Src[1]; |
65 | 0 | if (Length>2) { Dest[2]=Src[2]; |
66 | 0 | if (Length>3) { Dest[3]=Src[3]; |
67 | 0 | if (Length>4) { Dest[4]=Src[4]; |
68 | 0 | if (Length>5) { Dest[5]=Src[5]; |
69 | 0 | if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s. |
70 | 0 | } |
71 | 0 | else |
72 | 0 | while (Length-- > 0) // Slow copying with all possible precautions. |
73 | 0 | { |
74 | 0 | 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 | 0 | UnpPtr=(UnpPtr+1) & MaxWinMask; |
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | |
82 | | _forceinline uint Unpack::DecodeNumber(BitInput &Inp,DecodeTable *Dec) |
83 | 0 | { |
84 | | // Left aligned 15 bit length raw bit field. |
85 | 0 | uint BitField=Inp.getbits() & 0xfffe; |
86 | |
|
87 | 0 | if (BitField<Dec->DecodeLen[Dec->QuickBits]) |
88 | 0 | { |
89 | 0 | uint Code=BitField>>(16-Dec->QuickBits); |
90 | 0 | Inp.addbits(Dec->QuickLen[Code]); |
91 | 0 | return Dec->QuickNum[Code]; |
92 | 0 | } |
93 | | |
94 | | // Detect the real bit length for current code. |
95 | 0 | uint Bits=15; |
96 | 0 | for (uint I=Dec->QuickBits+1;I<15;I++) |
97 | 0 | if (BitField<Dec->DecodeLen[I]) |
98 | 0 | { |
99 | 0 | Bits=I; |
100 | 0 | break; |
101 | 0 | } |
102 | |
|
103 | 0 | Inp.addbits(Bits); |
104 | | |
105 | | // Calculate the distance from the start code for current bit length. |
106 | 0 | 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 | 0 | 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 | 0 | uint Pos=Dec->DecodePos[Bits]+Dist; |
116 | | |
117 | | // Out of bounds safety check required for damaged archives. |
118 | 0 | if (Pos>=Dec->MaxNum) |
119 | 0 | Pos=0; |
120 | | |
121 | | // Convert the position in the code list to position in alphabet |
122 | | // and return it. |
123 | 0 | return Dec->DecodeNum[Pos]; |
124 | 0 | } |
125 | | |
126 | | |
127 | | _forceinline uint Unpack::SlotToLength(BitInput &Inp,uint Slot) |
128 | 0 | { |
129 | 0 | uint LBits,Length=2; |
130 | 0 | if (Slot<8) |
131 | 0 | { |
132 | 0 | LBits=0; |
133 | 0 | Length+=Slot; |
134 | 0 | } |
135 | 0 | else |
136 | 0 | { |
137 | 0 | LBits=Slot/4-1; |
138 | 0 | Length+=(4 | (Slot & 3)) << LBits; |
139 | 0 | } |
140 | |
|
141 | 0 | if (LBits>0) |
142 | 0 | { |
143 | 0 | Length+=Inp.getbits()>>(16-LBits); |
144 | 0 | Inp.addbits(LBits); |
145 | 0 | } |
146 | 0 | return Length; |
147 | 0 | } |