rlm@1
|
1 // Rar3Decoder.h
|
rlm@1
|
2 // According to unRAR license, this code may not be used to develop
|
rlm@1
|
3 // a program that creates RAR archives
|
rlm@1
|
4
|
rlm@1
|
5 #ifndef __COMPRESS_RAR3_DECODER_H
|
rlm@1
|
6 #define __COMPRESS_RAR3_DECODER_H
|
rlm@1
|
7
|
rlm@1
|
8 #include "../../Common/MyCom.h"
|
rlm@1
|
9
|
rlm@1
|
10 #include "../ICoder.h"
|
rlm@1
|
11
|
rlm@1
|
12 #include "../Common/InBuffer.h"
|
rlm@1
|
13
|
rlm@1
|
14 #include "BitmDecoder.h"
|
rlm@1
|
15 #include "HuffmanDecoder.h"
|
rlm@1
|
16 #include "PpmdDecode.h"
|
rlm@1
|
17 #include "Rar3Vm.h"
|
rlm@1
|
18
|
rlm@1
|
19 namespace NCompress {
|
rlm@1
|
20 namespace NRar3 {
|
rlm@1
|
21
|
rlm@1
|
22 const UInt32 kWindowSize = 1 << 22;
|
rlm@1
|
23 const UInt32 kWindowMask = (kWindowSize - 1);
|
rlm@1
|
24
|
rlm@1
|
25 const UInt32 kNumReps = 4;
|
rlm@1
|
26 const UInt32 kNumLen2Symbols = 8;
|
rlm@1
|
27 const UInt32 kLenTableSize = 28;
|
rlm@1
|
28 const UInt32 kMainTableSize = 256 + 1 + 1 + 1 + kNumReps + kNumLen2Symbols + kLenTableSize;
|
rlm@1
|
29 const UInt32 kDistTableSize = 60;
|
rlm@1
|
30
|
rlm@1
|
31 const int kNumAlignBits = 4;
|
rlm@1
|
32 const UInt32 kAlignTableSize = (1 << kNumAlignBits) + 1;
|
rlm@1
|
33
|
rlm@1
|
34 const UInt32 kLevelTableSize = 20;
|
rlm@1
|
35
|
rlm@1
|
36 const UInt32 kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
|
rlm@1
|
37
|
rlm@1
|
38 class CBitDecoder
|
rlm@1
|
39 {
|
rlm@1
|
40 UInt32 m_Value;
|
rlm@1
|
41 public:
|
rlm@1
|
42 UInt32 m_BitPos;
|
rlm@1
|
43 CInBuffer m_Stream;
|
rlm@1
|
44 bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }
|
rlm@1
|
45 void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}
|
rlm@1
|
46 void ReleaseStream() { m_Stream.ReleaseStream();}
|
rlm@1
|
47
|
rlm@1
|
48 void Init()
|
rlm@1
|
49 {
|
rlm@1
|
50 m_Stream.Init();
|
rlm@1
|
51 m_BitPos = 0;
|
rlm@1
|
52 m_Value = 0;
|
rlm@1
|
53 // m_BitPos = kNumBigValueBits;
|
rlm@1
|
54 // Normalize();
|
rlm@1
|
55 }
|
rlm@1
|
56
|
rlm@1
|
57 UInt64 GetProcessedSize() const
|
rlm@1
|
58 { return m_Stream.GetProcessedSize() - (m_BitPos) / 8; }
|
rlm@1
|
59 UInt32 GetBitPosition() const { return ((8 - m_BitPos) & 7); }
|
rlm@1
|
60
|
rlm@1
|
61 /*
|
rlm@1
|
62 void Normalize()
|
rlm@1
|
63 {
|
rlm@1
|
64 for (;m_BitPos >= 8; m_BitPos -= 8)
|
rlm@1
|
65 m_Value = (m_Value << 8) | m_Stream.ReadByte();
|
rlm@1
|
66 }
|
rlm@1
|
67 */
|
rlm@1
|
68
|
rlm@1
|
69 UInt32 GetValue(UInt32 numBits)
|
rlm@1
|
70 {
|
rlm@1
|
71 // return (m_Value << m_BitPos) >> (kNumBigValueBits - numBits);
|
rlm@1
|
72 // return ((m_Value >> (8 - m_BitPos)) & kMask) >> (kNumValueBits - numBits);
|
rlm@1
|
73 if (m_BitPos < numBits)
|
rlm@1
|
74 {
|
rlm@1
|
75 m_BitPos += 8;
|
rlm@1
|
76 m_Value = (m_Value << 8) | m_Stream.ReadByte();
|
rlm@1
|
77 if (m_BitPos < numBits)
|
rlm@1
|
78 {
|
rlm@1
|
79 m_BitPos += 8;
|
rlm@1
|
80 m_Value = (m_Value << 8) | m_Stream.ReadByte();
|
rlm@1
|
81 }
|
rlm@1
|
82 }
|
rlm@1
|
83 return m_Value >> (m_BitPos - numBits);
|
rlm@1
|
84 }
|
rlm@1
|
85
|
rlm@1
|
86 void MovePos(UInt32 numBits)
|
rlm@1
|
87 {
|
rlm@1
|
88 m_BitPos -= numBits;
|
rlm@1
|
89 m_Value = m_Value & ((1 << m_BitPos) - 1);
|
rlm@1
|
90 }
|
rlm@1
|
91
|
rlm@1
|
92 UInt32 ReadBits(UInt32 numBits)
|
rlm@1
|
93 {
|
rlm@1
|
94 UInt32 res = GetValue(numBits);
|
rlm@1
|
95 MovePos(numBits);
|
rlm@1
|
96 return res;
|
rlm@1
|
97 }
|
rlm@1
|
98 };
|
rlm@1
|
99
|
rlm@1
|
100 const int kNumTopBits = 24;
|
rlm@1
|
101 const UInt32 kTopValue = (1 << kNumTopBits);
|
rlm@1
|
102 const UInt32 kBot = (1 << 15);
|
rlm@1
|
103
|
rlm@1
|
104 class CRangeDecoder:public NPpmd::CRangeDecoderVirt, public CBitDecoder
|
rlm@1
|
105 {
|
rlm@1
|
106 public:
|
rlm@1
|
107 UInt32 Range;
|
rlm@1
|
108 UInt32 Low;
|
rlm@1
|
109 UInt32 Code;
|
rlm@1
|
110
|
rlm@1
|
111 void Normalize()
|
rlm@1
|
112 {
|
rlm@1
|
113 while ((Low ^ (Low + Range)) < kTopValue ||
|
rlm@1
|
114 Range < kBot && ((Range = (0 - Low) & (kBot - 1)), 1))
|
rlm@1
|
115 {
|
rlm@1
|
116 Code = (Code << 8) | m_Stream.ReadByte();
|
rlm@1
|
117 Range <<= 8;
|
rlm@1
|
118 Low <<= 8;
|
rlm@1
|
119 }
|
rlm@1
|
120 }
|
rlm@1
|
121
|
rlm@1
|
122 void InitRangeCoder()
|
rlm@1
|
123 {
|
rlm@1
|
124 Code = 0;
|
rlm@1
|
125 Low = 0;
|
rlm@1
|
126 Range = 0xFFFFFFFF;
|
rlm@1
|
127 for(int i = 0; i < 4; i++)
|
rlm@1
|
128 Code = (Code << 8) | ReadBits(8);
|
rlm@1
|
129 }
|
rlm@1
|
130
|
rlm@1
|
131 virtual UInt32 GetThreshold(UInt32 total)
|
rlm@1
|
132 {
|
rlm@1
|
133 return (Code - Low) / ( Range /= total);
|
rlm@1
|
134 }
|
rlm@1
|
135
|
rlm@1
|
136 virtual void Decode(UInt32 start, UInt32 size)
|
rlm@1
|
137 {
|
rlm@1
|
138 Low += start * Range;
|
rlm@1
|
139 Range *= size;
|
rlm@1
|
140 Normalize();
|
rlm@1
|
141 }
|
rlm@1
|
142
|
rlm@1
|
143 virtual UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
|
rlm@1
|
144 {
|
rlm@1
|
145 if (((Code - Low) / (Range >>= numTotalBits)) < size0)
|
rlm@1
|
146 {
|
rlm@1
|
147 Decode(0, size0);
|
rlm@1
|
148 return 0;
|
rlm@1
|
149 }
|
rlm@1
|
150 else
|
rlm@1
|
151 {
|
rlm@1
|
152 Decode(size0, (1 << numTotalBits) - size0);
|
rlm@1
|
153 return 1;
|
rlm@1
|
154 }
|
rlm@1
|
155 }
|
rlm@1
|
156
|
rlm@1
|
157 // UInt64 GetProcessedSizeRangeCoder() {return Stream.GetProcessedSize(); }
|
rlm@1
|
158 };
|
rlm@1
|
159
|
rlm@1
|
160
|
rlm@1
|
161 struct CFilter: public NVm::CProgram
|
rlm@1
|
162 {
|
rlm@1
|
163 CRecordVector<Byte> GlobalData;
|
rlm@1
|
164 UInt32 BlockStart;
|
rlm@1
|
165 UInt32 BlockSize;
|
rlm@1
|
166 UInt32 ExecCount;
|
rlm@1
|
167 CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {}
|
rlm@1
|
168 };
|
rlm@1
|
169
|
rlm@1
|
170 struct CTempFilter: public NVm::CProgramInitState
|
rlm@1
|
171 {
|
rlm@1
|
172 UInt32 BlockStart;
|
rlm@1
|
173 UInt32 BlockSize;
|
rlm@1
|
174 UInt32 ExecCount;
|
rlm@1
|
175 bool NextWindow;
|
rlm@1
|
176
|
rlm@1
|
177 UInt32 FilterIndex;
|
rlm@1
|
178 };
|
rlm@1
|
179
|
rlm@1
|
180 const int kNumHuffmanBits = 15;
|
rlm@1
|
181
|
rlm@1
|
182 class CDecoder:
|
rlm@1
|
183 public ICompressCoder,
|
rlm@1
|
184 public ICompressSetDecoderProperties2,
|
rlm@1
|
185 public CMyUnknownImp
|
rlm@1
|
186 {
|
rlm@1
|
187 CRangeDecoder m_InBitStream;
|
rlm@1
|
188 Byte *_window;
|
rlm@1
|
189 UInt32 _winPos;
|
rlm@1
|
190 UInt32 _wrPtr;
|
rlm@1
|
191 UInt64 _lzSize;
|
rlm@1
|
192 UInt64 _unpackSize;
|
rlm@1
|
193 UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written
|
rlm@1
|
194 CMyComPtr<ISequentialOutStream> _outStream;
|
rlm@1
|
195 NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize> m_MainDecoder;
|
rlm@1
|
196 NHuffman::CDecoder<kNumHuffmanBits, kDistTableSize> m_DistDecoder;
|
rlm@1
|
197 NHuffman::CDecoder<kNumHuffmanBits, kAlignTableSize> m_AlignDecoder;
|
rlm@1
|
198 NHuffman::CDecoder<kNumHuffmanBits, kLenTableSize> m_LenDecoder;
|
rlm@1
|
199 NHuffman::CDecoder<kNumHuffmanBits, kLevelTableSize> m_LevelDecoder;
|
rlm@1
|
200
|
rlm@1
|
201 UInt32 _reps[kNumReps];
|
rlm@1
|
202 UInt32 _lastLength;
|
rlm@1
|
203
|
rlm@1
|
204 Byte m_LastLevels[kTablesSizesSum];
|
rlm@1
|
205
|
rlm@1
|
206 Byte *_vmData;
|
rlm@1
|
207 Byte *_vmCode;
|
rlm@1
|
208 NVm::CVm _vm;
|
rlm@1
|
209 CRecordVector<CFilter *> _filters;
|
rlm@1
|
210 CRecordVector<CTempFilter *> _tempFilters;
|
rlm@1
|
211 UInt32 _lastFilter;
|
rlm@1
|
212
|
rlm@1
|
213 bool m_IsSolid;
|
rlm@1
|
214
|
rlm@1
|
215 bool _lzMode;
|
rlm@1
|
216
|
rlm@1
|
217 UInt32 PrevAlignBits;
|
rlm@1
|
218 UInt32 PrevAlignCount;
|
rlm@1
|
219
|
rlm@1
|
220 bool TablesRead;
|
rlm@1
|
221
|
rlm@1
|
222 NPpmd::CDecodeInfo _ppm;
|
rlm@1
|
223 int PpmEscChar;
|
rlm@1
|
224
|
rlm@1
|
225 HRESULT WriteDataToStream(const Byte *data, UInt32 size);
|
rlm@1
|
226 HRESULT WriteData(const Byte *data, UInt32 size);
|
rlm@1
|
227 HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);
|
rlm@1
|
228 void ExecuteFilter(int tempFilterIndex, NVm::CBlockRef &outBlockRef);
|
rlm@1
|
229 HRESULT WriteBuf();
|
rlm@1
|
230
|
rlm@1
|
231 void InitFilters();
|
rlm@1
|
232 bool AddVmCode(UInt32 firstByte, UInt32 codeSize);
|
rlm@1
|
233 bool ReadVmCodeLZ();
|
rlm@1
|
234 bool ReadVmCodePPM();
|
rlm@1
|
235
|
rlm@1
|
236 UInt32 ReadBits(int numBits);
|
rlm@1
|
237
|
rlm@1
|
238 HRESULT InitPPM();
|
rlm@1
|
239 int DecodePpmSymbol();
|
rlm@1
|
240 HRESULT DecodePPM(Int32 num, bool &keepDecompressing);
|
rlm@1
|
241
|
rlm@1
|
242 HRESULT ReadTables(bool &keepDecompressing);
|
rlm@1
|
243 HRESULT ReadEndOfBlock(bool &keepDecompressing);
|
rlm@1
|
244 HRESULT DecodeLZ(bool &keepDecompressing);
|
rlm@1
|
245 HRESULT CodeReal(ICompressProgressInfo *progress);
|
rlm@1
|
246 public:
|
rlm@1
|
247 CDecoder();
|
rlm@1
|
248 ~CDecoder();
|
rlm@1
|
249
|
rlm@1
|
250 MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
|
rlm@1
|
251
|
rlm@1
|
252 void ReleaseStreams()
|
rlm@1
|
253 {
|
rlm@1
|
254 _outStream.Release();
|
rlm@1
|
255 m_InBitStream.ReleaseStream();
|
rlm@1
|
256 }
|
rlm@1
|
257
|
rlm@1
|
258 STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
rlm@1
|
259 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
rlm@1
|
260
|
rlm@1
|
261 STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
rlm@1
|
262
|
rlm@1
|
263 void CopyBlock(UInt32 distance, UInt32 len)
|
rlm@1
|
264 {
|
rlm@1
|
265 _lzSize += len;
|
rlm@1
|
266 UInt32 pos = (_winPos - distance - 1) & kWindowMask;
|
rlm@1
|
267 Byte *window = _window;
|
rlm@1
|
268 UInt32 winPos = _winPos;
|
rlm@1
|
269 if (kWindowSize - winPos > len && kWindowSize - pos > len)
|
rlm@1
|
270 {
|
rlm@1
|
271 const Byte *src = window + pos;
|
rlm@1
|
272 Byte *dest = window + winPos;
|
rlm@1
|
273 _winPos += len;
|
rlm@1
|
274 do
|
rlm@1
|
275 *dest++ = *src++;
|
rlm@1
|
276 while(--len != 0);
|
rlm@1
|
277 return;
|
rlm@1
|
278 }
|
rlm@1
|
279 do
|
rlm@1
|
280 {
|
rlm@1
|
281 window[winPos] = window[pos];
|
rlm@1
|
282 winPos = (winPos + 1) & kWindowMask;
|
rlm@1
|
283 pos = (pos + 1) & kWindowMask;
|
rlm@1
|
284 }
|
rlm@1
|
285 while(--len != 0);
|
rlm@1
|
286 _winPos = winPos;
|
rlm@1
|
287 }
|
rlm@1
|
288
|
rlm@1
|
289 void PutByte(Byte b)
|
rlm@1
|
290 {
|
rlm@1
|
291 _window[_winPos] = b;
|
rlm@1
|
292 _winPos = (_winPos + 1) & kWindowMask;
|
rlm@1
|
293 _lzSize++;
|
rlm@1
|
294 }
|
rlm@1
|
295
|
rlm@1
|
296
|
rlm@1
|
297 };
|
rlm@1
|
298
|
rlm@1
|
299 }}
|
rlm@1
|
300
|
rlm@1
|
301 #endif
|