mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-15 02:11:43 -06:00
4.27 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
31e7b924e8
commit
d66cf2fcf3
@@ -10,6 +10,9 @@
|
||||
namespace NCompress {
|
||||
namespace NPPMD {
|
||||
|
||||
const int kLenIdFinished = -1;
|
||||
const int kLenIdNeedInit = -2;
|
||||
|
||||
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
|
||||
{
|
||||
if (size < 5)
|
||||
@@ -18,6 +21,15 @@ STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size
|
||||
_usedMemorySize = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
_usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8);
|
||||
|
||||
if (_usedMemorySize > kMaxMemBlockSize)
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (!_rangeDecoder.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -25,76 +37,146 @@ class CDecoderFlusher
|
||||
{
|
||||
CDecoder *_coder;
|
||||
public:
|
||||
CDecoderFlusher(CDecoder *coder): _coder(coder) {}
|
||||
bool NeedFlush;
|
||||
CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {}
|
||||
~CDecoderFlusher()
|
||||
{
|
||||
_coder->Flush();
|
||||
if (NeedFlush)
|
||||
_coder->Flush();
|
||||
_coder->ReleaseStreams();
|
||||
}
|
||||
};
|
||||
|
||||
UInt32 GetMatchLen(const Byte *pointer1, const Byte *pointer2,
|
||||
UInt32 limit)
|
||||
{
|
||||
UInt32 i;
|
||||
for(i = 0; i < limit && *pointer1 == *pointer2;
|
||||
pointer1++, pointer2++, i++);
|
||||
return i;
|
||||
HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream)
|
||||
{
|
||||
const startSize = size;
|
||||
if (_outSizeDefined)
|
||||
{
|
||||
const UInt64 rem = _outSize - _processedSize;
|
||||
if (size > rem)
|
||||
size = (UInt32)rem;
|
||||
}
|
||||
|
||||
if (_remainLen == kLenIdFinished)
|
||||
return S_OK;
|
||||
if (_remainLen == kLenIdNeedInit)
|
||||
{
|
||||
_rangeDecoder.Init();
|
||||
_remainLen = 0;
|
||||
_info.MaxOrder = 0;
|
||||
_info.StartModelRare(_order);
|
||||
}
|
||||
while (size != 0)
|
||||
{
|
||||
int symbol = _info.DecodeSymbol(&_rangeDecoder);
|
||||
if (symbol < 0)
|
||||
{
|
||||
_remainLen = kLenIdFinished;
|
||||
break;
|
||||
}
|
||||
if (memStream != 0)
|
||||
*memStream++ = symbol;
|
||||
else
|
||||
_outStream.WriteByte((Byte)symbol);
|
||||
size--;
|
||||
}
|
||||
_processedSize += startSize - size;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
|
||||
ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
|
||||
ICompressProgressInfo *progress)
|
||||
{
|
||||
if (!_rangeDecoder.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
if (!_outStream.Create(1 << 20))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
_rangeDecoder.SetStream(inStream);
|
||||
_rangeDecoder.Init();
|
||||
|
||||
SetInStream(inStream);
|
||||
_outStream.SetStream(outStream);
|
||||
_outStream.Init();
|
||||
|
||||
SetOutStreamSize(outSize);
|
||||
CDecoderFlusher flusher(this);
|
||||
|
||||
UInt64 progressPosValuePrev = 0, pos = 0;
|
||||
|
||||
if (!_info.SubAllocator.StartSubAllocator(_usedMemorySize))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
// _info.Init();
|
||||
// _info.MaxOrder = _order;
|
||||
_info.MaxOrder = 0;
|
||||
_info.StartModelRare(_order);
|
||||
|
||||
UInt64 size = (outSize == NULL) ? (UInt64)(Int64)(-1) : *outSize;
|
||||
|
||||
while(pos < size)
|
||||
while(true)
|
||||
{
|
||||
pos++;
|
||||
int symbol = _info.DecodeSymbol(&_rangeDecoder);
|
||||
if (symbol < 0)
|
||||
return S_OK;
|
||||
_outStream.WriteByte(symbol);
|
||||
if (pos - progressPosValuePrev >= (1 << 18) && progress != NULL)
|
||||
_processedSize = _outStream.GetProcessedSize();
|
||||
UInt32 curSize = (1 << 18);
|
||||
RINOK(CodeSpec(curSize, NULL));
|
||||
if (_remainLen == kLenIdFinished)
|
||||
break;
|
||||
if (progress != NULL)
|
||||
{
|
||||
UInt64 inSize = _rangeDecoder.GetProcessedSize();
|
||||
RINOK(progress->SetRatioInfo(&inSize, &pos));
|
||||
progressPosValuePrev = pos;
|
||||
RINOK(progress->SetRatioInfo(&inSize, &_processedSize));
|
||||
}
|
||||
if (_outSizeDefined)
|
||||
if (_outStream.GetProcessedSize() >= _outSize)
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
flusher.NeedFlush = false;
|
||||
return Flush();
|
||||
}
|
||||
|
||||
#ifdef _NO_EXCEPTIONS
|
||||
|
||||
#define PPMD_TRY_BEGIN
|
||||
#define PPMD_TRY_END
|
||||
|
||||
#else
|
||||
|
||||
#define PPMD_TRY_BEGIN try {
|
||||
#define PPMD_TRY_END } \
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; } \
|
||||
catch(const COutBufferException &e) { return e.ErrorCode; } \
|
||||
catch(...) { return S_FALSE; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
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 COutBufferException &e) { return e.ErrorCode; }
|
||||
catch(const CInBufferException &e) { return e.ErrorCode; }
|
||||
catch(...) { return E_FAIL; }
|
||||
PPMD_TRY_BEGIN
|
||||
return CodeReal(inStream, outStream, inSize, outSize, progress);
|
||||
PPMD_TRY_END
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
|
||||
{
|
||||
_rangeDecoder.SetStream(inStream);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::ReleaseInStream()
|
||||
{
|
||||
_rangeDecoder.ReleaseStream();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
|
||||
{
|
||||
if (_outSizeDefined = (outSize != NULL))
|
||||
_outSize = *outSize;
|
||||
_remainLen = kLenIdNeedInit;
|
||||
_outStream.Init();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
#ifdef _ST_MODE
|
||||
|
||||
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
|
||||
{
|
||||
PPMD_TRY_BEGIN
|
||||
if (processedSize)
|
||||
*processedSize = 0;
|
||||
const UInt64 startPos = _processedSize;
|
||||
RINOK(CodeSpec(size, (Byte *)data));
|
||||
if (processedSize)
|
||||
*processedSize = (UInt32)(_processedSize - startPos);
|
||||
return Flush();
|
||||
PPMD_TRY_END
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user