xref: /aosp_15_r20/external/lzma/CPP/7zip/Compress/Rar3Decoder.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1 // Rar3Decoder.h
2 // According to unRAR license, this code may not be used to develop
3 // a program that creates RAR archives
4 
5 /* This code uses Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
6 
7 #ifndef ZIP7_INC_COMPRESS_RAR3_DECODER_H
8 #define ZIP7_INC_COMPRESS_RAR3_DECODER_H
9 
10 #include "../../../C/Ppmd7.h"
11 
12 #include "../../Common/MyCom.h"
13 
14 #include "../ICoder.h"
15 
16 #include "../Common/InBuffer.h"
17 
18 #include "BitmDecoder.h"
19 #include "HuffmanDecoder.h"
20 #include "Rar3Vm.h"
21 
22 namespace NCompress {
23 namespace NRar3 {
24 
25 const unsigned kNumHuffmanBits = 15;
26 
27 const UInt32 kWindowSize = 1 << 22;
28 const UInt32 kWindowMask = kWindowSize - 1;
29 
30 const unsigned kNumReps = 4;
31 const unsigned kNumLen2Symbols = 8;
32 const unsigned kLenTableSize = 28;
33 const unsigned kMainTableSize = 256 + 3 + kNumReps + kNumLen2Symbols + kLenTableSize;
34 const unsigned kDistTableSize = 60;
35 
36 const unsigned kNumAlignBits = 4;
37 const unsigned kAlignTableSize = (1 << kNumAlignBits) + 1;
38 
39 const unsigned kTablesSizesSum = kMainTableSize + kDistTableSize + kAlignTableSize + kLenTableSize;
40 
41 class CBitDecoder
42 {
43   UInt32 _value;
44   unsigned _bitPos;
45 public:
46   CInBuffer Stream;
47 
Create(UInt32 bufSize)48   bool Create(UInt32 bufSize) { return Stream.Create(bufSize); }
SetStream(ISequentialInStream * inStream)49   void SetStream(ISequentialInStream *inStream) { Stream.SetStream(inStream);}
50 
Init()51   void Init()
52   {
53     Stream.Init();
54     _bitPos = 0;
55     _value = 0;
56   }
57 
ExtraBitsWereRead()58   bool ExtraBitsWereRead() const
59   {
60     return (Stream.NumExtraBytes > 4 || _bitPos < (Stream.NumExtraBytes << 3));
61   }
62 
GetProcessedSize()63   UInt64 GetProcessedSize() const { return Stream.GetProcessedSize() - (_bitPos >> 3); }
64 
AlignToByte()65   void AlignToByte()
66   {
67     _bitPos &= ~(unsigned)7;
68     _value = _value & ((1 << _bitPos) - 1);
69   }
70 
71   Z7_FORCE_INLINE
GetValue(unsigned numBits)72   UInt32 GetValue(unsigned numBits)
73   {
74     if (_bitPos < numBits)
75     {
76       _bitPos += 8;
77       _value = (_value << 8) | Stream.ReadByte();
78       if (_bitPos < numBits)
79       {
80         _bitPos += 8;
81         _value = (_value << 8) | Stream.ReadByte();
82       }
83     }
84     return _value >> (_bitPos - numBits);
85   }
86 
87   Z7_FORCE_INLINE
GetValue_InHigh32bits()88   UInt32 GetValue_InHigh32bits()
89   {
90     return GetValue(kNumHuffmanBits) << (32 - kNumHuffmanBits);
91   }
92 
93 
94   Z7_FORCE_INLINE
MovePos(unsigned numBits)95   void MovePos(unsigned numBits)
96   {
97     _bitPos -= numBits;
98     _value = _value & ((1 << _bitPos) - 1);
99   }
100 
ReadBits(unsigned numBits)101   UInt32 ReadBits(unsigned numBits)
102   {
103     const UInt32 res = GetValue(numBits);
104     MovePos(numBits);
105     return res;
106   }
107 
ReadBits_upto8(unsigned numBits)108   UInt32 ReadBits_upto8(unsigned numBits)
109   {
110     if (_bitPos < numBits)
111     {
112       _bitPos += 8;
113       _value = (_value << 8) | Stream.ReadByte();
114     }
115     _bitPos -= numBits;
116     const UInt32 res = _value >> _bitPos;
117     _value = _value & ((1 << _bitPos) - 1);
118     return res;
119   }
120 
ReadByteFromAligned()121   Byte ReadByteFromAligned()
122   {
123     if (_bitPos == 0)
124       return Stream.ReadByte();
125     const unsigned bitsPos = _bitPos - 8;
126     const Byte b = (Byte)(_value >> bitsPos);
127     _value = _value & ((1 << bitsPos) - 1);
128     _bitPos = bitsPos;
129     return b;
130   }
131 };
132 
133 
134 struct CByteIn
135 {
136   IByteIn IByteIn_obj;
137   CBitDecoder BitDecoder;
138 };
139 
140 
141 struct CFilter: public NVm::CProgram
142 {
143   CRecordVector<Byte> GlobalData;
144   UInt32 BlockStart;
145   UInt32 BlockSize;
146   UInt32 ExecCount;
147 
CFilterCFilter148   CFilter(): BlockStart(0), BlockSize(0), ExecCount(0) {}
149 };
150 
151 struct CTempFilter: public NVm::CProgramInitState
152 {
153   UInt32 BlockStart;
154   UInt32 BlockSize;
155   bool NextWindow;
156 
157   UInt32 FilterIndex;
158 
CTempFilterCTempFilter159   CTempFilter()
160   {
161     // all filters must contain at least FixedGlobal block
162     AllocateEmptyFixedGlobal();
163   }
164 };
165 
166 
167 Z7_CLASS_IMP_NOQIB_2(
168   CDecoder
169   , ICompressCoder
170   , ICompressSetDecoderProperties2
171 )
172   bool _isSolid;
173   bool _solidAllowed;
174   // bool _errorMode;
175 
176   bool _lzMode;
177   bool _unsupportedFilter;
178 
179   CByteIn m_InBitStream;
180   Byte *_window;
181   UInt32 _winPos;
182   UInt32 _wrPtr;
183   UInt64 _lzSize;
184   UInt64 _unpackSize;
185   UInt64 _writtenFileSize; // if it's > _unpackSize, then _unpackSize only written
186   ISequentialOutStream *_outStream;
187 
188   NHuffman::CDecoder<kNumHuffmanBits, kMainTableSize, 9> m_MainDecoder;
189   UInt32 kDistStart[kDistTableSize];
190   NHuffman::CDecoder256<kNumHuffmanBits, kDistTableSize, 7> m_DistDecoder;
191   NHuffman::CDecoder256<kNumHuffmanBits, kAlignTableSize, 6> m_AlignDecoder;
192   NHuffman::CDecoder256<kNumHuffmanBits, kLenTableSize, 7> m_LenDecoder;
193 
194   UInt32 _reps[kNumReps];
195   UInt32 _lastLength;
196 
197   Byte m_LastLevels[kTablesSizesSum];
198 
199   Byte *_vmData;
200   Byte *_vmCode;
201   NVm::CVm _vm;
202   CRecordVector<CFilter *> _filters;
203   CRecordVector<CTempFilter *>  _tempFilters;
204   unsigned _numEmptyTempFilters;
205   UInt32 _lastFilter;
206 
207   UInt32 PrevAlignBits;
208   UInt32 PrevAlignCount;
209 
210   bool TablesRead;
211   bool TablesOK;
212   bool PpmError;
213 
214   int PpmEscChar;
215   CPpmd7 _ppmd;
216 
217   HRESULT WriteDataToStream(const Byte *data, UInt32 size);
218   HRESULT WriteData(const Byte *data, UInt32 size);
219   HRESULT WriteArea(UInt32 startPtr, UInt32 endPtr);
220   void ExecuteFilter(unsigned tempFilterIndex, NVm::CBlockRef &outBlockRef);
221   HRESULT WriteBuf();
222 
223   void InitFilters();
224   bool AddVmCode(UInt32 firstByte, UInt32 codeSize);
225   bool ReadVmCodeLZ();
226   bool ReadVmCodePPM();
227 
228   UInt32 ReadBits(unsigned numBits);
229 
230   HRESULT InitPPM();
231   // int DecodePpmSymbol();
232   HRESULT DecodePPM(Int32 num, bool &keepDecompressing);
233 
234   HRESULT ReadTables(bool &keepDecompressing);
235   HRESULT ReadEndOfBlock(bool &keepDecompressing);
236   HRESULT DecodeLZ(bool &keepDecompressing);
237   HRESULT CodeReal(ICompressProgressInfo *progress);
238 
InputEofError()239   bool InputEofError() const { return m_InBitStream.BitDecoder.ExtraBitsWereRead(); }
InputEofError_Fast()240   bool InputEofError_Fast() const { return (m_InBitStream.BitDecoder.Stream.NumExtraBytes > 2); }
241 
CopyBlock(UInt32 dist,UInt32 len)242   void CopyBlock(UInt32 dist, UInt32 len)
243   {
244     _lzSize += len;
245     UInt32 pos = (_winPos - dist - 1) & kWindowMask;
246     Byte *window = _window;
247     UInt32 winPos = _winPos;
248     if (kWindowSize - winPos > len && kWindowSize - pos > len)
249     {
250       const Byte *src = window + pos;
251       Byte *dest = window + winPos;
252       _winPos += len;
253       do
254         *dest++ = *src++;
255       while (--len != 0);
256       return;
257     }
258     do
259     {
260       window[winPos] = window[pos];
261       winPos = (winPos + 1) & kWindowMask;
262       pos = (pos + 1) & kWindowMask;
263     }
264     while (--len != 0);
265     _winPos = winPos;
266   }
267 
PutByte(Byte b)268   void PutByte(Byte b)
269   {
270     const UInt32 wp = _winPos;
271     _window[wp] = b;
272     _winPos = (wp + 1) & kWindowMask;
273     _lzSize++;
274   }
275 
276 public:
277   CDecoder();
278   ~CDecoder();
279 };
280 
281 }}
282 
283 #endif
284