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