📄 lzmaencoder.cs
字号:
numHashBytes = 2;
break;
case EMatchFinderType.BT4:
break;
case EMatchFinderType.BT4B:
big = true;
break;
}
bt.SetType(numHashBytes, big);
_matchFinder = bt;
}
_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
return;
_matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes,
Base.kMatchMaxLen * 2 + 1 - _numFastBytes);
_dictionarySizePrev = _dictionarySize;
_numFastBytesPrev = _numFastBytes;
}
public Encoder()
{
for (int i = 0; i < kNumOpts; i++)
_optimum[i] = new Optimal();
for (int i = 0; i < Base.kNumLenToPosStates; i++)
_posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits);
}
void SetWriteEndMarkerMode(bool writeEndMarker)
{
_writeEndMark = writeEndMarker;
}
void Init()
{
BaseInit();
_rangeEncoder.Init();
uint i;
for (i = 0; i < Base.kNumStates; i++)
{
for (uint j = 0; j <= _posStateMask; j++)
{
uint complexState = (i << Base.kNumPosStatesBitsMax) + j;
_isMatch[complexState].Init();
_isRep0Long[complexState].Init();
}
_isRep[i].Init();
_isRepG0[i].Init();
_isRepG1[i].Init();
_isRepG2[i].Init();
}
_literalEncoder.Init();
for (i = 0; i < Base.kNumLenToPosStates; i++)
_posSlotEncoder[i].Init();
for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
_posEncoders[i].Init();
_lenEncoder.Init((UInt32)1 << _posStateBits);
_repMatchLenEncoder.Init((UInt32)1 << _posStateBits);
_posAlignEncoder.Init();
_longestMatchWasFound = false;
_optimumEndIndex = 0;
_optimumCurrentIndex = 0;
_additionalOffset = 0;
}
void ReadMatchDistances(out UInt32 lenRes)
{
lenRes = _matchFinder.GetLongestMatch(_matchDistances);
if (lenRes == _numFastBytes)
lenRes += _matchFinder.GetMatchLen((int)lenRes, _matchDistances[lenRes],
Base.kMatchMaxLen - lenRes);
_additionalOffset++;
_matchFinder.MovePos();
}
void MovePos(UInt32 num)
{
for (; num > 0; num--)
{
_matchFinder.DummyLongestMatch();
_matchFinder.MovePos();
_additionalOffset++;
}
}
UInt32 GetRepLen1Price(Base.State state, UInt32 posState)
{
return _isRepG0[state.Index].GetPrice0() +
_isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();
}
UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)
{
UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
if (repIndex == 0)
{
price += _isRepG0[state.Index].GetPrice0();
price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
}
else
{
price += _isRepG0[state.Index].GetPrice1();
if (repIndex == 1)
price += _isRepG1[state.Index].GetPrice0();
else
{
price += _isRepG1[state.Index].GetPrice1();
price += _isRepG2[state.Index].GetPrice(repIndex - 2);
}
}
return price;
}
UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)
{
if (len == 2 && pos >= 0x80)
return kIfinityPrice;
UInt32 price;
UInt32 lenToPosState = Base.GetLenToPosState(len);
if (pos < Base.kNumFullDistances)
price = _distancesPrices[(pos << Base.kNumLenToPosStatesBits) + lenToPosState];
else
price = _posSlotPrices[(GetPosSlot2(pos) << Base.kNumLenToPosStatesBits) + lenToPosState] +
_alignPrices[pos & Base.kAlignMask];
return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
}
UInt32 Backward(out 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;
}
UInt32[] reps = new UInt32[Base.kNumRepDistances];
UInt32[] repLens = new UInt32[Base.kNumRepDistances];
UInt32 GetOptimum(UInt32 position, out UInt32 backRes)
{
if (_optimumEndIndex != _optimumCurrentIndex)
{
UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
backRes = _optimum[_optimumCurrentIndex].BackPrev;
_optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
return lenRes;
}
_optimumCurrentIndex = 0;
_optimumEndIndex = 0; // test it;
UInt32 lenMain;
if (!_longestMatchWasFound)
{
ReadMatchDistances(out lenMain);
}
else
{
lenMain = _longestMatchLength;
_longestMatchWasFound = false;
}
UInt32 repMaxIndex = 0;
UInt32 i;
for (i = 0; i < Base.kNumRepDistances; i++)
{
reps[i] = _repDistances[i];
repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
if (i == 0 || repLens[i] > repLens[repMaxIndex])
repMaxIndex = i;
}
if (repLens[repMaxIndex] >= _numFastBytes)
{
backRes = repMaxIndex;
UInt32 lenRes = repLens[repMaxIndex];
MovePos(lenRes - 1);
return lenRes;
}
if (lenMain >= _numFastBytes)
{
UInt32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] :
_matchDistances[_numFastBytes];
backRes = backMain + Base.kNumRepDistances;
MovePos(lenMain - 1);
return lenMain;
}
Byte currentByte = _matchFinder.GetIndexByte(0 - 1);
_optimum[0].State = _state;
Byte matchByte;
matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));
UInt32 posState = (position & _posStateMask);
_optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
_literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);
_optimum[1].MakeAsChar();
_optimum[1].PosPrev = 0;
_optimum[0].Backs0 = reps[0];
_optimum[0].Backs1 = reps[1];
_optimum[0].Backs2 = reps[2];
_optimum[0].Backs3 = reps[3];
UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
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;
return 1;
}
UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
if (lenMain <= repLens[repMaxIndex])
lenMain = 0;
UInt32 len;
for (len = 2; len <= lenMain; len++)
{
_optimum[len].PosPrev = 0;
_optimum[len].BackPrev = _matchDistances[len] + Base.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 < Base.kNumRepDistances; i++)
{
UInt32 repLen = repLens[i];
for (UInt32 lenTest = 2; lenTest <= repLen; lenTest++)
{
UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState);
Optimal 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)
{
return Backward(out backRes, cur);
}
position++;
UInt32 posPrev = _optimum[cur].PosPrev;
Base.State state;
if (_optimum[cur].Prev1IsChar)
{
posPrev--;
if (_optimum[cur].Prev2)
{
state = _optimum[_optimum[cur].PosPrev2].State;
if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
state.UpdateRep();
else
state.UpdateMatch();
}
else
state = _optimum[posPrev].State;
state.UpdateChar();
}
else
state = _optimum[posPrev].State;
if (posPrev == cur - 1)
{
if (_optimum[cur].IsShortRep())
state.UpdateShortRep();
else
state.UpdateChar();
}
else
{
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 < Base.kNumRepDistances)
state.UpdateRep();
else
state.UpdateMatch();
}
Optimal opt = _optimum[posPrev];
if (pos < Base.kNumRepDistances)
{
if (pos == 0)
{
reps[0] = opt.Backs0;
reps[1] = opt.Backs1;
reps[2] = opt.Backs2;
reps[3] = opt.Backs3;
}
else if (pos == 1)
{
reps[0] = opt.Backs1;
reps[1] = opt.Backs0;
reps[2] = opt.Backs2;
reps[3] = opt.Backs3;
}
else if (pos == 2)
{
reps[0] = opt.Backs2;
reps[1] = opt.Backs0;
reps[2] = opt.Backs1;
reps[3] = opt.Backs3;
}
else
{
reps[0] = opt.Backs3;
reps[1] = opt.Backs0;
reps[2] = opt.Backs1;
reps[3] = opt.Backs2;
}
}
else
{
reps[0] = (pos - Base.kNumRepDistances);
reps[1] = opt.Backs0;
reps[2] = opt.Backs1;
reps[3] = opt.Backs2;
}
}
_optimum[cur].State = state;
_optimum[cur].Backs0 = reps[0];
_optimum[cur].Backs1 = reps[1];
_optimum[cur].Backs2 = reps[2];
_optimum[cur].Backs3 = reps[3];
UInt32 newLen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -