quantumdecoder.h

来自「由7-zip提供的压缩、解压缩程序」· C头文件 代码 · 共 288 行

H
288
字号
// QuantumDecoder.h#ifndef __QUANTUM_DECODER_H#define __QUANTUM_DECODER_H#include "../../../Common/MyCom.h"#include "../../Common/InBuffer.h"#include "../../ICoder.h"#include "../LZ/LZOutWindow.h"namespace NCompress {namespace NQuantum {class CStreamBitDecoder{  UInt32 m_Value;  CInBuffer m_Stream;public:  bool Create(UInt32 bufferSize) { return m_Stream.Create(bufferSize); }  void SetStream(ISequentialInStream *inStream) { m_Stream.SetStream(inStream);}  void ReleaseStream() { m_Stream.ReleaseStream();}  void Finish() { m_Value = 0x10000; }  void Init()  {    m_Stream.Init();    m_Value = 0x10000;   }  UInt64 GetProcessedSize() const { return m_Stream.GetProcessedSize(); }  bool WasFinished() const { return m_Stream.WasFinished(); };    UInt32 ReadBit()  {    if (m_Value >= 0x10000)      m_Value = 0x100 | m_Stream.ReadByte();    UInt32 res = (m_Value >> 7) & 1;    m_Value <<= 1;    return res;  }  UInt32 ReadBits(int numBits) // numBits > 0  {    UInt32 res = 0;    do      res = (res << 1) | ReadBit();     while(--numBits != 0);    return res;  }};const int kNumLitSelectorBits = 2;const unsigned int kNumLitSelectors = (1 << kNumLitSelectorBits);const unsigned int kNumLitSymbols = 1 << (8 - kNumLitSelectorBits);const unsigned int kNumMatchSelectors = 3;const unsigned int kNumSelectors = kNumLitSelectors + kNumMatchSelectors;const unsigned int kNumLen3PosSymbolsMax = 24;const unsigned int kNumLen4PosSymbolsMax = 36;const unsigned int kNumLen5PosSymbolsMax = 42;const unsigned int kNumLenSymbols = 27;const unsigned int kNumSymbolsMax = kNumLitSymbols; // 64const unsigned int kMatchMinLen = 3;const unsigned int kNumSimplePosSlots = 4;const unsigned int kNumSimpleLenSlots = 6;namespace NRangeCoder {class CDecoder{  UInt32 Low;  UInt32 Range;  UInt32 Code;public:  CStreamBitDecoder Stream;  bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }  void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }  void ReleaseStream() { Stream.ReleaseStream(); }  void Init()  {    Stream.Init();    Low = 0;    Range = 0x10000;    Code = Stream.ReadBits(16);  }  void Finish()  {    // we need these extra two Bit_reads    Stream.ReadBit();    Stream.ReadBit();    Stream.Finish();  }  UInt64 GetProcessedSize() const { return Stream.GetProcessedSize(); }  UInt32 GetThreshold(UInt32 total) const   {    return ((Code + 1) * total - 1) / Range; // & 0xFFFF is not required;  }  void Decode(UInt32 start, UInt32 end, UInt32 total)  {    UInt32 high = Low + end * Range / total - 1;    UInt32 offset = start * Range / total;    Code -= offset;    Low += offset;    while (true)     {      if ((Low & 0x8000) != (high & 0x8000))       {        if ((Low & 0x4000) == 0 || (high & 0x4000) != 0)           break;        Low &= 0x3FFF;        high |= 0x4000;      }      Low = (Low << 1) & 0xFFFF;      high = ((high << 1) | 1) & 0xFFFF;      Code = ((Code << 1) | Stream.ReadBit());    }    Range = high - Low + 1;  }};const UInt16 kUpdateStep = 8;const UInt16 kFreqSumMax = 3800;const UInt16 kReorderCountStart = 4;const UInt16 kReorderCount = 50;class CModelDecoder{  unsigned int NumItems;  unsigned int ReorderCount;  UInt16 Freqs[kNumSymbolsMax + 1];  Byte Values[kNumSymbolsMax];public:  void Init(unsigned int numItems)  {    NumItems = numItems;    ReorderCount = kReorderCountStart;    for(unsigned int i = 0; i < numItems; i++)    {      Freqs[i] = (UInt16)(numItems - i);      Values[i] = (Byte)i;    }    Freqs[numItems] = 0;  }    unsigned int Decode(CDecoder *rangeDecoder)  {    UInt32 threshold = rangeDecoder->GetThreshold(Freqs[0]);    unsigned int i;    for (i = 1; Freqs[i] > threshold; i++);    rangeDecoder->Decode(Freqs[i], Freqs[i - 1], Freqs[0]);    unsigned int res = Values[--i];     do      Freqs[i] += kUpdateStep;    while(i-- != 0);    if (Freqs[0] > kFreqSumMax)    {      if (--ReorderCount == 0)      {        ReorderCount = kReorderCount;        for(i = 0; i < NumItems; i++)          Freqs[i] = ((Freqs[i] - Freqs[i + 1]) + 1) >> 1;        for(i = 0; i < NumItems - 1; i++)          for(unsigned int j = i + 1; j < NumItems; j++)            if (Freqs[i] < Freqs[j])            {              UInt16 tmpFreq = Freqs[i];              Byte tmpVal = Values[i];              Freqs[i] = Freqs[j];              Values[i] = Values[j];              Freqs[j] = tmpFreq;              Values[j] = tmpVal;            }        do          Freqs[i] += Freqs[i + 1];        while(i-- != 0);      }      else      {        i = NumItems - 1;        do        {          Freqs[i] >>= 1;          if (Freqs[i] <= Freqs[i + 1])            Freqs[i] = Freqs[i + 1] + 1;        }        while(i-- != 0);      }    }    return res;  };};}class CDecoder:   public ICompressCoder,  public ICompressSetInStream,  public ICompressSetOutStreamSize,  public CMyUnknownImp{  CLZOutWindow _outWindowStream;  NRangeCoder::CDecoder _rangeDecoder;  ///////////////////  // State  UInt64 _outSize;  // UInt64 _nowPos64;  int _remainLen; // -1 means end of stream. // -2 means need Init  UInt32 _rep0;  int _numDictBits;  UInt32 _dictionarySize;  NRangeCoder::CModelDecoder m_Selector;  NRangeCoder::CModelDecoder m_Literals[kNumLitSelectors];  NRangeCoder::CModelDecoder m_PosSlot[kNumMatchSelectors];  NRangeCoder::CModelDecoder m_LenSlot;  bool _keepHistory;    void Init();  HRESULT CodeSpec(UInt32 size);public:  MY_UNKNOWN_IMP2(      ICompressSetInStream,       ICompressSetOutStreamSize)  void ReleaseStreams()  {    _outWindowStream.ReleaseStream();    ReleaseInStream();  }  class CDecoderFlusher  {    CDecoder *_decoder;  public:    bool NeedFlush;    CDecoderFlusher(CDecoder *decoder): _decoder(decoder), NeedFlush(true) {}    ~CDecoderFlusher()     {       if (NeedFlush)        _decoder->Flush();      _decoder->ReleaseStreams();     }  };  HRESULT Flush() {  return _outWindowStream.Flush(); }    HRESULT CodeReal(ISequentialInStream *inStream,      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,      ICompressProgressInfo *progress);    STDMETHOD(Code)(ISequentialInStream *inStream,      ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,      ICompressProgressInfo *progress);  STDMETHOD(SetInStream)(ISequentialInStream *inStream);  STDMETHOD(ReleaseInStream)();  STDMETHOD(SetOutStreamSize)(const UInt64 *outSize);  void SetParams(int numDictBits)  {    _numDictBits = numDictBits;    _dictionarySize = (UInt32)1 << numDictBits;  }  void SetKeepHistory(bool keepHistory)  {    _keepHistory = keepHistory;  }  CDecoder(): _keepHistory(false) {}  virtual ~CDecoder() {}};}}#endif

⌨️ 快捷键说明

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