📄 lzmaencoder.cpp
字号:
STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream){ _rangeEncoder.SetStream(outStream); return S_OK;}HRESULT CEncoder::Init(){ CBaseState::Init(); // RINOK(_matchFinder->Init(inStream)); _rangeEncoder.Init(); for(int i = 0; i < kNumStates; i++) { for (UInt32 j = 0; j <= _posStateMask; j++) { _isMatch[i][j].Init(); _isRep0Long[i][j].Init(); } _isRep[i].Init(); _isRepG0[i].Init(); _isRepG1[i].Init(); _isRepG2[i].Init(); } _literalEncoder.Init(); // _repMatchLenEncoder.Init(); { for(UInt32 i = 0; i < kNumLenToPosStates; i++) _posSlotEncoder[i].Init(); } { for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) _posEncoders[i].Init(); } _lenEncoder.Init(1 << _posStateBits); _repMatchLenEncoder.Init(1 << _posStateBits); _posAlignEncoder.Init(); _longestMatchWasFound = false; _optimumEndIndex = 0; _optimumCurrentIndex = 0; _additionalOffset = 0; return S_OK;}HRESULT CEncoder::MovePos(UInt32 num){ for (;num > 0; num--) { _matchFinder->DummyLongestMatch(); RINOK(_matchFinder->MovePos()); _additionalOffset++; } return S_OK;}UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur){ _optimumEndIndex = cur; UInt32 posMem = _optimum[cur].PosPrev; UInt32 backMem = _optimum[cur].BackPrev; do { if (_optimum[cur].Prev1IsChar) { _optimum[posMem].MakeAsChar(); _optimum[posMem].PosPrev = posMem - 1; if (_optimum[cur].Prev2) { _optimum[posMem - 1].Prev1IsChar = false; _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; } } UInt32 posPrev = posMem; UInt32 backCur = backMem; backMem = _optimum[posPrev].BackPrev; posMem = _optimum[posPrev].PosPrev; _optimum[posPrev].BackPrev = backCur; _optimum[posPrev].PosPrev = cur; cur = posPrev; } while(cur > 0); backRes = _optimum[0].BackPrev; _optimumCurrentIndex = _optimum[0].PosPrev; return _optimumCurrentIndex; }/*inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit){ back++; for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++); return i;}*/HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes){ if(_optimumEndIndex != _optimumCurrentIndex) { lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; backRes = _optimum[_optimumCurrentIndex].BackPrev; _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; return S_OK; } _optimumCurrentIndex = 0; _optimumEndIndex = 0; // test it; UInt32 lenMain; if (!_longestMatchWasFound) { RINOK(ReadMatchDistances(lenMain)); } else { lenMain = _longestMatchLength; _longestMatchWasFound = false; } UInt32 reps[kNumRepDistances]; UInt32 repLens[kNumRepDistances]; UInt32 repMaxIndex = 0; UInt32 i; for(i = 0; i < kNumRepDistances; i++) { reps[i] = _repDistances[i]; repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[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) { UInt32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] : _matchDistances[_numFastBytes]; backRes = backMain + kNumRepDistances; MovePos(lenMain - 1); lenRes = lenMain; return S_OK; } Byte currentByte = _matchFinder->GetIndexByte(0 - 1); _optimum[0].State = _state; Byte matchByte; matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1); UInt32 posState = (position & _posStateMask); _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice(0) + _literalEncoder.GetPrice(position, _previousByte, _peviousIsMatch, matchByte, currentByte); _optimum[1].MakeAsChar(); _optimum[1].PosPrev = 0; for (i = 0; i < kNumRepDistances; i++) _optimum[0].Backs[i] = reps[i]; UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice(1); UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice(1); if(matchByte == currentByte) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); if(shortRepPrice < _optimum[1].Price) { _optimum[1].Price = shortRepPrice; _optimum[1].MakeAsShortRep(); } } if(lenMain < 2) { backRes = _optimum[1].BackPrev; lenRes = 1; return S_OK; } UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice(0); if (lenMain <= repLens[repMaxIndex]) lenMain = 0; UInt32 len; for(len = 2; len <= lenMain; len++) { _optimum[len].PosPrev = 0; _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances; _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len], len, posState); _optimum[len].Prev1IsChar = false; } if (lenMain < repLens[repMaxIndex]) lenMain = repLens[repMaxIndex]; for (; len <= lenMain; len++) _optimum[len].Price = kIfinityPrice; for(i = 0; i < kNumRepDistances; i++) { UInt32 repLen = repLens[i]; for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++) { UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState); COptimal &optimum = _optimum[lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = 0; optimum.BackPrev = i; optimum.Prev1IsChar = false; } } } UInt32 cur = 0; UInt32 lenEnd = lenMain; while(true) { cur++; if(cur == lenEnd) { lenRes = Backward(backRes, cur); return S_OK; } position++; UInt32 posPrev = _optimum[cur].PosPrev; CState state; if (_optimum[cur].Prev1IsChar) { posPrev--; if (_optimum[cur].Prev2) { state = _optimum[_optimum[cur].PosPrev2].State; if (_optimum[cur].BackPrev2 < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } else state = _optimum[posPrev].State; state.UpdateChar(); } else state = _optimum[posPrev].State; bool prevWasMatch; if (posPrev == cur - 1) { if (_optimum[cur].IsShortRep()) { prevWasMatch = true; state.UpdateShortRep(); } else { prevWasMatch = false; state.UpdateChar(); } /* if (_optimum[cur].Prev1IsChar) for(int i = 0; i < kNumRepDistances; i++) reps[i] = _optimum[posPrev].Backs[i]; */ } else { prevWasMatch = true; UInt32 pos; if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) { posPrev = _optimum[cur].PosPrev2; pos = _optimum[cur].BackPrev2; state.UpdateRep(); } else { pos = _optimum[cur].BackPrev; if (pos < kNumRepDistances) state.UpdateRep(); else state.UpdateMatch(); } if (pos < kNumRepDistances) { reps[0] = _optimum[posPrev].Backs[pos]; UInt32 i; for(i = 1; i <= pos; i++) reps[i] = _optimum[posPrev].Backs[i - 1]; for(; i < kNumRepDistances; i++) reps[i] = _optimum[posPrev].Backs[i]; } else { reps[0] = (pos - kNumRepDistances); for(UInt32 i = 1; i < kNumRepDistances; i++) reps[i] = _optimum[posPrev].Backs[i - 1]; } } _optimum[cur].State = state; for(UInt32 i = 0; i < kNumRepDistances; i++) _optimum[cur].Backs[i] = reps[i]; UInt32 newLen; RINOK(ReadMatchDistances(newLen)); if(newLen > _numFastBytes) { _longestMatchLength = newLen; _longestMatchWasFound = true; lenRes = Backward(backRes, cur); return S_OK; } UInt32 curPrice = _optimum[cur].Price; // Byte currentByte = _matchFinder->GetIndexByte(0 - 1); // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1); const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1; Byte currentByte = *data; Byte matchByte = data[(size_t)0 - reps[0] - 1]; UInt32 posState = (position & _posStateMask); UInt32 curAnd1Price = curPrice + _isMatch[state.Index][posState].GetPrice(0) + _literalEncoder.GetPrice(position, data[(size_t)0 - 1], prevWasMatch, matchByte, currentByte); COptimal &nextOptimum = _optimum[cur + 1]; bool nextIsChar = false; if (curAnd1Price < nextOptimum.Price) { nextOptimum.Price = curAnd1Price; nextOptimum.PosPrev = cur; nextOptimum.MakeAsChar(); nextIsChar = true; } UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice(1); UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice(1); if(matchByte == currentByte && !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) { UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); if(shortRepPrice <= nextOptimum.Price) { nextOptimum.Price = shortRepPrice; nextOptimum.PosPrev = cur; nextOptimum.MakeAsShortRep(); // nextIsChar = false; } } /* if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ? continue; */ UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1; numAvailableBytes = MyMin(kNumOpts - 1 - cur, numAvailableBytes); if (numAvailableBytes < 2) continue; if (numAvailableBytes > _numFastBytes) numAvailableBytes = _numFastBytes; if (numAvailableBytes >= 3 && !nextIsChar) { UInt32 backOffset = reps[0] + 1; UInt32 temp; for (temp = 1; temp < numAvailableBytes; temp++) if (data[temp] != data[(size_t)temp - backOffset]) break; UInt32 lenTest2 = temp - 1; if (lenTest2 >= 2) { CState state2 = state; state2.UpdateChar(); UInt32 posStateNext = (position + 1) & _posStateMask; UInt32 nextRepMatchPrice = curAnd1Price + _isMatch[state2.Index][posStateNext].GetPrice(1) + _isRep[state2.Index].GetPrice(1); // for (; lenTest2 >= 2; lenTest2--) { while(lenEnd < cur + 1 + lenTest2) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 0, lenTest2, state2, posStateNext); COptimal &optimum = _optimum[cur + 1 + lenTest2]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur + 1; optimum.BackPrev = 0; optimum.Prev1IsChar = true; optimum.Prev2 = false; } } } } for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++) { // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it; UInt32 backOffset = reps[repIndex] + 1; UInt32 lenTest; for (lenTest = 0; lenTest < numAvailableBytes; lenTest++) if (data[lenTest] != data[(size_t)lenTest - backOffset]) break; for(; lenTest >= 2; lenTest--) { while(lenEnd < cur + lenTest) _optimum[++lenEnd].Price = kIfinityPrice; UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); COptimal &optimum = _optimum[cur + lenTest]; if (curAndLenPrice < optimum.Price) { optimum.Price = curAndLenPrice; optimum.PosPrev = cur; optimum.BackPrev = repIndex; optimum.Prev1IsChar = false; } /* if (_maxMode) { 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.UpdateRep(); 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 = repIndex; } } } } */ } } // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++) if (newLen > numAvailableBytes) newLen = numAvailableBytes; if (newLen >= 2) { if (newLen == 2 && _matchDistances[2] >= 0x80) continue; UInt32 normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice(0); while(lenEnd < cur + newLen) _optimum[++lenEnd].Price = kIfinityPrice;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -