| // BZip2Encoder.h |
| |
| #ifndef ZIP7_INC_COMPRESS_BZIP2_ENCODER_H |
| #define ZIP7_INC_COMPRESS_BZIP2_ENCODER_H |
| |
| #include "../../Common/MyCom.h" |
| |
| #ifndef Z7_ST |
| #include "../../Windows/Synchronization.h" |
| #include "../../Windows/Thread.h" |
| #endif |
| |
| #include "../ICoder.h" |
| |
| #include "../Common/InBuffer.h" |
| #include "../Common/OutBuffer.h" |
| |
| #include "BitmEncoder.h" |
| #include "BZip2Const.h" |
| #include "BZip2Crc.h" |
| |
| namespace NCompress { |
| namespace NBZip2 { |
| |
| const unsigned kNumPassesMax = 10; |
| |
| struct CMsbfEncoderTemp |
| { |
| unsigned _bitPos; // 0 < _bitPos <= 8 : number of non-filled low bits in _curByte |
| unsigned _curByte; // low (_bitPos) bits are zeros |
| // high (8 - _bitPos) bits are filled |
| Byte *_buf; |
| Byte *_buf_base; |
| void SetStream(Byte *buf) { _buf_base = _buf = buf; } |
| Byte *GetStream() const { return _buf_base; } |
| |
| void Init() |
| { |
| _bitPos = 8; |
| _curByte = 0; |
| _buf = _buf_base; |
| } |
| |
| // required condition: (value >> numBits) == 0 |
| // numBits == 0 is allowed |
| void WriteBits(UInt32 value, unsigned numBits) |
| { |
| do |
| { |
| unsigned bp = _bitPos; |
| unsigned curByte = _curByte; |
| if (numBits < bp) |
| { |
| bp -= numBits; |
| _curByte = curByte | (value << bp); |
| _bitPos = bp; |
| return; |
| } |
| numBits -= bp; |
| const UInt32 hi = value >> numBits; |
| value -= (hi << numBits); |
| Byte *buf = _buf; |
| _bitPos = 8; |
| _curByte = 0; |
| *buf++ = (Byte)(curByte | hi); |
| _buf = buf; |
| } |
| while (numBits); |
| } |
| |
| void WriteBit(unsigned value) |
| { |
| const unsigned bp = _bitPos - 1; |
| const unsigned curByte = _curByte | (value << bp); |
| _curByte = curByte; |
| _bitPos = bp; |
| if (bp == 0) |
| { |
| *_buf++ = (Byte)curByte; |
| _curByte = 0; |
| _bitPos = 8; |
| } |
| } |
| |
| void WriteByte(unsigned b) |
| { |
| const unsigned bp = _bitPos; |
| const unsigned a = _curByte | (b >> (8 - bp)); |
| _curByte = b << bp; |
| Byte *buf = _buf; |
| *buf++ = (Byte)a; |
| _buf = buf; |
| } |
| |
| UInt32 GetBytePos() const { return (UInt32)(size_t)(_buf - _buf_base); } |
| UInt32 GetPos() const { return GetBytePos() * 8 + 8 - _bitPos; } |
| unsigned GetCurByte() const { return _curByte; } |
| unsigned GetNonFlushedByteBits() const { return _curByte >> _bitPos; } |
| void SetPos(UInt32 bitPos) |
| { |
| _buf = _buf_base + (bitPos >> 3); |
| _bitPos = 8 - ((unsigned)bitPos & 7); |
| } |
| void SetCurState(unsigned bitPos, unsigned curByte) |
| { |
| _bitPos = 8 - bitPos; |
| _curByte = curByte; |
| } |
| }; |
| |
| |
| class CEncoder; |
| |
| class CThreadInfo |
| { |
| private: |
| CMsbfEncoderTemp m_OutStreamCurrent; |
| public: |
| CEncoder *Encoder; |
| Byte *m_Block; |
| private: |
| Byte *m_MtfArray; |
| Byte *m_TempArray; |
| UInt32 *m_BlockSorterIndex; |
| |
| public: |
| bool m_OptimizeNumTables; |
| UInt32 m_NumCrcs; |
| UInt32 m_BlockIndex; |
| UInt64 m_UnpackSize; |
| |
| Byte *m_Block_Base; |
| |
| Byte Lens[kNumTablesMax][kMaxAlphaSize]; |
| UInt32 Freqs[kNumTablesMax][kMaxAlphaSize]; |
| UInt32 Codes[kNumTablesMax][kMaxAlphaSize]; |
| |
| Byte m_Selectors[kNumSelectorsMax]; |
| |
| UInt32 m_CRCs[1 << kNumPassesMax]; |
| |
| void WriteBits2(UInt32 value, unsigned numBits); |
| void WriteByte2(unsigned b) { WriteBits2(b, 8); } |
| void WriteBit2(unsigned v) { m_OutStreamCurrent.WriteBit(v); } |
| |
| void EncodeBlock(const Byte *block, UInt32 blockSize); |
| UInt32 EncodeBlockWithHeaders(const Byte *block, UInt32 blockSize); |
| void EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPasses); |
| public: |
| #ifndef Z7_ST |
| NWindows::CThread Thread; |
| |
| 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; |
| |
| public: |
| Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. |
| HRESULT Create(); |
| void FinishStream(bool needLeave); |
| THREAD_FUNC_RET_TYPE ThreadFunc(); |
| #endif |
| |
| CThreadInfo(): m_BlockSorterIndex(NULL), m_Block_Base(NULL) {} |
| ~CThreadInfo() { Free(); } |
| bool Alloc(); |
| void Free(); |
| |
| HRESULT EncodeBlock3(UInt32 blockSize); |
| }; |
| |
| |
| struct CEncProps |
| { |
| UInt32 BlockSizeMult; |
| UInt32 NumPasses; |
| UInt32 NumThreadGroups; |
| UInt64 Affinity; |
| |
| CEncProps() |
| { |
| BlockSizeMult = (UInt32)(Int32)-1; |
| NumPasses = (UInt32)(Int32)-1; |
| NumThreadGroups = 0; |
| Affinity = 0; |
| } |
| void Normalize(int level); |
| bool DoOptimizeNumTables() const { return NumPasses > 1; } |
| }; |
| |
| class CEncoder Z7_final: |
| public ICompressCoder, |
| public ICompressSetCoderProperties, |
| #ifndef Z7_ST |
| public ICompressSetCoderMt, |
| #endif |
| public CMyUnknownImp |
| { |
| Z7_COM_QI_BEGIN2(ICompressCoder) |
| Z7_COM_QI_ENTRY(ICompressSetCoderProperties) |
| #ifndef Z7_ST |
| Z7_COM_QI_ENTRY(ICompressSetCoderMt) |
| #endif |
| Z7_COM_QI_END |
| Z7_COM_ADDREF_RELEASE |
| |
| Z7_IFACE_COM7_IMP(ICompressCoder) |
| Z7_IFACE_COM7_IMP(ICompressSetCoderProperties) |
| #ifndef Z7_ST |
| Z7_IFACE_COM7_IMP(ICompressSetCoderMt) |
| #endif |
| |
| #ifndef Z7_ST |
| UInt32 m_NumThreadsPrev; |
| #endif |
| public: |
| CInBuffer m_InStream; |
| #ifndef Z7_ST |
| Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size. |
| #endif |
| CBitmEncoder<COutBuffer> m_OutStream; |
| CEncProps _props; |
| CBZip2CombinedCrc CombinedCrc; |
| |
| #ifndef Z7_ST |
| CThreadInfo *ThreadsInfo; |
| NWindows::NSynchronization::CManualResetEvent CanProcessEvent; |
| NWindows::NSynchronization::CCriticalSection CS; |
| UInt32 NumThreads; |
| bool MtMode; |
| UInt32 NextBlockIndex; |
| |
| bool CloseThreads; |
| bool StreamWasFinished; |
| NWindows::NSynchronization::CManualResetEvent CanStartWaitingEvent; |
| CThreadNextGroup ThreadNextGroup; |
| |
| HRESULT Result; |
| ICompressProgressInfo *Progress; |
| #else |
| CThreadInfo ThreadsInfo; |
| #endif |
| |
| UInt64 NumBlocks; |
| |
| UInt64 GetInProcessedSize() const { return m_InStream.GetProcessedSize(); } |
| |
| UInt32 ReadRleBlock(Byte *buf); |
| void WriteBytes(const Byte *data, UInt32 sizeInBits, unsigned lastByteBits); |
| void WriteByte(Byte b); |
| |
| #ifndef Z7_ST |
| HRESULT Create(); |
| void Free(); |
| #endif |
| |
| public: |
| CEncoder(); |
| #ifndef Z7_ST |
| ~CEncoder(); |
| #endif |
| |
| HRESULT Flush() { return m_OutStream.Flush(); } |
| |
| HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, |
| const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress); |
| }; |
| |
| }} |
| |
| #endif |