ppmddecoder.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 183 行

CPP
183
字号
// PPMDDecoder.cpp#include "StdAfx.h"#include "Common/Defs.h"#include "Windows/Defs.h"#include "PPMDDecoder.h"namespace NCompress {namespace NPPMD {const int kLenIdFinished = -1;const int kLenIdNeedInit = -2;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);  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;}class CDecoderFlusher{  CDecoder *_coder;public:  bool NeedFlush;  CDecoderFlusher(CDecoder *coder): _coder(coder), NeedFlush(true) {}  ~CDecoderFlusher()  {    if (NeedFlush)      _coder->Flush();    _coder->ReleaseStreams();  }};HRESULT CDecoder::CodeSpec(UInt32 size, Byte *memStream){  const UInt32 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 (!_outStream.Create(1 << 20))    return E_OUTOFMEMORY;    SetInStream(inStream);  _outStream.SetStream(outStream);  SetOutStreamSize(outSize);  CDecoderFlusher flusher(this);  while(true)  {    _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, &_processedSize));    }    if (_outSizeDefined)      if (_outStream.GetProcessedSize() >= _outSize)        break;  }  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; }#endifSTDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress){  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_MODESTDMETHODIMP 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}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?