diff options
Diffstat (limited to 'CPP/7zip/Compress/BZip2Decoder.h')
-rw-r--r-- | CPP/7zip/Compress/BZip2Decoder.h | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/CPP/7zip/Compress/BZip2Decoder.h b/CPP/7zip/Compress/BZip2Decoder.h new file mode 100644 index 0000000..8fe4ef1 --- /dev/null +++ b/CPP/7zip/Compress/BZip2Decoder.h | |||
@@ -0,0 +1,402 @@ | |||
1 | // Compress/BZip2Decoder.h | ||
2 | |||
3 | #ifndef __COMPRESS_BZIP2_DECODER_H | ||
4 | #define __COMPRESS_BZIP2_DECODER_H | ||
5 | |||
6 | #include "../../Common/MyCom.h" | ||
7 | |||
8 | // #define NO_READ_FROM_CODER | ||
9 | // #define _7ZIP_ST | ||
10 | |||
11 | #ifndef _7ZIP_ST | ||
12 | #include "../../Windows/Synchronization.h" | ||
13 | #include "../../Windows/Thread.h" | ||
14 | #endif | ||
15 | |||
16 | #include "../ICoder.h" | ||
17 | |||
18 | #include "BZip2Const.h" | ||
19 | #include "BZip2Crc.h" | ||
20 | #include "HuffmanDecoder.h" | ||
21 | #include "Mtf8.h" | ||
22 | |||
23 | namespace NCompress { | ||
24 | namespace NBZip2 { | ||
25 | |||
26 | bool IsEndSig(const Byte *p) throw(); | ||
27 | bool IsBlockSig(const Byte *p) throw(); | ||
28 | |||
29 | const unsigned kNumTableBits = 9; | ||
30 | const unsigned kNumBitsMax = kMaxHuffmanLen; | ||
31 | |||
32 | typedef NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize, kNumTableBits> CHuffmanDecoder; | ||
33 | |||
34 | |||
35 | struct CBlockProps | ||
36 | { | ||
37 | UInt32 blockSize; | ||
38 | UInt32 origPtr; | ||
39 | unsigned randMode; | ||
40 | |||
41 | CBlockProps(): blockSize(0), origPtr(0), randMode(0) {} | ||
42 | }; | ||
43 | |||
44 | |||
45 | struct CBitDecoder | ||
46 | { | ||
47 | unsigned _numBits; | ||
48 | UInt32 _value; | ||
49 | const Byte *_buf; | ||
50 | const Byte *_lim; | ||
51 | |||
52 | void InitBitDecoder() | ||
53 | { | ||
54 | _numBits = 0; | ||
55 | _value = 0; | ||
56 | } | ||
57 | |||
58 | void AlignToByte() | ||
59 | { | ||
60 | unsigned bits = _numBits & 7; | ||
61 | _numBits -= bits; | ||
62 | _value <<= bits; | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | bool AreRemainByteBitsEmpty() const | ||
67 | { | ||
68 | unsigned bits = _numBits & 7; | ||
69 | if (bits != 0) | ||
70 | return (_value >> (32 - bits)) == 0; | ||
71 | return true; | ||
72 | } | ||
73 | */ | ||
74 | |||
75 | SRes ReadByte(int &b); | ||
76 | |||
77 | CBitDecoder(): | ||
78 | _buf(NULL), | ||
79 | _lim(NULL) | ||
80 | { | ||
81 | InitBitDecoder(); | ||
82 | } | ||
83 | }; | ||
84 | |||
85 | |||
86 | // 19.03: we allow additional 8 selectors to support files created by lbzip2. | ||
87 | const UInt32 kNumSelectorsMax_Decoder = kNumSelectorsMax + 8; | ||
88 | |||
89 | struct CBase: public CBitDecoder | ||
90 | { | ||
91 | unsigned numInUse; | ||
92 | UInt32 groupIndex; | ||
93 | UInt32 groupSize; | ||
94 | unsigned runPower; | ||
95 | UInt32 runCounter; | ||
96 | UInt32 blockSize; | ||
97 | |||
98 | UInt32 *Counters; | ||
99 | UInt32 blockSizeMax; | ||
100 | |||
101 | unsigned state; | ||
102 | unsigned state2; | ||
103 | unsigned state3; | ||
104 | unsigned state4; | ||
105 | unsigned state5; | ||
106 | unsigned numTables; | ||
107 | UInt32 numSelectors; | ||
108 | |||
109 | CBlockProps Props; | ||
110 | |||
111 | private: | ||
112 | CMtf8Decoder mtf; | ||
113 | Byte selectors[kNumSelectorsMax_Decoder]; | ||
114 | CHuffmanDecoder huffs[kNumTablesMax]; | ||
115 | |||
116 | Byte lens[kMaxAlphaSize]; | ||
117 | |||
118 | Byte temp[10]; | ||
119 | |||
120 | public: | ||
121 | UInt32 crc; | ||
122 | CBZip2CombinedCrc CombinedCrc; | ||
123 | |||
124 | bool IsBz; | ||
125 | bool StreamCrcError; | ||
126 | bool MinorError; | ||
127 | bool NeedMoreInput; | ||
128 | |||
129 | bool DecodeAllStreams; | ||
130 | |||
131 | UInt64 NumStreams; | ||
132 | UInt64 NumBlocks; | ||
133 | UInt64 FinishedPackSize; | ||
134 | |||
135 | ISequentialInStream *InStream; | ||
136 | |||
137 | #ifndef NO_READ_FROM_CODER | ||
138 | CMyComPtr<ISequentialInStream> InStreamRef; | ||
139 | #endif | ||
140 | |||
141 | CBase(): | ||
142 | StreamCrcError(false), | ||
143 | MinorError(false), | ||
144 | NeedMoreInput(false), | ||
145 | |||
146 | DecodeAllStreams(false), | ||
147 | |||
148 | NumStreams(0), | ||
149 | NumBlocks(0), | ||
150 | FinishedPackSize(0) | ||
151 | {} | ||
152 | |||
153 | void InitNumStreams2() | ||
154 | { | ||
155 | StreamCrcError = false; | ||
156 | MinorError = false; | ||
157 | NeedMoreInput = 0; | ||
158 | NumStreams = 0; | ||
159 | NumBlocks = 0; | ||
160 | FinishedPackSize = 0; | ||
161 | } | ||
162 | |||
163 | SRes ReadStreamSignature2(); | ||
164 | SRes ReadBlockSignature2(); | ||
165 | |||
166 | /* ReadBlock2() : Props->randMode: | ||
167 | in: need read randMode bit | ||
168 | out: randMode status */ | ||
169 | SRes ReadBlock2(); | ||
170 | }; | ||
171 | |||
172 | |||
173 | class CSpecState | ||
174 | { | ||
175 | UInt32 _tPos; | ||
176 | unsigned _prevByte; | ||
177 | int _reps; | ||
178 | |||
179 | public: | ||
180 | CBZip2Crc _crc; | ||
181 | UInt32 _blockSize; | ||
182 | UInt32 *_tt; | ||
183 | |||
184 | int _randToGo; | ||
185 | unsigned _randIndex; | ||
186 | |||
187 | void Init(UInt32 origPtr, unsigned randMode) throw(); | ||
188 | |||
189 | bool Finished() const { return _reps <= 0 && _blockSize == 0; } | ||
190 | |||
191 | Byte *Decode(Byte *data, size_t size) throw(); | ||
192 | }; | ||
193 | |||
194 | |||
195 | |||
196 | |||
197 | class CDecoder : | ||
198 | public ICompressCoder, | ||
199 | public ICompressSetFinishMode, | ||
200 | public ICompressGetInStreamProcessedSize, | ||
201 | public ICompressReadUnusedFromInBuf, | ||
202 | |||
203 | #ifndef NO_READ_FROM_CODER | ||
204 | public ICompressSetInStream, | ||
205 | public ICompressSetOutStreamSize, | ||
206 | public ISequentialInStream, | ||
207 | #endif | ||
208 | |||
209 | #ifndef _7ZIP_ST | ||
210 | public ICompressSetCoderMt, | ||
211 | #endif | ||
212 | |||
213 | public CMyUnknownImp | ||
214 | { | ||
215 | Byte *_outBuf; | ||
216 | size_t _outPos; | ||
217 | UInt64 _outWritten; | ||
218 | ISequentialOutStream *_outStream; | ||
219 | HRESULT _writeRes; | ||
220 | |||
221 | protected: | ||
222 | HRESULT ErrorResult; // for ISequentialInStream::Read mode only | ||
223 | |||
224 | public: | ||
225 | |||
226 | UInt32 _calcedBlockCrc; | ||
227 | bool _blockFinished; | ||
228 | bool BlockCrcError; | ||
229 | |||
230 | bool FinishMode; | ||
231 | bool _outSizeDefined; | ||
232 | UInt64 _outSize; | ||
233 | UInt64 _outPosTotal; | ||
234 | |||
235 | CSpecState _spec; | ||
236 | UInt32 *_counters; | ||
237 | |||
238 | #ifndef _7ZIP_ST | ||
239 | |||
240 | struct CBlock | ||
241 | { | ||
242 | bool StopScout; | ||
243 | |||
244 | bool WasFinished; | ||
245 | bool Crc_Defined; | ||
246 | // bool NextCrc_Defined; | ||
247 | |||
248 | UInt32 Crc; | ||
249 | UInt32 NextCrc; | ||
250 | HRESULT Res; | ||
251 | UInt64 PackPos; | ||
252 | |||
253 | CBlockProps Props; | ||
254 | }; | ||
255 | |||
256 | CBlock _block; | ||
257 | |||
258 | bool NeedWaitScout; | ||
259 | bool MtMode; | ||
260 | |||
261 | NWindows::CThread Thread; | ||
262 | NWindows::NSynchronization::CAutoResetEvent DecoderEvent; | ||
263 | NWindows::NSynchronization::CAutoResetEvent ScoutEvent; | ||
264 | // HRESULT ScoutRes; | ||
265 | |||
266 | Byte MtPad[1 << 7]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. | ||
267 | |||
268 | |||
269 | void RunScout(); | ||
270 | |||
271 | void WaitScout() | ||
272 | { | ||
273 | if (NeedWaitScout) | ||
274 | { | ||
275 | DecoderEvent.Lock(); | ||
276 | NeedWaitScout = false; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | class CWaitScout_Releaser | ||
281 | { | ||
282 | CDecoder *_decoder; | ||
283 | public: | ||
284 | CWaitScout_Releaser(CDecoder *decoder): _decoder(decoder) {} | ||
285 | ~CWaitScout_Releaser() { _decoder->WaitScout(); } | ||
286 | }; | ||
287 | |||
288 | HRESULT CreateThread(); | ||
289 | |||
290 | #endif | ||
291 | |||
292 | Byte *_inBuf; | ||
293 | UInt64 _inProcessed; | ||
294 | bool _inputFinished; | ||
295 | HRESULT _inputRes; | ||
296 | |||
297 | CBase Base; | ||
298 | |||
299 | bool GetCrcError() const { return BlockCrcError || Base.StreamCrcError; } | ||
300 | |||
301 | void InitOutSize(const UInt64 *outSize); | ||
302 | |||
303 | bool CreateInputBufer(); | ||
304 | |||
305 | void InitInputBuffer() | ||
306 | { | ||
307 | // We use InitInputBuffer() before stream init. | ||
308 | // So don't read from stream here | ||
309 | _inProcessed = 0; | ||
310 | Base._buf = _inBuf; | ||
311 | Base._lim = _inBuf; | ||
312 | Base.InitBitDecoder(); | ||
313 | } | ||
314 | |||
315 | UInt64 GetInputProcessedSize() const | ||
316 | { | ||
317 | // for NSIS case : we need also look the number of bits in bitDecoder | ||
318 | return _inProcessed + (size_t)(Base._buf - _inBuf); | ||
319 | } | ||
320 | |||
321 | UInt64 GetInStreamSize() const | ||
322 | { | ||
323 | return _inProcessed + (size_t)(Base._buf - _inBuf) - (Base._numBits >> 3); | ||
324 | } | ||
325 | |||
326 | UInt64 GetOutProcessedSize() const { return _outWritten + _outPos; } | ||
327 | |||
328 | HRESULT ReadInput(); | ||
329 | |||
330 | void StartNewStream(); | ||
331 | |||
332 | HRESULT ReadStreamSignature(); | ||
333 | HRESULT StartRead(); | ||
334 | |||
335 | HRESULT ReadBlockSignature(); | ||
336 | HRESULT ReadBlock(); | ||
337 | |||
338 | HRESULT Flush(); | ||
339 | HRESULT DecodeBlock(const CBlockProps &props); | ||
340 | HRESULT DecodeStreams(ICompressProgressInfo *progress); | ||
341 | |||
342 | MY_QUERYINTERFACE_BEGIN2(ICompressCoder) | ||
343 | MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode) | ||
344 | MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize) | ||
345 | MY_QUERYINTERFACE_ENTRY(ICompressReadUnusedFromInBuf) | ||
346 | |||
347 | #ifndef NO_READ_FROM_CODER | ||
348 | MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) | ||
349 | MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) | ||
350 | MY_QUERYINTERFACE_ENTRY(ISequentialInStream) | ||
351 | #endif | ||
352 | |||
353 | #ifndef _7ZIP_ST | ||
354 | MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) | ||
355 | #endif | ||
356 | |||
357 | MY_QUERYINTERFACE_END | ||
358 | MY_ADDREF_RELEASE | ||
359 | |||
360 | |||
361 | STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, | ||
362 | const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); | ||
363 | |||
364 | STDMETHOD(SetFinishMode)(UInt32 finishMode); | ||
365 | STDMETHOD(GetInStreamProcessedSize)(UInt64 *value); | ||
366 | STDMETHOD(ReadUnusedFromInBuf)(void *data, UInt32 size, UInt32 *processedSize); | ||
367 | |||
368 | UInt64 GetNumStreams() const { return Base.NumStreams; } | ||
369 | UInt64 GetNumBlocks() const { return Base.NumBlocks; } | ||
370 | |||
371 | #ifndef NO_READ_FROM_CODER | ||
372 | |||
373 | STDMETHOD(SetInStream)(ISequentialInStream *inStream); | ||
374 | STDMETHOD(ReleaseInStream)(); | ||
375 | STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); | ||
376 | STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); | ||
377 | |||
378 | #endif | ||
379 | |||
380 | #ifndef _7ZIP_ST | ||
381 | STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); | ||
382 | #endif | ||
383 | |||
384 | CDecoder(); | ||
385 | ~CDecoder(); | ||
386 | }; | ||
387 | |||
388 | |||
389 | |||
390 | #ifndef NO_READ_FROM_CODER | ||
391 | |||
392 | class CNsisDecoder : public CDecoder | ||
393 | { | ||
394 | public: | ||
395 | STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); | ||
396 | }; | ||
397 | |||
398 | #endif | ||
399 | |||
400 | }} | ||
401 | |||
402 | #endif | ||