1 // Rar2Decoder.cpp
2 // According to unRAR license, this code may not be used to develop
3 // a program that creates RAR archives
4
5 #include "StdAfx.h"
6
7 #include <stdlib.h>
8
9 #include "Rar2Decoder.h"
10
11 namespace NCompress {
12 namespace NRar2 {
13
14 namespace NMultimedia {
15
Decode(int & channelDelta,Byte deltaByte)16 Byte CFilter::Decode(int &channelDelta, Byte deltaByte)
17 {
18 D4 = D3;
19 D3 = D2;
20 D2 = LastDelta - D1;
21 D1 = LastDelta;
22 int predictedValue = ((8 * LastChar + K1 * D1 + K2 * D2 + K3 * D3 + K4 * D4 + K5 * channelDelta) >> 3);
23
24 Byte realValue = (Byte)(predictedValue - deltaByte);
25
26 {
27 int i = ((int)(signed char)deltaByte) << 3;
28
29 Dif[0] += abs(i);
30 Dif[1] += abs(i - D1);
31 Dif[2] += abs(i + D1);
32 Dif[3] += abs(i - D2);
33 Dif[4] += abs(i + D2);
34 Dif[5] += abs(i - D3);
35 Dif[6] += abs(i + D3);
36 Dif[7] += abs(i - D4);
37 Dif[8] += abs(i + D4);
38 Dif[9] += abs(i - channelDelta);
39 Dif[10] += abs(i + channelDelta);
40 }
41
42 channelDelta = LastDelta = (signed char)(realValue - LastChar);
43 LastChar = realValue;
44
45 if (((++ByteCount) & 0x1F) == 0)
46 {
47 UInt32 minDif = Dif[0];
48 UInt32 numMinDif = 0;
49 Dif[0] = 0;
50
51 for (unsigned i = 1; i < ARRAY_SIZE(Dif); i++)
52 {
53 if (Dif[i] < minDif)
54 {
55 minDif = Dif[i];
56 numMinDif = i;
57 }
58 Dif[i] = 0;
59 }
60
61 switch (numMinDif)
62 {
63 case 1: if (K1 >= -16) K1--; break;
64 case 2: if (K1 < 16) K1++; break;
65 case 3: if (K2 >= -16) K2--; break;
66 case 4: if (K2 < 16) K2++; break;
67 case 5: if (K3 >= -16) K3--; break;
68 case 6: if (K3 < 16) K3++; break;
69 case 7: if (K4 >= -16) K4--; break;
70 case 8: if (K4 < 16) K4++; break;
71 case 9: if (K5 >= -16) K5--; break;
72 case 10:if (K5 < 16) K5++; break;
73 }
74 }
75
76 return realValue;
77 }
78 }
79
80 static const UInt32 kHistorySize = 1 << 20;
81
82 // static const UInt32 kWindowReservSize = (1 << 22) + 256;
83
CDecoder()84 CDecoder::CDecoder():
85 _isSolid(false),
86 _solidAllowed(false),
87 m_TablesOK(false)
88 {
89 }
90
InitStructures()91 void CDecoder::InitStructures()
92 {
93 m_MmFilter.Init();
94 for (unsigned i = 0; i < kNumRepDists; i++)
95 m_RepDists[i] = 0;
96 m_RepDistPtr = 0;
97 m_LastLength = 0;
98 memset(m_LastLevels, 0, kMaxTableSize);
99 }
100
ReadBits(unsigned numBits)101 UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InBitStream.ReadBits(numBits); }
102
103 #define RIF(x) { if (!(x)) return false; }
104
ReadTables(void)105 bool CDecoder::ReadTables(void)
106 {
107 m_TablesOK = false;
108
109 Byte levelLevels[kLevelTableSize];
110 Byte lens[kMaxTableSize];
111
112 m_AudioMode = (ReadBits(1) == 1);
113
114 if (ReadBits(1) == 0)
115 memset(m_LastLevels, 0, kMaxTableSize);
116
117 unsigned numLevels;
118
119 if (m_AudioMode)
120 {
121 m_NumChannels = ReadBits(2) + 1;
122 if (m_MmFilter.CurrentChannel >= m_NumChannels)
123 m_MmFilter.CurrentChannel = 0;
124 numLevels = m_NumChannels * kMMTableSize;
125 }
126 else
127 numLevels = kHeapTablesSizesSum;
128
129 unsigned i;
130 for (i = 0; i < kLevelTableSize; i++)
131 levelLevels[i] = (Byte)ReadBits(4);
132 RIF(m_LevelDecoder.Build(levelLevels));
133
134 i = 0;
135
136 do
137 {
138 UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream);
139 if (sym < kTableDirectLevels)
140 {
141 lens[i] = (Byte)((sym + m_LastLevels[i]) & kLevelMask);
142 i++;
143 }
144 else
145 {
146 if (sym == kTableLevelRepNumber)
147 {
148 unsigned num = ReadBits(2) + 3;
149 if (i == 0)
150 return false;
151 num += i;
152 if (num > numLevels)
153 {
154 // return false;
155 num = numLevels; // original unRAR
156 }
157 Byte v = lens[(size_t)i - 1];
158 do
159 lens[i++] = v;
160 while (i < num);
161 }
162 else
163 {
164 unsigned num;
165 if (sym == kTableLevel0Number)
166 num = ReadBits(3) + 3;
167 else if (sym == kTableLevel0Number2)
168 num = ReadBits(7) + 11;
169 else
170 return false;
171 num += i;
172 if (num > numLevels)
173 {
174 // return false;
175 num = numLevels; // original unRAR
176 }
177 do
178 lens[i++] = 0;
179 while (i < num);
180 }
181 }
182 }
183 while (i < numLevels);
184
185 if (m_InBitStream.ExtraBitsWereRead())
186 return false;
187
188 if (m_AudioMode)
189 for (i = 0; i < m_NumChannels; i++)
190 {
191 RIF(m_MMDecoders[i].Build(&lens[i * kMMTableSize]));
192 }
193 else
194 {
195 RIF(m_MainDecoder.Build(&lens[0]));
196 RIF(m_DistDecoder.Build(&lens[kMainTableSize]));
197 RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize]));
198 }
199
200 memcpy(m_LastLevels, lens, kMaxTableSize);
201
202 m_TablesOK = true;
203
204 return true;
205 }
206
ReadLastTables()207 bool CDecoder::ReadLastTables()
208 {
209 // it differs a little from pure RAR sources;
210 // UInt64 ttt = m_InBitStream.GetProcessedSize() + 2;
211 // + 2 works for: return 0xFF; in CInBuffer::ReadByte.
212 if (m_InBitStream.GetProcessedSize() + 7 <= m_PackSize) // test it: probably incorrect;
213 // if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;
214 {
215 if (m_AudioMode)
216 {
217 UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);
218 if (symbol == 256)
219 return ReadTables();
220 if (symbol >= kMMTableSize)
221 return false;
222 }
223 else
224 {
225 UInt32 sym = m_MainDecoder.Decode(&m_InBitStream);
226 if (sym == kReadTableNumber)
227 return ReadTables();
228 if (sym >= kMainTableSize)
229 return false;
230 }
231 }
232 return true;
233 }
234
235
DecodeMm(UInt32 pos)236 bool CDecoder::DecodeMm(UInt32 pos)
237 {
238 while (pos-- != 0)
239 {
240 UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);
241 if (m_InBitStream.ExtraBitsWereRead())
242 return false;
243 if (symbol >= 256)
244 return symbol == 256;
245 /*
246 Byte byPredict = m_Predictor.Predict();
247 Byte byReal = (Byte)(byPredict - (Byte)symbol);
248 m_Predictor.Update(byReal, byPredict);
249 */
250 Byte byReal = m_MmFilter.Decode((Byte)symbol);
251 m_OutWindowStream.PutByte(byReal);
252 if (++m_MmFilter.CurrentChannel == m_NumChannels)
253 m_MmFilter.CurrentChannel = 0;
254 }
255 return true;
256 }
257
DecodeLz(Int32 pos)258 bool CDecoder::DecodeLz(Int32 pos)
259 {
260 while (pos > 0)
261 {
262 UInt32 sym = m_MainDecoder.Decode(&m_InBitStream);
263 if (m_InBitStream.ExtraBitsWereRead())
264 return false;
265 UInt32 length, distance;
266 if (sym < 256)
267 {
268 m_OutWindowStream.PutByte(Byte(sym));
269 pos--;
270 continue;
271 }
272 else if (sym >= kMatchNumber)
273 {
274 if (sym >= kMainTableSize)
275 return false;
276 sym -= kMatchNumber;
277 length = kNormalMatchMinLen + UInt32(kLenStart[sym]) +
278 m_InBitStream.ReadBits(kLenDirectBits[sym]);
279 sym = m_DistDecoder.Decode(&m_InBitStream);
280 if (sym >= kDistTableSize)
281 return false;
282 distance = kDistStart[sym] + m_InBitStream.ReadBits(kDistDirectBits[sym]);
283 if (distance >= kDistLimit3)
284 {
285 length += 2 - ((distance - kDistLimit4) >> 31);
286 // length++;
287 // if (distance >= kDistLimit4)
288 // length++;
289 }
290 }
291 else if (sym == kRepBothNumber)
292 {
293 length = m_LastLength;
294 if (length == 0)
295 return false;
296 distance = m_RepDists[(m_RepDistPtr + 4 - 1) & 3];
297 }
298 else if (sym < kLen2Number)
299 {
300 distance = m_RepDists[(m_RepDistPtr - (sym - kRepNumber + 1)) & 3];
301 sym = m_LenDecoder.Decode(&m_InBitStream);
302 if (sym >= kLenTableSize)
303 return false;
304 length = 2 + kLenStart[sym] + m_InBitStream.ReadBits(kLenDirectBits[sym]);
305 if (distance >= kDistLimit2)
306 {
307 length++;
308 if (distance >= kDistLimit3)
309 {
310 length += 2 - ((distance - kDistLimit4) >> 31);
311 // length++;
312 // if (distance >= kDistLimit4)
313 // length++;
314 }
315 }
316 }
317 else if (sym < kReadTableNumber)
318 {
319 sym -= kLen2Number;
320 distance = kLen2DistStarts[sym] +
321 m_InBitStream.ReadBits(kLen2DistDirectBits[sym]);
322 length = 2;
323 }
324 else // (sym == kReadTableNumber)
325 return true;
326
327 m_RepDists[m_RepDistPtr++ & 3] = distance;
328 m_LastLength = length;
329 if (!m_OutWindowStream.CopyBlock(distance, length))
330 return false;
331 pos -= length;
332 }
333 return true;
334 }
335
CodeReal(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress)336 HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
337 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
338 {
339 if (!inSize || !outSize)
340 return E_INVALIDARG;
341
342 if (_isSolid && !_solidAllowed)
343 return S_FALSE;
344 _solidAllowed = false;
345
346 if (!m_OutWindowStream.Create(kHistorySize))
347 return E_OUTOFMEMORY;
348 if (!m_InBitStream.Create(1 << 20))
349 return E_OUTOFMEMORY;
350
351 m_PackSize = *inSize;
352
353 UInt64 pos = 0, unPackSize = *outSize;
354
355 m_OutWindowStream.SetStream(outStream);
356 m_OutWindowStream.Init(_isSolid);
357 m_InBitStream.SetStream(inStream);
358 m_InBitStream.Init();
359
360 // CCoderReleaser coderReleaser(this);
361 if (!_isSolid)
362 {
363 InitStructures();
364 if (unPackSize == 0)
365 {
366 if (m_InBitStream.GetProcessedSize() + 2 <= m_PackSize) // test it: probably incorrect;
367 if (!ReadTables())
368 return S_FALSE;
369 _solidAllowed = true;
370 return S_OK;
371 }
372 ReadTables();
373 }
374
375 if (!m_TablesOK)
376 return S_FALSE;
377
378 UInt64 startPos = m_OutWindowStream.GetProcessedSize();
379 while (pos < unPackSize)
380 {
381 UInt32 blockSize = 1 << 20;
382 if (blockSize > unPackSize - pos)
383 blockSize = (UInt32)(unPackSize - pos);
384 UInt64 blockStartPos = m_OutWindowStream.GetProcessedSize();
385 if (m_AudioMode)
386 {
387 if (!DecodeMm(blockSize))
388 return S_FALSE;
389 }
390 else
391 {
392 if (!DecodeLz((Int32)blockSize))
393 return S_FALSE;
394 }
395
396 if (m_InBitStream.ExtraBitsWereRead())
397 return S_FALSE;
398
399 UInt64 globalPos = m_OutWindowStream.GetProcessedSize();
400 pos = globalPos - blockStartPos;
401 if (pos < blockSize)
402 if (!ReadTables())
403 return S_FALSE;
404 pos = globalPos - startPos;
405 if (progress)
406 {
407 const UInt64 packSize = m_InBitStream.GetProcessedSize();
408 RINOK(progress->SetRatioInfo(&packSize, &pos));
409 }
410 }
411 if (pos > unPackSize)
412 return S_FALSE;
413
414 if (!ReadLastTables())
415 return S_FALSE;
416
417 _solidAllowed = true;
418
419 return m_OutWindowStream.Flush();
420 }
421
Code(ISequentialInStream * inStream,ISequentialOutStream * outStream,const UInt64 * inSize,const UInt64 * outSize,ICompressProgressInfo * progress)422 STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
423 const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
424 {
425 try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
426 catch(const CInBufferException &e) { return e.ErrorCode; }
427 catch(const CLzOutWindowException &e) { return e.ErrorCode; }
428 catch(...) { return S_FALSE; }
429 }
430
SetDecoderProperties2(const Byte * data,UInt32 size)431 STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size)
432 {
433 if (size < 1)
434 return E_INVALIDARG;
435 _isSolid = ((data[0] & 1) != 0);
436 return S_OK;
437 }
438
439 }}
440