📄 lzmaencoder.cs
字号:
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,
_matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
GetPrice(true,
_matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 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();
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;
}
}
}
offs += 2;
if (offs == numDistancePairs)
break;
}
}
}
}
}
bool ChangePair(UInt32 smallDist, UInt32 bigDist)
{
const int kDif = 7;
return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
}
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;
_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.SetStream(_inStream);
_matchFinder.Init();
_needReleaseMFStream = true;
_inStream = null;
if (_trainSize > 0)
_matchFinder.Skip(_trainSize);
}
if (_finished)
return;
_finished = true;
Int64 progressPosValuePrev = nowPos64;
if (nowPos64 == 0)
{
if (_matchFinder.GetNumAvailableBytes() == 0)
{
Flush((UInt32)nowPos64);
return;
}
UInt32 len, numDistancePairs; // it's not used
ReadMatchDistances(out len, out numDistancePairs);
UInt32 posState = (UInt32)(nowPos64) & _posStateMask;
_isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);
_state.UpdateChar();
Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
_literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
_previousByte = curByte;
_additionalOffset--;
nowPos64++;
}
if (_matchFinder.GetNumAvailableBytes() == 0)
{
Flush((UInt32)nowPos64);
return;
}
while (true)
{
UInt32 pos;
UInt32 len = GetOptimum((UInt32)nowPos64, out pos);
UInt32 posState = ((UInt32)nowPos64) & _posStateMask;
UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;
if (len == 1 && pos == 0xFFFFFFFF)
{
_isMatch[complexState].Encode(_rangeEncoder, 0);
Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);
if (!_state.IsCharState())
{
Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));
subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
}
else
subCoder.Encode(_rangeEncoder, curByte);
_previousByte = curByte;
_state.UpdateChar();
}
else
{
_isMatch[complexState].Encode(_rangeEncoder, 1);
if (pos < Base.kNumRepDistances)
{
_isRep[_state.Index].Encode(_rangeEncoder, 1);
if (pos == 0)
{
_isRepG0[_state.Index].Encode(_rangeEncoder, 0);
if (len == 1)
_isRep0Long[complexState].Encode(_rangeEncoder, 0);
else
_isRep0Long[complexState].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 - Base.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 - Base.kMatchMinLen, posState);
pos -= Base.kNumRepDistances;
UInt32 posSlot = GetPosSlot(pos);
UInt32 lenToPosState = Base.GetLenToPosState(len);
_posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
if (posSlot >= Base.kStartPosModelIndex)
{
int footerBits = (int)((posSlot >> 1) - 1);
UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
UInt32 posReduced = pos - baseVal;
if (posSlot < Base.kEndPosModelIndex)
RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders,
baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
else
{
_rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
_posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
_alignPriceCount++;
}
}
UInt32 distance = pos;
for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)
_repDistances[i] = _repDistances[i - 1];
_repDistances[0] = distance;
_matchPriceCount++;
}
_previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));
}
_additionalOffset -= len;
nowPos64 += len;
if (_additionalOffset == 0)
{
// if (!_fastMode)
if (_matchPriceCount >= (1 << 7))
FillDistancesPrices();
if (_alignPriceCount >= Base.kAlignTableSize)
FillAlignPrices();
inSize = nowPos64;
outSize = _rangeEncoder.GetProcessedSizeAdd();
if (_matchFinder.GetNumAvailableBytes() == 0)
{
Flush((UInt32)nowPos64);
return;
}
if (nowPos64 - progressPosValuePrev >= (1 << 12))
{
_finished = false;
finished = false;
return;
}
}
}
}
void ReleaseMFStream()
{
if (_matchFinder != null && _needReleaseMFStream)
{
_matchFinder.ReleaseStream();
_needReleaseMFStream = false;
}
}
void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }
void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }
void ReleaseStreams()
{
ReleaseMFStream();
ReleaseOutStream();
}
void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize)
{
_inStream = inStream;
_finished = false;
Create();
SetOutStream(outStream);
Init();
// if (!_fastMode)
{
FillDistancesPrices();
FillAlignPrices();
}
_lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
_lenEncoder.UpdateTables((UInt32)1 << _posStateBits);
_repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
_repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);
nowPos64 = 0;
}
public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
Int64 inSize, Int64 outSize, ICodeProgress progress)
{
_needReleaseMFStream = false;
try
{
SetStreams(inStream, outStream, inSize, outSize);
while (true)
{
Int64 processedInSize;
Int64 processedOutSize;
bool finished;
CodeOneBlock(out processedInSize, out processedOutSize, out finished);
if (finished)
return;
if (progress != null)
{
progress.SetProgress(processedInSize, processedOutSize);
}
}
}
finally
{
ReleaseStreams();
}
}
const int kPropSize = 5;
Byte[] properties = new Byte[kPropSize];
public void WriteCoderProperties(System.IO.Stream outStream)
{
properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
for (int i = 0; i < 4; i++)
properties[1 + i] = (Byte)(_dictionarySize >> (8 * i));
outStream.Write(properties, 0, kPropSize);
}
UInt32[] tempPrices = new UInt32[Base.kNumFullDistances];
UInt32 _matchPriceCount;
void FillDistancesPrices()
{
for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
{
UInt32 posSlot = GetPosSlot(i);
int footerBits = (int)((posSlot >> 1) - 1);
UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,
baseVal - posSlot - 1, footerBits, i - baseVal);
}
for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
{
UInt32 posSlot;
RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
UInt32 st = (lenToPosState << Base.kNumPosSlotBits);
for (posSlot = 0; posSlot < _distTableSize; posSlot++)
_posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
_posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits);
UInt32 st2 = lenToPosState * Base.kNumFullDistances;
UInt32 i;
for (i = 0; i < Base.kStartPosModelIndex; i++)
_distancesPrices[st2 + i] = _posSlotPrices[st + i];
for (; i < Base.kNumFullDistances; i++)
_distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
}
_matchPriceCount = 0;
}
void FillAlignPrices()
{
for (UInt32 i = 0; i < Base.kAlignTableSize; i++)
_alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
_alignPriceCount = 0;
}
static string[] kMatchFinderIDs =
{
"BT2",
"BT4",
};
static int FindMatchFinder(string s)
{
for (int m = 0; m < kMatchFinderIDs.Length; m++)
if (s == kMatchFinderIDs[m])
return m;
return -1;
}
public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
{
for (UInt32 i = 0; i < properties.Length; i++)
{
object prop = properties[i];
switch (propIDs[i])
{
case CoderPropID.NumFastBytes:
{
if (!(prop is Int32))
throw new InvalidParamException();
Int32 numFastBytes = (Int32)prop;
if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
throw new InvalidParamException();
_numFastBytes = (UInt32)numFastBytes;
break;
}
case CoderPropID.Algorithm:
{
/*
if (!(prop is Int32))
throw new InvalidParamException();
Int32 maximize = (Int32)prop;
_fastMode = (maximize == 0);
_maxMode = (maximize >= 2);
*/
break;
}
case CoderPropID.MatchFinder:
{
if (!(prop is String))
throw new InvalidParamException();
EMatchFinderType matchFinderIndexPrev = _matchFinderType;
int m = FindMatchFinder(((string)prop).ToUpper());
if (m < 0)
throw new InvalidParamException();
_matchFinderType = (EMatchFinderType)m;
if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
{
_dictionarySizePrev = 0xFFFFFFFF;
_matchFinder = null;
}
break;
}
case CoderPropID.DictionarySize:
{
const int kDicLogSizeMaxCompress = 30;
if (!(prop is Int32))
throw new InvalidParamException(); ;
Int32 dictionarySize = (Int32)prop;
if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||
dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
throw new InvalidParamException();
_dictionarySize = (UInt32)dictionarySize;
int dicLogSize;
for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
if (dictionarySize <= ((UInt32)(1) << dicLogSize))
break;
_distTableSize = (UInt32)dicLogSize * 2;
break;
}
case CoderPropID.PosStateBits:
{
if (!(prop is Int32))
throw new InvalidParamException();
Int32 v = (Int32)prop;
if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)
throw new InvalidParamException();
_posStateBits = (int)v;
_posStateMask = (((UInt32)1) << (int)_posStateBits) - 1;
break;
}
case CoderPropID.LitPosBits:
{
if (!(prop is Int32))
throw new InvalidParamException();
Int32 v = (Int32)prop;
if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax)
throw new InvalidParamException();
_numLiteralPosStateBits = (int)v;
break;
}
case CoderPropID.LitContextBits:
{
if (!(prop is Int32))
throw new InvalidParamException();
Int32 v = (Int32)prop;
if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax)
throw new InvalidParamException(); ;
_numLiteralContextBits = (int)v;
break;
}
case CoderPropID.EndMarker:
{
if (!(prop is Boolean))
throw new InvalidParamException();
SetWriteEndMarkerMode((Boolean)prop);
break;
}
default:
throw new InvalidParamException();
}
}
}
uint _trainSize = 0;
public void SetTrainSize(uint trainSize)
{
_trainSize = trainSize;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -