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