⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lzmaencoder.cpp

📁 proximap bootloader for study
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--)      {        UInt32 curBack = _matchDistances[lenTest];        UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);        COptimal &optimum = _optimum[cur + lenTest];        if (curAndLenPrice < optimum.Price)         {          optimum.Price = curAndLenPrice;          optimum.PosPrev = cur;          optimum.BackPrev = curBack + kNumRepDistances;          optimum.Prev1IsChar = false;        }        if (_maxMode)        {          UInt32 backOffset = curBack + 1;          UInt32 temp;          for (temp = lenTest + 1; temp < numAvailableBytes; temp++)            if (data[temp] != data[(size_t)temp - backOffset])              break;          UInt32 lenTest2 = temp - (lenTest + 1);          if (lenTest2 >= 2)          {            CState state2 = state;            state2.UpdateMatch();            UInt32 posStateNext = (position + lenTest) & _posStateMask;            UInt32 curAndLenCharPrice = curAndLenPrice +                 _isMatch[state2.Index][posStateNext].GetPrice(0) +                _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],                 true, data[(size_t)lenTest - backOffset], data[lenTest]);            state2.UpdateChar();            posStateNext = (position + lenTest + 1) & _posStateMask;            UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice(1);            UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice(1);                        // for(; lenTest2 >= 2; lenTest2--)            {              UInt32 offset = lenTest + 1 + lenTest2;              while(lenEnd < cur + offset)                _optimum[++lenEnd].Price = kIfinityPrice;              UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(                  0, lenTest2, state2, posStateNext);              COptimal &optimum = _optimum[cur + offset];              if (curAndLenPrice < optimum.Price)               {                optimum.Price = curAndLenPrice;                optimum.PosPrev = cur + lenTest + 1;                optimum.BackPrev = 0;                optimum.Prev1IsChar = true;                optimum.Prev2 = true;                optimum.PosPrev2 = cur;                optimum.BackPrev2 = curBack + kNumRepDistances;              }            }          }        }      }    }  }}static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist){  const int kDif = 7;  return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif));}HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes){  lenRes = _matchFinder->GetLongestMatch(_matchDistances);  if (lenRes == _numFastBytes)    lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes],         kMatchMaxLen - lenRes);  _additionalOffset++;  return _matchFinder->MovePos();}HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes){  UInt32 lenMain;  if (!_longestMatchWasFound)  {    RINOK(ReadMatchDistances(lenMain));  }  else  {    lenMain = _longestMatchLength;    _longestMatchWasFound = false;  }  UInt32 repLens[kNumRepDistances];  UInt32 repMaxIndex = 0;  for(UInt32 i = 0; i < kNumRepDistances; i++)  {    repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);    if (i == 0 || repLens[i] > repLens[repMaxIndex])      repMaxIndex = i;  }  if(repLens[repMaxIndex] >= _numFastBytes)  {    backRes = repMaxIndex;    lenRes = repLens[repMaxIndex];    MovePos(lenRes - 1);    return S_OK;  }  if(lenMain >= _numFastBytes)  {    backRes = _matchDistances[_numFastBytes] + kNumRepDistances;     MovePos(lenMain - 1);    lenRes = lenMain;    return S_OK;  }  while (lenMain > 2)  {    if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain]))      break;    lenMain--;  }  if (lenMain == 2 && _matchDistances[2] >= 0x80)    lenMain = 1;  UInt32 backMain = _matchDistances[lenMain];  if (repLens[repMaxIndex] >= 2)  {    if (repLens[repMaxIndex] + 1 >= lenMain ||         repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12)))    {      backRes = repMaxIndex;      lenRes = repLens[repMaxIndex];      MovePos(lenRes - 1);      return S_OK;    }  }    if (lenMain >= 2)  {    RINOK(ReadMatchDistances(_longestMatchLength));    if (_longestMatchLength >= 2 &&      (        (_longestMatchLength >= lenMain &&           _matchDistances[lenMain] < backMain) ||         _longestMatchLength == lenMain + 1 &&           !ChangePair(backMain, _matchDistances[_longestMatchLength]) ||        _longestMatchLength > lenMain + 1 ||        _longestMatchLength + 1 >= lenMain &&           ChangePair(_matchDistances[lenMain - 1], backMain)      )      )    {      _longestMatchWasFound = true;      backRes = UInt32(-1);      lenRes = 1;      return S_OK;    }    for(UInt32 i = 0; i < kNumRepDistances; i++)    {      UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);      if (repLen >= 2 && repLen + 1 >= lenMain)      {        _longestMatchWasFound = true;        backRes = UInt32(-1);        lenRes = 1;        return S_OK;      }    }    backRes = backMain + kNumRepDistances;     MovePos(lenMain - 2);    lenRes = lenMain;    return S_OK;  }  backRes = UInt32(-1);  lenRes = 1;  return S_OK;}STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder){  _matchFinder = matchFinder;  return S_OK;}HRESULT CEncoder::Flush(UInt32 nowPos){  ReleaseMFStream();  WriteEndMarker(nowPos & _posStateMask);  _rangeEncoder.FlushData();  return _rangeEncoder.FlushStream();}void CEncoder::WriteEndMarker(UInt32 posState){  // This function for writing End Mark for stream version of LZMA.   // In current version this feature is not used.  if (!_writeEndMark)    return;  _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);  _isRep[_state.Index].Encode(&_rangeEncoder, 0);  _state.UpdateMatch();  UInt32 len = kMatchMinLen; // kMatchMaxLen;  _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);  UInt32 posSlot = (1 << kNumPosSlotBits)  - 1;  UInt32 lenToPosState = GetLenToPosState(len);  _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);  UInt32 footerBits = 30;  UInt32 posReduced = (UInt32(1) << footerBits) - 1;  _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);  _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);}HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,      ISequentialOutStream *outStream,       const UInt64 *inSize, const UInt64 *outSize,      ICompressProgressInfo *progress){  _needReleaseMFStream = false;  CCoderReleaser coderReleaser(this);  RINOK(SetStreams(inStream, outStream, inSize, outSize));  while(true)  {    UInt64 processedInSize;    UInt64 processedOutSize;    Int32 finished;    RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));    if (finished != 0)      return S_OK;    if (progress != 0)    {      RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));    }  }}HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,      ISequentialOutStream *outStream,       const UInt64 *inSize, const UInt64 *outSize){  _inStream = inStream;  _finished = false;  RINOK(Create());  RINOK(SetOutStream(outStream));  RINOK(Init());    // CCoderReleaser releaser(this);  /*  if (_matchFinder->GetNumAvailableBytes() == 0)    return Flush();  */  if (!_fastMode)  {    FillPosSlotPrices();    FillDistancesPrices();    FillAlignPrices();  }  _lenEncoder.SetTableSize(_numFastBytes);  _lenEncoder.UpdateTables(1 << _posStateBits);  _repMatchLenEncoder.SetTableSize(_numFastBytes);  _repMatchLenEncoder.UpdateTables(1 << _posStateBits);  lastPosSlotFillingPos = 0;  nowPos64 = 0;  return S_OK;}HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished){  if (_inStream != 0)  {    RINOK(_matchFinder->Init(_inStream));    _needReleaseMFStream = true;    _inStream = 0;  }  *finished = 1;  if (_finished)    return S_OK;  _finished = true;  UInt64 progressPosValuePrev = nowPos64;  if (nowPos64 == 0)  {    if (_matchFinder->GetNumAvailableBytes() == 0)      return Flush(UInt32(nowPos64));    UInt32 len; // it's not used    RINOK(ReadMatchDistances(len));    UInt32 posState = UInt32(nowPos64) & _posStateMask;    _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);    _state.UpdateChar();    Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);    _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);    _previousByte = curByte;    _additionalOffset--;    nowPos64++;  }  if (_matchFinder->GetNumAvailableBytes() == 0)    return Flush(UInt32(nowPos64));  while(true)  {    #ifdef _NO_EXCEPTIONS    if (_rangeEncoder.Stream.ErrorCode != S_OK)      return _rangeEncoder.Stream.ErrorCode;    #endif    UInt32 pos;    UInt32 posState = UInt32(nowPos64) & _posStateMask;    UInt32 len;    HRESULT result;    if (_fastMode)      result = GetOptimumFast(UInt32(nowPos64), pos, len);    else      result = GetOptimum(UInt32(nowPos64), pos, len);    RINOK(result);    if(len == 1 && pos == 0xFFFFFFFF)    {      _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);      _state.UpdateChar();      Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);      CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte);      if(_peviousIsMatch)      {        Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);        subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);      }      else        subCoder->Encode(&_rangeEncoder, curByte);      _previousByte = curByte;      _peviousIsMatch = false;    }    else    {      _peviousIsMatch = true;      _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);      if(pos < kNumRepDistances)      {        _isRep[_state.Index].Encode(&_rangeEncoder, 1);        if(pos == 0)        {          _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);          if(len == 1)            _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0);          else            _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1);        }        else        {          _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);          if (pos == 1)            _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);          else          {            _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);            _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);          }        }        if (len == 1)          _state.UpdateShortRep();        else        {          _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);          _state.UpdateRep();        }        UInt32 distance = _repDistances[pos];        if (pos != 0)        {          for(UInt32 i = pos; i >= 1; i--)            _repDistances[i] = _repDistances[i - 1];          _repDistances[0] = distance;        }      }      else      {        _isRep[_state.Index].Encode(&_rangeEncoder, 0);        _state.UpdateMatch();        _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);        pos -= kNumRepDistances;        UInt32 posSlot = GetPosSlot(pos);        UInt32 lenToPosState = GetLenToPosState(len);        _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);                if (posSlot >= kStartPosModelIndex)        {          UInt32 footerBits = ((posSlot >> 1) - 1);          UInt32 base = ((2 | (posSlot & 1)) << footerBits);          UInt32 posReduced = pos - base;          if (posSlot < kEndPosModelIndex)            NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1,                 &_rangeEncoder, footerBits, posReduced);          else          {            _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);            _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);            if (!_fastMode)              if (--_alignPriceCount == 0)                FillAlignPrices();          }        }        UInt32 distance = pos;        for(UInt32 i = kNumRepDistances - 1; i >= 1; i--)          _repDistances[i] = _repDistances[i - 1];        _repDistances[0] = distance;      }      _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);    }    _additionalOffset -= len;    nowPos64 += len;    if (!_fastMode)      if (nowPos64 - lastPosSlotFillingPos >= (1 << 9))      {        FillPosSlotPrices();        FillDistancesPrices();        lastPosSlotFillingPos = nowPos64;      }    if (_additionalOffset == 0)    {      *inSize = nowPos64;      *outSize = _rangeEncoder.GetProcessedSize();      if (_matchFinder->GetNumAvailableBytes() == 0)        return Flush(UInt32(nowPos64));      if (nowPos64 - progressPosValuePrev >= (1 << 12))      {        _finished = false;        *finished = 0;        return S_OK;      }    }  }}STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress){  #ifndef _NO_EXCEPTIONS  try   {   #endif    return CodeReal(inStream, outStream, inSize, outSize, progress);   #ifndef _NO_EXCEPTIONS  }  catch(const COutBufferException &e) { return e.ErrorCode; }  catch(...) { return E_FAIL; }  #endif}  void CEncoder::FillPosSlotPrices(){  for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)  {	  UInt32 posSlot;    for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++)      _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot);    for (; posSlot < _distTableSize; posSlot++)      _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) +       ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);  }}void CEncoder::FillDistancesPrices(){  for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)  {	  UInt32 i;    for (i = 0; i < kStartPosModelIndex; i++)      _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i];    for (; i < kNumFullDistances; i++)    {       UInt32 posSlot = GetPosSlot(i);      UInt32 footerBits = ((posSlot >> 1) - 1);      UInt32 base = ((2 | (posSlot & 1)) << footerBits);      _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] +          NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +               base - posSlot - 1, footerBits, i - base);                }  }}void CEncoder::FillAlignPrices(){  for (UInt32 i = 0; i < kAlignTableSize; i++)    _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);  _alignPriceCount = kAlignTableSize;}}}

⌨️ 快捷键说明

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