📄 lzmaencoder.cs
字号:
ReadMatchDistances(out newLen);
if (newLen >= _numFastBytes)
{
_longestMatchLength = newLen;
_longestMatchWasFound = true;
return Backward(out backRes, cur);
}
UInt32 curPrice = _optimum[cur].Price;
currentByte = _matchFinder.GetIndexByte(0 - 1);
matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));
posState = (position & _posStateMask);
UInt32 curAnd1Price = curPrice +
_isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
_literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
GetPrice(!state.IsCharState(), matchByte, currentByte);
Optimal nextOptimum = _optimum[cur + 1];
bool nextIsChar = false;
if (curAnd1Price < nextOptimum.Price)
{
nextOptimum.Price = curAnd1Price;
nextOptimum.PosPrev = cur;
nextOptimum.MakeAsChar();
nextIsChar = true;
}
matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
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 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);
UInt32 numAvailableBytes = numAvailableBytesFull;
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])
if (_matchFinder.GetIndexByte((Int32)temp - 1) != _matchFinder.GetIndexByte((Int32)temp - (Int32)backOffset - 1))
break;
UInt32 lenTest2 = temp - 1;
if (lenTest2 >= 2)
{
Base.State state2 = state;
state2.UpdateChar();
UInt32 posStateNext = (position + 1) & _posStateMask;
UInt32 nextRepMatchPrice = curAnd1Price +
_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +
_isRep[state2.Index].GetPrice1();
// for (; lenTest2 >= 2; lenTest2--)
{
while (lenEnd < cur + 1 + lenTest2)
_optimum[++lenEnd].Price = kIfinityPrice;
UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
0, lenTest2, state2, posStateNext);
Optimal 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 < Base.kNumRepDistances; repIndex++)
{
// UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
UInt32 backOffset = reps[repIndex] + 1;
if (_matchFinder.GetIndexByte(-1) !=
_matchFinder.GetIndexByte((Int32)(-1 - (Int32)backOffset)) ||
_matchFinder.GetIndexByte(0) !=
_matchFinder.GetIndexByte((Int32)(0 - (Int32)backOffset)))
continue;
UInt32 lenTest;
for (lenTest = 2; lenTest < numAvailableBytes; lenTest++)
if (_matchFinder.GetIndexByte((Int32)lenTest - 1) !=
_matchFinder.GetIndexByte((Int32)lenTest - 1 - (Int32)backOffset))
break;
UInt32 lenTestTemp = lenTest;
do
{
while (lenEnd < cur + lenTest)
_optimum[++lenEnd].Price = kIfinityPrice;
UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
Optimal optimum = _optimum[cur + lenTest];
if (curAndLenPrice < optimum.Price)
{
optimum.Price = curAndLenPrice;
optimum.PosPrev = cur;
optimum.BackPrev = repIndex;
optimum.Prev1IsChar = false;
}
}
while(--lenTest >= 2);
lenTest = lenTestTemp;
if (_maxMode)
{
UInt32 lenTest2 = lenTest + 1;
UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes);
for (; lenTest2 < limit; lenTest2++)
if (_matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1)) !=
_matchFinder.GetIndexByte((Int32)((Int32)lenTest2 - 1 - (Int32)backOffset)))
break;
lenTest2 -= lenTest + 1;
if (lenTest2 >= 2)
{
Base.State state2 = state;
state2.UpdateRep();
UInt32 posStateNext = (position + lenTest) & _posStateMask;
UInt32 curAndLenCharPrice =
repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
_literalEncoder.GetSubCoder(position + lenTest,
_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,
_matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)backOffset)),
_matchFinder.GetIndexByte((Int32)lenTest - 1));
state2.UpdateChar();
posStateNext = (position + lenTest + 1) & _posStateMask;
UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
// 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);
Optimal 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;
normalMatchPrice = matchPrice +
_isRep[state.Index].GetPrice0();
while (lenEnd < cur + newLen)
_optimum[++lenEnd].Price = kIfinityPrice;
for (UInt32 lenTest = newLen; lenTest >= 2; lenTest--)
{
UInt32 curBack = _matchDistances[lenTest];
UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
Optimal optimum = _optimum[cur + lenTest];
if (curAndLenPrice < optimum.Price)
{
optimum.Price = curAndLenPrice;
optimum.PosPrev = cur;
optimum.BackPrev = curBack + Base.kNumRepDistances;
optimum.Prev1IsChar = false;
}
if (_maxMode && (lenTest == newLen || curBack != _matchDistances[lenTest + 1]))
{
UInt32 backOffset = curBack + 1;
UInt32 lenTest2 = lenTest + 1;
UInt32 limit = Math.Min(numAvailableBytesFull, lenTest2 + _numFastBytes);
for (; lenTest2 < limit; lenTest2++)
if (_matchFinder.GetIndexByte((Int32)lenTest2 - 1) != _matchFinder.GetIndexByte((Int32)lenTest2 - (Int32)backOffset - 1))
break;
lenTest2 -= lenTest + 1;
if (lenTest2 >= 2)
{
Base.State state2 = state;
state2.UpdateMatch();
UInt32 posStateNext = (position + lenTest) & _posStateMask;
UInt32 curAndLenCharPrice = curAndLenPrice +
_isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
_literalEncoder.GetSubCoder(position + lenTest,
// data[(size_t)lenTest - 1],
_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
GetPrice(true,
// data[(size_t)lenTest - backOffset], data[lenTest]
_matchFinder.GetIndexByte((Int32)lenTest - (Int32)backOffset - 1),
_matchFinder.GetIndexByte((Int32)lenTest - 1)
);
state2.UpdateChar();
posStateNext = (position + lenTest + 1) & _posStateMask;
UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
// for(; lenTest2 >= 2; lenTest2--)
{
UInt32 offset = lenTest + 1 + lenTest2;
while (lenEnd < cur + offset)
_optimum[++lenEnd].Price = kIfinityPrice;
curAndLenPrice = nextRepMatchPrice + GetRepPrice(
0, lenTest2, state2, posStateNext);
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 + Base.kNumRepDistances;
}
}
}
}
}
}
}
}
bool ChangePair(UInt32 smallDist, UInt32 bigDist)
{
const int kDif = 7;
return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
}
UInt32 GetOptimumFast(UInt32 position, out UInt32 backRes)
{
UInt32 lenMain;
if (!_longestMatchWasFound)
{
ReadMatchDistances(out lenMain);
}
else
{
lenMain = _longestMatchLength;
_longestMatchWasFound = false;
}
UInt32 repMaxIndex = 0;
for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
{
repLens[i] = _matchFinder.GetMatchLen(0 - 1, _repDistances[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)
{
backRes = _matchDistances[_numFastBytes] + Base.kNumRepDistances;
MovePos(lenMain - 1);
return lenMain;
}
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;
UInt32 lenRes = repLens[repMaxIndex];
MovePos(lenRes - 1);
return lenRes;
}
}
if (lenMain >= 2)
{
ReadMatchDistances(out _longestMatchLength);
if (_longestMatchLength >= 2 &&
(
(_longestMatchLength >= lenMain &&
_matchDistances[lenMain] < backMain) ||
_longestMatchLength == lenMain + 1 &&
!ChangePair(backMain, _matchDistances[_longestMatchLength]) ||
_longestMatchLength > lenMain + 1 ||
_longestMatchLength + 1 >= lenMain && lenMain >= 3 &&
ChangePair(_matchDistances[lenMain - 1], backMain)
)
)
{
_longestMatchWasFound = true;
backRes = 0xFFFFFFFF;
return 1;
}
for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
{
UInt32 repLen = _matchFinder.GetMatchLen(0 - 1, _repDistances[i], Base.kMatchMaxLen);
if (repLen >= 2 && repLen + 1 >= lenMain)
{
_longestMatchWasFound = true;
backRes = 0xFFFFFFFF;
return 1;
}
}
backRes = backMain + Base.kNumRepDistances;
MovePos(lenMain - 2);
return lenMain;
}
backRes = 0xFFFFFFFF;
return 1;
}
void InitMatchFinder(LZ.IMatchFinder matchFinder)
{
_matchFinder = matchFinder;
}
void WriteEndMarker(UInt32 posState)
{
if (!_writeEndMark)
return;
_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);
_isRep[_state.Index].Encode(_rangeEncoder, 0);
_state.UpdateMatch();
UInt32 len = Base.kMatchMinLen; // kMatchMaxLen;
_lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;
UInt32 lenToPosState = Base.GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
int footerBits = 30;
UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
}
void Flush(UInt32 nowPos)
{
ReleaseMFStream();
WriteEndMarker(nowPos & _posStateMask);
_rangeEncoder.FlushData();
_rangeEncoder.FlushStream();
}
public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
{
inSize = 0;
outSize = 0;
finished = true;
if (_inStream != null)
{
_matchFinder.Init(_inStream);
_needReleaseMFStream = true;
_inStream = null;
}
if (_finished)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -