zdecoder.cpp

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

CPP
173
字号
// ZDecoder.cpp#include "StdAfx.h"#include "ZDecoder.h"#include "../../../Common/Alloc.h"#include "../../Common/InBuffer.h"#include "../../Common/OutBuffer.h"#include "../../Common/LSBFDecoder.h"namespace NCompress {namespace NZ {static const UInt32 kBufferSize = (1 << 20);static const Byte kNumBitsMask = 0x1F;   static const Byte kBlockModeMask = 0x80;   static const int kNumMinBits = 9;   static const int kNumMaxBits = 16;   void CDecoder::Free(){  MyFree(_parents);  _parents = 0;  MyFree(_suffixes);  _suffixes = 0;  MyFree(_stack);  _stack = 0;}bool CDecoder::Alloc(size_t numItems){  Free();  _parents = (UInt16 *)MyAlloc(numItems * sizeof(UInt16));  if (_parents == 0)    return false;  _suffixes = (Byte *)MyAlloc(numItems * sizeof(Byte));  if (_suffixes == 0)    return false;  _stack = (Byte *)MyAlloc(numItems * sizeof(Byte));  return _stack != 0;}CDecoder::~CDecoder(){  Free();}STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress){  NStream::NLSBF::CBaseDecoder<CInBuffer> inBuffer;  COutBuffer outBuffer;  if (!inBuffer.Create(kBufferSize))    return E_OUTOFMEMORY;  inBuffer.SetStream(inStream);  inBuffer.Init();  if (!outBuffer.Create(kBufferSize))    return E_OUTOFMEMORY;  outBuffer.SetStream(outStream);  outBuffer.Init();  int	maxbits = _properties & kNumBitsMask;  if (maxbits < kNumMinBits || maxbits > kNumMaxBits)    return S_FALSE;  UInt32 numItems = 1 << maxbits;  bool blockMode = ((_properties & kBlockModeMask) != 0);  if (!blockMode)    return E_NOTIMPL;  if (maxbits != _numMaxBits || _parents == 0 || _suffixes == 0 || _stack == 0)  {    if (!Alloc(numItems))      return E_OUTOFMEMORY;    _numMaxBits = maxbits;  }  UInt64 prevPos = 0;  int numBits = kNumMinBits;  UInt32 head = blockMode ? 257 : 256;  bool needPrev = false;  int keepBits = 0;  _parents[256] = 0; // virus protection  _suffixes[256] = 0;  while (true)  {    if (keepBits < numBits)      keepBits = numBits * 8;    UInt32 symbol = inBuffer.ReadBits(numBits);    if (inBuffer.ExtraBitsWereRead())      break;    keepBits -= numBits;    if (symbol >= head)      return S_FALSE;    if (blockMode && symbol == 256)    {      for (;keepBits > 0; keepBits--)        inBuffer.ReadBits(1);      numBits = kNumMinBits;      head = 257;      needPrev = false;      continue;    }    UInt32 cur = symbol;    int i = 0;    while (cur >= 256)    {      _stack[i++] = _suffixes[cur];      cur = _parents[cur];    }    _stack[i++] = (Byte)cur;    if (needPrev)    {      _suffixes[head - 1] = (Byte)cur;      if (symbol == head - 1)        _stack[0] = (Byte)cur;    }    while (i > 0)      outBuffer.WriteByte((_stack[--i]));    if (head < numItems)    {      needPrev = true;      _parents[head++] = (UInt16)symbol;      if (head > ((UInt32)1 << numBits))      {        if (numBits < maxbits)        {          numBits++;          keepBits = numBits * 8;        }      }    }    else      needPrev = false;    UInt64 nowPos = outBuffer.GetProcessedSize();    if (progress != NULL && nowPos - prevPos > (1 << 18))    {      prevPos = nowPos;      UInt64 packSize = inBuffer.GetProcessedSize();      RINOK(progress->SetRatioInfo(&packSize, &nowPos));    }  }  return outBuffer.Flush();}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(...) { return S_FALSE; }}STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *data, UInt32 size){  if (size < 1)    return E_INVALIDARG;  _properties = data[0];  return S_OK;}}}

⌨️ 快捷键说明

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