This commit is contained in:
Igor Pavlov
2017-04-30 00:00:00 +00:00
committed by Kornel
parent 603abd5528
commit 2efa10565a
442 changed files with 15479 additions and 8525 deletions

View File

@@ -5,6 +5,9 @@
#include "../../Common/MyCom.h"
// #define NO_READ_FROM_CODER
// #define _7ZIP_ST
#ifndef _7ZIP_ST
#include "../../Windows/Synchronization.h"
#include "../../Windows/Thread.h"
@@ -12,13 +15,10 @@
#include "../ICoder.h"
#include "../Common/InBuffer.h"
#include "../Common/OutBuffer.h"
#include "BitmDecoder.h"
#include "BZip2Const.h"
#include "BZip2Crc.h"
#include "HuffmanDecoder.h"
#include "Mtf8.h"
namespace NCompress {
namespace NBZip2 {
@@ -26,154 +26,311 @@ namespace NBZip2 {
bool IsEndSig(const Byte *p) throw();
bool IsBlockSig(const Byte *p) throw();
typedef NCompress::NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize> CHuffmanDecoder;
const unsigned kNumTableBits = 9;
const unsigned kNumBitsMax = kMaxHuffmanLen;
class CDecoder;
typedef NHuffman::CDecoder<kMaxHuffmanLen, kMaxAlphaSize, kNumTableBits> CHuffmanDecoder;
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();
};
struct CBlockProps
{
UInt32 blockSize;
UInt32 origPtr;
bool randMode;
unsigned randMode;
CBlockProps(): blockSize(0), origPtr(0), randMode(false) {}
CBlockProps(): blockSize(0), origPtr(0), randMode(0) {}
};
struct CBase
struct CBitDecoder
{
CMyComPtr<ISequentialInStream> InStreamRef;
NBitm::CDecoder<CInBuffer> BitDecoder;
unsigned _numBits;
UInt32 _value;
const Byte *_buf;
const Byte *_lim;
private:
Byte m_Selectors[kNumSelectorsMax];
CHuffmanDecoder m_HuffmanDecoders[kNumTablesMax];
void InitBitDecoder()
{
_numBits = 0;
_value = 0;
}
public:
UInt64 NumBlocks;
CBase(): NumBlocks(0) {}
UInt32 ReadBits(unsigned numBits);
unsigned ReadBit();
void InitNumBlocks() { NumBlocks = 0; }
void AlignToByte()
{
unsigned bits = _numBits & 7;
_numBits -= bits;
_value <<= bits;
}
/*
ReadBlock() props->randMode:
in: need read randMode bit,
out: randMode status
bool AreRemainByteBitsEmpty() const
{
unsigned bits = _numBits & 7;
if (bits != 0)
return (_value >> (32 - bits)) == 0;
return true;
}
*/
HRESULT ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps *props);
SRes ReadByte(int &b);
};
struct CBase: public CBitDecoder
{
unsigned numInUse;
UInt32 groupIndex;
UInt32 groupSize;
unsigned runPower;
UInt32 runCounter;
UInt32 blockSize;
UInt32 *Counters;
UInt32 blockSizeMax;
unsigned state;
unsigned state2;
unsigned state3;
unsigned state4;
unsigned state5;
unsigned numTables;
UInt32 numSelectors;
CBlockProps Props;
private:
CMtf8Decoder mtf;
Byte selectors[kNumSelectorsMax];
CHuffmanDecoder huffs[kNumTablesMax];
Byte lens[kMaxAlphaSize];
Byte temp[10];
public:
UInt32 crc;
CBZip2CombinedCrc CombinedCrc;
bool IsBz;
bool StreamCrcError;
bool MinorError;
bool NeedMoreInput;
bool DecodeAllStreams;
UInt64 NumStreams;
UInt64 NumBlocks;
UInt64 FinishedPackSize;
ISequentialInStream *InStream;
#ifndef NO_READ_FROM_CODER
CMyComPtr<ISequentialInStream> InStreamRef;
#endif
CBase():
StreamCrcError(false),
MinorError(false),
NeedMoreInput(false),
DecodeAllStreams(false),
NumStreams(0),
NumBlocks(0),
FinishedPackSize(0)
{}
void InitNumStreams2()
{
StreamCrcError = false;
MinorError = false;
NeedMoreInput = 0;
NumStreams = 0;
NumBlocks = 0;
FinishedPackSize = 0;
}
SRes ReadStreamSignature2();
SRes ReadBlockSignature2();
/* ReadBlock2() : Props->randMode:
in: need read randMode bit
out: randMode status */
SRes ReadBlock2();
};
class CSpecState
{
UInt32 _tPos;
unsigned _prevByte;
int _reps;
public:
CBZip2Crc _crc;
UInt32 _blockSize;
UInt32 *_tt;
int _randToGo;
unsigned _randIndex;
void Init(UInt32 origPtr, unsigned randMode) throw();
bool Finished() const { return _reps <= 0 && _blockSize == 0; }
Byte *Decode(Byte *data, size_t size) throw();
};
class CDecoder :
public ICompressCoder,
public ICompressSetFinishMode,
public ICompressGetInStreamProcessedSize,
#ifndef NO_READ_FROM_CODER
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public ISequentialInStream,
#endif
#ifndef _7ZIP_ST
public ICompressSetCoderMt,
#endif
public CMyUnknownImp
{
Byte *_outBuf;
size_t _outPos;
UInt64 _outWritten;
ISequentialOutStream *_outStream;
HRESULT _writeRes;
protected:
HRESULT ErrorResult; // for ISequentialInStream::Read mode only
public:
COutBuffer m_OutStream;
Byte MtPad[1 << 8]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
CBase Base;
UInt32 _calcedBlockCrc;
bool _blockFinished;
bool BlockCrcError;
UInt64 _inStart;
bool FinishMode;
bool _outSizeDefined;
UInt64 _outSize;
UInt64 _outPosTotal;
private:
CSpecState _spec;
UInt32 *_counters;
bool _needInStreamInit;
#ifndef _7ZIP_ST
Byte ReadByte();
struct CBlock
{
bool StopScout;
bool WasFinished;
bool Crc_Defined;
// bool NextCrc_Defined;
UInt32 Crc;
UInt32 NextCrc;
HRESULT Res;
UInt64 PackPos;
CBlockProps Props;
};
HRESULT DecodeFile(ICompressProgressInfo *progress);
HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
CBlock _block;
bool NeedWaitScout;
bool MtMode;
NWindows::CThread Thread;
NWindows::NSynchronization::CAutoResetEvent DecoderEvent;
NWindows::NSynchronization::CAutoResetEvent ScoutEvent;
// HRESULT ScoutRes;
class CDecoderFlusher
Byte MtPad[1 << 7]; // It's pad for Multi-Threading. Must be >= Cache_Line_Size.
void RunScout();
void WaitScout()
{
if (NeedWaitScout)
{
DecoderEvent.Lock();
NeedWaitScout = false;
}
}
class CWaitScout_Releaser
{
CDecoder *_decoder;
public:
bool NeedFlush;
CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}
~CDecoderFlusher()
{
if (NeedFlush)
_decoder->Flush();
}
CWaitScout_Releaser(CDecoder *decoder): _decoder(decoder) {}
~CWaitScout_Releaser() { _decoder->WaitScout(); }
};
public:
CBZip2CombinedCrc CombinedCrc;
ICompressProgressInfo *Progress;
HRESULT CreateThread();
#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
bool IsBz;
bool BzWasFinished; // bzip stream was finished with end signature
bool CrcError; // it can CRC error of block or CRC error of whole stream.
Byte *_inBuf;
UInt64 _inProcessed;
bool _inputFinished;
HRESULT _inputRes;
CDecoder();
CBase Base;
HRESULT SetRatioProgress(UInt64 packSize);
HRESULT ReadSignature(UInt32 &crc);
bool GetCrcError() const { return BlockCrcError || Base.StreamCrcError; }
HRESULT Flush() { return m_OutStream.Flush(); }
void InitOutSize(const UInt64 *outSize);
bool CreateInputBufer();
void InitInputBuffer()
{
_inProcessed = 0;
Base._buf = _inBuf;
Base._lim = _inBuf;
Base.InitBitDecoder();
}
UInt64 GetInputProcessedSize() const
{
// for NSIS case : we need also look the number of bits in bitDecoder
return _inProcessed + (Base._buf - _inBuf);
}
UInt64 GetOutProcessedSize() const { return _outWritten + _outPos; }
HRESULT ReadInput();
void StartNewStream();
HRESULT ReadStreamSignature();
HRESULT StartRead();
HRESULT ReadBlockSignature();
HRESULT ReadBlock();
HRESULT Flush();
HRESULT DecodeBlock(const CBlockProps &props);
HRESULT DecodeStreams(ICompressProgressInfo *progress);
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
#ifndef NO_READ_FROM_CODER
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
#endif
#ifndef _7ZIP_ST
MY_QUERYINTERFACE_ENTRY(ICompressSetCoderMt)
#endif
@@ -185,54 +342,41 @@ public:
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
STDMETHOD(ReleaseInStream)();
STDMETHOD(SetFinishMode)(UInt32 finishMode);
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
HRESULT CodeResume(ISequentialOutStream *outStream, ICompressProgressInfo *progress);
UInt64 GetStreamSize() const { return Base.BitDecoder.GetStreamSize(); }
UInt64 GetInputProcessedSize() const { return Base.BitDecoder.GetProcessedSize(); }
void InitNumBlocks() { Base.InitNumBlocks(); }
UInt64 GetNumStreams() const { return Base.NumStreams; }
UInt64 GetNumBlocks() const { return Base.NumBlocks; }
#ifndef _7ZIP_ST
STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
#endif
};
#ifndef NO_READ_FROM_CODER
class CNsisDecoder :
public ISequentialInStream,
public ICompressSetInStream,
public ICompressSetOutStreamSize,
public CMyUnknownImp
{
CBase Base;
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);
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
#endif
#ifndef _7ZIP_ST
STDMETHOD(SetNumberOfThreads)(UInt32 numThreads);
#endif
CDecoder();
~CDecoder();
};
#ifndef NO_READ_FROM_CODER
class CNsisDecoder : public CDecoder
{
public:
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
};
#endif
}}
#endif