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 
CBlockPropsCBlockProps41   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 
InitBitDecoderCBitDecoder52   void InitBitDecoder()
53   {
54     _numBits = 0;
55     _value = 0;
56   }
57 
AlignToByteCBitDecoder58   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 
CBitDecoderCBitDecoder77   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 
CBaseCBase141   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 
InitNumStreams2CBase153   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 
Finished()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 
WaitScout()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:
CWaitScout_Releaser(CDecoder * decoder)284     CWaitScout_Releaser(CDecoder *decoder): _decoder(decoder) {}
~CWaitScout_Releaser()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 
GetCrcError()299   bool GetCrcError() const { return BlockCrcError || Base.StreamCrcError; }
300 
301   void InitOutSize(const UInt64 *outSize);
302 
303   bool CreateInputBufer();
304 
InitInputBuffer()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 
GetInputProcessedSize()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 
GetInStreamSize()321   UInt64 GetInStreamSize() const
322   {
323     return _inProcessed + (size_t)(Base._buf - _inBuf) - (Base._numBits >> 3);
324   }
325 
GetOutProcessedSize()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 
GetNumStreams()368   UInt64 GetNumStreams() const { return Base.NumStreams; }
GetNumBlocks()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
403