lzhdecoder.cpp

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

CPP
217
字号
// LzhDecoder.cpp#include "StdAfx.h"#include "LzhDecoder.h"#include "Windows/Defs.h"namespace NCompress{namespace NLzh {namespace NDecoder {static const UInt32 kHistorySize = (1 << 16);static const int kBlockSizeBits = 16;static const int kNumCBits = 9;static const int kNumLevelBits = 5;	 // smallest integer such that (1 << kNumLevelBits) > kNumLevelSymbols/UInt32 CCoder::ReadBits(int numBits) {  return m_InBitStream.ReadBits(numBits); }HRESULT CCoder::ReadLevelTable(){  int n = ReadBits(kNumLevelBits);  if (n == 0)   {    m_LevelHuffman.Symbol = ReadBits(kNumLevelBits);    if (m_LevelHuffman.Symbol >= kNumLevelSymbols)      return S_FALSE;  }  else   {    if (n > kNumLevelSymbols)      return S_FALSE;    m_LevelHuffman.Symbol = -1;    Byte lens[kNumLevelSymbols];    int i = 0;    while (i < n)     {      int c = m_InBitStream.ReadBits(3);      if (c == 7)         while (ReadBits(1))           if (c++ > kMaxHuffmanLen)            return S_FALSE;      lens[i++] = (Byte)c;      if (i == kNumSpecLevelSymbols)       {        c = ReadBits(2);        while (--c >= 0)          lens[i++] = 0;      }    }    while (i < kNumLevelSymbols)      lens[i++] = 0;    m_LevelHuffman.SetCodeLengths(lens);  }  return S_OK;}HRESULT CCoder::ReadPTable(int numBits){  int n = ReadBits(numBits);  if (n == 0)  {    m_PHuffmanDecoder.Symbol = ReadBits(numBits);    if (m_PHuffmanDecoder.Symbol >= kNumDistanceSymbols)      return S_FALSE;  }  else   {    if (n > kNumDistanceSymbols)      return S_FALSE;    m_PHuffmanDecoder.Symbol = -1;    Byte lens[kNumDistanceSymbols];    int i = 0;    while (i < n)     {      int c = m_InBitStream.ReadBits(3);      if (c == 7)         while (ReadBits(1))         {          if (c > kMaxHuffmanLen)            return S_FALSE;          c++;        }      lens[i++] = (Byte)c;    }    while (i < kNumDistanceSymbols)      lens[i++] = 0;    m_PHuffmanDecoder.SetCodeLengths(lens);  }  return S_OK;}HRESULT CCoder::ReadCTable(){  int n = ReadBits(kNumCBits);  if (n == 0)   {    m_CHuffmanDecoder.Symbol = ReadBits(kNumCBits);    if (m_CHuffmanDecoder.Symbol >= kNumCSymbols)      return S_FALSE;  }  else   {    if (n > kNumCSymbols)      return S_FALSE;    m_CHuffmanDecoder.Symbol = -1;    Byte lens[kNumCSymbols];    int i = 0;    while (i < n)     {      int c = m_LevelHuffman.Decode(&m_InBitStream);      if (c < kNumSpecLevelSymbols)       {        if (c == 0)          c = 1;        else if (c == 1)          c = ReadBits(4) + 3;        else          c = ReadBits(kNumCBits) + 20;        while (--c >= 0)        {          if (i > kNumCSymbols)            return S_FALSE;          lens[i++] = 0;        }      }      else        lens[i++] = c - 2;    }    while (i < kNumCSymbols)      lens[i++] = 0;    m_CHuffmanDecoder.SetCodeLengths(lens);  }  return S_OK;}STDMETHODIMP CCoder::CodeReal(ISequentialInStream *inStream,    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress){  if (outSize == NULL)    return E_INVALIDARG;  if (!m_OutWindowStream.Create(kHistorySize))    return E_OUTOFMEMORY;  if (!m_InBitStream.Create(1 << 20))    return E_OUTOFMEMORY;  UInt64 pos = 0;  m_OutWindowStream.SetStream(outStream);  m_OutWindowStream.Init(false);  m_InBitStream.SetStream(inStream);  m_InBitStream.Init();    CCoderReleaser coderReleaser(this);  int pbit;  if (m_NumDictBits <= 13)      pbit = 4;  else       pbit = 5;  UInt32 blockSize = 0;  while(pos < *outSize)  {    // for (i = 0; i < dictSize; i++) dtext[i] = 0x20;        if (blockSize == 0)     {      if (progress != NULL)      {        UInt64 packSize = m_InBitStream.GetProcessedSize();        RINOK(progress->SetRatioInfo(&packSize, &pos));      }		  blockSize = ReadBits(kBlockSizeBits);      ReadLevelTable();      ReadCTable();      RINOK(ReadPTable(pbit));		}    blockSize--;    UInt32 c = m_CHuffmanDecoder.Decode(&m_InBitStream);    if (c < 256)     {      m_OutWindowStream.PutByte((Byte)c);      pos++;    }    else     {      // offset = (interface->method == LARC_METHOD_NUM) ? 0x100 - 2 : 0x100 - 3;      UInt32 len  = c - 256 + kMinMatch;      UInt32 distance = m_PHuffmanDecoder.Decode(&m_InBitStream);    	if (distance != 0)		    distance = (1 << (distance - 1)) + ReadBits(distance - 1);      pos += len;      if (distance >= pos)        throw 1;      m_OutWindowStream.CopyBlock(distance, len);    }  }  coderReleaser.NeedFlush = false;  return m_OutWindowStream.Flush();}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 CInBufferException &e) { return e.ErrorCode; }  catch(const CLZOutWindowException &e) { return e.ErrorCode; }  catch(...) { return S_FALSE; }}}}}

⌨️ 快捷键说明

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