mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-08 10:07:02 -06:00
17.00
This commit is contained in:
@@ -13,8 +13,8 @@ void CBZip2Crc::InitTable()
|
||||
for (UInt32 i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = (i << 24);
|
||||
for (int j = 8; j > 0; j--)
|
||||
r = (r & 0x80000000) ? ((r << 1) ^ kBZip2CrcPoly) : (r << 1);
|
||||
for (unsigned j = 0; j < 8; j++)
|
||||
r = (r << 1) ^ (kBZip2CrcPoly & ((UInt32)0 - (r >> 31)));
|
||||
Table[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -337,7 +337,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
|
||||
}
|
||||
else
|
||||
mtfs[mtfArraySize++] = (Byte)(pos + 1);
|
||||
symbolCounts[pos + 1]++;
|
||||
symbolCounts[(size_t)pos + 1]++;
|
||||
}
|
||||
}
|
||||
while (++i < blockSize);
|
||||
@@ -357,7 +357,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
|
||||
mtfs[mtfArraySize++] = 0xFF;
|
||||
mtfs[mtfArraySize++] = (Byte)(alphaSize - 256);
|
||||
}
|
||||
symbolCounts[alphaSize - 1]++;
|
||||
symbolCounts[(size_t)alphaSize - 1]++;
|
||||
}
|
||||
|
||||
UInt32 numSymbols = 0;
|
||||
@@ -412,7 +412,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
|
||||
if (ge > gs + 1 && t != numTables && t != 1 && (((numTables - t) & 1) == 1))
|
||||
aFreq -= symbolCounts[--ge];
|
||||
|
||||
Byte *lens = Lens[t - 1];
|
||||
Byte *lens = Lens[(size_t)t - 1];
|
||||
unsigned i = 0;
|
||||
do
|
||||
lens[i] = (Byte)((i >= gs && i < ge) ? 0 : 1);
|
||||
@@ -507,7 +507,7 @@ void CThreadInfo::EncodeBlock(const Byte *block, UInt32 blockSize)
|
||||
WriteBit2(1);
|
||||
WriteBit2(0);
|
||||
for (; pos > 0; pos--)
|
||||
mtfSel[pos] = mtfSel[pos - 1];
|
||||
mtfSel[pos] = mtfSel[(size_t)pos - 1];
|
||||
mtfSel[0] = sel;
|
||||
}
|
||||
while (++i < numSelectors);
|
||||
@@ -634,10 +634,13 @@ void CThreadInfo::EncodeBlock2(const Byte *block, UInt32 blockSize, UInt32 numPa
|
||||
UInt32 endPos = 0;
|
||||
if (numPasses > 1 && blockSize >= (1 << 10))
|
||||
{
|
||||
UInt32 blockSize0 = blockSize / 2;
|
||||
for (;(block[blockSize0] == block[blockSize0 - 1] ||
|
||||
block[blockSize0 - 1] == block[blockSize0 - 2]) &&
|
||||
blockSize0 < blockSize; blockSize0++);
|
||||
UInt32 blockSize0 = blockSize / 2; // ????
|
||||
|
||||
for (; (block[blockSize0] == block[(size_t)blockSize0 - 1]
|
||||
|| block[(size_t)blockSize0 - 1] == block[(size_t)blockSize0 - 2])
|
||||
&& blockSize0 < blockSize;
|
||||
blockSize0++);
|
||||
|
||||
if (blockSize0 < blockSize)
|
||||
{
|
||||
EncodeBlock2(block, blockSize0, numPasses - 1);
|
||||
|
||||
@@ -463,10 +463,10 @@ HRESULT CDecoder::Code(ISequentialInStream * const *inStreams, const UInt64 * co
|
||||
|
||||
if (progress)
|
||||
{
|
||||
UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]);
|
||||
const UInt64 outSize2 = outSizeProcessed + (dec.dest - _bufs[BCJ2_NUM_STREAMS]);
|
||||
if (outSize2 - prevProgress >= (1 << 22))
|
||||
{
|
||||
UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]);
|
||||
const UInt64 inSize2 = outSize2 + _inStreamsProcessed[BCJ2_STREAM_RC] - (dec.lims[BCJ2_STREAM_RC] - dec.bufs[BCJ2_STREAM_RC]);
|
||||
RINOK(progress->SetRatioInfo(&inSize2, &outSize2));
|
||||
prevProgress = outSize2;
|
||||
}
|
||||
@@ -655,4 +655,12 @@ STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize2(UInt32 streamIndex, UInt64 *value)
|
||||
{
|
||||
const size_t rem = dec.lims[streamIndex] - dec.bufs[streamIndex] + _extraReadSizes[streamIndex];
|
||||
*value = _inStreamsProcessed[streamIndex] - rem;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
class CDecoder:
|
||||
public ICompressCoder2,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize2,
|
||||
public ICompressSetInStream2,
|
||||
public ISequentialInStream,
|
||||
public ICompressSetOutStreamSize,
|
||||
@@ -84,9 +85,10 @@ class CDecoder:
|
||||
// HRESULT ReadSpec();
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP6(
|
||||
MY_UNKNOWN_IMP7(
|
||||
ICompressCoder2,
|
||||
ICompressSetFinishMode,
|
||||
ICompressGetInStreamProcessedSize2,
|
||||
ICompressSetInStream2,
|
||||
ISequentialInStream,
|
||||
ICompressSetOutStreamSize,
|
||||
@@ -98,6 +100,7 @@ public:
|
||||
ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize2)(UInt32 streamIndex, UInt64 *value);
|
||||
|
||||
STDMETHOD(SetInStream2)(UInt32 streamIndex, ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream2)(UInt32 streamIndex);
|
||||
|
||||
@@ -42,13 +42,15 @@ public:
|
||||
UInt64 GetProcessedSize() const { return _stream.GetProcessedSize() - ((kNumBigValueBits - _bitPos) >> 3); }
|
||||
|
||||
bool ThereAreDataInBitsBuffer() const { return this->_bitPos != kNumBigValueBits; }
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
void Normalize()
|
||||
{
|
||||
for (; _bitPos >= 8; _bitPos -= 8)
|
||||
_value = ((UInt32)_stream.ReadByte() << (kNumBigValueBits - _bitPos)) | _value;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 ReadBits(unsigned numBits)
|
||||
{
|
||||
Normalize();
|
||||
@@ -88,7 +90,8 @@ public:
|
||||
CBaseDecoder<TInByte>::Init();
|
||||
_normalValue = 0;
|
||||
}
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
void Normalize()
|
||||
{
|
||||
for (; this->_bitPos >= 8; this->_bitPos -= 8)
|
||||
@@ -99,18 +102,21 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 GetValue(unsigned numBits)
|
||||
{
|
||||
Normalize();
|
||||
return ((this->_value >> (8 - this->_bitPos)) & kMask) >> (kNumValueBits - numBits);
|
||||
}
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
void MovePos(unsigned numBits)
|
||||
{
|
||||
this->_bitPos += numBits;
|
||||
_normalValue >>= numBits;
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 ReadBits(unsigned numBits)
|
||||
{
|
||||
Normalize();
|
||||
@@ -120,9 +126,11 @@ public:
|
||||
}
|
||||
|
||||
void AlignToByte() { MovePos((32 - this->_bitPos) & 7); }
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Byte ReadDirectByte() { return this->_stream.ReadByte(); }
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Byte ReadAlignedByte()
|
||||
{
|
||||
if (this->_bitPos == kNumBigValueBits)
|
||||
|
||||
@@ -46,25 +46,29 @@ public:
|
||||
{
|
||||
return (_stream.NumExtraBytes > 4);
|
||||
}
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
void Normalize()
|
||||
{
|
||||
for (; _bitPos >= 8; _bitPos -= 8)
|
||||
_value = (_value << 8) | _stream.ReadByte();
|
||||
}
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 GetValue(unsigned numBits) const
|
||||
{
|
||||
// return (_value << _bitPos) >> (kNumBigValueBits - numBits);
|
||||
return ((_value >> (8 - _bitPos)) & kMask) >> (kNumValueBits - numBits);
|
||||
}
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
void MovePos(unsigned numBits)
|
||||
{
|
||||
_bitPos += numBits;
|
||||
Normalize();
|
||||
}
|
||||
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 ReadBits(unsigned numBits)
|
||||
{
|
||||
UInt32 res = GetValue(numBits);
|
||||
@@ -87,6 +91,7 @@ public:
|
||||
|
||||
void AlignToByte() { MovePos((kNumBigValueBits - _bitPos) & 7); }
|
||||
|
||||
MY_FORCE_INLINE
|
||||
UInt32 ReadAlignBits() { return ReadBits((kNumBigValueBits - _bitPos) & 7); }
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,11 @@ CCopyCoder::~CCopyCoder()
|
||||
::MidFree(_buf);
|
||||
}
|
||||
|
||||
STDMETHODIMP CCopyCoder::SetFinishMode(UInt32 /* finishMode */)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCopyCoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize,
|
||||
|
||||
@@ -13,6 +13,7 @@ class CCopyCoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetInStream,
|
||||
public ISequentialInStream,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
@@ -24,10 +25,11 @@ public:
|
||||
CCopyCoder(): _buf(0), TotalSize(0) {};
|
||||
~CCopyCoder();
|
||||
|
||||
MY_UNKNOWN_IMP4(
|
||||
MY_UNKNOWN_IMP5(
|
||||
ICompressCoder,
|
||||
ICompressSetInStream,
|
||||
ISequentialInStream,
|
||||
ICompressSetFinishMode,
|
||||
ICompressGetInStreamProcessedSize)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
@@ -35,6 +37,7 @@ public:
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ CCoder::CCoder(bool deflate64Mode):
|
||||
_keepHistory(false),
|
||||
_needFinishInput(false),
|
||||
_needInitInStream(true),
|
||||
_outSizeDefined(false),
|
||||
_outStartPos(0),
|
||||
ZlibMode(false) {}
|
||||
|
||||
UInt32 CCoder::ReadBits(unsigned numBits)
|
||||
@@ -50,7 +52,7 @@ bool CCoder::DecodeLevels(Byte *levels, unsigned numSymbols)
|
||||
return false;
|
||||
numBits = 2;
|
||||
num = 0;
|
||||
symbol = levels[i - 1];
|
||||
symbol = levels[(size_t)i - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -145,10 +147,28 @@ bool CCoder::ReadTables(void)
|
||||
return m_DistDecoder.Build(levels.distLevels);
|
||||
}
|
||||
|
||||
HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream)
|
||||
|
||||
HRESULT CCoder::InitInStream(bool needInit)
|
||||
{
|
||||
if (needInit)
|
||||
{
|
||||
// for HDD-Windows:
|
||||
// (1 << 15) - best for reading only prefetch
|
||||
// (1 << 22) - best for real reading / writing
|
||||
if (!m_InBitStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
m_InBitStream.Init();
|
||||
_needInitInStream = false;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit)
|
||||
{
|
||||
if (_remainLen == kLenIdFinished)
|
||||
return S_OK;
|
||||
|
||||
if (_remainLen == kLenIdNeedInit)
|
||||
{
|
||||
if (!_keepHistory)
|
||||
@@ -156,6 +176,7 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream)
|
||||
return E_OUTOFMEMORY;
|
||||
RINOK(InitInStream(_needInitInStream));
|
||||
m_OutWindowStream.Init(_keepHistory);
|
||||
|
||||
m_FinalBlock = false;
|
||||
_remainLen = 0;
|
||||
_needReadTable = true;
|
||||
@@ -169,6 +190,10 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream)
|
||||
curSize--;
|
||||
}
|
||||
|
||||
UInt64 inputStart = 0;
|
||||
if (inputProgressLimit != 0)
|
||||
inputStart = m_InBitStream.GetProcessedSize();
|
||||
|
||||
while (curSize > 0 || finishInputStream)
|
||||
{
|
||||
if (m_InBitStream.ExtraBitsWereRead())
|
||||
@@ -181,6 +206,11 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream)
|
||||
_remainLen = kLenIdFinished;
|
||||
break;
|
||||
}
|
||||
|
||||
if (inputProgressLimit != 0)
|
||||
if (m_InBitStream.GetProcessedSize() - inputStart >= inputProgressLimit)
|
||||
return S_OK;
|
||||
|
||||
if (!ReadTables())
|
||||
return S_FALSE;
|
||||
if (m_InBitStream.ExtraBitsWereRead())
|
||||
@@ -284,31 +314,34 @@ HRESULT CCoder::CodeSpec(UInt32 curSize, bool finishInputStream)
|
||||
|
||||
#define DEFLATE_TRY_BEGIN try {
|
||||
#define DEFLATE_TRY_END(res) } \
|
||||
catch(const CInBufferException &e) { res = e.ErrorCode; } \
|
||||
catch(const CLzOutWindowException &e) { res = e.ErrorCode; } \
|
||||
catch(const CSystemException &e) { res = e.ErrorCode; } \
|
||||
catch(...) { res = S_FALSE; }
|
||||
|
||||
// catch(const CInBufferException &e) { res = e.ErrorCode; }
|
||||
// catch(const CLzOutWindowException &e) { res = e.ErrorCode; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
HRESULT CCoder::CodeReal(ISequentialOutStream *outStream,
|
||||
const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
HRESULT CCoder::CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress)
|
||||
{
|
||||
HRESULT res;
|
||||
|
||||
DEFLATE_TRY_BEGIN
|
||||
|
||||
m_OutWindowStream.SetStream(outStream);
|
||||
CCoderReleaser flusher(this);
|
||||
|
||||
const UInt64 inStart = _needInitInStream ? 0 : m_InBitStream.GetProcessedSize();
|
||||
const UInt64 start = m_OutWindowStream.GetProcessedSize();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 curSize = 1 << 18;
|
||||
const UInt32 kInputProgressLimit = 1 << 21;
|
||||
UInt32 curSize = 1 << 20;
|
||||
bool finishInputStream = false;
|
||||
if (outSize)
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = *outSize - (m_OutWindowStream.GetProcessedSize() - start);
|
||||
const UInt64 rem = _outSize - GetOutProcessedCur();
|
||||
if (curSize >= rem)
|
||||
{
|
||||
curSize = (UInt32)rem;
|
||||
@@ -318,13 +351,16 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream,
|
||||
}
|
||||
if (!finishInputStream && curSize == 0)
|
||||
break;
|
||||
RINOK(CodeSpec(curSize, finishInputStream));
|
||||
|
||||
RINOK(CodeSpec(curSize, finishInputStream, progress ? kInputProgressLimit : 0));
|
||||
|
||||
if (_remainLen == kLenIdFinished)
|
||||
break;
|
||||
|
||||
if (progress)
|
||||
{
|
||||
const UInt64 inSize = m_InBitStream.GetProcessedSize() - inStart;
|
||||
const UInt64 nowPos64 = m_OutWindowStream.GetProcessedSize() - start;
|
||||
const UInt64 nowPos64 = GetOutProcessedCur();
|
||||
RINOK(progress->SetRatioInfo(&inSize, &nowPos64));
|
||||
}
|
||||
}
|
||||
@@ -340,20 +376,36 @@ HRESULT CCoder::CodeReal(ISequentialOutStream *outStream,
|
||||
res = Flush();
|
||||
if (res == S_OK && _remainLen != kLenIdNeedInit && InputEofError())
|
||||
return S_FALSE;
|
||||
|
||||
DEFLATE_TRY_END(res)
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
SetInStream(inStream);
|
||||
SetOutStreamSize(outSize);
|
||||
HRESULT res = CodeReal(outStream, outSize, progress);
|
||||
HRESULT res = CodeReal(outStream, progress);
|
||||
ReleaseInStream();
|
||||
/*
|
||||
if (res == S_OK)
|
||||
if (_needFinishInput && inSize && *inSize != m_InBitStream.GetProcessedSize())
|
||||
res = S_FALSE;
|
||||
*/
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::SetFinishMode(UInt32 finishMode)
|
||||
{
|
||||
Set_NeedFinishInput(finishMode != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
if (!value)
|
||||
@@ -362,6 +414,7 @@ STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
|
||||
{
|
||||
m_InStreamRef = inStream;
|
||||
@@ -369,49 +422,88 @@ STDMETHODIMP CCoder::SetInStream(ISequentialInStream *inStream)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::ReleaseInStream()
|
||||
{
|
||||
m_InStreamRef.Release();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 * /* outSize */)
|
||||
|
||||
void CCoder::SetOutStreamSizeResume(const UInt64 *outSize)
|
||||
{
|
||||
_remainLen = kLenIdNeedInit;
|
||||
_needInitInStream = true;
|
||||
_outSizeDefined = (outSize != NULL);
|
||||
_outSize = 0;
|
||||
if (_outSizeDefined)
|
||||
_outSize = *outSize;
|
||||
|
||||
m_OutWindowStream.Init(_keepHistory);
|
||||
_outStartPos = m_OutWindowStream.GetProcessedSize();
|
||||
|
||||
_remainLen = kLenIdNeedInit;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
_needInitInStream = true;
|
||||
SetOutStreamSizeResume(outSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
|
||||
STDMETHODIMP CCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
HRESULT res;
|
||||
DEFLATE_TRY_BEGIN
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
const UInt64 startPos = m_OutWindowStream.GetProcessedSize();
|
||||
m_OutWindowStream.SetMemStream((Byte *)data);
|
||||
res = CodeSpec(size, false);
|
||||
if (res == S_OK)
|
||||
const UInt64 outPos = GetOutProcessedCur();
|
||||
|
||||
bool finishInputStream = false;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
res = Flush();
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)(m_OutWindowStream.GetProcessedSize() - startPos);
|
||||
const UInt64 rem = _outSize - outPos;
|
||||
if (size >= rem)
|
||||
{
|
||||
size = (UInt32)rem;
|
||||
if (ZlibMode || _needFinishInput)
|
||||
finishInputStream = true;
|
||||
}
|
||||
}
|
||||
if (!finishInputStream && size == 0)
|
||||
return S_OK;
|
||||
|
||||
DEFLATE_TRY_BEGIN
|
||||
|
||||
m_OutWindowStream.SetMemStream((Byte *)data);
|
||||
|
||||
res = CodeSpec(size, finishInputStream);
|
||||
|
||||
DEFLATE_TRY_END(res)
|
||||
|
||||
{
|
||||
HRESULT res2 = Flush();
|
||||
if (res2 != S_OK)
|
||||
res = res2;
|
||||
}
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)(GetOutProcessedCur() - outPos);
|
||||
|
||||
m_OutWindowStream.SetMemStream(NULL);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
STDMETHODIMP CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
|
||||
HRESULT CCoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
_remainLen = kLenIdNeedInit;
|
||||
m_OutWindowStream.Init(_keepHistory);
|
||||
return CodeReal(outStream, outSize, progress);
|
||||
SetOutStreamSizeResume(outSize);
|
||||
return CodeReal(outStream, progress);
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
@@ -23,6 +23,7 @@ const int kLenIdNeedInit = -2;
|
||||
|
||||
class CCoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
public ICompressSetInStream,
|
||||
@@ -54,6 +55,13 @@ class CCoder:
|
||||
Int32 _remainLen;
|
||||
UInt32 _rep0;
|
||||
|
||||
bool _outSizeDefined;
|
||||
UInt64 _outSize;
|
||||
UInt64 _outStartPos;
|
||||
|
||||
void SetOutStreamSizeResume(const UInt64 *outSize);
|
||||
UInt64 GetOutProcessedCur() const { return m_OutWindowStream.GetProcessedSize() - _outStartPos; }
|
||||
|
||||
UInt32 ReadBits(unsigned numBits);
|
||||
|
||||
bool DecodeLevels(Byte *levels, unsigned numSymbols);
|
||||
@@ -74,7 +82,7 @@ class CCoder:
|
||||
};
|
||||
friend class CCoderReleaser;
|
||||
|
||||
HRESULT CodeSpec(UInt32 curSize, bool finishInputStream);
|
||||
HRESULT CodeSpec(UInt32 curSize, bool finishInputStream, UInt32 inputProgressLimit = 0);
|
||||
public:
|
||||
bool ZlibMode;
|
||||
Byte ZlibFooter[4];
|
||||
@@ -90,26 +98,28 @@ public:
|
||||
bool IsFinished() const { return _remainLen == kLenIdFinished;; }
|
||||
bool IsFinalBlock() const { return m_FinalBlock; }
|
||||
|
||||
HRESULT CodeReal(ISequentialOutStream *outStream,
|
||||
const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
HRESULT CodeReal(ISequentialOutStream *outStream, ICompressProgressInfo *progress);
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
MY_UNKNOWN_IMP5(
|
||||
ICompressCoder,
|
||||
ICompressGetInStreamProcessedSize,
|
||||
ICompressSetInStream,
|
||||
ICompressSetOutStreamSize,
|
||||
ISequentialInStream
|
||||
)
|
||||
#else
|
||||
MY_UNKNOWN_IMP2(
|
||||
ICompressCoder,
|
||||
ICompressGetInStreamProcessedSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetOutStreamSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
|
||||
#endif
|
||||
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
@@ -118,19 +128,9 @@ public:
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
#endif
|
||||
|
||||
STDMETHOD(CodeResume)(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
HRESULT InitInStream(bool needInit)
|
||||
{
|
||||
if (!m_InBitStream.Create(1 << 17))
|
||||
return E_OUTOFMEMORY;
|
||||
if (needInit)
|
||||
{
|
||||
m_InBitStream.Init();
|
||||
_needInitInStream = false;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT InitInStream(bool needInit);
|
||||
|
||||
void AlignToByte() { m_InBitStream.AlignToByte(); }
|
||||
Byte ReadAlignedByte();
|
||||
@@ -143,9 +143,6 @@ public:
|
||||
|
||||
UInt64 GetStreamSize() const { return m_InBitStream.GetStreamSize(); }
|
||||
UInt64 GetInputProcessedSize() const { return m_InBitStream.GetProcessedSize(); }
|
||||
|
||||
// IGetInStreamProcessedSize
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
};
|
||||
|
||||
class CCOMCoder : public CCoder { public: CCOMCoder(): CCoder(false) {} };
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "../../Common/ComTry.h"
|
||||
|
||||
#include "../Common/CWrappers.h"
|
||||
|
||||
#include "DeflateEncoder.h"
|
||||
|
||||
#undef NO_INLINE
|
||||
@@ -262,19 +264,19 @@ NO_INLINE void CCoder::GetMatches()
|
||||
UInt32 i;
|
||||
for (i = 0; i < numPairs; i += 2)
|
||||
{
|
||||
m_MatchDistances[i + 1] = (UInt16)distanceTmp[i];
|
||||
m_MatchDistances[i + 2] = (UInt16)distanceTmp[i + 1];
|
||||
m_MatchDistances[(size_t)i + 1] = (UInt16)distanceTmp[i];
|
||||
m_MatchDistances[(size_t)i + 2] = (UInt16)distanceTmp[(size_t)i + 1];
|
||||
}
|
||||
UInt32 len = distanceTmp[numPairs - 2];
|
||||
UInt32 len = distanceTmp[(size_t)numPairs - 2];
|
||||
if (len == m_NumFastBytes && m_NumFastBytes != m_MatchMaxLen)
|
||||
{
|
||||
UInt32 numAvail = Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) + 1;
|
||||
const Byte *pby = Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) - 1;
|
||||
const Byte *pby2 = pby - (distanceTmp[numPairs - 1] + 1);
|
||||
const Byte *pby2 = pby - (distanceTmp[(size_t)numPairs - 1] + 1);
|
||||
if (numAvail > m_MatchMaxLen)
|
||||
numAvail = m_MatchMaxLen;
|
||||
for (; len < numAvail && pby[len] == pby2[len]; len++);
|
||||
m_MatchDistances[i - 1] = (UInt16)len;
|
||||
m_MatchDistances[(size_t)i - 1] = (UInt16)len;
|
||||
}
|
||||
}
|
||||
if (m_IsMultiPass)
|
||||
@@ -337,11 +339,11 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
|
||||
if (numDistancePairs == 0)
|
||||
return 1;
|
||||
const UInt16 *matchDistances = m_MatchDistances + 1;
|
||||
lenEnd = matchDistances[numDistancePairs - 2];
|
||||
lenEnd = matchDistances[(size_t)numDistancePairs - 2];
|
||||
|
||||
if (lenEnd > m_NumFastBytes)
|
||||
{
|
||||
backRes = matchDistances[numDistancePairs - 1];
|
||||
backRes = matchDistances[(size_t)numDistancePairs - 1];
|
||||
MovePos(lenEnd - 1);
|
||||
return lenEnd;
|
||||
}
|
||||
@@ -356,10 +358,10 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
|
||||
|
||||
for (UInt32 i = kMatchMinLen; i <= lenEnd; i++)
|
||||
{
|
||||
UInt32 distance = matchDistances[offs + 1];
|
||||
UInt32 distance = matchDistances[(size_t)offs + 1];
|
||||
m_Optimum[i].PosPrev = 0;
|
||||
m_Optimum[i].BackPrev = (UInt16)distance;
|
||||
m_Optimum[i].Price = m_LenPrices[i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)];
|
||||
m_Optimum[i].Price = m_LenPrices[(size_t)i - kMatchMinLen] + m_PosPrices[GetPosSlot(distance)];
|
||||
if (i == matchDistances[offs])
|
||||
offs += 2;
|
||||
}
|
||||
@@ -378,11 +380,11 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
|
||||
UInt32 newLen = 0;
|
||||
if (numDistancePairs != 0)
|
||||
{
|
||||
newLen = matchDistances[numDistancePairs - 2];
|
||||
newLen = matchDistances[(size_t)numDistancePairs - 2];
|
||||
if (newLen > m_NumFastBytes)
|
||||
{
|
||||
UInt32 len = Backward(backRes, cur);
|
||||
m_Optimum[cur].BackPrev = matchDistances[numDistancePairs - 1];
|
||||
m_Optimum[cur].BackPrev = matchDistances[(size_t)numDistancePairs - 1];
|
||||
m_OptimumEndIndex = cur + newLen;
|
||||
m_Optimum[cur].PosPrev = (UInt16)m_OptimumEndIndex;
|
||||
MovePos(newLen - 1);
|
||||
@@ -392,7 +394,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
|
||||
UInt32 curPrice = m_Optimum[cur].Price;
|
||||
{
|
||||
const UInt32 curAnd1Price = curPrice + m_LiteralPrices[*(Inline_MatchFinder_GetPointerToCurrentPos(&_lzInWindow) + cur - m_AdditionalOffset)];
|
||||
COptimal &optimum = m_Optimum[cur + 1];
|
||||
COptimal &optimum = m_Optimum[(size_t)cur + 1];
|
||||
if (curAnd1Price < optimum.Price)
|
||||
{
|
||||
optimum.Price = curAnd1Price;
|
||||
@@ -404,11 +406,11 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
|
||||
while (lenEnd < cur + newLen)
|
||||
m_Optimum[++lenEnd].Price = kIfinityPrice;
|
||||
UInt32 offs = 0;
|
||||
UInt32 distance = matchDistances[offs + 1];
|
||||
UInt32 distance = matchDistances[(size_t)offs + 1];
|
||||
curPrice += m_PosPrices[GetPosSlot(distance)];
|
||||
for (UInt32 lenTest = kMatchMinLen; ; lenTest++)
|
||||
{
|
||||
UInt32 curAndLenPrice = curPrice + m_LenPrices[lenTest - kMatchMinLen];
|
||||
UInt32 curAndLenPrice = curPrice + m_LenPrices[(size_t)lenTest - kMatchMinLen];
|
||||
COptimal &optimum = m_Optimum[cur + lenTest];
|
||||
if (curAndLenPrice < optimum.Price)
|
||||
{
|
||||
@@ -422,7 +424,7 @@ NO_INLINE UInt32 CCoder::GetOptimal(UInt32 &backRes)
|
||||
if (offs == numDistancePairs)
|
||||
break;
|
||||
curPrice -= m_PosPrices[GetPosSlot(distance)];
|
||||
distance = matchDistances[offs + 1];
|
||||
distance = matchDistances[(size_t)offs + 1];
|
||||
curPrice += m_PosPrices[GetPosSlot(distance)];
|
||||
}
|
||||
}
|
||||
@@ -435,7 +437,7 @@ UInt32 CCoder::GetOptimalFast(UInt32 &backRes)
|
||||
UInt32 numDistancePairs = m_MatchDistances[0];
|
||||
if (numDistancePairs == 0)
|
||||
return 1;
|
||||
UInt32 lenMain = m_MatchDistances[numDistancePairs - 1];
|
||||
UInt32 lenMain = m_MatchDistances[(size_t)numDistancePairs - 1];
|
||||
backRes = m_MatchDistances[numDistancePairs];
|
||||
MovePos(lenMain - 1);
|
||||
return lenMain;
|
||||
@@ -470,7 +472,7 @@ NO_INLINE void CCoder::LevelTableDummy(const Byte *levels, unsigned numLevels, U
|
||||
for (unsigned n = 0; n < numLevels; n++)
|
||||
{
|
||||
unsigned curLen = nextLen;
|
||||
nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;
|
||||
nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF;
|
||||
count++;
|
||||
if (count < maxCount && curLen == nextLen)
|
||||
continue;
|
||||
@@ -537,7 +539,7 @@ NO_INLINE void CCoder::LevelTableCode(const Byte *levels, unsigned numLevels, co
|
||||
for (unsigned n = 0; n < numLevels; n++)
|
||||
{
|
||||
unsigned curLen = nextLen;
|
||||
nextLen = (n < numLevels - 1) ? levels[n + 1] : 0xFF;
|
||||
nextLen = (n < numLevels - 1) ? levels[(size_t)n + 1] : 0xFF;
|
||||
count++;
|
||||
if (count < maxCount && curLen == nextLen)
|
||||
continue;
|
||||
@@ -642,7 +644,7 @@ NO_INLINE void CCoder::TryBlock()
|
||||
{
|
||||
UInt32 newLen = len - kMatchMinLen;
|
||||
codeValue.Len = (UInt16)newLen;
|
||||
mainFreqs[kSymbolMatch + g_LenSlots[newLen]]++;
|
||||
mainFreqs[kSymbolMatch + (size_t)g_LenSlots[newLen]]++;
|
||||
codeValue.Pos = (UInt16)pos;
|
||||
distFreqs[GetPosSlot(pos)]++;
|
||||
}
|
||||
@@ -675,7 +677,7 @@ NO_INLINE void CCoder::SetPrices(const CLevels &levels)
|
||||
for (i = 0; i < m_NumLenCombinations; i++)
|
||||
{
|
||||
UInt32 slot = g_LenSlots[i];
|
||||
Byte price = levels.litLenLevels[kSymbolMatch + slot];
|
||||
Byte price = levels.litLenLevels[kSymbolMatch + (size_t)slot];
|
||||
m_LenPrices[i] = (Byte)(((price != 0) ? price : kNoLenStatPrice) + m_LenDirectBits[slot]);
|
||||
}
|
||||
|
||||
@@ -780,11 +782,11 @@ NO_INLINE UInt32 CCoder::TryDynBlock(unsigned tableIndex, UInt32 numPasses)
|
||||
(CLevels &)t = m_NewLevels;
|
||||
|
||||
m_NumLitLenLevels = kMainTableSize;
|
||||
while (m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[m_NumLitLenLevels - 1] == 0)
|
||||
while (m_NumLitLenLevels > kNumLitLenCodesMin && m_NewLevels.litLenLevels[(size_t)m_NumLitLenLevels - 1] == 0)
|
||||
m_NumLitLenLevels--;
|
||||
|
||||
m_NumDistLevels = kDistTableSize64;
|
||||
while (m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[m_NumDistLevels - 1] == 0)
|
||||
while (m_NumDistLevels > kNumDistCodesMin && m_NewLevels.distLevels[(size_t)m_NumDistLevels - 1] == 0)
|
||||
m_NumDistLevels--;
|
||||
|
||||
UInt32 levelFreqs[kLevelTableSize];
|
||||
@@ -923,14 +925,6 @@ void CCoder::CodeBlock(unsigned tableIndex, bool finalBlock)
|
||||
}
|
||||
}
|
||||
|
||||
SRes Read(void *object, void *data, size_t *size)
|
||||
{
|
||||
const UInt32 kStepSize = (UInt32)1 << 31;
|
||||
UInt32 curSize = ((*size < kStepSize) ? (UInt32)*size : kStepSize);
|
||||
HRESULT res = ((CSeqInStream *)object)->RealStream->Read(data, curSize, &curSize);
|
||||
*size = curSize;
|
||||
return (SRes)res;
|
||||
}
|
||||
|
||||
HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */ , const UInt64 * /* outSize */ , ICompressProgressInfo *progress)
|
||||
@@ -944,9 +938,11 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou
|
||||
|
||||
UInt64 nowPos = 0;
|
||||
|
||||
_seqInStream.RealStream = inStream;
|
||||
_seqInStream.SeqInStream.Read = Read;
|
||||
_lzInWindow.stream = &_seqInStream.SeqInStream;
|
||||
CSeqInStreamWrap _seqInStream;
|
||||
|
||||
_seqInStream.Init(inStream);
|
||||
|
||||
_lzInWindow.stream = &_seqInStream.vt;
|
||||
|
||||
MatchFinder_Init(&_lzInWindow);
|
||||
m_OutStream.SetStream(outStream);
|
||||
@@ -974,7 +970,7 @@ HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *ou
|
||||
}
|
||||
while (Inline_MatchFinder_GetNumAvailableBytes(&_lzInWindow) != 0);
|
||||
if (_lzInWindow.result != SZ_OK)
|
||||
return _lzInWindow.result;
|
||||
return SResToHRESULT(_lzInWindow.result);
|
||||
return m_OutStream.Flush();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,11 +46,6 @@ struct CTables: public CLevels
|
||||
void InitStructures();
|
||||
};
|
||||
|
||||
typedef struct _CSeqInStream
|
||||
{
|
||||
ISeqInStream SeqInStream;
|
||||
ISequentialInStream *RealStream;
|
||||
} CSeqInStream;
|
||||
|
||||
struct CEncProps
|
||||
{
|
||||
@@ -76,8 +71,6 @@ class CCoder
|
||||
CMatchFinder _lzInWindow;
|
||||
CBitlEncoder m_OutStream;
|
||||
|
||||
CSeqInStream _seqInStream;
|
||||
|
||||
public:
|
||||
CCodeValue *m_Values;
|
||||
|
||||
|
||||
@@ -8,45 +8,52 @@
|
||||
namespace NCompress {
|
||||
namespace NHuffman {
|
||||
|
||||
const unsigned kNumPairLenBits = 4;
|
||||
const unsigned kPairLenMask = (1 << kNumPairLenBits) - 1;
|
||||
|
||||
template <unsigned kNumBitsMax, UInt32 m_NumSymbols, unsigned kNumTableBits = 9>
|
||||
class CDecoder
|
||||
{
|
||||
public:
|
||||
UInt32 _limits[kNumBitsMax + 2];
|
||||
UInt32 _poses[kNumBitsMax + 1];
|
||||
UInt16 _lens[1 << kNumTableBits];
|
||||
UInt16 _symbols[m_NumSymbols];
|
||||
public:
|
||||
|
||||
bool Build(const Byte *lens) throw()
|
||||
{
|
||||
UInt32 lenCounts[kNumBitsMax + 1];
|
||||
UInt32 tmpPoses[kNumBitsMax + 1];
|
||||
UInt32 counts[kNumBitsMax + 1];
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i <= kNumBitsMax; i++)
|
||||
lenCounts[i] = 0;
|
||||
counts[i] = 0;
|
||||
|
||||
UInt32 sym;
|
||||
|
||||
for (sym = 0; sym < m_NumSymbols; sym++)
|
||||
lenCounts[lens[sym]]++;
|
||||
counts[lens[sym]]++;
|
||||
|
||||
lenCounts[0] = 0;
|
||||
_poses[0] = 0;
|
||||
_limits[0] = 0;
|
||||
UInt32 startPos = 0;
|
||||
const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
|
||||
|
||||
_limits[0] = 0;
|
||||
|
||||
UInt32 startPos = 0;
|
||||
UInt32 sum = 0;
|
||||
|
||||
for (i = 1; i <= kNumBitsMax; i++)
|
||||
{
|
||||
startPos += lenCounts[i] << (kNumBitsMax - i);
|
||||
const UInt32 cnt = counts[i];
|
||||
startPos += cnt << (kNumBitsMax - i);
|
||||
if (startPos > kMaxValue)
|
||||
return false;
|
||||
_limits[i] = startPos;
|
||||
_poses[i] = _poses[i - 1] + lenCounts[i - 1];
|
||||
tmpPoses[i] = _poses[i];
|
||||
counts[i] = sum;
|
||||
_poses[i] = sum;
|
||||
sum += cnt;
|
||||
}
|
||||
|
||||
counts[0] = sum;
|
||||
_poses[0] = sum;
|
||||
_limits[kNumBitsMax + 1] = kMaxValue;
|
||||
|
||||
for (sym = 0; sym < m_NumSymbols; sym++)
|
||||
@@ -55,16 +62,15 @@ public:
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
unsigned offset = tmpPoses[len];
|
||||
unsigned offset = counts[len]++;
|
||||
_symbols[offset] = (UInt16)sym;
|
||||
tmpPoses[len] = offset + 1;
|
||||
|
||||
if (len <= kNumTableBits)
|
||||
{
|
||||
offset -= _poses[len];
|
||||
UInt32 num = (UInt32)1 << (kNumTableBits - len);
|
||||
UInt16 val = (UInt16)((sym << 4) | len);
|
||||
UInt16 *dest = _lens + (_limits[len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len));
|
||||
UInt16 val = (UInt16)((sym << kNumPairLenBits) | len);
|
||||
UInt16 *dest = _lens + (_limits[(size_t)len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len));
|
||||
for (UInt32 k = 0; k < num; k++)
|
||||
dest[k] = val;
|
||||
}
|
||||
@@ -73,36 +79,41 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BuildFull(const Byte *lens, UInt32 numSymbols = m_NumSymbols) throw()
|
||||
{
|
||||
UInt32 lenCounts[kNumBitsMax + 1];
|
||||
UInt32 tmpPoses[kNumBitsMax + 1];
|
||||
UInt32 counts[kNumBitsMax + 1];
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i <= kNumBitsMax; i++)
|
||||
lenCounts[i] = 0;
|
||||
counts[i] = 0;
|
||||
|
||||
UInt32 sym;
|
||||
|
||||
for (sym = 0; sym < numSymbols; sym++)
|
||||
lenCounts[lens[sym]]++;
|
||||
counts[lens[sym]]++;
|
||||
|
||||
lenCounts[0] = 0;
|
||||
_poses[0] = 0;
|
||||
_limits[0] = 0;
|
||||
UInt32 startPos = 0;
|
||||
const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
|
||||
|
||||
_limits[0] = 0;
|
||||
|
||||
UInt32 startPos = 0;
|
||||
UInt32 sum = 0;
|
||||
|
||||
for (i = 1; i <= kNumBitsMax; i++)
|
||||
{
|
||||
startPos += lenCounts[i] << (kNumBitsMax - i);
|
||||
const UInt32 cnt = counts[i];
|
||||
startPos += cnt << (kNumBitsMax - i);
|
||||
if (startPos > kMaxValue)
|
||||
return false;
|
||||
_limits[i] = startPos;
|
||||
_poses[i] = _poses[i - 1] + lenCounts[i - 1];
|
||||
tmpPoses[i] = _poses[i];
|
||||
counts[i] = sum;
|
||||
_poses[i] = sum;
|
||||
sum += cnt;
|
||||
}
|
||||
|
||||
counts[0] = sum;
|
||||
_poses[0] = sum;
|
||||
_limits[kNumBitsMax + 1] = kMaxValue;
|
||||
|
||||
for (sym = 0; sym < numSymbols; sym++)
|
||||
@@ -111,16 +122,15 @@ public:
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
unsigned offset = tmpPoses[len];
|
||||
unsigned offset = counts[len]++;
|
||||
_symbols[offset] = (UInt16)sym;
|
||||
tmpPoses[len] = offset + 1;
|
||||
|
||||
if (len <= kNumTableBits)
|
||||
{
|
||||
offset -= _poses[len];
|
||||
UInt32 num = (UInt32)1 << (kNumTableBits - len);
|
||||
UInt16 val = (UInt16)((sym << 4) | len);
|
||||
UInt16 *dest = _lens + (_limits[len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len));
|
||||
UInt16 val = (UInt16)((sym << kNumPairLenBits) | len);
|
||||
UInt16 *dest = _lens + (_limits[(size_t)len - 1] >> (kNumBitsMax - kNumTableBits)) + (offset << (kNumTableBits - len));
|
||||
for (UInt32 k = 0; k < num; k++)
|
||||
dest[k] = val;
|
||||
}
|
||||
@@ -129,16 +139,18 @@ public:
|
||||
return startPos == kMaxValue;
|
||||
}
|
||||
|
||||
|
||||
template <class TBitDecoder>
|
||||
UInt32 Decode(TBitDecoder *bitStream) const throw()
|
||||
MY_FORCE_INLINE
|
||||
UInt32 Decode(TBitDecoder *bitStream) const
|
||||
{
|
||||
UInt32 val = bitStream->GetValue(kNumBitsMax);
|
||||
|
||||
if (val < _limits[kNumTableBits])
|
||||
{
|
||||
UInt32 pair = _lens[val >> (kNumBitsMax - kNumTableBits)];
|
||||
bitStream->MovePos((unsigned)(pair & 0xF));
|
||||
return pair >> 4;
|
||||
bitStream->MovePos((unsigned)(pair & kPairLenMask));
|
||||
return pair >> kNumPairLenBits;
|
||||
}
|
||||
|
||||
unsigned numBits;
|
||||
@@ -148,27 +160,29 @@ public:
|
||||
return 0xFFFFFFFF;
|
||||
|
||||
bitStream->MovePos(numBits);
|
||||
UInt32 index = _poses[numBits] + ((val - _limits[numBits - 1]) >> (kNumBitsMax - numBits));
|
||||
UInt32 index = _poses[numBits] + ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits));
|
||||
return _symbols[index];
|
||||
}
|
||||
|
||||
|
||||
template <class TBitDecoder>
|
||||
UInt32 DecodeFull(TBitDecoder *bitStream) const throw()
|
||||
MY_FORCE_INLINE
|
||||
UInt32 DecodeFull(TBitDecoder *bitStream) const
|
||||
{
|
||||
UInt32 val = bitStream->GetValue(kNumBitsMax);
|
||||
|
||||
if (val < _limits[kNumTableBits])
|
||||
{
|
||||
UInt32 pair = _lens[val >> (kNumBitsMax - kNumTableBits)];
|
||||
bitStream->MovePos((unsigned)(pair & 0xF));
|
||||
return pair >> 4;
|
||||
bitStream->MovePos((unsigned)(pair & kPairLenMask));
|
||||
return pair >> kNumPairLenBits;
|
||||
}
|
||||
|
||||
unsigned numBits;
|
||||
for (numBits = kNumTableBits + 1; val >= _limits[numBits]; numBits++);
|
||||
|
||||
bitStream->MovePos(numBits);
|
||||
UInt32 index = _poses[numBits] + ((val - _limits[numBits - 1]) >> (kNumBitsMax - numBits));
|
||||
UInt32 index = _poses[numBits] + ((val - _limits[(size_t)numBits - 1]) >> (kNumBitsMax - numBits));
|
||||
return _symbols[index];
|
||||
}
|
||||
};
|
||||
@@ -185,50 +199,54 @@ public:
|
||||
{
|
||||
const unsigned kNumBitsMax = 7;
|
||||
|
||||
UInt32 lenCounts[kNumBitsMax + 1];
|
||||
UInt32 tmpPoses[kNumBitsMax + 1];
|
||||
UInt32 counts[kNumBitsMax + 1];
|
||||
UInt32 _poses[kNumBitsMax + 1];
|
||||
UInt32 _limits[kNumBitsMax + 1];
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i <= kNumBitsMax; i++)
|
||||
lenCounts[i] = 0;
|
||||
counts[i] = 0;
|
||||
|
||||
UInt32 sym;
|
||||
|
||||
for (sym = 0; sym < m_NumSymbols; sym++)
|
||||
lenCounts[lens[sym]]++;
|
||||
counts[lens[sym]]++;
|
||||
|
||||
lenCounts[0] = 0;
|
||||
_poses[0] = 0;
|
||||
_limits[0] = 0;
|
||||
UInt32 startPos = 0;
|
||||
const UInt32 kMaxValue = (UInt32)1 << kNumBitsMax;
|
||||
|
||||
_limits[0] = 0;
|
||||
|
||||
UInt32 startPos = 0;
|
||||
UInt32 sum = 0;
|
||||
|
||||
for (i = 1; i <= kNumBitsMax; i++)
|
||||
{
|
||||
startPos += lenCounts[i] << (kNumBitsMax - i);
|
||||
const UInt32 cnt = counts[i];
|
||||
startPos += cnt << (kNumBitsMax - i);
|
||||
if (startPos > kMaxValue)
|
||||
return false;
|
||||
_limits[i] = startPos;
|
||||
_poses[i] = _poses[i - 1] + lenCounts[i - 1];
|
||||
tmpPoses[i] = _poses[i];
|
||||
counts[i] = sum;
|
||||
_poses[i] = sum;
|
||||
sum += cnt;
|
||||
}
|
||||
|
||||
counts[0] = sum;
|
||||
_poses[0] = sum;
|
||||
|
||||
for (sym = 0; sym < m_NumSymbols; sym++)
|
||||
{
|
||||
unsigned len = lens[sym];
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
unsigned offset = tmpPoses[len];
|
||||
tmpPoses[len] = offset + 1;
|
||||
unsigned offset = counts[len]++;
|
||||
|
||||
{
|
||||
offset -= _poses[len];
|
||||
UInt32 num = (UInt32)1 << (kNumBitsMax - len);
|
||||
Byte val = (Byte)((sym << 3) | len);
|
||||
Byte *dest = _lens + (_limits[len - 1]) + (offset << (kNumBitsMax - len));
|
||||
Byte *dest = _lens + (_limits[(size_t)len - 1]) + (offset << (kNumBitsMax - len));
|
||||
for (UInt32 k = 0; k < num; k++)
|
||||
dest[k] = val;
|
||||
}
|
||||
@@ -246,7 +264,7 @@ public:
|
||||
}
|
||||
|
||||
template <class TBitDecoder>
|
||||
UInt32 Decode(TBitDecoder *bitStream) const throw()
|
||||
UInt32 Decode(TBitDecoder *bitStream) const
|
||||
{
|
||||
UInt32 val = bitStream->GetValue(7);
|
||||
UInt32 pair = _lens[val];
|
||||
|
||||
@@ -10,214 +10,248 @@ namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NDecoder {
|
||||
|
||||
class CException
|
||||
bool CHuffmanDecoder::Build(const Byte *lens, unsigned numSymbols) throw()
|
||||
{
|
||||
public:
|
||||
enum ECauseType
|
||||
unsigned counts[kNumHuffmanBits + 1];
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i <= kNumHuffmanBits; i++)
|
||||
counts[i] = 0;
|
||||
|
||||
unsigned sym;
|
||||
for (sym = 0; sym < numSymbols; sym++)
|
||||
counts[lens[sym]]++;
|
||||
|
||||
const UInt32 kMaxValue = (UInt32)1 << kNumHuffmanBits;
|
||||
|
||||
// _limits[0] = kMaxValue;
|
||||
|
||||
UInt32 startPos = kMaxValue;
|
||||
UInt32 sum = 0;
|
||||
|
||||
for (i = 1; i <= kNumHuffmanBits; i++)
|
||||
{
|
||||
kData
|
||||
} m_Cause;
|
||||
CException(ECauseType cause): m_Cause(cause) {}
|
||||
};
|
||||
const UInt32 cnt = counts[i];
|
||||
const UInt32 range = cnt << (kNumHuffmanBits - i);
|
||||
if (startPos < range)
|
||||
return false;
|
||||
startPos -= range;
|
||||
_limits[i] = startPos;
|
||||
_poses[i] = sum;
|
||||
sum += cnt;
|
||||
counts[i] = sum;
|
||||
}
|
||||
|
||||
static const int kNumDistanceLowDirectBitsForBigDict = 7;
|
||||
static const int kNumDistanceLowDirectBitsForSmallDict = 6;
|
||||
// counts[0] += sum;
|
||||
|
||||
static const int kNumBitsInByte = 8;
|
||||
if (startPos != 0)
|
||||
return false;
|
||||
|
||||
// static const int kLevelStructuresNumberFieldSize = kNumBitsInByte;
|
||||
static const int kLevelStructuresNumberAdditionalValue = 1;
|
||||
for (sym = 0; sym < numSymbols; sym++)
|
||||
{
|
||||
unsigned len = lens[sym];
|
||||
if (len != 0)
|
||||
_symbols[--counts[len]] = (Byte)sym;
|
||||
}
|
||||
|
||||
static const int kNumLevelStructureLevelBits = 4;
|
||||
static const int kLevelStructureLevelAdditionalValue = 1;
|
||||
|
||||
static const int kNumLevelStructureRepNumberBits = 4;
|
||||
static const int kLevelStructureRepNumberAdditionalValue = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static const int kLiteralTableSize = (1 << kNumBitsInByte);
|
||||
static const int kDistanceTableSize = 64;
|
||||
static const int kLengthTableSize = 64;
|
||||
|
||||
static const UInt32 kHistorySize =
|
||||
(1 << MyMax(kNumDistanceLowDirectBitsForBigDict,
|
||||
kNumDistanceLowDirectBitsForSmallDict)) *
|
||||
kDistanceTableSize; // = 8 KB;
|
||||
|
||||
static const int kNumAdditionalLengthBits = 8;
|
||||
|
||||
static const UInt32 kMatchMinLenWhenLiteralsOn = 3;
|
||||
static const UInt32 kMatchMinLenWhenLiteralsOff = 2;
|
||||
|
||||
static const UInt32 kMatchMinLenMax = MyMax(kMatchMinLenWhenLiteralsOn,
|
||||
kMatchMinLenWhenLiteralsOff); // 3
|
||||
|
||||
// static const UInt32 kMatchMaxLenMax = kMatchMinLenMax + (kLengthTableSize - 1) + (1 << kNumAdditionalLengthBits) - 1; // or 2
|
||||
|
||||
enum
|
||||
UInt32 CHuffmanDecoder::Decode(CInBit *inStream) const throw()
|
||||
{
|
||||
kMatchId = 0,
|
||||
kLiteralId = 1
|
||||
};
|
||||
UInt32 val = inStream->GetValue(kNumHuffmanBits);
|
||||
unsigned numBits;
|
||||
for (numBits = 1; val < _limits[numBits]; numBits++);
|
||||
UInt32 sym = _symbols[_poses[numBits] + ((val - _limits[numBits]) >> (kNumHuffmanBits - numBits))];
|
||||
inStream->MovePos(numBits);
|
||||
return sym;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const unsigned kNumLenDirectBits = 8;
|
||||
|
||||
static const unsigned kNumDistDirectBitsSmall = 6;
|
||||
static const unsigned kNumDistDirectBitsBig = 7;
|
||||
|
||||
static const unsigned kLitTableSize = (1 << 8);
|
||||
static const unsigned kDistTableSize = 64;
|
||||
static const unsigned kLenTableSize = 64;
|
||||
|
||||
static const UInt32 kHistorySize = (1 << kNumDistDirectBitsBig) * kDistTableSize; // 8 KB
|
||||
|
||||
|
||||
CCoder::CCoder():
|
||||
m_LiteralDecoder(kLiteralTableSize),
|
||||
m_LengthDecoder(kLengthTableSize),
|
||||
m_DistanceDecoder(kDistanceTableSize)
|
||||
{
|
||||
}
|
||||
_fullStreamMode(false),
|
||||
_flags(0)
|
||||
{}
|
||||
|
||||
/*
|
||||
void CCoder::ReleaseStreams()
|
||||
{
|
||||
m_OutWindowStream.ReleaseStream();
|
||||
m_InBitStream.ReleaseStream();
|
||||
}
|
||||
*/
|
||||
|
||||
bool CCoder::ReadLevelItems(NImplode::NHuffman::CDecoder &decoder,
|
||||
Byte *levels, int numLevelItems)
|
||||
bool CCoder::BuildHuff(CHuffmanDecoder &decoder, unsigned numSymbols)
|
||||
{
|
||||
int numCodedStructures = m_InBitStream.ReadBits(kNumBitsInByte) +
|
||||
kLevelStructuresNumberAdditionalValue;
|
||||
int currentIndex = 0;
|
||||
for (int i = 0; i < numCodedStructures; i++)
|
||||
Byte levels[kMaxHuffTableSize];
|
||||
unsigned numRecords = (unsigned)_inBitStream.ReadAlignedByte() + 1;
|
||||
unsigned index = 0;
|
||||
do
|
||||
{
|
||||
int level = m_InBitStream.ReadBits(kNumLevelStructureLevelBits) +
|
||||
kLevelStructureLevelAdditionalValue;
|
||||
int rep = m_InBitStream.ReadBits(kNumLevelStructureRepNumberBits) +
|
||||
kLevelStructureRepNumberAdditionalValue;
|
||||
if (currentIndex + rep > numLevelItems)
|
||||
throw CException(CException::kData);
|
||||
for (int j = 0; j < rep; j++)
|
||||
levels[currentIndex++] = (Byte)level;
|
||||
}
|
||||
if (currentIndex != numLevelItems)
|
||||
return false;
|
||||
return decoder.SetCodeLengths(levels);
|
||||
}
|
||||
|
||||
|
||||
bool CCoder::ReadTables(void)
|
||||
{
|
||||
if (m_LiteralsOn)
|
||||
{
|
||||
Byte literalLevels[kLiteralTableSize];
|
||||
if (!ReadLevelItems(m_LiteralDecoder, literalLevels, kLiteralTableSize))
|
||||
unsigned b = (unsigned)_inBitStream.ReadAlignedByte();
|
||||
Byte level = (Byte)((b & 0xF) + 1);
|
||||
unsigned rep = ((unsigned)b >> 4) + 1;
|
||||
if (index + rep > numSymbols)
|
||||
return false;
|
||||
for (unsigned j = 0; j < rep; j++)
|
||||
levels[index++] = level;
|
||||
}
|
||||
while (--numRecords);
|
||||
|
||||
Byte lengthLevels[kLengthTableSize];
|
||||
if (!ReadLevelItems(m_LengthDecoder, lengthLevels, kLengthTableSize))
|
||||
if (index != numSymbols)
|
||||
return false;
|
||||
|
||||
Byte distanceLevels[kDistanceTableSize];
|
||||
return ReadLevelItems(m_DistanceDecoder, distanceLevels, kDistanceTableSize);
|
||||
return decoder.Build(levels, numSymbols);
|
||||
}
|
||||
|
||||
/*
|
||||
class CCoderReleaser
|
||||
{
|
||||
CCoder *m_Coder;
|
||||
public:
|
||||
CCoderReleaser(CCoder *coder): m_Coder(coder) {}
|
||||
~CCoderReleaser() { m_Coder->ReleaseStreams(); }
|
||||
};
|
||||
*/
|
||||
|
||||
HRESULT CCoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
if (!m_InBitStream.Create(1 << 20))
|
||||
if (!_inBitStream.Create(1 << 18))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!m_OutWindowStream.Create(kHistorySize))
|
||||
if (!_outWindowStream.Create(kHistorySize << 1)) // 16 KB
|
||||
return E_OUTOFMEMORY;
|
||||
if (outSize == NULL)
|
||||
if (!outSize)
|
||||
return E_INVALIDARG;
|
||||
|
||||
_outWindowStream.SetStream(outStream);
|
||||
_outWindowStream.Init(false);
|
||||
_inBitStream.SetStream(inStream);
|
||||
_inBitStream.Init();
|
||||
|
||||
const unsigned numDistDirectBits = (_flags & 2) ?
|
||||
kNumDistDirectBitsBig:
|
||||
kNumDistDirectBitsSmall;
|
||||
const bool literalsOn = ((_flags & 4) != 0);
|
||||
const UInt32 minMatchLen = (literalsOn ? 3 : 2);
|
||||
|
||||
if (literalsOn)
|
||||
if (!BuildHuff(_litDecoder, kLitTableSize))
|
||||
return S_FALSE;
|
||||
if (!BuildHuff(_lenDecoder, kLenTableSize))
|
||||
return S_FALSE;
|
||||
if (!BuildHuff(_distDecoder, kDistTableSize))
|
||||
return S_FALSE;
|
||||
|
||||
UInt64 prevProgress = 0;
|
||||
bool moreOut = false;
|
||||
UInt64 pos = 0, unPackSize = *outSize;
|
||||
|
||||
m_OutWindowStream.SetStream(outStream);
|
||||
m_OutWindowStream.Init(false);
|
||||
m_InBitStream.SetStream(inStream);
|
||||
m_InBitStream.Init();
|
||||
// CCoderReleaser coderReleaser(this);
|
||||
|
||||
if (!ReadTables())
|
||||
return S_FALSE;
|
||||
|
||||
while (pos < unPackSize)
|
||||
{
|
||||
if (progress != NULL && pos % (1 << 16) == 0)
|
||||
if (progress && (pos - prevProgress) >= (1 << 18))
|
||||
{
|
||||
UInt64 packSize = m_InBitStream.GetProcessedSize();
|
||||
const UInt64 packSize = _inBitStream.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &pos));
|
||||
prevProgress = pos;
|
||||
}
|
||||
if (m_InBitStream.ReadBits(1) == kMatchId) // match
|
||||
|
||||
if (_inBitStream.ReadBits(1) != 0)
|
||||
{
|
||||
UInt32 lowDistBits = m_InBitStream.ReadBits(m_NumDistanceLowDirectBits);
|
||||
UInt32 distance = m_DistanceDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (distance >= kDistanceTableSize)
|
||||
return S_FALSE;
|
||||
distance = (distance << m_NumDistanceLowDirectBits) + lowDistBits;
|
||||
UInt32 lengthSymbol = m_LengthDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (lengthSymbol >= kLengthTableSize)
|
||||
return S_FALSE;
|
||||
UInt32 length = lengthSymbol + m_MinMatchLength;
|
||||
if (lengthSymbol == kLengthTableSize - 1) // special symbol = 63
|
||||
length += m_InBitStream.ReadBits(kNumAdditionalLengthBits);
|
||||
while (distance >= pos && length > 0)
|
||||
Byte b;
|
||||
if (literalsOn)
|
||||
{
|
||||
m_OutWindowStream.PutByte(0);
|
||||
pos++;
|
||||
length--;
|
||||
UInt32 sym = _litDecoder.Decode(&_inBitStream);
|
||||
// if (sym >= kLitTableSize) break;
|
||||
b = (Byte)sym;
|
||||
}
|
||||
if (length > 0)
|
||||
m_OutWindowStream.CopyBlock(distance, length);
|
||||
pos += length;
|
||||
else
|
||||
b = (Byte)_inBitStream.ReadBits(8);
|
||||
_outWindowStream.PutByte(b);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Byte b;
|
||||
if (m_LiteralsOn)
|
||||
UInt32 lowDistBits = _inBitStream.ReadBits(numDistDirectBits);
|
||||
UInt32 dist = _distDecoder.Decode(&_inBitStream);
|
||||
// if (dist >= kDistTableSize) break;
|
||||
dist = (dist << numDistDirectBits) + lowDistBits;
|
||||
UInt32 len = _lenDecoder.Decode(&_inBitStream);
|
||||
// if (len >= kLenTableSize) break;
|
||||
if (len == kLenTableSize - 1)
|
||||
len += _inBitStream.ReadBits(kNumLenDirectBits);
|
||||
len += minMatchLen;
|
||||
|
||||
{
|
||||
UInt32 temp = m_LiteralDecoder.DecodeSymbol(&m_InBitStream);
|
||||
if (temp >= kLiteralTableSize)
|
||||
return S_FALSE;
|
||||
b = (Byte)temp;
|
||||
const UInt64 limit = unPackSize - pos;
|
||||
if (len > limit)
|
||||
{
|
||||
moreOut = true;
|
||||
len = (UInt32)limit;
|
||||
}
|
||||
}
|
||||
|
||||
while (dist >= pos && len != 0)
|
||||
{
|
||||
_outWindowStream.PutByte(0);
|
||||
pos++;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
{
|
||||
_outWindowStream.CopyBlock(dist, len);
|
||||
pos += len;
|
||||
}
|
||||
else
|
||||
b = (Byte)m_InBitStream.ReadBits(kNumBitsInByte);
|
||||
m_OutWindowStream.PutByte(b);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
if (pos > unPackSize)
|
||||
return S_FALSE;
|
||||
return m_OutWindowStream.Flush();
|
||||
|
||||
HRESULT res = _outWindowStream.Flush();
|
||||
|
||||
if (res == S_OK)
|
||||
{
|
||||
if (_fullStreamMode)
|
||||
{
|
||||
if (moreOut)
|
||||
res = S_FALSE;
|
||||
if (inSize && *inSize != _inBitStream.GetProcessedSize())
|
||||
res = S_FALSE;
|
||||
}
|
||||
if (pos != unPackSize)
|
||||
res = S_FALSE;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
|
||||
catch(const CLzOutWindowException &e) { return e.ErrorCode; }
|
||||
// catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
// catch(const CLzOutWindowException &e) { return e.ErrorCode; }
|
||||
catch(const CSystemException &e) { return e.ErrorCode; }
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
|
||||
{
|
||||
if (size < 1)
|
||||
return E_INVALIDARG;
|
||||
Byte flag = data[0];
|
||||
m_BigDictionaryOn = ((flag & 2) != 0);
|
||||
m_NumDistanceLowDirectBits = m_BigDictionaryOn ?
|
||||
kNumDistanceLowDirectBitsForBigDict:
|
||||
kNumDistanceLowDirectBitsForSmallDict;
|
||||
m_LiteralsOn = ((flag & 4) != 0);
|
||||
m_MinMatchLength = m_LiteralsOn ?
|
||||
kMatchMinLenWhenLiteralsOn :
|
||||
kMatchMinLenWhenLiteralsOff;
|
||||
if (size == 0)
|
||||
return E_NOTIMPL;
|
||||
_flags = data[0];
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::SetFinishMode(UInt32 finishMode)
|
||||
{
|
||||
_fullStreamMode = (finishMode != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CCoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _inBitStream.GetProcessedSize();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,48 +7,65 @@
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
#include "ImplodeHuffmanDecoder.h"
|
||||
#include "../Common/InBuffer.h"
|
||||
|
||||
#include "BitlDecoder.h"
|
||||
#include "LzOutWindow.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NDecoder {
|
||||
|
||||
typedef NBitl::CDecoder<CInBuffer> CInBit;
|
||||
|
||||
const unsigned kNumHuffmanBits = 16;
|
||||
const unsigned kMaxHuffTableSize = 1 << 8;
|
||||
|
||||
class CHuffmanDecoder
|
||||
{
|
||||
UInt32 _limits[kNumHuffmanBits + 1];
|
||||
UInt32 _poses[kNumHuffmanBits + 1];
|
||||
Byte _symbols[kMaxHuffTableSize];
|
||||
public:
|
||||
bool Build(const Byte *lens, unsigned numSymbols) throw();
|
||||
UInt32 Decode(CInBit *inStream) const throw();
|
||||
};
|
||||
|
||||
|
||||
class CCoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetDecoderProperties2,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CLzOutWindow m_OutWindowStream;
|
||||
NBitl::CDecoder<CInBuffer> m_InBitStream;
|
||||
CLzOutWindow _outWindowStream;
|
||||
CInBit _inBitStream;
|
||||
|
||||
NImplode::NHuffman::CDecoder m_LiteralDecoder;
|
||||
NImplode::NHuffman::CDecoder m_LengthDecoder;
|
||||
NImplode::NHuffman::CDecoder m_DistanceDecoder;
|
||||
CHuffmanDecoder _litDecoder;
|
||||
CHuffmanDecoder _lenDecoder;
|
||||
CHuffmanDecoder _distDecoder;
|
||||
|
||||
bool m_BigDictionaryOn;
|
||||
bool m_LiteralsOn;
|
||||
Byte _flags;
|
||||
bool _fullStreamMode;
|
||||
|
||||
int m_NumDistanceLowDirectBits;
|
||||
UInt32 m_MinMatchLength;
|
||||
|
||||
bool ReadLevelItems(NImplode::NHuffman::CDecoder &table, Byte *levels, int numLevelItems);
|
||||
bool ReadTables();
|
||||
void DeCodeLevelTable(Byte *newLevels, int numLevels);
|
||||
public:
|
||||
CCoder();
|
||||
|
||||
MY_UNKNOWN_IMP1(ICompressSetDecoderProperties2)
|
||||
|
||||
// void ReleaseStreams();
|
||||
|
||||
bool BuildHuff(CHuffmanDecoder &table, unsigned numSymbols);
|
||||
HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP3(
|
||||
ICompressSetDecoderProperties2,
|
||||
ICompressSetFinishMode,
|
||||
ICompressGetInStreamProcessedSize)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
|
||||
CCoder();
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -1,89 +1,3 @@
|
||||
// ImplodeHuffmanDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "ImplodeHuffmanDecoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NHuffman {
|
||||
|
||||
CDecoder::CDecoder(UInt32 numSymbols):
|
||||
m_NumSymbols(numSymbols)
|
||||
{
|
||||
m_Symbols = new UInt32[m_NumSymbols];
|
||||
}
|
||||
|
||||
CDecoder::~CDecoder()
|
||||
{
|
||||
delete []m_Symbols;
|
||||
}
|
||||
|
||||
bool CDecoder::SetCodeLengths(const Byte *codeLengths)
|
||||
{
|
||||
// unsigned lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];
|
||||
unsigned lenCounts[kNumBitsInLongestCode + 2], tmpPositions[kNumBitsInLongestCode + 1];
|
||||
unsigned i;
|
||||
for (i = 0; i <= kNumBitsInLongestCode; i++)
|
||||
lenCounts[i] = 0;
|
||||
UInt32 symbolIndex;
|
||||
for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++)
|
||||
lenCounts[codeLengths[symbolIndex]]++;
|
||||
// lenCounts[0] = 0;
|
||||
|
||||
// tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0;
|
||||
m_Limitits[kNumBitsInLongestCode + 1] = 0;
|
||||
m_Positions[kNumBitsInLongestCode + 1] = 0;
|
||||
lenCounts[kNumBitsInLongestCode + 1] = 0;
|
||||
|
||||
|
||||
UInt32 startPos = 0;
|
||||
static const UInt32 kMaxValue = (1 << kNumBitsInLongestCode);
|
||||
|
||||
for (i = kNumBitsInLongestCode; i > 0; i--)
|
||||
{
|
||||
startPos += lenCounts[i] << (kNumBitsInLongestCode - i);
|
||||
if (startPos > kMaxValue)
|
||||
return false;
|
||||
m_Limitits[i] = startPos;
|
||||
m_Positions[i] = m_Positions[i + 1] + lenCounts[i + 1];
|
||||
tmpPositions[i] = m_Positions[i] + lenCounts[i];
|
||||
|
||||
}
|
||||
|
||||
// if _ZIP_MODE do not throw exception for trees containing only one node
|
||||
// #ifndef _ZIP_MODE
|
||||
if (startPos != kMaxValue)
|
||||
return false;
|
||||
// #endif
|
||||
|
||||
for (symbolIndex = 0; symbolIndex < m_NumSymbols; symbolIndex++)
|
||||
if (codeLengths[symbolIndex] != 0)
|
||||
m_Symbols[--tmpPositions[codeLengths[symbolIndex]]] = symbolIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
UInt32 CDecoder::DecodeSymbol(CInBit *inStream)
|
||||
{
|
||||
UInt32 numBits = 0;
|
||||
UInt32 value = inStream->GetValue(kNumBitsInLongestCode);
|
||||
unsigned i;
|
||||
for (i = kNumBitsInLongestCode; i > 0; i--)
|
||||
{
|
||||
if (value < m_Limitits[i])
|
||||
{
|
||||
numBits = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 0)
|
||||
return 0xFFFFFFFF;
|
||||
inStream->MovePos(numBits);
|
||||
UInt32 index = m_Positions[numBits] +
|
||||
((value - m_Limitits[numBits + 1]) >> (kNumBitsInLongestCode - numBits));
|
||||
if (index >= m_NumSymbols)
|
||||
return 0xFFFFFFFF;
|
||||
return m_Symbols[index];
|
||||
}
|
||||
|
||||
}}}
|
||||
|
||||
@@ -3,32 +3,4 @@
|
||||
#ifndef __IMPLODE_HUFFMAN_DECODER_H
|
||||
#define __IMPLODE_HUFFMAN_DECODER_H
|
||||
|
||||
#include "../Common/InBuffer.h"
|
||||
|
||||
#include "BitlDecoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NImplode {
|
||||
namespace NHuffman {
|
||||
|
||||
const unsigned kNumBitsInLongestCode = 16;
|
||||
|
||||
typedef NBitl::CDecoder<CInBuffer> CInBit;
|
||||
|
||||
class CDecoder
|
||||
{
|
||||
UInt32 m_Limitits[kNumBitsInLongestCode + 2]; // m_Limitits[i] = value limit for symbols with length = i
|
||||
UInt32 m_Positions[kNumBitsInLongestCode + 2]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
|
||||
UInt32 m_NumSymbols; // number of symbols in m_Symbols
|
||||
UInt32 *m_Symbols; // symbols: at first with len=1 then 2, ... 15.
|
||||
public:
|
||||
CDecoder(UInt32 numSymbols);
|
||||
~CDecoder();
|
||||
|
||||
bool SetCodeLengths(const Byte *codeLengths);
|
||||
UInt32 DecodeSymbol(CInBit *inStream);
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@ static HRESULT SResToHRESULT(SRes res)
|
||||
case SZ_OK: return S_OK;
|
||||
case SZ_ERROR_MEM: return E_OUTOFMEMORY;
|
||||
case SZ_ERROR_PARAM: return E_INVALIDARG;
|
||||
// case SZ_ERROR_PROGRESS: return E_ABORT;
|
||||
case SZ_ERROR_UNSUPPORTED: return E_NOTIMPL;
|
||||
case SZ_ERROR_DATA: return S_FALSE;
|
||||
}
|
||||
return E_FAIL;
|
||||
@@ -26,30 +26,31 @@ namespace NLzma2 {
|
||||
|
||||
CDecoder::CDecoder():
|
||||
_inBuf(NULL),
|
||||
_inBufSize(0),
|
||||
_inBufSizeNew(1 << 20),
|
||||
_outStepSize(1 << 22),
|
||||
_finishMode(false),
|
||||
_outSizeDefined(false),
|
||||
_finishMode(false)
|
||||
_outStep(1 << 22),
|
||||
_inBufSize(0),
|
||||
_inBufSizeNew(1 << 20)
|
||||
{
|
||||
Lzma2Dec_Construct(&_state);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStepSize = size; return S_OK; }
|
||||
|
||||
CDecoder::~CDecoder()
|
||||
{
|
||||
Lzma2Dec_Free(&_state, &g_Alloc);
|
||||
MidFree(_inBuf);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
|
||||
{
|
||||
if (size != 1)
|
||||
return E_NOTIMPL;
|
||||
|
||||
RINOK(SResToHRESULT(Lzma2Dec_Allocate(&_state, prop[0], &g_Alloc)));
|
||||
|
||||
if (!_inBuf || _inBufSize != _inBufSizeNew)
|
||||
{
|
||||
MidFree(_inBuf);
|
||||
@@ -63,9 +64,6 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) { *value = _inSizeProcessed; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
|
||||
STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
|
||||
|
||||
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
@@ -73,191 +71,197 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
_outSize = 0;
|
||||
if (_outSizeDefined)
|
||||
_outSize = *outSize;
|
||||
_inPos = _inLim = 0;
|
||||
_inProcessed = 0;
|
||||
_outProcessed = 0;
|
||||
|
||||
Lzma2Dec_Init(&_state);
|
||||
|
||||
_inPos = _inSize = 0;
|
||||
_inSizeProcessed = _outSizeProcessed = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
|
||||
{
|
||||
_finishMode = (finishMode != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize,
|
||||
const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _inProcessed;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
if (!_inBuf)
|
||||
return S_FALSE;
|
||||
|
||||
SetOutStreamSize(outSize);
|
||||
|
||||
UInt32 step = _outStepSize;
|
||||
const UInt32 kOutStepSize_Min = 1 << 12;
|
||||
if (step < kOutStepSize_Min)
|
||||
step = kOutStepSize_Min;
|
||||
|
||||
SizeT wrPos = _state.decoder.dicPos;
|
||||
|
||||
SizeT next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?
|
||||
_state.decoder.dicBufSize :
|
||||
_state.decoder.dicPos + step;
|
||||
|
||||
HRESULT hres = S_OK;
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (_inPos == _inSize)
|
||||
if (_inPos == _inLim && readRes == S_OK)
|
||||
{
|
||||
_inPos = _inSize = 0;
|
||||
hres = inStream->Read(_inBuf, _inBufSize, &_inSize);
|
||||
if (hres != S_OK)
|
||||
break;
|
||||
_inPos = _inLim = 0;
|
||||
readRes = inStream->Read(_inBuf, _inBufSize, &_inLim);
|
||||
}
|
||||
|
||||
const SizeT dicPos = _state.decoder.dicPos;
|
||||
SizeT size;
|
||||
{
|
||||
SizeT next = _state.decoder.dicBufSize;
|
||||
if (next - wrPos > _outStep)
|
||||
next = wrPos + _outStep;
|
||||
size = next - dicPos;
|
||||
}
|
||||
|
||||
SizeT dicPos = _state.decoder.dicPos;
|
||||
SizeT curSize = next - dicPos;
|
||||
|
||||
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _outSizeProcessed;
|
||||
if (curSize >= rem)
|
||||
const UInt64 rem = _outSize - _outProcessed;
|
||||
if (size >= rem)
|
||||
{
|
||||
curSize = (SizeT)rem;
|
||||
size = (SizeT)rem;
|
||||
if (_finishMode)
|
||||
finishMode = LZMA_FINISH_END;
|
||||
}
|
||||
}
|
||||
|
||||
SizeT inSizeProcessed = _inSize - _inPos;
|
||||
SizeT inProcessed = _inLim - _inPos;
|
||||
ELzmaStatus status;
|
||||
SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);
|
||||
|
||||
SRes res = Lzma2Dec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status);
|
||||
|
||||
_inPos += (UInt32)inSizeProcessed;
|
||||
_inSizeProcessed += inSizeProcessed;
|
||||
SizeT outSizeProcessed = _state.decoder.dicPos - dicPos;
|
||||
_outSizeProcessed += outSizeProcessed;
|
||||
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inProcessed += inProcessed;
|
||||
const SizeT outProcessed = _state.decoder.dicPos - dicPos;
|
||||
_outProcessed += outProcessed;
|
||||
|
||||
bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0
|
||||
|| status == LZMA_STATUS_FINISHED_WITH_MARK);
|
||||
bool outFinished = (_outSizeDefined && _outSizeProcessed >= _outSize);
|
||||
|
||||
bool outFinished = (_outSizeDefined && _outProcessed >= _outSize);
|
||||
|
||||
if (res != 0
|
||||
|| _state.decoder.dicPos >= next
|
||||
|| finished
|
||||
|| outFinished)
|
||||
bool needStop = (res != 0
|
||||
|| (inProcessed == 0 && outProcessed == 0)
|
||||
|| status == LZMA_STATUS_FINISHED_WITH_MARK
|
||||
|| (!_finishMode && outFinished));
|
||||
|
||||
if (needStop || outProcessed >= size)
|
||||
{
|
||||
HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);
|
||||
|
||||
if (_state.decoder.dicPos == _state.decoder.dicBufSize)
|
||||
_state.decoder.dicPos = 0;
|
||||
|
||||
wrPos = _state.decoder.dicPos;
|
||||
|
||||
next = (_state.decoder.dicBufSize - _state.decoder.dicPos < step) ?
|
||||
_state.decoder.dicBufSize :
|
||||
_state.decoder.dicPos + step;
|
||||
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
RINOK(res2);
|
||||
|
||||
if (finished)
|
||||
if (needStop)
|
||||
{
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (_finishMode && inSize && *inSize != _inSizeProcessed)
|
||||
return S_FALSE;
|
||||
if (finishMode == LZMA_FINISH_END && !outFinished)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
if (_finishMode)
|
||||
{
|
||||
if (inSize && *inSize != _inProcessed)
|
||||
return S_FALSE;
|
||||
if (_outSizeDefined && _outSize != _outProcessed)
|
||||
return S_FALSE;
|
||||
}
|
||||
return readRes;
|
||||
}
|
||||
return (finishMode == LZMA_FINISH_END) ? S_FALSE : S_OK;
|
||||
}
|
||||
|
||||
if (outFinished && finishMode == LZMA_FINISH_ANY)
|
||||
return S_OK;
|
||||
if (!_finishMode && outFinished)
|
||||
return readRes;
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (progress)
|
||||
{
|
||||
RINOK(progress->SetRatioInfo(&_inSizeProcessed, &_outSizeProcessed));
|
||||
RINOK(progress->SetRatioInfo(&_inProcessed, &_outProcessed));
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT res2 = WriteStream(outStream, _state.decoder.dic + wrPos, _state.decoder.dicPos - wrPos);
|
||||
if (hres != S_OK)
|
||||
return hres;
|
||||
return res2;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
|
||||
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
|
||||
STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
UInt32 totalProcessed = 0;
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
|
||||
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _outProcessed;
|
||||
if (size >= rem)
|
||||
{
|
||||
size = (UInt32)rem;
|
||||
if (_finishMode)
|
||||
finishMode = LZMA_FINISH_END;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (_inPos == _inSize)
|
||||
if (_inPos == _inLim && readRes == S_OK)
|
||||
{
|
||||
_inPos = _inSize = 0;
|
||||
RINOK(_inStream->Read(_inBuf, _inBufSize, &_inSize));
|
||||
_inPos = _inLim = 0;
|
||||
readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
|
||||
}
|
||||
|
||||
SizeT inProcessed = _inLim - _inPos;
|
||||
SizeT outProcessed = size;
|
||||
ELzmaStatus status;
|
||||
|
||||
SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
|
||||
_inBuf + _inPos, &inProcessed, finishMode, &status);
|
||||
|
||||
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inProcessed += inProcessed;
|
||||
_outProcessed += outProcessed;
|
||||
size -= (UInt32)outProcessed;
|
||||
data = (Byte *)data + outProcessed;
|
||||
if (processedSize)
|
||||
*processedSize += (UInt32)outProcessed;
|
||||
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
|
||||
/*
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
return readRes;
|
||||
|
||||
if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
{
|
||||
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _outSizeProcessed;
|
||||
if (rem <= size)
|
||||
{
|
||||
size = (UInt32)rem;
|
||||
if (_finishMode)
|
||||
finishMode = LZMA_FINISH_END;
|
||||
}
|
||||
}
|
||||
|
||||
SizeT outProcessed = size;
|
||||
SizeT inProcessed = _inSize - _inPos;
|
||||
|
||||
ELzmaStatus status;
|
||||
SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
|
||||
_inBuf + _inPos, &inProcessed, finishMode, &status);
|
||||
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inSizeProcessed += inProcessed;
|
||||
_outSizeProcessed += outProcessed;
|
||||
size -= (UInt32)outProcessed;
|
||||
data = (Byte *)data + outProcessed;
|
||||
|
||||
totalProcessed += (UInt32)outProcessed;
|
||||
if (processedSize)
|
||||
*processedSize = totalProcessed;
|
||||
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
if (totalProcessed != 0)
|
||||
return S_OK;
|
||||
return SResToHRESULT(res);
|
||||
}
|
||||
|
||||
if (inProcessed == 0 && outProcessed == 0)
|
||||
return S_OK;
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
return S_OK;
|
||||
if (outProcessed != 0)
|
||||
{
|
||||
if (finishMode != LZMA_FINISH_END || _outSize != _outSizeProcessed)
|
||||
return S_OK;
|
||||
}
|
||||
if (_finishMode && _outSizeDefined && _outProcessed >= _outSize)
|
||||
return S_FALSE;
|
||||
return readRes;
|
||||
}
|
||||
*/
|
||||
|
||||
if (inProcessed == 0 && outProcessed == 0)
|
||||
return readRes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "../../../C/Lzma2Dec.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
@@ -25,25 +24,23 @@ class CDecoder:
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
Byte *_inBuf;
|
||||
UInt32 _inPos;
|
||||
UInt32 _inSize;
|
||||
UInt32 _inLim;
|
||||
|
||||
bool _finishMode;
|
||||
bool _outSizeDefined;
|
||||
UInt64 _outSize;
|
||||
|
||||
UInt64 _inSizeProcessed;
|
||||
UInt64 _outSizeProcessed;
|
||||
UInt64 _inProcessed;
|
||||
UInt64 _outProcessed;
|
||||
|
||||
UInt32 _outStep;
|
||||
UInt32 _inBufSize;
|
||||
UInt32 _inBufSizeNew;
|
||||
UInt32 _outStepSize;
|
||||
|
||||
CLzma2Dec _state;
|
||||
public:
|
||||
|
||||
public:
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
|
||||
@@ -59,28 +56,27 @@ public:
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
|
||||
private:
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
public:
|
||||
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
|
||||
|
||||
#endif
|
||||
|
||||
CDecoder();
|
||||
virtual ~CDecoder();
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -82,11 +82,15 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
||||
{
|
||||
CSeqInStreamWrap inWrap(inStream);
|
||||
CSeqOutStreamWrap outWrap(outStream);
|
||||
CCompressProgressWrap progressWrap(progress);
|
||||
CSeqInStreamWrap inWrap;
|
||||
CSeqOutStreamWrap outWrap;
|
||||
CCompressProgressWrap progressWrap;
|
||||
|
||||
inWrap.Init(inStream);
|
||||
outWrap.Init(outStream);
|
||||
progressWrap.Init(progress);
|
||||
|
||||
SRes res = Lzma2Enc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL);
|
||||
SRes res = Lzma2Enc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL);
|
||||
if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
|
||||
return inWrap.Res;
|
||||
if (res == SZ_ERROR_WRITE && outWrap.Res != S_OK)
|
||||
|
||||
@@ -24,14 +24,19 @@ static HRESULT SResToHRESULT(SRes res)
|
||||
namespace NCompress {
|
||||
namespace NLzma {
|
||||
|
||||
CDecoder::CDecoder(): _inBuf(0), _propsWereSet(false), _outSizeDefined(false),
|
||||
_inBufSize(1 << 20),
|
||||
_outBufSize(1 << 22),
|
||||
CDecoder::CDecoder():
|
||||
_inBuf(NULL),
|
||||
_lzmaStatus(LZMA_STATUS_NOT_SPECIFIED),
|
||||
FinishStream(false),
|
||||
NeedMoreInput(false)
|
||||
_propsWereSet(false),
|
||||
_outSizeDefined(false),
|
||||
_outStep(1 << 22),
|
||||
_inBufSize(0),
|
||||
_inBufSizeNew(1 << 20)
|
||||
{
|
||||
_inSizeProcessed = 0;
|
||||
_inPos = _inSize = 0;
|
||||
_inProcessed = 0;
|
||||
_inPos = _inLim = 0;
|
||||
|
||||
LzmaDec_Construct(&_state);
|
||||
}
|
||||
|
||||
@@ -41,22 +46,24 @@ CDecoder::~CDecoder()
|
||||
MyFree(_inBuf);
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSize = size; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outBufSize = size; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetInBufSize(UInt32 , UInt32 size) { _inBufSizeNew = size; return S_OK; }
|
||||
STDMETHODIMP CDecoder::SetOutBufSize(UInt32 , UInt32 size) { _outStep = size; return S_OK; }
|
||||
|
||||
HRESULT CDecoder::CreateInputBuffer()
|
||||
{
|
||||
if (_inBuf == 0 || _inBufSize != _inBufSizeAllocated)
|
||||
if (!_inBuf || _inBufSizeNew != _inBufSize)
|
||||
{
|
||||
MyFree(_inBuf);
|
||||
_inBuf = (Byte *)MyAlloc(_inBufSize);
|
||||
if (_inBuf == 0)
|
||||
_inBufSize = 0;
|
||||
_inBuf = (Byte *)MyAlloc(_inBufSizeNew);
|
||||
if (!_inBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
_inBufSizeAllocated = _inBufSize;
|
||||
_inBufSize = _inBufSizeNew;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
|
||||
{
|
||||
RINOK(SResToHRESULT(LzmaDec_Allocate(&_state, prop, size, &g_Alloc)));
|
||||
@@ -64,203 +71,266 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *prop, UInt32 size)
|
||||
return CreateInputBuffer();
|
||||
}
|
||||
|
||||
|
||||
void CDecoder::SetOutStreamSizeResume(const UInt64 *outSize)
|
||||
{
|
||||
_outSizeDefined = (outSize != NULL);
|
||||
_outSize = 0;
|
||||
if (_outSizeDefined)
|
||||
_outSize = *outSize;
|
||||
_outSizeProcessed = 0;
|
||||
_wrPos = 0;
|
||||
_outProcessed = 0;
|
||||
_lzmaStatus = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
LzmaDec_Init(&_state);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
_inSizeProcessed = 0;
|
||||
_inPos = _inSize = 0;
|
||||
NeedMoreInput = false;
|
||||
_inProcessed = 0;
|
||||
_inPos = _inLim = 0;
|
||||
SetOutStreamSizeResume(outSize);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
|
||||
{
|
||||
FinishStream = (finishMode != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _inProcessed;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CDecoder::CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress)
|
||||
{
|
||||
if (_inBuf == 0 || !_propsWereSet)
|
||||
if (!_inBuf || !_propsWereSet)
|
||||
return S_FALSE;
|
||||
|
||||
const UInt64 startInProgress = _inProcessed;
|
||||
SizeT wrPos = _state.dicPos;
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
UInt64 startInProgress = _inSizeProcessed;
|
||||
|
||||
SizeT next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);
|
||||
for (;;)
|
||||
{
|
||||
if (_inPos == _inSize)
|
||||
if (_inPos == _inLim && readRes == S_OK)
|
||||
{
|
||||
_inPos = _inSize = 0;
|
||||
RINOK(inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
|
||||
_inPos = _inLim = 0;
|
||||
readRes = inStream->Read(_inBuf, _inBufSize, &_inLim);
|
||||
}
|
||||
|
||||
const SizeT dicPos = _state.dicPos;
|
||||
SizeT size;
|
||||
{
|
||||
SizeT next = _state.dicBufSize;
|
||||
if (next - wrPos > _outStep)
|
||||
next = wrPos + _outStep;
|
||||
size = next - dicPos;
|
||||
}
|
||||
|
||||
SizeT dicPos = _state.dicPos;
|
||||
SizeT curSize = next - dicPos;
|
||||
|
||||
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _outSizeProcessed;
|
||||
if (rem <= curSize)
|
||||
const UInt64 rem = _outSize - _outProcessed;
|
||||
if (size >= rem)
|
||||
{
|
||||
curSize = (SizeT)rem;
|
||||
size = (SizeT)rem;
|
||||
if (FinishStream)
|
||||
finishMode = LZMA_FINISH_END;
|
||||
}
|
||||
}
|
||||
|
||||
SizeT inSizeProcessed = _inSize - _inPos;
|
||||
SizeT inProcessed = _inLim - _inPos;
|
||||
ELzmaStatus status;
|
||||
SRes res = LzmaDec_DecodeToDic(&_state, dicPos + curSize, _inBuf + _inPos, &inSizeProcessed, finishMode, &status);
|
||||
|
||||
SRes res = LzmaDec_DecodeToDic(&_state, dicPos + size, _inBuf + _inPos, &inProcessed, finishMode, &status);
|
||||
|
||||
_inPos += (UInt32)inSizeProcessed;
|
||||
_inSizeProcessed += inSizeProcessed;
|
||||
SizeT outSizeProcessed = _state.dicPos - dicPos;
|
||||
_outSizeProcessed += outSizeProcessed;
|
||||
_lzmaStatus = status;
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inProcessed += inProcessed;
|
||||
const SizeT outProcessed = _state.dicPos - dicPos;
|
||||
_outProcessed += outProcessed;
|
||||
|
||||
bool finished = (inSizeProcessed == 0 && outSizeProcessed == 0);
|
||||
bool stopDecoding = (_outSizeDefined && _outSizeProcessed >= _outSize);
|
||||
// we check for LZMA_STATUS_NEEDS_MORE_INPUT to allow RangeCoder initialization, if (_outSizeDefined && _outSize == 0)
|
||||
bool outFinished = (_outSizeDefined && _outProcessed >= _outSize);
|
||||
|
||||
if (res != 0 || _state.dicPos == next || finished || stopDecoding)
|
||||
bool needStop = (res != 0
|
||||
|| (inProcessed == 0 && outProcessed == 0)
|
||||
|| status == LZMA_STATUS_FINISHED_WITH_MARK
|
||||
|| (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT));
|
||||
|
||||
if (needStop || outProcessed >= size)
|
||||
{
|
||||
HRESULT res2 = WriteStream(outStream, _state.dic + _wrPos, _state.dicPos - _wrPos);
|
||||
HRESULT res2 = WriteStream(outStream, _state.dic + wrPos, _state.dicPos - wrPos);
|
||||
|
||||
_wrPos = _state.dicPos;
|
||||
if (_state.dicPos == _state.dicBufSize)
|
||||
{
|
||||
_state.dicPos = 0;
|
||||
_wrPos = 0;
|
||||
}
|
||||
next = (_state.dicBufSize - _state.dicPos < _outBufSize) ? _state.dicBufSize : (_state.dicPos + _outBufSize);
|
||||
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
wrPos = _state.dicPos;
|
||||
|
||||
RINOK(res2);
|
||||
if (stopDecoding)
|
||||
|
||||
if (needStop)
|
||||
{
|
||||
if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
NeedMoreInput = true;
|
||||
if (FinishStream &&
|
||||
status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
if (finished)
|
||||
{
|
||||
if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
NeedMoreInput = true;
|
||||
return (status == LZMA_STATUS_FINISHED_WITH_MARK ? S_OK : S_FALSE);
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (FinishStream)
|
||||
if (_outSizeDefined && _outSize != _outProcessed)
|
||||
return S_FALSE;
|
||||
return readRes;
|
||||
}
|
||||
|
||||
if (outFinished && status != LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
if (!FinishStream || status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
return readRes;
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (progress)
|
||||
{
|
||||
UInt64 inSize = _inSizeProcessed - startInProgress;
|
||||
RINOK(progress->SetRatioInfo(&inSize, &_outSizeProcessed));
|
||||
const UInt64 inSize = _inProcessed - startInProgress;
|
||||
RINOK(progress->SetRatioInfo(&inSize, &_outProcessed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
if (_inBuf == 0)
|
||||
if (!_inBuf)
|
||||
return E_INVALIDARG;
|
||||
SetOutStreamSize(outSize);
|
||||
return CodeSpec(inStream, outStream, progress);
|
||||
HRESULT res = CodeSpec(inStream, outStream, progress);
|
||||
if (res == S_OK)
|
||||
if (FinishStream && inSize && *inSize != _inProcessed)
|
||||
res = S_FALSE;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
|
||||
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { _inStream = inStream; return S_OK; }
|
||||
STDMETHODIMP CDecoder::ReleaseInStream() { _inStream.Release(); return S_OK; }
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
do
|
||||
|
||||
ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
if (_inPos == _inSize)
|
||||
const UInt64 rem = _outSize - _outProcessed;
|
||||
if (size >= rem)
|
||||
{
|
||||
_inPos = _inSize = 0;
|
||||
RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
|
||||
}
|
||||
{
|
||||
SizeT inProcessed = _inSize - _inPos;
|
||||
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _outSizeProcessed;
|
||||
if (rem < size)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
|
||||
SizeT outProcessed = size;
|
||||
ELzmaStatus status;
|
||||
SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
|
||||
_inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status);
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inSizeProcessed += inProcessed;
|
||||
_outSizeProcessed += outProcessed;
|
||||
size -= (UInt32)outProcessed;
|
||||
data = (Byte *)data + outProcessed;
|
||||
if (processedSize)
|
||||
*processedSize += (UInt32)outProcessed;
|
||||
RINOK(SResToHRESULT(res));
|
||||
if (inProcessed == 0 && outProcessed == 0)
|
||||
return S_OK;
|
||||
size = (UInt32)rem;
|
||||
if (FinishStream)
|
||||
finishMode = LZMA_FINISH_END;
|
||||
}
|
||||
}
|
||||
while (size != 0);
|
||||
return S_OK;
|
||||
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (_inPos == _inLim && readRes == S_OK)
|
||||
{
|
||||
_inPos = _inLim = 0;
|
||||
readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
|
||||
}
|
||||
|
||||
SizeT inProcessed = _inLim - _inPos;
|
||||
SizeT outProcessed = size;
|
||||
ELzmaStatus status;
|
||||
|
||||
SRes res = LzmaDec_DecodeToBuf(&_state, (Byte *)data, &outProcessed,
|
||||
_inBuf + _inPos, &inProcessed, finishMode, &status);
|
||||
|
||||
_lzmaStatus = status;
|
||||
_inPos += (UInt32)inProcessed;
|
||||
_inProcessed += inProcessed;
|
||||
_outProcessed += outProcessed;
|
||||
size -= (UInt32)outProcessed;
|
||||
data = (Byte *)data + outProcessed;
|
||||
if (processedSize)
|
||||
*processedSize += (UInt32)outProcessed;
|
||||
|
||||
if (res != 0)
|
||||
return S_FALSE;
|
||||
|
||||
/*
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
return readRes;
|
||||
|
||||
if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
{
|
||||
if (FinishStream
|
||||
&& _outSizeDefined && _outProcessed >= _outSize
|
||||
&& status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
return S_FALSE;
|
||||
return readRes;
|
||||
}
|
||||
*/
|
||||
|
||||
if (inProcessed == 0 && outProcessed == 0)
|
||||
return readRes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
SetOutStreamSizeResume(outSize);
|
||||
return CodeSpec(_inStream, outStream, progress);
|
||||
}
|
||||
|
||||
|
||||
HRESULT CDecoder::ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
RINOK(CreateInputBuffer());
|
||||
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
while (size > 0)
|
||||
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
while (size != 0)
|
||||
{
|
||||
if (_inPos == _inSize)
|
||||
if (_inPos == _inLim)
|
||||
{
|
||||
_inPos = _inSize = 0;
|
||||
RINOK(_inStream->Read(_inBuf, _inBufSizeAllocated, &_inSize));
|
||||
if (_inSize == 0)
|
||||
_inPos = _inLim = 0;
|
||||
if (readRes == S_OK)
|
||||
readRes = _inStream->Read(_inBuf, _inBufSize, &_inLim);
|
||||
if (_inLim == 0)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 curSize = _inSize - _inPos;
|
||||
if (curSize > size)
|
||||
curSize = size;
|
||||
memcpy(data, _inBuf + _inPos, curSize);
|
||||
_inPos += curSize;
|
||||
_inSizeProcessed += curSize;
|
||||
size -= curSize;
|
||||
data = (Byte *)data + curSize;
|
||||
if (processedSize)
|
||||
*processedSize += curSize;
|
||||
}
|
||||
|
||||
UInt32 cur = _inLim - _inPos;
|
||||
if (cur > size)
|
||||
cur = size;
|
||||
memcpy(data, _inBuf + _inPos, cur);
|
||||
_inPos += cur;
|
||||
_inProcessed += cur;
|
||||
size -= cur;
|
||||
data = (Byte *)data + cur;
|
||||
if (processedSize)
|
||||
*processedSize += cur;
|
||||
}
|
||||
return S_OK;
|
||||
|
||||
return readRes;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,7 @@ class CDecoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetDecoderProperties2,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
public ICompressSetBufSize,
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
public ICompressSetInStream,
|
||||
@@ -23,21 +24,26 @@ class CDecoder:
|
||||
#endif
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
Byte *_inBuf;
|
||||
UInt32 _inPos;
|
||||
UInt32 _inSize;
|
||||
UInt32 _inLim;
|
||||
|
||||
CLzmaDec _state;
|
||||
ELzmaStatus _lzmaStatus;
|
||||
|
||||
public:
|
||||
bool FinishStream; // set it before decoding, if you need to decode full LZMA stream
|
||||
|
||||
private:
|
||||
bool _propsWereSet;
|
||||
bool _outSizeDefined;
|
||||
UInt64 _outSize;
|
||||
UInt64 _inSizeProcessed;
|
||||
UInt64 _outSizeProcessed;
|
||||
UInt64 _inProcessed;
|
||||
UInt64 _outProcessed;
|
||||
|
||||
UInt32 _inBufSizeAllocated;
|
||||
UInt32 _outStep;
|
||||
UInt32 _inBufSize;
|
||||
UInt32 _outBufSize;
|
||||
SizeT _wrPos;
|
||||
UInt32 _inBufSizeNew;
|
||||
|
||||
HRESULT CreateInputBuffer();
|
||||
HRESULT CodeSpec(ISequentialInStream *inStream, ISequentialOutStream *outStream, ICompressProgressInfo *progress);
|
||||
@@ -47,6 +53,7 @@ public:
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetFinishMode)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressGetInStreamProcessedSize)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetBufSize)
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
|
||||
@@ -60,11 +67,16 @@ public:
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
STDMETHOD(SetInBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
STDMETHOD(SetOutBufSize)(UInt32 streamIndex, UInt32 size);
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
|
||||
private:
|
||||
CMyComPtr<ISequentialInStream> _inStream;
|
||||
public:
|
||||
|
||||
STDMETHOD(SetInStream)(ISequentialInStream *inStream);
|
||||
STDMETHOD(ReleaseInStream)();
|
||||
@@ -72,18 +84,24 @@ public:
|
||||
|
||||
HRESULT CodeResume(ISequentialOutStream *outStream, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
HRESULT ReadFromInputStream(void *data, UInt32 size, UInt32 *processedSize);
|
||||
UInt64 GetInputProcessedSize() const { return _inSizeProcessed; }
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
bool FinishStream; // set it before decoding, if you need to decode full LZMA stream
|
||||
|
||||
bool NeedMoreInput; // it's set by decoder, if it needs more input data to decode stream
|
||||
UInt64 GetInputProcessedSize() const { return _inProcessed; }
|
||||
|
||||
CDecoder();
|
||||
virtual ~CDecoder();
|
||||
|
||||
UInt64 GetOutputProcessedSize() const { return _outSizeProcessed; }
|
||||
UInt64 GetOutputProcessedSize() const { return _outProcessed; }
|
||||
|
||||
bool NeedsMoreInput() const { return _lzmaStatus == LZMA_STATUS_NEEDS_MORE_INPUT; }
|
||||
|
||||
bool CheckFinishStatus(bool withEndMark) const
|
||||
{
|
||||
return _lzmaStatus == (withEndMark ?
|
||||
LZMA_STATUS_FINISHED_WITH_MARK :
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK);
|
||||
}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -134,11 +134,16 @@ STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
||||
{
|
||||
CSeqInStreamWrap inWrap(inStream);
|
||||
CSeqOutStreamWrap outWrap(outStream);
|
||||
CCompressProgressWrap progressWrap(progress);
|
||||
CSeqInStreamWrap inWrap;
|
||||
CSeqOutStreamWrap outWrap;
|
||||
CCompressProgressWrap progressWrap;
|
||||
|
||||
inWrap.Init(inStream);
|
||||
outWrap.Init(outStream);
|
||||
progressWrap.Init(progress);
|
||||
|
||||
SRes res = LzmaEnc_Encode(_encoder, &outWrap.vt, &inWrap.vt, progress ? &progressWrap.vt : NULL, &g_Alloc, &g_BigAlloc);
|
||||
|
||||
SRes res = LzmaEnc_Encode(_encoder, &outWrap.p, &inWrap.p, progress ? &progressWrap.p : NULL, &g_Alloc, &g_BigAlloc);
|
||||
_inputProcessed = inWrap.Processed;
|
||||
if (res == SZ_ERROR_READ && inWrap.Res != S_OK)
|
||||
return inWrap.Res;
|
||||
|
||||
@@ -30,7 +30,9 @@ public:
|
||||
|
||||
CEncoder();
|
||||
virtual ~CEncoder();
|
||||
|
||||
UInt64 GetInputProcessedSize() const { return _inputProcessed; }
|
||||
bool IsWriteEndMark() const { return LzmaEnc_IsWriteEndMark(_encoder) != 0; }
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -114,8 +114,8 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history)
|
||||
|
||||
size -= 16;
|
||||
const unsigned kSave = 6;
|
||||
const Byte savedByte = data[size + kSave];
|
||||
data[size + kSave] = 0xE8;
|
||||
const Byte savedByte = data[(size_t)size + kSave];
|
||||
data[(size_t)size + kSave] = 0xE8;
|
||||
Int32 last_x86_pos = -k_x86_TransOffset - 1;
|
||||
|
||||
// first byte is ignored
|
||||
@@ -215,7 +215,7 @@ static void x86_Filter(Byte *data, UInt32 size, Int32 *history)
|
||||
*target = i;
|
||||
}
|
||||
|
||||
data[size + kSave] = savedByte;
|
||||
data[(size_t)size + kSave] = savedByte;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 tra
|
||||
return;
|
||||
size -= kResidue;
|
||||
|
||||
Byte save = data[size + 4];
|
||||
data[size + 4] = 0xE8;
|
||||
Byte save = data[(size_t)size + 4];
|
||||
data[(size_t)size + 4] = 0xE8;
|
||||
|
||||
for (UInt32 i = 0;;)
|
||||
{
|
||||
@@ -57,7 +57,7 @@ static void x86_Filter(Byte *data, UInt32 size, UInt32 processedSize, UInt32 tra
|
||||
}
|
||||
}
|
||||
|
||||
data[size + 4] = save;
|
||||
data[(size_t)size + 4] = save;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ struct CMtf8Encoder
|
||||
{
|
||||
Byte Buf[256];
|
||||
|
||||
unsigned FindAndMove(Byte v)
|
||||
unsigned FindAndMove(Byte v) throw()
|
||||
{
|
||||
unsigned pos;
|
||||
size_t pos;
|
||||
for (pos = 0; Buf[pos] != v; pos++);
|
||||
unsigned resPos = pos;
|
||||
unsigned resPos = (unsigned)pos;
|
||||
for (; pos >= 8; pos -= 8)
|
||||
{
|
||||
Buf[pos] = Buf[pos - 1];
|
||||
@@ -39,9 +39,10 @@ struct CMtf8Decoder
|
||||
{
|
||||
Byte Buf[256];
|
||||
|
||||
void Init(int) {};
|
||||
void StartInit() { memset(Buf, 0, sizeof(Buf)); }
|
||||
void Add(unsigned pos, Byte val) { Buf[pos] = val; }
|
||||
Byte GetHead() const { return Buf[0]; }
|
||||
Byte GetAndMove(int pos)
|
||||
Byte GetAndMove(unsigned pos)
|
||||
{
|
||||
Byte res = Buf[pos];
|
||||
for (; pos >= 8; pos -= 8)
|
||||
@@ -64,11 +65,11 @@ struct CMtf8Decoder
|
||||
*/
|
||||
|
||||
#ifdef MY_CPU_64BIT
|
||||
typedef UInt64 CMtfVar;
|
||||
#define MTF_MOVS 3
|
||||
typedef UInt64 CMtfVar;
|
||||
#define MTF_MOVS 3
|
||||
#else
|
||||
typedef UInt32 CMtfVar;
|
||||
#define MTF_MOVS 2
|
||||
typedef UInt32 CMtfVar;
|
||||
#define MTF_MOVS 2
|
||||
#endif
|
||||
|
||||
#define MTF_MASK ((1 << MTF_MOVS) - 1)
|
||||
@@ -81,13 +82,18 @@ struct CMtf8Decoder
|
||||
void StartInit() { memset(Buf, 0, sizeof(Buf)); }
|
||||
void Add(unsigned pos, Byte val) { Buf[pos >> MTF_MOVS] |= ((CMtfVar)val << ((pos & MTF_MASK) << 3)); }
|
||||
Byte GetHead() const { return (Byte)Buf[0]; }
|
||||
Byte GetAndMove(unsigned pos)
|
||||
|
||||
MY_FORCE_INLINE
|
||||
Byte GetAndMove(unsigned pos) throw()
|
||||
{
|
||||
UInt32 lim = ((UInt32)pos >> MTF_MOVS);
|
||||
pos = (pos & MTF_MASK) << 3;
|
||||
CMtfVar prev = (Buf[lim] >> pos) & 0xFF;
|
||||
|
||||
UInt32 i = 0;
|
||||
|
||||
|
||||
/*
|
||||
if ((lim & 1) != 0)
|
||||
{
|
||||
CMtfVar next = Buf[0];
|
||||
@@ -104,6 +110,16 @@ struct CMtf8Decoder
|
||||
Buf[i + 1] = (n1 << 8) | (n0 >> (MTF_MASK << 3));
|
||||
prev = (n1 >> (MTF_MASK << 3));
|
||||
}
|
||||
*/
|
||||
|
||||
for (; i < lim; i++)
|
||||
{
|
||||
CMtfVar n0 = Buf[i];
|
||||
Buf[i ] = (n0 << 8) | prev;
|
||||
prev = (n0 >> (MTF_MASK << 3));
|
||||
}
|
||||
|
||||
|
||||
CMtfVar next = Buf[i];
|
||||
CMtfVar mask = (((CMtfVar)0x100 << pos) - 1);
|
||||
Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask);
|
||||
@@ -117,7 +133,7 @@ class CMtf8Decoder
|
||||
{
|
||||
Byte SmallBuffer[kSmallSize];
|
||||
int SmallSize;
|
||||
Byte Counts[16];
|
||||
int Counts[16];
|
||||
int Size;
|
||||
public:
|
||||
Byte Buf[256];
|
||||
@@ -140,6 +156,11 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void Add(unsigned pos, Byte val)
|
||||
{
|
||||
Buf[pos] = val;
|
||||
}
|
||||
|
||||
Byte GetAndMove(int pos)
|
||||
{
|
||||
if (pos < SmallSize)
|
||||
|
||||
@@ -75,7 +75,7 @@ HRESULT CDecoder::CodeSpec(Byte *memStream, UInt32 size)
|
||||
int sym = 0;
|
||||
for (i = 0; i != size; i++)
|
||||
{
|
||||
sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.p);
|
||||
sym = Ppmd7_DecodeSymbol(&_ppmd, &_rangeDec.vt);
|
||||
if (_inStream.Extra || sym < 0)
|
||||
break;
|
||||
memStream[i] = (Byte)sym;
|
||||
@@ -134,6 +134,13 @@ STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _inStream.GetProcessed();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
|
||||
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace NPpmd {
|
||||
class CDecoder :
|
||||
public ICompressCoder,
|
||||
public ICompressSetDecoderProperties2,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
public ICompressSetInStream,
|
||||
public ICompressSetOutStreamSize,
|
||||
@@ -42,19 +43,26 @@ public:
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
CMyComPtr<ISequentialInStream> InSeqStream;
|
||||
MY_UNKNOWN_IMP4(
|
||||
ICompressSetDecoderProperties2,
|
||||
ICompressSetInStream,
|
||||
ICompressSetOutStreamSize,
|
||||
ISequentialInStream)
|
||||
#else
|
||||
MY_UNKNOWN_IMP1(
|
||||
ICompressSetDecoderProperties2)
|
||||
#endif
|
||||
|
||||
MY_QUERYINTERFACE_BEGIN2(ICompressCoder)
|
||||
MY_QUERYINTERFACE_ENTRY(ICompressSetDecoderProperties2)
|
||||
// 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
|
||||
MY_QUERYINTERFACE_END
|
||||
MY_ADDREF_RELEASE
|
||||
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
|
||||
STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);
|
||||
|
||||
#ifndef NO_READ_FROM_CODER
|
||||
@@ -66,7 +74,7 @@ public:
|
||||
CDecoder(): _outBuf(NULL), _outSizeDefined(false)
|
||||
{
|
||||
Ppmd7z_RangeDec_CreateVTable(&_rangeDec);
|
||||
_rangeDec.Stream = &_inStream.p;
|
||||
_rangeDec.Stream = &_inStream.vt;
|
||||
Ppmd7_Construct(&_ppmd);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ CEncoder::CEncoder():
|
||||
_inBuf(NULL)
|
||||
{
|
||||
_props.Normalize(-1);
|
||||
_rangeEnc.Stream = &_outStream.p;
|
||||
_rangeEnc.Stream = &_outStream.vt;
|
||||
Ppmd7_Construct(&_ppmd);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace NPpmdZip {
|
||||
CDecoder::CDecoder(bool fullFileMode):
|
||||
_fullFileMode(fullFileMode)
|
||||
{
|
||||
_ppmd.Stream.In = &_inStream.p;
|
||||
_ppmd.Stream.In = &_inStream.vt;
|
||||
Ppmd8_Construct(&_ppmd);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ CDecoder::~CDecoder()
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
if (!_outStream.Alloc())
|
||||
return E_OUTOFMEMORY;
|
||||
@@ -64,15 +64,21 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
|
||||
bool wasFinished = false;
|
||||
UInt64 processedSize = 0;
|
||||
while (!outSize || processedSize < *outSize)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
size_t size = kBufSize;
|
||||
if (outSize != NULL)
|
||||
if (outSize)
|
||||
{
|
||||
const UInt64 rem = *outSize - processedSize;
|
||||
if (size > rem)
|
||||
{
|
||||
size = (size_t)rem;
|
||||
if (size == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Byte *data = _outStream.Buf;
|
||||
size_t i = 0;
|
||||
int sym = 0;
|
||||
@@ -84,6 +90,7 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
data[i] = (Byte)sym;
|
||||
}
|
||||
while (++i != size);
|
||||
|
||||
processedSize += i;
|
||||
|
||||
RINOK(WriteStream(outStream, _outStream.Buf, i));
|
||||
@@ -99,13 +106,16 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
wasFinished = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (progress)
|
||||
{
|
||||
UInt64 inSize = _inStream.GetProcessed();
|
||||
RINOK(progress->SetRatioInfo(&inSize, &processedSize));
|
||||
const UInt64 inProccessed = _inStream.GetProcessed();
|
||||
RINOK(progress->SetRatioInfo(&inProccessed, &processedSize));
|
||||
}
|
||||
}
|
||||
|
||||
RINOK(_inStream.Res);
|
||||
|
||||
if (_fullFileMode)
|
||||
{
|
||||
if (!wasFinished)
|
||||
@@ -117,11 +127,29 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
}
|
||||
if (!Ppmd8_RangeDec_IsFinishedOK(&_ppmd))
|
||||
return S_FALSE;
|
||||
|
||||
if (inSize && *inSize != _inStream.GetProcessed())
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
|
||||
{
|
||||
_fullFileMode = (finishMode != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _inStream.GetProcessed();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---------- Encoder ----------
|
||||
|
||||
void CEncProps::Normalize(int level)
|
||||
@@ -206,7 +234,7 @@ STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIA
|
||||
CEncoder::CEncoder()
|
||||
{
|
||||
_props.Normalize(-1);
|
||||
_ppmd.Stream.Out = &_outStream.p;
|
||||
_ppmd.Stream.Out = &_outStream.vt;
|
||||
Ppmd8_Construct(&_ppmd);
|
||||
}
|
||||
|
||||
@@ -248,10 +276,10 @@ STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream
|
||||
RINOK(_outStream.Res);
|
||||
}
|
||||
processed += size;
|
||||
if (progress != NULL)
|
||||
if (progress)
|
||||
{
|
||||
UInt64 outSize = _outStream.GetProcessed();
|
||||
RINOK(progress->SetRatioInfo(&processed, &outSize));
|
||||
const UInt64 outProccessed = _outStream.GetProcessed();
|
||||
RINOK(progress->SetRatioInfo(&processed, &outProccessed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,11 @@ struct CBuf
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class CDecoder :
|
||||
public ICompressCoder,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CByteInBufWrap _inStream;
|
||||
@@ -40,13 +43,20 @@ class CDecoder :
|
||||
CPpmd8 _ppmd;
|
||||
bool _fullFileMode;
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
MY_UNKNOWN_IMP2(
|
||||
ICompressSetFinishMode,
|
||||
ICompressGetInStreamProcessedSize)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
|
||||
CDecoder(bool fullFileMode);
|
||||
~CDecoder();
|
||||
};
|
||||
|
||||
|
||||
struct CEncProps
|
||||
{
|
||||
UInt32 MemSizeMB;
|
||||
|
||||
@@ -37,7 +37,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc)
|
||||
unsigned i;
|
||||
for (i = 1; Freqs[i] > threshold; i++);
|
||||
|
||||
rc->Decode(Freqs[i], Freqs[i - 1], Freqs[0]);
|
||||
rc->Decode(Freqs[i], Freqs[(size_t)i - 1], Freqs[0]);
|
||||
unsigned res = Vals[--i];
|
||||
|
||||
do
|
||||
@@ -50,7 +50,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc)
|
||||
{
|
||||
ReorderCount = kReorderCount;
|
||||
for (i = 0; i < NumItems; i++)
|
||||
Freqs[i] = (UInt16)(((Freqs[i] - Freqs[i + 1]) + 1) >> 1);
|
||||
Freqs[i] = (UInt16)(((Freqs[i] - Freqs[(size_t)i + 1]) + 1) >> 1);
|
||||
for (i = 0; i < NumItems - 1; i++)
|
||||
for (unsigned j = i + 1; j < NumItems; j++)
|
||||
if (Freqs[i] < Freqs[j])
|
||||
@@ -64,7 +64,7 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc)
|
||||
}
|
||||
|
||||
do
|
||||
Freqs[i] = (UInt16)(Freqs[i] + Freqs[i + 1]);
|
||||
Freqs[i] = (UInt16)(Freqs[i] + Freqs[(size_t)i + 1]);
|
||||
while (i--);
|
||||
}
|
||||
else
|
||||
@@ -73,8 +73,8 @@ unsigned CModelDecoder::Decode(CRangeDecoder *rc)
|
||||
do
|
||||
{
|
||||
Freqs[i] >>= 1;
|
||||
if (Freqs[i] <= Freqs[i + 1])
|
||||
Freqs[i] = (UInt16)(Freqs[i + 1] + 1);
|
||||
if (Freqs[i] <= Freqs[(size_t)i + 1])
|
||||
Freqs[i] = (UInt16)(Freqs[(size_t)i + 1] + 1);
|
||||
}
|
||||
while (i--);
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ UInt32 CDecoder::DecodeNum(const UInt32 *posTab)
|
||||
UInt32 num = m_InBitStream.GetValue(12);
|
||||
for (;;)
|
||||
{
|
||||
UInt32 cur = (posTab[startPos + 1] - posTab[startPos]) << (12 - startPos);
|
||||
UInt32 cur = (posTab[(size_t)startPos + 1] - posTab[startPos]) << (12 - startPos);
|
||||
if (num < cur)
|
||||
break;
|
||||
startPos++;
|
||||
@@ -149,7 +149,7 @@ HRESULT CDecoder::ShortLZ()
|
||||
PlaceA[dist]--;
|
||||
UInt32 lastDistance = ChSetA[(unsigned)distancePlace];
|
||||
PlaceA[lastDistance]++;
|
||||
ChSetA[(unsigned)distancePlace + 1] = lastDistance;
|
||||
ChSetA[(size_t)(unsigned)distancePlace + 1] = lastDistance;
|
||||
ChSetA[(unsigned)distancePlace] = dist;
|
||||
}
|
||||
len += 2;
|
||||
|
||||
@@ -104,7 +104,8 @@ bool CDecoder::ReadTables(void)
|
||||
m_TablesOK = false;
|
||||
|
||||
Byte levelLevels[kLevelTableSize];
|
||||
Byte newLevels[kMaxTableSize];
|
||||
Byte lens[kMaxTableSize];
|
||||
|
||||
m_AudioMode = (ReadBits(1) == 1);
|
||||
|
||||
if (ReadBits(1) == 0)
|
||||
@@ -134,16 +135,29 @@ bool CDecoder::ReadTables(void)
|
||||
UInt32 sym = m_LevelDecoder.Decode(&m_InBitStream);
|
||||
if (sym < kTableDirectLevels)
|
||||
{
|
||||
newLevels[i] = (Byte)((sym + m_LastLevels[i]) & kLevelMask);
|
||||
lens[i] = (Byte)((sym + m_LastLevels[i]) & kLevelMask);
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sym == kTableLevelRepNumber)
|
||||
{
|
||||
unsigned t = ReadBits(2) + 3;
|
||||
for (unsigned reps = t; reps > 0 && i < numLevels; reps--, i++)
|
||||
newLevels[i] = newLevels[i - 1];
|
||||
unsigned num = ReadBits(2) + 3;
|
||||
if (i == 0)
|
||||
{
|
||||
// return false;
|
||||
continue; // original unRAR
|
||||
}
|
||||
num += i;
|
||||
if (num > numLevels)
|
||||
{
|
||||
// return false;
|
||||
num = numLevels; // original unRAR
|
||||
}
|
||||
Byte v = lens[(size_t)i - 1];
|
||||
do
|
||||
lens[i++] = v;
|
||||
while (i < num);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -154,8 +168,15 @@ bool CDecoder::ReadTables(void)
|
||||
num = ReadBits(7) + 11;
|
||||
else
|
||||
return false;
|
||||
for (; num > 0 && i < numLevels; num--)
|
||||
newLevels[i++] = 0;
|
||||
num += i;
|
||||
if (num > numLevels)
|
||||
{
|
||||
// return false;
|
||||
num = numLevels; // original unRAR
|
||||
}
|
||||
do
|
||||
lens[i++] = 0;
|
||||
while (i < num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,16 +184,16 @@ bool CDecoder::ReadTables(void)
|
||||
if (m_AudioMode)
|
||||
for (i = 0; i < m_NumChannels; i++)
|
||||
{
|
||||
RIF(m_MMDecoders[i].Build(&newLevels[i * kMMTableSize]));
|
||||
RIF(m_MMDecoders[i].Build(&lens[i * kMMTableSize]));
|
||||
}
|
||||
else
|
||||
{
|
||||
RIF(m_MainDecoder.Build(&newLevels[0]));
|
||||
RIF(m_DistDecoder.Build(&newLevels[kMainTableSize]));
|
||||
RIF(m_LenDecoder.Build(&newLevels[kMainTableSize + kDistTableSize]));
|
||||
RIF(m_MainDecoder.Build(&lens[0]));
|
||||
RIF(m_DistDecoder.Build(&lens[kMainTableSize]));
|
||||
RIF(m_LenDecoder.Build(&lens[kMainTableSize + kDistTableSize]));
|
||||
}
|
||||
|
||||
memcpy(m_LastLevels, newLevels, kMaxTableSize);
|
||||
memcpy(m_LastLevels, lens, kMaxTableSize);
|
||||
|
||||
m_TablesOK = true;
|
||||
|
||||
@@ -220,13 +241,11 @@ public:
|
||||
|
||||
bool CDecoder::DecodeMm(UInt32 pos)
|
||||
{
|
||||
while (pos-- > 0)
|
||||
while (pos-- != 0)
|
||||
{
|
||||
UInt32 symbol = m_MMDecoders[m_MmFilter.CurrentChannel].Decode(&m_InBitStream);
|
||||
if (symbol == 256)
|
||||
return true;
|
||||
if (symbol >= kMMTableSize)
|
||||
return false;
|
||||
if (symbol >= 256)
|
||||
return symbol == 256;
|
||||
/*
|
||||
Byte byPredict = m_Predictor.Predict();
|
||||
Byte byReal = (Byte)(byPredict - (Byte)symbol);
|
||||
@@ -254,6 +273,8 @@ bool CDecoder::DecodeLz(Int32 pos)
|
||||
}
|
||||
else if (sym >= kMatchNumber)
|
||||
{
|
||||
if (sym >= kMainTableSize)
|
||||
return false;
|
||||
sym -= kMatchNumber;
|
||||
length = kNormalMatchMinLen + UInt32(kLenStart[sym]) +
|
||||
m_InBitStream.ReadBits(kLenDirectBits[sym]);
|
||||
@@ -302,10 +323,9 @@ bool CDecoder::DecodeLz(Int32 pos)
|
||||
m_InBitStream.ReadBits(kLen2DistDirectBits[sym]);
|
||||
length = 2;
|
||||
}
|
||||
else if (sym == kReadTableNumber)
|
||||
else // (sym == kReadTableNumber)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
||||
m_RepDists[m_RepDistPtr++ & 3] = distance;
|
||||
m_LastLength = length;
|
||||
if (!m_OutWindowStream.CopyBlock(distance, length))
|
||||
|
||||
@@ -44,15 +44,17 @@ static const UInt32 kVmCodeSizeMax = 1 << 16;
|
||||
|
||||
extern "C" {
|
||||
|
||||
static UInt32 Range_GetThreshold(void *pp, UInt32 total)
|
||||
#define GET_RangeDecoder CRangeDecoder *p = CONTAINER_FROM_VTBL_CLS(pp, CRangeDecoder, vt);
|
||||
|
||||
static UInt32 Range_GetThreshold(const IPpmd7_RangeDec *pp, UInt32 total)
|
||||
{
|
||||
CRangeDecoder *p = (CRangeDecoder *)pp;
|
||||
GET_RangeDecoder;
|
||||
return p->Code / (p->Range /= total);
|
||||
}
|
||||
|
||||
static void Range_Decode(void *pp, UInt32 start, UInt32 size)
|
||||
static void Range_Decode(const IPpmd7_RangeDec *pp, UInt32 start, UInt32 size)
|
||||
{
|
||||
CRangeDecoder *p = (CRangeDecoder *)pp;
|
||||
GET_RangeDecoder;
|
||||
start *= p->Range;
|
||||
p->Low += start;
|
||||
p->Code -= start;
|
||||
@@ -60,28 +62,28 @@ static void Range_Decode(void *pp, UInt32 start, UInt32 size)
|
||||
p->Normalize();
|
||||
}
|
||||
|
||||
static UInt32 Range_DecodeBit(void *pp, UInt32 size0)
|
||||
static UInt32 Range_DecodeBit(const IPpmd7_RangeDec *pp, UInt32 size0)
|
||||
{
|
||||
CRangeDecoder *p = (CRangeDecoder *)pp;
|
||||
GET_RangeDecoder;
|
||||
if (p->Code / (p->Range >>= 14) < size0)
|
||||
{
|
||||
Range_Decode(p, 0, size0);
|
||||
Range_Decode(&p->vt, 0, size0);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Range_Decode(p, size0, (1 << 14) - size0);
|
||||
Range_Decode(&p->vt, size0, (1 << 14) - size0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CRangeDecoder::CRangeDecoder()
|
||||
CRangeDecoder::CRangeDecoder() throw()
|
||||
{
|
||||
s.GetThreshold = Range_GetThreshold;
|
||||
s.Decode = Range_Decode;
|
||||
s.DecodeBit = Range_DecodeBit;
|
||||
vt.GetThreshold = Range_GetThreshold;
|
||||
vt.Decode = Range_Decode;
|
||||
vt.DecodeBit = Range_DecodeBit;
|
||||
}
|
||||
|
||||
CDecoder::CDecoder():
|
||||
@@ -445,7 +447,7 @@ HRESULT CDecoder::InitPPM()
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.s); }
|
||||
int CDecoder::DecodePpmSymbol() { return Ppmd7_DecodeSymbol(&_ppmd, &m_InBitStream.vt); }
|
||||
|
||||
HRESULT CDecoder::DecodePPM(Int32 num, bool &keepDecompressing)
|
||||
{
|
||||
@@ -545,6 +547,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
|
||||
return InitPPM();
|
||||
}
|
||||
|
||||
TablesRead = false;
|
||||
TablesOK = false;
|
||||
|
||||
_lzMode = true;
|
||||
PrevAlignBits = 0;
|
||||
PrevAlignCount = 0;
|
||||
@@ -597,7 +602,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
|
||||
if (i == 0)
|
||||
return S_FALSE;
|
||||
for (; num > 0 && i < kTablesSizesSum; num--, i++)
|
||||
newLevels[i] = newLevels[i - 1];
|
||||
newLevels[i] = newLevels[(size_t)i - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -606,6 +611,7 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TablesRead = true;
|
||||
|
||||
// original code has check here:
|
||||
@@ -623,6 +629,9 @@ HRESULT CDecoder::ReadTables(bool &keepDecompressing)
|
||||
RIF(m_LenDecoder.Build(&newLevels[kMainTableSize + kDistTableSize + kAlignTableSize]));
|
||||
|
||||
memcpy(m_LastLevels, newLevels, kTablesSizesSum);
|
||||
|
||||
TablesOK = true;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -641,16 +650,15 @@ public:
|
||||
|
||||
HRESULT CDecoder::ReadEndOfBlock(bool &keepDecompressing)
|
||||
{
|
||||
if (ReadBits(1) != 0)
|
||||
if (ReadBits(1) == 0)
|
||||
{
|
||||
// old file
|
||||
TablesRead = false;
|
||||
return ReadTables(keepDecompressing);
|
||||
// new file
|
||||
keepDecompressing = false;
|
||||
TablesRead = (ReadBits(1) == 0);
|
||||
return S_OK;
|
||||
}
|
||||
// new file
|
||||
keepDecompressing = false;
|
||||
TablesRead = (ReadBits(1) == 0);
|
||||
return S_OK;
|
||||
TablesRead = false;
|
||||
return ReadTables(keepDecompressing);
|
||||
}
|
||||
|
||||
UInt32 kDistStart[kDistTableSize];
|
||||
@@ -807,10 +815,12 @@ HRESULT CDecoder::DecodeLZ(bool &keepDecompressing)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
||||
{
|
||||
_writtenFileSize = 0;
|
||||
_unsupportedFilter = false;
|
||||
|
||||
if (!m_IsSolid)
|
||||
{
|
||||
_lzSize = 0;
|
||||
@@ -825,6 +835,7 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
||||
PpmError = true;
|
||||
InitFilters();
|
||||
}
|
||||
|
||||
if (!m_IsSolid || !TablesRead)
|
||||
{
|
||||
bool keepDecompressing;
|
||||
@@ -838,6 +849,8 @@ HRESULT CDecoder::CodeReal(ICompressProgressInfo *progress)
|
||||
bool keepDecompressing;
|
||||
if (_lzMode)
|
||||
{
|
||||
if (!TablesOK)
|
||||
return S_FALSE;
|
||||
RINOK(DecodeLZ(keepDecompressing))
|
||||
}
|
||||
else
|
||||
|
||||
@@ -102,7 +102,7 @@ const UInt32 kBot = (1 << 15);
|
||||
|
||||
struct CRangeDecoder
|
||||
{
|
||||
IPpmd7_RangeDec s;
|
||||
IPpmd7_RangeDec vt;
|
||||
UInt32 Range;
|
||||
UInt32 Code;
|
||||
UInt32 Low;
|
||||
@@ -130,7 +130,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
CRangeDecoder();
|
||||
CRangeDecoder() throw();
|
||||
};
|
||||
|
||||
struct CFilter: public NVm::CProgram
|
||||
@@ -200,6 +200,7 @@ class CDecoder:
|
||||
UInt32 PrevAlignCount;
|
||||
|
||||
bool TablesRead;
|
||||
bool TablesOK;
|
||||
|
||||
CPpmd7 _ppmd;
|
||||
int PpmEscChar;
|
||||
|
||||
@@ -891,53 +891,47 @@ static void E8E9Decode(Byte *data, UInt32 dataSize, UInt32 fileOffset, bool e9)
|
||||
}
|
||||
}
|
||||
|
||||
static inline UInt32 ItaniumGetOpType(const Byte *data, unsigned bitPos)
|
||||
{
|
||||
return (data[bitPos >> 3] >> (bitPos & 7)) & 0xF;
|
||||
}
|
||||
|
||||
static const Byte kCmdMasks[16] = {4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0};
|
||||
|
||||
static void ItaniumDecode(Byte *data, UInt32 dataSize, UInt32 fileOffset)
|
||||
{
|
||||
UInt32 curPos = 0;
|
||||
if (dataSize <= 21)
|
||||
return;
|
||||
fileOffset >>= 4;
|
||||
while (curPos < dataSize - 21)
|
||||
dataSize -= 21;
|
||||
dataSize += 15;
|
||||
dataSize >>= 4;
|
||||
dataSize += fileOffset;
|
||||
do
|
||||
{
|
||||
int b = (data[0] & 0x1F) - 0x10;
|
||||
if (b >= 0)
|
||||
unsigned m = ((UInt32)0x334B0000 >> (data[0] & 0x1E)) & 3;
|
||||
if (m)
|
||||
{
|
||||
Byte cmdMask = kCmdMasks[b];
|
||||
if (cmdMask != 0)
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
if (cmdMask & (1 << i))
|
||||
{
|
||||
unsigned startPos = i * 41 + 18;
|
||||
if (ItaniumGetOpType(data, startPos + 24) == 5)
|
||||
{
|
||||
const UInt32 kMask = 0xFFFFF;
|
||||
Byte *p = data + (startPos >> 3);
|
||||
UInt32 bitField = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);
|
||||
unsigned inBit = (startPos & 7);
|
||||
UInt32 offset = (bitField >> inBit) & kMask;
|
||||
UInt32 andMask = ~(kMask << inBit);
|
||||
bitField = ((offset - fileOffset) & kMask) << inBit;
|
||||
for (unsigned j = 0; j < 3; j++)
|
||||
{
|
||||
p[j] &= andMask;
|
||||
p[j] |= bitField;
|
||||
andMask >>= 8;
|
||||
bitField >>= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
m++;
|
||||
do
|
||||
{
|
||||
Byte *p = data + ((size_t)m * 5 - 8);
|
||||
if (((p[3] >> m) & 15) == 5)
|
||||
{
|
||||
const UInt32 kMask = 0xFFFFF;
|
||||
// UInt32 raw = ((UInt32)p[0]) | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16);
|
||||
UInt32 raw = GetUi32(p);
|
||||
UInt32 v = raw >> m;
|
||||
v -= fileOffset;
|
||||
v &= kMask;
|
||||
raw &= ~(kMask << m);
|
||||
raw |= (v << m);
|
||||
// p[0] = (Byte)raw; p[1] = (Byte)(raw >> 8); p[2] = (Byte)(raw >> 16);
|
||||
SetUi32(p, raw);
|
||||
}
|
||||
}
|
||||
while (++m <= 4);
|
||||
}
|
||||
data += 16;
|
||||
curPos += 16;
|
||||
fileOffset++;
|
||||
}
|
||||
while (++fileOffset != dataSize);
|
||||
}
|
||||
|
||||
|
||||
static void DeltaDecode(Byte *data, UInt32 dataSize, UInt32 numChannels)
|
||||
{
|
||||
UInt32 srcPos = 0;
|
||||
|
||||
@@ -448,7 +448,7 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
|
||||
// return S_FALSE;
|
||||
continue; // original unRAR
|
||||
}
|
||||
Byte v = lens[i - 1];
|
||||
Byte v = lens[(size_t)i - 1];
|
||||
do
|
||||
lens[i++] = v;
|
||||
while (i < num);
|
||||
@@ -475,7 +475,7 @@ HRESULT CDecoder::ReadTables(CBitDecoder &_bitStream)
|
||||
_useAlignBits = false;
|
||||
// _useAlignBits = true;
|
||||
for (i = 0; i < kAlignTableSize; i++)
|
||||
if (lens[kMainTableSize + kDistTableSize + i] != kNumAlignBits)
|
||||
if (lens[kMainTableSize + kDistTableSize + (size_t)i] != kNumAlignBits)
|
||||
{
|
||||
_useAlignBits = true;
|
||||
break;
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
#ifndef __COMPRESS_RAR5_DECODER_H
|
||||
#define __COMPRESS_RAR5_DECODER_H
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
#include "../../../C/CpuArch.h"
|
||||
|
||||
#include "../../Common/MyBuffer.h"
|
||||
#include "../../Common/MyBuffer2.h"
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../../Common/MyException.h"
|
||||
#include "../../Common/MyVector.h"
|
||||
@@ -20,35 +19,6 @@
|
||||
namespace NCompress {
|
||||
namespace NRar5 {
|
||||
|
||||
class CMidBuffer
|
||||
{
|
||||
Byte *_data;
|
||||
size_t _size;
|
||||
|
||||
CLASS_NO_COPY(CMidBuffer)
|
||||
|
||||
public:
|
||||
CMidBuffer(): _data(NULL), _size(0) {};
|
||||
~CMidBuffer() { ::MidFree(_data); }
|
||||
|
||||
bool IsAllocated() const { return _data != NULL; }
|
||||
operator Byte *() { return _data; }
|
||||
operator const Byte *() const { return _data; }
|
||||
size_t Size() const { return _size; }
|
||||
|
||||
void AllocAtLeast(size_t size)
|
||||
{
|
||||
if (size > _size)
|
||||
{
|
||||
const size_t kMinSize = (1 << 16);
|
||||
if (size < kMinSize)
|
||||
size = kMinSize;
|
||||
::MidFree(_data);
|
||||
_data = (Byte *)::MidAlloc(size);
|
||||
_size = size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
struct CInBufferException: public CSystemException
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
// ShrinkDecoder.cpp
|
||||
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "../Common/InBuffer.h"
|
||||
@@ -20,18 +17,19 @@ static const UInt32 kBufferSize = (1 << 18);
|
||||
static const unsigned kNumMinBits = 9;
|
||||
|
||||
HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress)
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
NBitl::CBaseDecoder<CInBuffer> inBuffer;
|
||||
COutBuffer outBuffer;
|
||||
|
||||
if (!inBuffer.Create(kBufferSize))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!outBuffer.Create(kBufferSize))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
inBuffer.SetStream(inStream);
|
||||
inBuffer.Init();
|
||||
|
||||
if (!outBuffer.Create(kBufferSize))
|
||||
return E_OUTOFMEMORY;
|
||||
outBuffer.SetStream(outStream);
|
||||
outBuffer.Init();
|
||||
|
||||
@@ -45,31 +43,69 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
_suffixes[i] = 0;
|
||||
}
|
||||
|
||||
UInt64 prevPos = 0;
|
||||
UInt64 prevPos = 0, inPrev = 0;
|
||||
unsigned numBits = kNumMinBits;
|
||||
unsigned head = 257;
|
||||
int lastSym = -1;
|
||||
Byte lastChar2 = 0;
|
||||
bool moreOut = false;
|
||||
|
||||
HRESULT res = S_FALSE;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
_inProcessed = inBuffer.GetProcessedSize();
|
||||
const UInt64 nowPos = outBuffer.GetProcessedSize();
|
||||
|
||||
bool eofCheck = false;
|
||||
|
||||
if (outSize && nowPos >= *outSize)
|
||||
{
|
||||
if (!_fullStreamMode || moreOut)
|
||||
{
|
||||
res = S_OK;
|
||||
break;
|
||||
}
|
||||
eofCheck = true;
|
||||
// Is specSym(=256) allowed after end of stream
|
||||
// Do we need to read it here
|
||||
}
|
||||
|
||||
if (progress)
|
||||
{
|
||||
if (nowPos - prevPos >= (1 << 18)
|
||||
|| _inProcessed - inPrev >= (1 << 20))
|
||||
{
|
||||
prevPos = nowPos;
|
||||
inPrev = _inProcessed;
|
||||
RINOK(progress->SetRatioInfo(&_inProcessed, &nowPos));
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 sym = inBuffer.ReadBits(numBits);
|
||||
|
||||
|
||||
if (inBuffer.ExtraBitsWereRead())
|
||||
{
|
||||
res = S_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sym == 256)
|
||||
{
|
||||
sym = inBuffer.ReadBits(numBits);
|
||||
|
||||
if (inBuffer.ExtraBitsWereRead())
|
||||
break;
|
||||
|
||||
if (sym == 1)
|
||||
{
|
||||
if (numBits >= kNumMaxBits)
|
||||
return S_FALSE;
|
||||
break;
|
||||
numBits++;
|
||||
continue;
|
||||
}
|
||||
if (sym != 2)
|
||||
return S_FALSE;
|
||||
break;
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 257; i < kNumItems; i++)
|
||||
@@ -90,6 +126,14 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
}
|
||||
}
|
||||
|
||||
if (eofCheck)
|
||||
{
|
||||
// It's can be error case.
|
||||
// That error can be detected later in (*inSize != _inProcessed) check.
|
||||
res = S_OK;
|
||||
break;
|
||||
}
|
||||
|
||||
bool needPrev = false;
|
||||
if (head < kNumItems && lastSym >= 0)
|
||||
{
|
||||
@@ -101,7 +145,8 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
{
|
||||
// we need to fix the code for that case
|
||||
// _parents[head] is not allowed to link to itself
|
||||
return E_NOTIMPL;
|
||||
res = E_NOTIMPL;
|
||||
break;
|
||||
}
|
||||
needPrev = true;
|
||||
_parents[head] = (UInt16)lastSym;
|
||||
@@ -111,7 +156,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
}
|
||||
|
||||
if (_parents[sym] == kNumItems)
|
||||
return S_FALSE;
|
||||
break;
|
||||
|
||||
lastSym = sym;
|
||||
unsigned cur = sym;
|
||||
@@ -127,34 +172,64 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
lastChar2 = (Byte)cur;
|
||||
|
||||
if (needPrev)
|
||||
_suffixes[head - 1] = (Byte)cur;
|
||||
_suffixes[(size_t)head - 1] = (Byte)cur;
|
||||
|
||||
if (outSize)
|
||||
{
|
||||
const UInt64 limit = *outSize - nowPos;
|
||||
if (i > limit)
|
||||
{
|
||||
moreOut = true;
|
||||
i = (unsigned)limit;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
outBuffer.WriteByte(_stack[--i]);
|
||||
while (i);
|
||||
|
||||
if (progress)
|
||||
{
|
||||
const UInt64 nowPos = outBuffer.GetProcessedSize();
|
||||
if (nowPos - prevPos >= (1 << 18))
|
||||
{
|
||||
prevPos = nowPos;
|
||||
const UInt64 packSize = inBuffer.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&packSize, &nowPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outBuffer.Flush();
|
||||
RINOK(outBuffer.Flush());
|
||||
|
||||
if (res == S_OK)
|
||||
if (_fullStreamMode)
|
||||
{
|
||||
if (moreOut)
|
||||
res = S_FALSE;
|
||||
const UInt64 nowPos = outBuffer.GetProcessedSize();
|
||||
if (outSize && *outSize != nowPos)
|
||||
res = S_FALSE;
|
||||
if (inSize && *inSize != _inProcessed)
|
||||
res = S_FALSE;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder ::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
|
||||
STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
try { return CodeReal(inStream, outStream, inSize, outSize, progress); }
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(const COutBufferException &e) { return e.ErrorCode; }
|
||||
// catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
// catch(const COutBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CSystemException &e) { return e.ErrorCode; }
|
||||
catch(...) { return S_FALSE; }
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::SetFinishMode(UInt32 finishMode)
|
||||
{
|
||||
_fullStreamMode = (finishMode != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _inProcessed;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -15,20 +15,29 @@ const unsigned kNumItems = 1 << kNumMaxBits;
|
||||
|
||||
class CDecoder :
|
||||
public ICompressCoder,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
UInt64 _inProcessed;
|
||||
bool _fullStreamMode;
|
||||
|
||||
UInt16 _parents[kNumItems];
|
||||
Byte _suffixes[kNumItems];
|
||||
Byte _stack[kNumItems];
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP
|
||||
|
||||
HRESULT CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(
|
||||
ICompressSetFinishMode,
|
||||
ICompressGetInStreamProcessedSize)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
@@ -49,8 +49,8 @@ HRESULT Decode(const Byte *in, size_t inSize, Byte *out, size_t outSize)
|
||||
for (unsigned i = 0; i < kNumSyms / 2; i++)
|
||||
{
|
||||
Byte b = in[i];
|
||||
levels[i * 2] = (Byte)(b & 0xF);
|
||||
levels[i * 2 + 1] = (Byte)(b >> 4);
|
||||
levels[(size_t)i * 2] = (Byte)(b & 0xF);
|
||||
levels[(size_t)i * 2 + 1] = (Byte)(b >> 4);
|
||||
}
|
||||
if (!huff.BuildFull(levels))
|
||||
return S_FALSE;
|
||||
|
||||
260
CPP/7zip/Compress/XzDecoder.cpp
Normal file
260
CPP/7zip/Compress/XzDecoder.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
// XzDecoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "../Archive/IArchive.h"
|
||||
|
||||
#include "XzDecoder.h"
|
||||
|
||||
using namespace NArchive;
|
||||
|
||||
namespace NCompress {
|
||||
namespace NXz {
|
||||
|
||||
|
||||
void CStatInfo::Clear()
|
||||
{
|
||||
InSize = 0;
|
||||
OutSize = 0;
|
||||
PhySize = 0;
|
||||
|
||||
NumStreams = 0;
|
||||
NumBlocks = 0;
|
||||
|
||||
UnpackSize_Defined = false;
|
||||
|
||||
NumStreams_Defined = false;
|
||||
NumBlocks_Defined = false;
|
||||
|
||||
IsArc = false;
|
||||
UnexpectedEnd = false;
|
||||
DataAfterEnd = false;
|
||||
Unsupported = false;
|
||||
HeadersError = false;
|
||||
DataError = false;
|
||||
CrcError = false;
|
||||
}
|
||||
|
||||
|
||||
CXzUnpackerCPP::CXzUnpackerCPP(): InBuf(0), OutBuf(0)
|
||||
{
|
||||
XzUnpacker_Construct(&p, &g_Alloc);
|
||||
}
|
||||
|
||||
CXzUnpackerCPP::~CXzUnpackerCPP()
|
||||
{
|
||||
XzUnpacker_Free(&p);
|
||||
MidFree(InBuf);
|
||||
MidFree(OutBuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CDecoder::Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *progress)
|
||||
{
|
||||
const size_t kInBufSize = (size_t)1 << 20;
|
||||
const size_t kOutBufSize = (size_t)1 << 21;
|
||||
|
||||
Clear();
|
||||
DecodeRes = SZ_OK;
|
||||
|
||||
XzUnpacker_Init(&xzu.p);
|
||||
|
||||
if (!xzu.InBuf)
|
||||
{
|
||||
xzu.InBuf = (Byte *)MidAlloc(kInBufSize);
|
||||
if (!xzu.InBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
if (!xzu.OutBuf)
|
||||
{
|
||||
xzu.OutBuf = (Byte *)MidAlloc(kOutBufSize);
|
||||
if (!xzu.OutBuf)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
UInt32 inSize = 0;
|
||||
UInt32 inPos = 0;
|
||||
SizeT outPos = 0;
|
||||
|
||||
HRESULT readRes = S_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (inPos == inSize && readRes == S_OK)
|
||||
{
|
||||
inPos = inSize = 0;
|
||||
readRes = seqInStream->Read(xzu.InBuf, kInBufSize, &inSize);
|
||||
}
|
||||
|
||||
SizeT inLen = inSize - inPos;
|
||||
SizeT outLen = kOutBufSize - outPos;
|
||||
ECoderFinishMode finishMode = CODER_FINISH_ANY;
|
||||
if (inSize == 0)
|
||||
finishMode = CODER_FINISH_END;
|
||||
|
||||
if (outSizeLimit)
|
||||
{
|
||||
const UInt64 rem = *outSizeLimit - OutSize;
|
||||
if (outLen >= rem)
|
||||
{
|
||||
outLen = (SizeT)rem;
|
||||
if (finishStream)
|
||||
finishMode = CODER_FINISH_END;
|
||||
}
|
||||
}
|
||||
|
||||
ECoderStatus status;
|
||||
|
||||
const SizeT outLenRequested = outLen;
|
||||
|
||||
SRes res = XzUnpacker_Code(&xzu.p,
|
||||
xzu.OutBuf + outPos, &outLen,
|
||||
xzu.InBuf + inPos, &inLen,
|
||||
finishMode, &status);
|
||||
|
||||
DecodeRes = res;
|
||||
|
||||
inPos += (UInt32)inLen;
|
||||
outPos += outLen;
|
||||
|
||||
InSize += inLen;
|
||||
OutSize += outLen;
|
||||
|
||||
bool finished = ((inLen == 0 && outLen == 0) || res != SZ_OK);
|
||||
|
||||
if (outLen >= outLenRequested || finished)
|
||||
{
|
||||
if (outStream && outPos != 0)
|
||||
{
|
||||
RINOK(WriteStream(outStream, xzu.OutBuf, outPos));
|
||||
}
|
||||
outPos = 0;
|
||||
}
|
||||
|
||||
if (progress)
|
||||
{
|
||||
RINOK(progress->SetRatioInfo(&InSize, &OutSize));
|
||||
}
|
||||
|
||||
if (!finished)
|
||||
continue;
|
||||
|
||||
{
|
||||
PhySize = InSize;
|
||||
NumStreams = xzu.p.numStartedStreams;
|
||||
if (NumStreams > 0)
|
||||
IsArc = true;
|
||||
NumBlocks = xzu.p.numTotalBlocks;
|
||||
|
||||
UnpackSize_Defined = true;
|
||||
NumStreams_Defined = true;
|
||||
NumBlocks_Defined = true;
|
||||
|
||||
UInt64 extraSize = XzUnpacker_GetExtraSize(&xzu.p);
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
if (status == CODER_STATUS_NEEDS_MORE_INPUT)
|
||||
{
|
||||
extraSize = 0;
|
||||
if (!XzUnpacker_IsStreamWasFinished(&xzu.p))
|
||||
{
|
||||
// finished at padding bytes, but padding is not aligned for 4
|
||||
UnexpectedEnd = true;
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
else // status == CODER_STATUS_NOT_FINISHED
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
else if (res == SZ_ERROR_NO_ARCHIVE)
|
||||
{
|
||||
if (InSize == extraSize)
|
||||
IsArc = false;
|
||||
else
|
||||
{
|
||||
if (extraSize != 0 || inPos != inSize)
|
||||
{
|
||||
DataAfterEnd = true;
|
||||
res = SZ_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DecodeRes = res;
|
||||
PhySize -= extraSize;
|
||||
|
||||
switch (res)
|
||||
{
|
||||
case SZ_OK: break;
|
||||
case SZ_ERROR_NO_ARCHIVE: IsArc = false; break;
|
||||
case SZ_ERROR_ARCHIVE: HeadersError = true; break;
|
||||
case SZ_ERROR_UNSUPPORTED: Unsupported = true; break;
|
||||
case SZ_ERROR_CRC: CrcError = true; break;
|
||||
case SZ_ERROR_DATA: DataError = true; break;
|
||||
default: DataError = true; break;
|
||||
}
|
||||
|
||||
return readRes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Int32 CDecoder::Get_Extract_OperationResult() const
|
||||
{
|
||||
Int32 opRes;
|
||||
if (!IsArc)
|
||||
opRes = NExtract::NOperationResult::kIsNotArc;
|
||||
else if (UnexpectedEnd)
|
||||
opRes = NExtract::NOperationResult::kUnexpectedEnd;
|
||||
else if (DataAfterEnd)
|
||||
opRes = NExtract::NOperationResult::kDataAfterEnd;
|
||||
else if (CrcError)
|
||||
opRes = NExtract::NOperationResult::kCRCError;
|
||||
else if (Unsupported)
|
||||
opRes = NExtract::NOperationResult::kUnsupportedMethod;
|
||||
else if (HeadersError)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (DataError)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else if (DecodeRes != SZ_OK)
|
||||
opRes = NExtract::NOperationResult::kDataError;
|
||||
else
|
||||
opRes = NExtract::NOperationResult::kOK;
|
||||
return opRes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CComDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 * /* inSize */, const UInt64 *outSize, ICompressProgressInfo *progress)
|
||||
{
|
||||
RINOK(_decoder.Decode(inStream, outStream, outSize, _finishStream, progress));
|
||||
Int32 opRes = _decoder.Get_Extract_OperationResult();
|
||||
if (opRes == NArchive::NExtract::NOperationResult::kUnsupportedMethod)
|
||||
return E_NOTIMPL;
|
||||
if (opRes != NArchive::NExtract::NOperationResult::kOK)
|
||||
return S_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CComDecoder::SetFinishMode(UInt32 finishMode)
|
||||
{
|
||||
_finishStream = (finishMode != 0);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CComDecoder::GetInStreamProcessedSize(UInt64 *value)
|
||||
{
|
||||
*value = _decoder.InSize;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}}
|
||||
95
CPP/7zip/Compress/XzDecoder.h
Normal file
95
CPP/7zip/Compress/XzDecoder.h
Normal file
@@ -0,0 +1,95 @@
|
||||
// XzDecoder.h
|
||||
|
||||
#ifndef __XZ_DECODER_H
|
||||
#define __XZ_DECODER_H
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
#include "../ICoder.h"
|
||||
|
||||
#include "../../../C/Xz.h"
|
||||
|
||||
|
||||
// #include "../../Archive/XzHandler.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NXz {
|
||||
|
||||
struct CXzUnpackerCPP
|
||||
{
|
||||
Byte *InBuf;
|
||||
Byte *OutBuf;
|
||||
CXzUnpacker p;
|
||||
|
||||
CXzUnpackerCPP();
|
||||
~CXzUnpackerCPP();
|
||||
};
|
||||
|
||||
|
||||
struct CStatInfo
|
||||
{
|
||||
UInt64 InSize;
|
||||
UInt64 OutSize;
|
||||
UInt64 PhySize;
|
||||
|
||||
UInt64 NumStreams;
|
||||
UInt64 NumBlocks;
|
||||
|
||||
bool UnpackSize_Defined;
|
||||
|
||||
bool NumStreams_Defined;
|
||||
bool NumBlocks_Defined;
|
||||
|
||||
bool IsArc;
|
||||
bool UnexpectedEnd;
|
||||
bool DataAfterEnd;
|
||||
bool Unsupported;
|
||||
bool HeadersError;
|
||||
bool DataError;
|
||||
bool CrcError;
|
||||
|
||||
CStatInfo() { Clear(); }
|
||||
|
||||
void Clear();
|
||||
};
|
||||
|
||||
|
||||
struct CDecoder: public CStatInfo
|
||||
{
|
||||
CXzUnpackerCPP xzu;
|
||||
SRes DecodeRes; // it's not HRESULT
|
||||
|
||||
CDecoder(): DecodeRes(SZ_OK) {}
|
||||
|
||||
/* Decode() can return ERROR code only if there is progress or stream error.
|
||||
Decode() returns S_OK in case of xz decoding error, but DecodeRes and CStatInfo contain error information */
|
||||
HRESULT Decode(ISequentialInStream *seqInStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *outSizeLimit, bool finishStream, ICompressProgressInfo *compressProgress);
|
||||
Int32 Get_Extract_OperationResult() const;
|
||||
};
|
||||
|
||||
|
||||
class CComDecoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetFinishMode,
|
||||
public ICompressGetInStreamProcessedSize,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
CDecoder _decoder;
|
||||
bool _finishStream;
|
||||
|
||||
public:
|
||||
MY_UNKNOWN_IMP2(
|
||||
ICompressSetFinishMode,
|
||||
ICompressGetInStreamProcessedSize)
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetFinishMode)(UInt32 finishMode);
|
||||
STDMETHOD(GetInStreamProcessedSize)(UInt64 *value);
|
||||
|
||||
CComDecoder(): _finishStream(false) {}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
190
CPP/7zip/Compress/XzEncoder.cpp
Normal file
190
CPP/7zip/Compress/XzEncoder.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
// XzEncoder.cpp
|
||||
|
||||
#include "StdAfx.h"
|
||||
|
||||
#include "../../../C/Alloc.h"
|
||||
|
||||
#include "../Common/CWrappers.h"
|
||||
#include "../Common/StreamUtils.h"
|
||||
|
||||
#include "XzEncoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
|
||||
namespace NLzma2 {
|
||||
|
||||
HRESULT SetLzma2Prop(PROPID propID, const PROPVARIANT &prop, CLzma2EncProps &lzma2Props);
|
||||
|
||||
}
|
||||
|
||||
namespace NXz {
|
||||
|
||||
extern "C" {
|
||||
|
||||
static void *SzBigAlloc(ISzAllocPtr, size_t size) { return BigAlloc(size); }
|
||||
static void SzBigFree(ISzAllocPtr, void *address) { BigFree(address); }
|
||||
static const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
|
||||
static void *SzAlloc(ISzAllocPtr, size_t size) { return MyAlloc(size); }
|
||||
static void SzFree(ISzAllocPtr, void *address) { MyFree(address); }
|
||||
static const ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
}
|
||||
|
||||
void CEncoder::InitCoderProps()
|
||||
{
|
||||
Lzma2EncProps_Init(&_lzma2Props);
|
||||
XzProps_Init(&xzProps);
|
||||
XzFilterProps_Init(&filter);
|
||||
|
||||
xzProps.lzma2Props = &_lzma2Props;
|
||||
// xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
|
||||
xzProps.filterProps = NULL;
|
||||
}
|
||||
|
||||
CEncoder::CEncoder()
|
||||
{
|
||||
InitCoderProps();
|
||||
}
|
||||
|
||||
CEncoder::~CEncoder()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HRESULT CEncoder::SetCoderProp(PROPID propID, const PROPVARIANT &prop)
|
||||
{
|
||||
return NLzma2::SetLzma2Prop(propID, prop, _lzma2Props);
|
||||
}
|
||||
|
||||
STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
|
||||
const PROPVARIANT *coderProps, UInt32 numProps)
|
||||
{
|
||||
Lzma2EncProps_Init(&_lzma2Props);
|
||||
|
||||
for (UInt32 i = 0; i < numProps; i++)
|
||||
{
|
||||
RINOK(SetCoderProp(propIDs[i], coderProps[i]));
|
||||
}
|
||||
return S_OK;
|
||||
// return SResToHRESULT(Lzma2Enc_SetProps(_encoder, &lzma2Props));
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 * /* outSize */,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
CSeqOutStreamWrap seqOutStream;
|
||||
|
||||
seqOutStream.Init(outStream);
|
||||
|
||||
// if (IntToBool(newData))
|
||||
{
|
||||
/*
|
||||
UInt64 size;
|
||||
{
|
||||
NCOM::CPropVariant prop;
|
||||
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
|
||||
if (prop.vt != VT_UI8)
|
||||
return E_INVALIDARG;
|
||||
size = prop.uhVal.QuadPart;
|
||||
RINOK(updateCallback->SetTotal(size));
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
CLzma2EncProps lzma2Props;
|
||||
Lzma2EncProps_Init(&lzma2Props);
|
||||
|
||||
lzma2Props.lzmaProps.level = GetLevel();
|
||||
*/
|
||||
|
||||
CSeqInStreamWrap seqInStream;
|
||||
|
||||
seqInStream.Init(inStream);
|
||||
|
||||
|
||||
/*
|
||||
{
|
||||
NCOM::CPropVariant prop = (UInt64)size;
|
||||
RINOK(NCompress::NLzma2::SetLzma2Prop(NCoderPropID::kReduceSize, prop, lzma2Props));
|
||||
}
|
||||
|
||||
FOR_VECTOR (i, _methods)
|
||||
{
|
||||
COneMethodInfo &m = _methods[i];
|
||||
SetGlobalLevelAndThreads(m
|
||||
#ifndef _7ZIP_ST
|
||||
, _numThreads
|
||||
#endif
|
||||
);
|
||||
{
|
||||
FOR_VECTOR (j, m.Props)
|
||||
{
|
||||
const CProp &prop = m.Props[j];
|
||||
RINOK(NCompress::NLzma2::SetLzma2Prop(prop.Id, prop.Value, lzma2Props));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
lzma2Props.numTotalThreads = _numThreads;
|
||||
#endif
|
||||
|
||||
*/
|
||||
|
||||
CCompressProgressWrap progressWrap;
|
||||
|
||||
progressWrap.Init(progress);
|
||||
|
||||
xzProps.checkId = XZ_CHECK_CRC32;
|
||||
// xzProps.checkId = XZ_CHECK_CRC64;
|
||||
/*
|
||||
CXzProps xzProps;
|
||||
CXzFilterProps filter;
|
||||
XzProps_Init(&xzProps);
|
||||
XzFilterProps_Init(&filter);
|
||||
xzProps.lzma2Props = &_lzma2Props;
|
||||
*/
|
||||
/*
|
||||
xzProps.filterProps = (_filterId != 0 ? &filter : NULL);
|
||||
switch (_crcSize)
|
||||
{
|
||||
case 0: xzProps.checkId = XZ_CHECK_NO; break;
|
||||
case 4: xzProps.checkId = XZ_CHECK_CRC32; break;
|
||||
case 8: xzProps.checkId = XZ_CHECK_CRC64; break;
|
||||
case 32: xzProps.checkId = XZ_CHECK_SHA256; break;
|
||||
default: return E_INVALIDARG;
|
||||
}
|
||||
filter.id = _filterId;
|
||||
if (_filterId == XZ_ID_Delta)
|
||||
{
|
||||
bool deltaDefined = false;
|
||||
FOR_VECTOR (j, _filterMethod.Props)
|
||||
{
|
||||
const CProp &prop = _filterMethod.Props[j];
|
||||
if (prop.Id == NCoderPropID::kDefaultProp && prop.Value.vt == VT_UI4)
|
||||
{
|
||||
UInt32 delta = (UInt32)prop.Value.ulVal;
|
||||
if (delta < 1 || delta > 256)
|
||||
return E_INVALIDARG;
|
||||
filter.delta = delta;
|
||||
deltaDefined = true;
|
||||
}
|
||||
}
|
||||
if (!deltaDefined)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*/
|
||||
SRes res = Xz_Encode(&seqOutStream.vt, &seqInStream.vt, &xzProps, progress ? &progressWrap.vt : NULL);
|
||||
/*
|
||||
if (res == SZ_OK)
|
||||
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
||||
*/
|
||||
return SResToHRESULT(res);
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
44
CPP/7zip/Compress/XzEncoder.h
Normal file
44
CPP/7zip/Compress/XzEncoder.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// XzEncoder.h
|
||||
|
||||
#ifndef __XZ_ENCODER_H
|
||||
#define __XZ_ENCODER_H
|
||||
|
||||
#include "../../../C/XzEnc.h"
|
||||
|
||||
#include "../../Common/MyCom.h"
|
||||
|
||||
#include "../ICoder.h"
|
||||
|
||||
namespace NCompress {
|
||||
namespace NXz {
|
||||
|
||||
|
||||
class CEncoder:
|
||||
public ICompressCoder,
|
||||
public ICompressSetCoderProperties,
|
||||
public CMyUnknownImp
|
||||
{
|
||||
// CXzEncHandle _encoder;
|
||||
public:
|
||||
CLzma2EncProps _lzma2Props;
|
||||
|
||||
CXzProps xzProps;
|
||||
CXzFilterProps filter;
|
||||
|
||||
MY_UNKNOWN_IMP2(ICompressCoder, ICompressSetCoderProperties)
|
||||
|
||||
void InitCoderProps();
|
||||
|
||||
HRESULT SetCoderProp(PROPID propID, const PROPVARIANT &prop);
|
||||
|
||||
STDMETHOD(Code)(ISequentialInStream *inStream, ISequentialOutStream *outStream,
|
||||
const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress);
|
||||
STDMETHOD(SetCoderProperties)(const PROPID *propIDs, const PROPVARIANT *props, UInt32 numProps);
|
||||
|
||||
CEncoder();
|
||||
virtual ~CEncoder();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -100,7 +100,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
}
|
||||
}
|
||||
unsigned bytePos = bitPos >> 3;
|
||||
UInt32 symbol = buf[bytePos] | ((UInt32)buf[bytePos + 1] << 8) | ((UInt32)buf[bytePos + 2] << 16);
|
||||
UInt32 symbol = buf[bytePos] | ((UInt32)buf[(size_t)bytePos + 1] << 8) | ((UInt32)buf[(size_t)bytePos + 2] << 16);
|
||||
symbol >>= (bitPos & 7);
|
||||
symbol &= (1 << numBits) - 1;
|
||||
bitPos += numBits;
|
||||
@@ -129,7 +129,7 @@ HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *
|
||||
_stack[i++] = (Byte)cur;
|
||||
if (needPrev)
|
||||
{
|
||||
_suffixes[head - 1] = (Byte)cur;
|
||||
_suffixes[(size_t)head - 1] = (Byte)cur;
|
||||
if (symbol == head - 1)
|
||||
_stack[0] = (Byte)cur;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user