// Compress/BZip2Decoder.h #ifndef __COMPRESS_BZIP2_DECODER_H #define __COMPRESS_BZIP2_DECODER_H #include "../../Common/MyCom.h" #ifndef _7ZIP_ST #include "../../Windows/Synchronization.h" #include "../../Windows/Thread.h" #endif #include "../ICoder.h" #include "../Common/InBuffer.h" #include "../Common/OutBuffer.h" #include "BitmDecoder.h" #include "BZip2Const.h" #include "BZip2Crc.h" #include "HuffmanDecoder.h" namespace NCompress { namespace NBZip2 { typedef NCompress::NHuffman::CDecoder CHuffmanDecoder; class CDecoder; struct CState { UInt32 *Counters; #ifndef _7ZIP_ST CDecoder *Decoder; NWindows::CThread Thread; bool m_OptimizeNumTables; NWindows::NSynchronization::CAutoResetEvent StreamWasFinishedEvent; NWindows::NSynchronization::CAutoResetEvent WaitingWasStartedEvent; // it's not member of this thread. We just need one event per thread NWindows::NSynchronization::CAutoResetEvent CanWriteEvent; Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. HRESULT Create(); void FinishStream(); void ThreadFunc(); #endif CState(): Counters(0) {} ~CState() { Free(); } bool Alloc(); void Free(); }; class CDecoder : public ICompressCoder, #ifndef _7ZIP_ST public ICompressSetCoderMt, #endif public CMyUnknownImp { public: COutBuffer m_OutStream; Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. NBitm::CDecoder m_InStream; Byte m_Selectors[kNumSelectorsMax]; CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; UInt64 _inStart; private: bool _needInStreamInit; UInt32 ReadBits(unsigned numBits); Byte ReadByte(); bool ReadBit(); UInt32 ReadCrc(); HRESULT DecodeFile(bool &isBZ, ICompressProgressInfo *progress); HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress); class CDecoderFlusher { CDecoder *_decoder; public: bool NeedFlush; bool ReleaseInStream; CDecoderFlusher(CDecoder *decoder, bool releaseInStream): _decoder(decoder), NeedFlush(true), ReleaseInStream(releaseInStream) {} // PQR for MinGW-w64: Initialization order. ~CDecoderFlusher() { if (NeedFlush) _decoder->Flush(); _decoder->ReleaseStreams(ReleaseInStream); } }; public: CBZip2CombinedCrc CombinedCrc; ICompressProgressInfo *Progress; #ifndef _7ZIP_ST CState *m_States; UInt32 m_NumThreadsPrev; NWindows::NSynchronization::CManualResetEvent CanProcessEvent; NWindows::NSynchronization::CCriticalSection CS; UInt32 NumThreads; bool MtMode; UInt32 NextBlockIndex; bool CloseThreads; bool StreamWasFinished1; bool StreamWasFinished2; NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; HRESULT Result1; HRESULT Result2; UInt32 BlockSizeMax; ~CDecoder(); HRESULT Create(); void Free(); #else CState m_States[1]; #endif CDecoder(); HRESULT SetRatioProgress(UInt64 packSize); HRESULT ReadSignatures(bool &wasFinished, UInt32 &crc); HRESULT Flush() { return m_OutStream.Flush(); } void ReleaseStreams(bool releaseInStream) { if (releaseInStream) m_InStream.ReleaseStream(); m_OutStream.ReleaseStream(); } MY_QUERYINTERFACE_BEGIN2(ICompressCoder) #ifndef _7ZIP_ST MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt) #endif MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); HRESULT CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress); UInt64 GetInputProcessedSize() const { return m_InStream.GetProcessedSize(); } #ifndef _7ZIP_ST STDMETHOD(SetNumberOfThreads)(UInt32 numThreads); #endif }; class CNsisDecoder : public ISequentialInStream, public ICompressSetInStream, public ICompressSetOutStreamSize, public CMyUnknownImp { NBitm::CDecoder m_InStream; Byte m_Selectors[kNumSelectorsMax]; CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax]; CState m_State; int _nsisState; UInt32 _tPos; unsigned _prevByte; unsigned _repRem; unsigned _numReps; UInt32 _blockSize; public: MY_QUERYINTERFACE_BEGIN2(ISequentialInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetInStream) MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize) MY_QUERYINTERFACE_END MY_ADDREF_RELEASE STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); STDMETHOD(SetInStream)(ISequentialInStream *inStream); STDMETHOD(ReleaseInStream)(); STDMETHOD(SetOutStreamSize)(const UInt64 *outSize); }; }} #endif