Files
easy7zip/7zip/Compress/PPMD/PPMDDecoder.cpp
Igor Pavlov 3c510ba80b 4.20
2016-05-28 00:15:41 +01:00

101 lines
2.4 KiB
C++
Executable File

// PPMDDecoder.cpp
#include "StdAfx.h"
#include "Common/Defs.h"
#include "Windows/Defs.h"
#include "PPMDDecoder.h"
namespace NCompress {
namespace NPPMD {
STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
{
if (size < 5)
return E_INVALIDARG;
_order = properties[0];
_usedMemorySize = 0;
for (int i = 0; i < 4; i++)
_usedMemorySize += ((UInt32)(properties[1 + i])) << (i * 8);
return S_OK;
}
class CDecoderFlusher
{
CDecoder *_coder;
public:
CDecoderFlusher(CDecoder *coder): _coder(coder) {}
~CDecoderFlusher()
{
_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;
}
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();
_outStream.SetStream(outStream);
_outStream.Init();
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)
{
pos++;
int symbol = _info.DecodeSymbol(&_rangeDecoder);
if (symbol < 0)
return S_OK;
_outStream.WriteByte(symbol);
if (pos - progressPosValuePrev >= (1 << 18) && progress != NULL)
{
UInt64 inSize = _rangeDecoder.GetProcessedSize();
RINOK(progress->SetRatioInfo(&inSize, &pos));
progressPosValuePrev = pos;
}
}
return S_OK;
}
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; }
}
}}