mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-22 19:36:11 +00:00
f2ac1ece55
add
1330 lines
51 KiB
C#
1330 lines
51 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: SevenZip.Compression.LZMA.Encoder
|
|
// Assembly: P4CTEMP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
|
|
// MVID: 7BE4E538-8555-4C2E-974B-99E556F5462C
|
|
// Assembly location: C:\Users\Administrateur\Downloads\Virusshare-00000-msil\Trojan-Ransom.Win32.Gimemo.ayt-624a52079bf1703bcd3bcc9d2d3716b6126fd05655e25289d19142f9aae02eb5.exe
|
|
|
|
using SevenZip.Compression.LZ;
|
|
using SevenZip.Compression.RangeCoder;
|
|
using System;
|
|
using System.IO;
|
|
|
|
namespace SevenZip.Compression.LZMA
|
|
{
|
|
public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
|
|
{
|
|
private const uint kIfinityPrice = 268435455;
|
|
private const int kDefaultDictionaryLogSize = 22;
|
|
private const uint kNumFastBytesDefault = 32;
|
|
private const uint kNumLenSpecSymbols = 16;
|
|
private const uint kNumOpts = 4096;
|
|
private const int kPropSize = 5;
|
|
private static byte[] g_FastPos = new byte[2048];
|
|
private Base.State _state = new Base.State();
|
|
private byte _previousByte;
|
|
private uint[] _repDistances = new uint[new IntPtr(4)];
|
|
private Encoder.Optimal[] _optimum = new Encoder.Optimal[new IntPtr(4096)];
|
|
private IMatchFinder _matchFinder;
|
|
private SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder();
|
|
private BitEncoder[] _isMatch = new BitEncoder[new IntPtr(192)];
|
|
private BitEncoder[] _isRep = new BitEncoder[new IntPtr(12)];
|
|
private BitEncoder[] _isRepG0 = new BitEncoder[new IntPtr(12)];
|
|
private BitEncoder[] _isRepG1 = new BitEncoder[new IntPtr(12)];
|
|
private BitEncoder[] _isRepG2 = new BitEncoder[new IntPtr(12)];
|
|
private BitEncoder[] _isRep0Long = new BitEncoder[new IntPtr(192)];
|
|
private BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[new IntPtr(4)];
|
|
private BitEncoder[] _posEncoders = new BitEncoder[new IntPtr(114)];
|
|
private BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(4);
|
|
private Encoder.LenPriceTableEncoder _lenEncoder = new Encoder.LenPriceTableEncoder();
|
|
private Encoder.LenPriceTableEncoder _repMatchLenEncoder = new Encoder.LenPriceTableEncoder();
|
|
private Encoder.LiteralEncoder _literalEncoder = new Encoder.LiteralEncoder();
|
|
private uint[] _matchDistances = new uint[new IntPtr(548)];
|
|
private uint _numFastBytes = 32;
|
|
private uint _longestMatchLength;
|
|
private uint _numDistancePairs;
|
|
private uint _additionalOffset;
|
|
private uint _optimumEndIndex;
|
|
private uint _optimumCurrentIndex;
|
|
private bool _longestMatchWasFound;
|
|
private uint[] _posSlotPrices = new uint[256];
|
|
private uint[] _distancesPrices = new uint[new IntPtr(512)];
|
|
private uint[] _alignPrices = new uint[new IntPtr(16)];
|
|
private uint _alignPriceCount;
|
|
private uint _distTableSize = 44;
|
|
private int _posStateBits = 2;
|
|
private uint _posStateMask = 3;
|
|
private int _numLiteralPosStateBits;
|
|
private int _numLiteralContextBits = 3;
|
|
private uint _dictionarySize = 4194304;
|
|
private uint _dictionarySizePrev = uint.MaxValue;
|
|
private uint _numFastBytesPrev = uint.MaxValue;
|
|
private long nowPos64;
|
|
private bool _finished;
|
|
private Stream _inStream;
|
|
private Encoder.EMatchFinderType _matchFinderType = Encoder.EMatchFinderType.BT4;
|
|
private bool _writeEndMark;
|
|
private bool _needReleaseMFStream;
|
|
private uint[] reps = new uint[new IntPtr(4)];
|
|
private uint[] repLens = new uint[new IntPtr(4)];
|
|
private byte[] properties = new byte[5];
|
|
private uint[] tempPrices = new uint[new IntPtr(128)];
|
|
private uint _matchPriceCount;
|
|
private static string[] kMatchFinderIDs = new string[2]
|
|
{
|
|
"BT2",
|
|
"BT4"
|
|
};
|
|
private uint _trainSize;
|
|
|
|
static Encoder()
|
|
{
|
|
int index1 = 2;
|
|
Encoder.g_FastPos[0] = (byte) 0;
|
|
Encoder.g_FastPos[1] = (byte) 1;
|
|
for (byte index2 = 2; index2 < (byte) 22; ++index2)
|
|
{
|
|
uint num1 = (uint) (1 << ((int) index2 >> 1) - 1);
|
|
uint num2 = 0;
|
|
while (num2 < num1)
|
|
{
|
|
Encoder.g_FastPos[index1] = index2;
|
|
++num2;
|
|
++index1;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static uint GetPosSlot(uint pos)
|
|
{
|
|
if (pos < 2048U)
|
|
return (uint) Encoder.g_FastPos[(IntPtr) pos];
|
|
return pos < 2097152U ? (uint) Encoder.g_FastPos[(IntPtr) (pos >> 10)] + 20U : (uint) Encoder.g_FastPos[(IntPtr) (pos >> 20)] + 40U;
|
|
}
|
|
|
|
private static uint GetPosSlot2(uint pos)
|
|
{
|
|
if (pos < 131072U)
|
|
return (uint) Encoder.g_FastPos[(IntPtr) (pos >> 6)] + 12U;
|
|
return pos < 134217728U ? (uint) Encoder.g_FastPos[(IntPtr) (pos >> 16)] + 32U : (uint) Encoder.g_FastPos[(IntPtr) (pos >> 26)] + 52U;
|
|
}
|
|
|
|
private void BaseInit()
|
|
{
|
|
this._state.Init();
|
|
this._previousByte = (byte) 0;
|
|
for (uint index = 0; index < 4U; ++index)
|
|
this._repDistances[(IntPtr) index] = 0U;
|
|
}
|
|
|
|
private void Create()
|
|
{
|
|
if (this._matchFinder == null)
|
|
{
|
|
BinTree binTree = new BinTree();
|
|
int numHashBytes = 4;
|
|
if (this._matchFinderType == Encoder.EMatchFinderType.BT2)
|
|
numHashBytes = 2;
|
|
binTree.SetType(numHashBytes);
|
|
this._matchFinder = (IMatchFinder) binTree;
|
|
}
|
|
this._literalEncoder.Create(this._numLiteralPosStateBits, this._numLiteralContextBits);
|
|
if ((int) this._dictionarySize == (int) this._dictionarySizePrev && (int) this._numFastBytesPrev == (int) this._numFastBytes)
|
|
return;
|
|
this._matchFinder.Create(this._dictionarySize, 4096U, this._numFastBytes, 274U);
|
|
this._dictionarySizePrev = this._dictionarySize;
|
|
this._numFastBytesPrev = this._numFastBytes;
|
|
}
|
|
|
|
public Encoder()
|
|
{
|
|
for (int index = 0; index < 4096; ++index)
|
|
this._optimum[index] = new Encoder.Optimal();
|
|
for (int index = 0; index < 4; ++index)
|
|
this._posSlotEncoder[index] = new BitTreeEncoder(6);
|
|
}
|
|
|
|
private void SetWriteEndMarkerMode(bool writeEndMarker) => this._writeEndMark = writeEndMarker;
|
|
|
|
private void Init()
|
|
{
|
|
this.BaseInit();
|
|
this._rangeEncoder.Init();
|
|
for (uint index1 = 0; index1 < 12U; ++index1)
|
|
{
|
|
for (uint index2 = 0; index2 <= this._posStateMask; ++index2)
|
|
{
|
|
uint index3 = (index1 << 4) + index2;
|
|
this._isMatch[(IntPtr) index3].Init();
|
|
this._isRep0Long[(IntPtr) index3].Init();
|
|
}
|
|
this._isRep[(IntPtr) index1].Init();
|
|
this._isRepG0[(IntPtr) index1].Init();
|
|
this._isRepG1[(IntPtr) index1].Init();
|
|
this._isRepG2[(IntPtr) index1].Init();
|
|
}
|
|
this._literalEncoder.Init();
|
|
for (uint index = 0; index < 4U; ++index)
|
|
this._posSlotEncoder[(IntPtr) index].Init();
|
|
for (uint index = 0; index < 114U; ++index)
|
|
this._posEncoders[(IntPtr) index].Init();
|
|
this._lenEncoder.Init((uint) (1 << this._posStateBits));
|
|
this._repMatchLenEncoder.Init((uint) (1 << this._posStateBits));
|
|
this._posAlignEncoder.Init();
|
|
this._longestMatchWasFound = false;
|
|
this._optimumEndIndex = 0U;
|
|
this._optimumCurrentIndex = 0U;
|
|
this._additionalOffset = 0U;
|
|
}
|
|
|
|
private void ReadMatchDistances(out uint lenRes, out uint numDistancePairs)
|
|
{
|
|
lenRes = 0U;
|
|
numDistancePairs = this._matchFinder.GetMatches(this._matchDistances);
|
|
if (numDistancePairs > 0U)
|
|
{
|
|
lenRes = this._matchDistances[(IntPtr) (numDistancePairs - 2U)];
|
|
if ((int) lenRes == (int) this._numFastBytes)
|
|
lenRes += this._matchFinder.GetMatchLen((int) lenRes - 1, this._matchDistances[(IntPtr) (numDistancePairs - 1U)], 273U - lenRes);
|
|
}
|
|
++this._additionalOffset;
|
|
}
|
|
|
|
private void MovePos(uint num)
|
|
{
|
|
if (num <= 0U)
|
|
return;
|
|
this._matchFinder.Skip(num);
|
|
this._additionalOffset += num;
|
|
}
|
|
|
|
private uint GetRepLen1Price(Base.State state, uint posState) => this._isRepG0[(IntPtr) state.Index].GetPrice0() + this._isRep0Long[(IntPtr) ((state.Index << 4) + posState)].GetPrice0();
|
|
|
|
private uint GetPureRepPrice(uint repIndex, Base.State state, uint posState)
|
|
{
|
|
uint pureRepPrice;
|
|
if (repIndex == 0U)
|
|
{
|
|
pureRepPrice = this._isRepG0[(IntPtr) state.Index].GetPrice0() + this._isRep0Long[(IntPtr) ((state.Index << 4) + posState)].GetPrice1();
|
|
}
|
|
else
|
|
{
|
|
uint price1 = this._isRepG0[(IntPtr) state.Index].GetPrice1();
|
|
pureRepPrice = repIndex != 1U ? price1 + this._isRepG1[(IntPtr) state.Index].GetPrice1() + this._isRepG2[(IntPtr) state.Index].GetPrice(repIndex - 2U) : price1 + this._isRepG1[(IntPtr) state.Index].GetPrice0();
|
|
}
|
|
return pureRepPrice;
|
|
}
|
|
|
|
private uint GetRepPrice(uint repIndex, uint len, Base.State state, uint posState) => this._repMatchLenEncoder.GetPrice(len - 2U, posState) + this.GetPureRepPrice(repIndex, state, posState);
|
|
|
|
private uint GetPosLenPrice(uint pos, uint len, uint posState)
|
|
{
|
|
uint lenToPosState = Base.GetLenToPosState(len);
|
|
return (pos >= 128U ? this._posSlotPrices[(IntPtr) ((lenToPosState << 6) + Encoder.GetPosSlot2(pos))] + this._alignPrices[(IntPtr) (pos & 15U)] : this._distancesPrices[(IntPtr) (lenToPosState * 128U + pos)]) + this._lenEncoder.GetPrice(len - 2U, posState);
|
|
}
|
|
|
|
private uint Backward(out uint backRes, uint cur)
|
|
{
|
|
this._optimumEndIndex = cur;
|
|
uint posPrev = this._optimum[(IntPtr) cur].PosPrev;
|
|
uint backPrev = this._optimum[(IntPtr) cur].BackPrev;
|
|
do
|
|
{
|
|
if (this._optimum[(IntPtr) cur].Prev1IsChar)
|
|
{
|
|
this._optimum[(IntPtr) posPrev].MakeAsChar();
|
|
this._optimum[(IntPtr) posPrev].PosPrev = posPrev - 1U;
|
|
if (this._optimum[(IntPtr) cur].Prev2)
|
|
{
|
|
this._optimum[(IntPtr) (posPrev - 1U)].Prev1IsChar = false;
|
|
this._optimum[(IntPtr) (posPrev - 1U)].PosPrev = this._optimum[(IntPtr) cur].PosPrev2;
|
|
this._optimum[(IntPtr) (posPrev - 1U)].BackPrev = this._optimum[(IntPtr) cur].BackPrev2;
|
|
}
|
|
}
|
|
uint index = posPrev;
|
|
uint num = backPrev;
|
|
backPrev = this._optimum[(IntPtr) index].BackPrev;
|
|
posPrev = this._optimum[(IntPtr) index].PosPrev;
|
|
this._optimum[(IntPtr) index].BackPrev = num;
|
|
this._optimum[(IntPtr) index].PosPrev = cur;
|
|
cur = index;
|
|
}
|
|
while (cur > 0U);
|
|
backRes = this._optimum[0].BackPrev;
|
|
this._optimumCurrentIndex = this._optimum[0].PosPrev;
|
|
return this._optimumCurrentIndex;
|
|
}
|
|
|
|
private uint GetOptimum(uint position, out uint backRes)
|
|
{
|
|
if ((int) this._optimumEndIndex != (int) this._optimumCurrentIndex)
|
|
{
|
|
uint optimum = this._optimum[(IntPtr) this._optimumCurrentIndex].PosPrev - this._optimumCurrentIndex;
|
|
backRes = this._optimum[(IntPtr) this._optimumCurrentIndex].BackPrev;
|
|
this._optimumCurrentIndex = this._optimum[(IntPtr) this._optimumCurrentIndex].PosPrev;
|
|
return optimum;
|
|
}
|
|
this._optimumCurrentIndex = this._optimumEndIndex = 0U;
|
|
uint lenRes1;
|
|
uint numDistancePairs;
|
|
if (!this._longestMatchWasFound)
|
|
{
|
|
this.ReadMatchDistances(out lenRes1, out numDistancePairs);
|
|
}
|
|
else
|
|
{
|
|
lenRes1 = this._longestMatchLength;
|
|
numDistancePairs = this._numDistancePairs;
|
|
this._longestMatchWasFound = false;
|
|
}
|
|
uint num1 = this._matchFinder.GetNumAvailableBytes() + 1U;
|
|
if (num1 < 2U)
|
|
{
|
|
backRes = uint.MaxValue;
|
|
return 1;
|
|
}
|
|
if (num1 > 273U)
|
|
;
|
|
uint index1 = 0;
|
|
for (uint index2 = 0; index2 < 4U; ++index2)
|
|
{
|
|
this.reps[(IntPtr) index2] = this._repDistances[(IntPtr) index2];
|
|
this.repLens[(IntPtr) index2] = this._matchFinder.GetMatchLen(-1, this.reps[(IntPtr) index2], 273U);
|
|
if (this.repLens[(IntPtr) index2] > this.repLens[(IntPtr) index1])
|
|
index1 = index2;
|
|
}
|
|
if (this.repLens[(IntPtr) index1] >= this._numFastBytes)
|
|
{
|
|
backRes = index1;
|
|
uint repLen = this.repLens[(IntPtr) index1];
|
|
this.MovePos(repLen - 1U);
|
|
return repLen;
|
|
}
|
|
if (lenRes1 >= this._numFastBytes)
|
|
{
|
|
backRes = this._matchDistances[(IntPtr) (numDistancePairs - 1U)] + 4U;
|
|
this.MovePos(lenRes1 - 1U);
|
|
return lenRes1;
|
|
}
|
|
byte indexByte1 = this._matchFinder.GetIndexByte(-1);
|
|
byte indexByte2 = this._matchFinder.GetIndexByte(-(int) this._repDistances[0] - 1 - 1);
|
|
if (lenRes1 < 2U && (int) indexByte1 != (int) indexByte2 && this.repLens[(IntPtr) index1] < 2U)
|
|
{
|
|
backRes = uint.MaxValue;
|
|
return 1;
|
|
}
|
|
this._optimum[0].State = this._state;
|
|
uint posState1 = position & this._posStateMask;
|
|
Encoder.Optimal optimal1 = this._optimum[1];
|
|
int price0 = (int) this._isMatch[(IntPtr) ((this._state.Index << 4) + posState1)].GetPrice0();
|
|
Encoder.LiteralEncoder.Encoder2 subCoder = this._literalEncoder.GetSubCoder(position, this._previousByte);
|
|
int price1 = (int) subCoder.GetPrice(!this._state.IsCharState(), indexByte2, indexByte1);
|
|
int num2 = price0 + price1;
|
|
optimal1.Price = (uint) num2;
|
|
this._optimum[1].MakeAsChar();
|
|
uint price1_1 = this._isMatch[(IntPtr) ((this._state.Index << 4) + posState1)].GetPrice1();
|
|
uint num3 = price1_1 + this._isRep[(IntPtr) this._state.Index].GetPrice1();
|
|
if ((int) indexByte2 == (int) indexByte1)
|
|
{
|
|
uint num4 = num3 + this.GetRepLen1Price(this._state, posState1);
|
|
if (num4 < this._optimum[1].Price)
|
|
{
|
|
this._optimum[1].Price = num4;
|
|
this._optimum[1].MakeAsShortRep();
|
|
}
|
|
}
|
|
uint num5 = lenRes1 >= this.repLens[(IntPtr) index1] ? lenRes1 : this.repLens[(IntPtr) index1];
|
|
if (num5 < 2U)
|
|
{
|
|
backRes = this._optimum[1].BackPrev;
|
|
return 1;
|
|
}
|
|
this._optimum[1].PosPrev = 0U;
|
|
this._optimum[0].Backs0 = this.reps[0];
|
|
this._optimum[0].Backs1 = this.reps[1];
|
|
this._optimum[0].Backs2 = this.reps[2];
|
|
this._optimum[0].Backs3 = this.reps[3];
|
|
uint num6 = num5;
|
|
do
|
|
{
|
|
this._optimum[(IntPtr) num6--].Price = 268435455U;
|
|
}
|
|
while (num6 >= 2U);
|
|
for (uint repIndex = 0; repIndex < 4U; ++repIndex)
|
|
{
|
|
uint repLen = this.repLens[(IntPtr) repIndex];
|
|
if (repLen >= 2U)
|
|
{
|
|
uint num7 = num3 + this.GetPureRepPrice(repIndex, this._state, posState1);
|
|
do
|
|
{
|
|
uint num8 = num7 + this._repMatchLenEncoder.GetPrice(repLen - 2U, posState1);
|
|
Encoder.Optimal optimal2 = this._optimum[(IntPtr) repLen];
|
|
if (num8 < optimal2.Price)
|
|
{
|
|
optimal2.Price = num8;
|
|
optimal2.PosPrev = 0U;
|
|
optimal2.BackPrev = repIndex;
|
|
optimal2.Prev1IsChar = false;
|
|
}
|
|
}
|
|
while (--repLen >= 2U);
|
|
}
|
|
}
|
|
uint num9 = price1_1 + this._isRep[(IntPtr) this._state.Index].GetPrice0();
|
|
uint len = this.repLens[0] >= 2U ? this.repLens[0] + 1U : 2U;
|
|
if (len <= lenRes1)
|
|
{
|
|
uint index3 = 0;
|
|
while (len > this._matchDistances[(IntPtr) index3])
|
|
index3 += 2U;
|
|
while (true)
|
|
{
|
|
uint matchDistance = this._matchDistances[(IntPtr) (index3 + 1U)];
|
|
uint num10 = num9 + this.GetPosLenPrice(matchDistance, len, posState1);
|
|
Encoder.Optimal optimal3 = this._optimum[(IntPtr) len];
|
|
if (num10 < optimal3.Price)
|
|
{
|
|
optimal3.Price = num10;
|
|
optimal3.PosPrev = 0U;
|
|
optimal3.BackPrev = matchDistance + 4U;
|
|
optimal3.Prev1IsChar = false;
|
|
}
|
|
if ((int) len == (int) this._matchDistances[(IntPtr) index3])
|
|
{
|
|
index3 += 2U;
|
|
if ((int) index3 == (int) numDistancePairs)
|
|
break;
|
|
}
|
|
++len;
|
|
}
|
|
}
|
|
uint cur = 0;
|
|
label_45:
|
|
uint lenRes2;
|
|
Base.State state1;
|
|
uint posState2;
|
|
uint num11;
|
|
uint num12;
|
|
uint num13;
|
|
do
|
|
{
|
|
byte indexByte3;
|
|
byte indexByte4;
|
|
uint num14;
|
|
bool flag;
|
|
uint num15;
|
|
uint limit1;
|
|
do
|
|
{
|
|
++cur;
|
|
if ((int) cur == (int) num5)
|
|
return this.Backward(out backRes, cur);
|
|
this.ReadMatchDistances(out lenRes2, out numDistancePairs);
|
|
if (lenRes2 >= this._numFastBytes)
|
|
{
|
|
this._numDistancePairs = numDistancePairs;
|
|
this._longestMatchLength = lenRes2;
|
|
this._longestMatchWasFound = true;
|
|
return this.Backward(out backRes, cur);
|
|
}
|
|
++position;
|
|
uint index4 = this._optimum[(IntPtr) cur].PosPrev;
|
|
if (this._optimum[(IntPtr) cur].Prev1IsChar)
|
|
{
|
|
--index4;
|
|
if (this._optimum[(IntPtr) cur].Prev2)
|
|
{
|
|
state1 = this._optimum[(IntPtr) this._optimum[(IntPtr) cur].PosPrev2].State;
|
|
if (this._optimum[(IntPtr) cur].BackPrev2 < 4U)
|
|
state1.UpdateRep();
|
|
else
|
|
state1.UpdateMatch();
|
|
}
|
|
else
|
|
state1 = this._optimum[(IntPtr) index4].State;
|
|
state1.UpdateChar();
|
|
}
|
|
else
|
|
state1 = this._optimum[(IntPtr) index4].State;
|
|
if ((int) index4 == (int) cur - 1)
|
|
{
|
|
if (this._optimum[(IntPtr) cur].IsShortRep())
|
|
state1.UpdateShortRep();
|
|
else
|
|
state1.UpdateChar();
|
|
}
|
|
else
|
|
{
|
|
uint num16;
|
|
if (this._optimum[(IntPtr) cur].Prev1IsChar && this._optimum[(IntPtr) cur].Prev2)
|
|
{
|
|
index4 = this._optimum[(IntPtr) cur].PosPrev2;
|
|
num16 = this._optimum[(IntPtr) cur].BackPrev2;
|
|
state1.UpdateRep();
|
|
}
|
|
else
|
|
{
|
|
num16 = this._optimum[(IntPtr) cur].BackPrev;
|
|
if (num16 < 4U)
|
|
state1.UpdateRep();
|
|
else
|
|
state1.UpdateMatch();
|
|
}
|
|
Encoder.Optimal optimal4 = this._optimum[(IntPtr) index4];
|
|
if (num16 < 4U)
|
|
{
|
|
switch (num16)
|
|
{
|
|
case 0:
|
|
this.reps[0] = optimal4.Backs0;
|
|
this.reps[1] = optimal4.Backs1;
|
|
this.reps[2] = optimal4.Backs2;
|
|
this.reps[3] = optimal4.Backs3;
|
|
break;
|
|
case 1:
|
|
this.reps[0] = optimal4.Backs1;
|
|
this.reps[1] = optimal4.Backs0;
|
|
this.reps[2] = optimal4.Backs2;
|
|
this.reps[3] = optimal4.Backs3;
|
|
break;
|
|
case 2:
|
|
this.reps[0] = optimal4.Backs2;
|
|
this.reps[1] = optimal4.Backs0;
|
|
this.reps[2] = optimal4.Backs1;
|
|
this.reps[3] = optimal4.Backs3;
|
|
break;
|
|
default:
|
|
this.reps[0] = optimal4.Backs3;
|
|
this.reps[1] = optimal4.Backs0;
|
|
this.reps[2] = optimal4.Backs1;
|
|
this.reps[3] = optimal4.Backs2;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.reps[0] = num16 - 4U;
|
|
this.reps[1] = optimal4.Backs0;
|
|
this.reps[2] = optimal4.Backs1;
|
|
this.reps[3] = optimal4.Backs2;
|
|
}
|
|
}
|
|
this._optimum[(IntPtr) cur].State = state1;
|
|
this._optimum[(IntPtr) cur].Backs0 = this.reps[0];
|
|
this._optimum[(IntPtr) cur].Backs1 = this.reps[1];
|
|
this._optimum[(IntPtr) cur].Backs2 = this.reps[2];
|
|
this._optimum[(IntPtr) cur].Backs3 = this.reps[3];
|
|
uint price2 = this._optimum[(IntPtr) cur].Price;
|
|
indexByte3 = this._matchFinder.GetIndexByte(-1);
|
|
indexByte4 = this._matchFinder.GetIndexByte(-(int) this.reps[0] - 1 - 1);
|
|
posState2 = position & this._posStateMask;
|
|
int num17 = (int) price2 + (int) this._isMatch[(IntPtr) ((state1.Index << 4) + posState2)].GetPrice0();
|
|
subCoder = this._literalEncoder.GetSubCoder(position, this._matchFinder.GetIndexByte(-2));
|
|
int price3 = (int) subCoder.GetPrice(!state1.IsCharState(), indexByte4, indexByte3);
|
|
num14 = (uint) (num17 + price3);
|
|
Encoder.Optimal optimal5 = this._optimum[(IntPtr) (cur + 1U)];
|
|
flag = false;
|
|
if (num14 < optimal5.Price)
|
|
{
|
|
optimal5.Price = num14;
|
|
optimal5.PosPrev = cur;
|
|
optimal5.MakeAsChar();
|
|
flag = true;
|
|
}
|
|
num11 = price2 + this._isMatch[(IntPtr) ((state1.Index << 4) + posState2)].GetPrice1();
|
|
num15 = num11 + this._isRep[(IntPtr) state1.Index].GetPrice1();
|
|
if ((int) indexByte4 == (int) indexByte3 && (optimal5.PosPrev >= cur || optimal5.BackPrev != 0U))
|
|
{
|
|
uint num18 = num15 + this.GetRepLen1Price(state1, posState2);
|
|
if (num18 <= optimal5.Price)
|
|
{
|
|
optimal5.Price = num18;
|
|
optimal5.PosPrev = cur;
|
|
optimal5.MakeAsShortRep();
|
|
flag = true;
|
|
}
|
|
}
|
|
uint val2 = this._matchFinder.GetNumAvailableBytes() + 1U;
|
|
num12 = Math.Min(4095U - cur, val2);
|
|
limit1 = num12;
|
|
}
|
|
while (limit1 < 2U);
|
|
if (limit1 > this._numFastBytes)
|
|
limit1 = this._numFastBytes;
|
|
if (!flag && (int) indexByte4 != (int) indexByte3)
|
|
{
|
|
uint matchLen = this._matchFinder.GetMatchLen(0, this.reps[0], Math.Min(num12 - 1U, this._numFastBytes));
|
|
if (matchLen >= 2U)
|
|
{
|
|
Base.State state2 = state1;
|
|
state2.UpdateChar();
|
|
uint posState3 = position + 1U & this._posStateMask;
|
|
uint num19 = num14 + this._isMatch[(IntPtr) ((state2.Index << 4) + posState3)].GetPrice1() + this._isRep[(IntPtr) state2.Index].GetPrice1();
|
|
uint index5 = cur + 1U + matchLen;
|
|
while (num5 < index5)
|
|
this._optimum[(IntPtr) ++num5].Price = 268435455U;
|
|
uint num20 = num19 + this.GetRepPrice(0U, matchLen, state2, posState3);
|
|
Encoder.Optimal optimal6 = this._optimum[(IntPtr) index5];
|
|
if (num20 < optimal6.Price)
|
|
{
|
|
optimal6.Price = num20;
|
|
optimal6.PosPrev = cur + 1U;
|
|
optimal6.BackPrev = 0U;
|
|
optimal6.Prev1IsChar = true;
|
|
optimal6.Prev2 = false;
|
|
}
|
|
}
|
|
}
|
|
num13 = 2U;
|
|
for (uint repIndex = 0; repIndex < 4U; ++repIndex)
|
|
{
|
|
uint matchLen1 = this._matchFinder.GetMatchLen(-1, this.reps[(IntPtr) repIndex], limit1);
|
|
if (matchLen1 >= 2U)
|
|
{
|
|
uint num21 = matchLen1;
|
|
do
|
|
{
|
|
while (num5 < cur + matchLen1)
|
|
this._optimum[(IntPtr) ++num5].Price = 268435455U;
|
|
uint num22 = num15 + this.GetRepPrice(repIndex, matchLen1, state1, posState2);
|
|
Encoder.Optimal optimal7 = this._optimum[(IntPtr) (cur + matchLen1)];
|
|
if (num22 < optimal7.Price)
|
|
{
|
|
optimal7.Price = num22;
|
|
optimal7.PosPrev = cur;
|
|
optimal7.BackPrev = repIndex;
|
|
optimal7.Prev1IsChar = false;
|
|
}
|
|
}
|
|
while (--matchLen1 >= 2U);
|
|
uint num23 = num21;
|
|
if (repIndex == 0U)
|
|
num13 = num23 + 1U;
|
|
if (num23 < num12)
|
|
{
|
|
uint limit2 = Math.Min(num12 - 1U - num23, this._numFastBytes);
|
|
uint matchLen2 = this._matchFinder.GetMatchLen((int) num23, this.reps[(IntPtr) repIndex], limit2);
|
|
if (matchLen2 >= 2U)
|
|
{
|
|
Base.State state3 = state1;
|
|
state3.UpdateRep();
|
|
uint num24 = position + num23 & this._posStateMask;
|
|
int num25 = (int) num15 + (int) this.GetRepPrice(repIndex, num23, state1, posState2) + (int) this._isMatch[(IntPtr) ((state3.Index << 4) + num24)].GetPrice0();
|
|
subCoder = this._literalEncoder.GetSubCoder(position + num23, this._matchFinder.GetIndexByte((int) num23 - 1 - 1));
|
|
int price4 = (int) subCoder.GetPrice(true, this._matchFinder.GetIndexByte((int) num23 - 1 - ((int) this.reps[(IntPtr) repIndex] + 1)), this._matchFinder.GetIndexByte((int) num23 - 1));
|
|
uint num26 = (uint) (num25 + price4);
|
|
state3.UpdateChar();
|
|
uint posState4 = (uint) ((int) position + (int) num23 + 1) & this._posStateMask;
|
|
uint num27 = num26 + this._isMatch[(IntPtr) ((state3.Index << 4) + posState4)].GetPrice1() + this._isRep[(IntPtr) state3.Index].GetPrice1();
|
|
uint num28 = num23 + 1U + matchLen2;
|
|
while (num5 < cur + num28)
|
|
this._optimum[(IntPtr) ++num5].Price = 268435455U;
|
|
uint num29 = num27 + this.GetRepPrice(0U, matchLen2, state3, posState4);
|
|
Encoder.Optimal optimal8 = this._optimum[(IntPtr) (cur + num28)];
|
|
if (num29 < optimal8.Price)
|
|
{
|
|
optimal8.Price = num29;
|
|
optimal8.PosPrev = (uint) ((int) cur + (int) num23 + 1);
|
|
optimal8.BackPrev = 0U;
|
|
optimal8.Prev1IsChar = true;
|
|
optimal8.Prev2 = true;
|
|
optimal8.PosPrev2 = cur;
|
|
optimal8.BackPrev2 = repIndex;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (lenRes2 > limit1)
|
|
{
|
|
lenRes2 = limit1;
|
|
uint index6 = 0;
|
|
while (lenRes2 > this._matchDistances[(IntPtr) index6])
|
|
index6 += 2U;
|
|
this._matchDistances[(IntPtr) index6] = lenRes2;
|
|
numDistancePairs = index6 + 2U;
|
|
}
|
|
}
|
|
while (lenRes2 < num13);
|
|
uint num30 = num11 + this._isRep[(IntPtr) state1.Index].GetPrice0();
|
|
while (num5 < cur + lenRes2)
|
|
this._optimum[(IntPtr) ++num5].Price = 268435455U;
|
|
uint index7 = 0;
|
|
while (num13 > this._matchDistances[(IntPtr) index7])
|
|
index7 += 2U;
|
|
uint num31 = num13;
|
|
while (true)
|
|
{
|
|
uint matchDistance = this._matchDistances[(IntPtr) (index7 + 1U)];
|
|
uint num32 = num30 + this.GetPosLenPrice(matchDistance, num31, posState2);
|
|
Encoder.Optimal optimal9 = this._optimum[(IntPtr) (cur + num31)];
|
|
if (num32 < optimal9.Price)
|
|
{
|
|
optimal9.Price = num32;
|
|
optimal9.PosPrev = cur;
|
|
optimal9.BackPrev = matchDistance + 4U;
|
|
optimal9.Prev1IsChar = false;
|
|
}
|
|
if ((int) num31 == (int) this._matchDistances[(IntPtr) index7])
|
|
{
|
|
if (num31 < num12)
|
|
{
|
|
uint limit = Math.Min(num12 - 1U - num31, this._numFastBytes);
|
|
uint matchLen = this._matchFinder.GetMatchLen((int) num31, matchDistance, limit);
|
|
if (matchLen >= 2U)
|
|
{
|
|
Base.State state4 = state1;
|
|
state4.UpdateMatch();
|
|
uint num33 = position + num31 & this._posStateMask;
|
|
int num34 = (int) num32 + (int) this._isMatch[(IntPtr) ((state4.Index << 4) + num33)].GetPrice0();
|
|
subCoder = this._literalEncoder.GetSubCoder(position + num31, this._matchFinder.GetIndexByte((int) num31 - 1 - 1));
|
|
int price5 = (int) subCoder.GetPrice(true, this._matchFinder.GetIndexByte((int) num31 - ((int) matchDistance + 1) - 1), this._matchFinder.GetIndexByte((int) num31 - 1));
|
|
uint num35 = (uint) (num34 + price5);
|
|
state4.UpdateChar();
|
|
uint posState5 = (uint) ((int) position + (int) num31 + 1) & this._posStateMask;
|
|
uint num36 = num35 + this._isMatch[(IntPtr) ((state4.Index << 4) + posState5)].GetPrice1() + this._isRep[(IntPtr) state4.Index].GetPrice1();
|
|
uint num37 = num31 + 1U + matchLen;
|
|
while (num5 < cur + num37)
|
|
this._optimum[(IntPtr) ++num5].Price = 268435455U;
|
|
uint num38 = num36 + this.GetRepPrice(0U, matchLen, state4, posState5);
|
|
Encoder.Optimal optimal10 = this._optimum[(IntPtr) (cur + num37)];
|
|
if (num38 < optimal10.Price)
|
|
{
|
|
optimal10.Price = num38;
|
|
optimal10.PosPrev = (uint) ((int) cur + (int) num31 + 1);
|
|
optimal10.BackPrev = 0U;
|
|
optimal10.Prev1IsChar = true;
|
|
optimal10.Prev2 = true;
|
|
optimal10.PosPrev2 = cur;
|
|
optimal10.BackPrev2 = matchDistance + 4U;
|
|
}
|
|
}
|
|
}
|
|
index7 += 2U;
|
|
if ((int) index7 == (int) numDistancePairs)
|
|
goto label_45;
|
|
}
|
|
++num31;
|
|
}
|
|
}
|
|
|
|
private bool ChangePair(uint smallDist, uint bigDist) => smallDist < 33554432U && bigDist >= smallDist << 7;
|
|
|
|
private void WriteEndMarker(uint posState)
|
|
{
|
|
if (!this._writeEndMark)
|
|
return;
|
|
this._isMatch[(IntPtr) ((this._state.Index << 4) + posState)].Encode(this._rangeEncoder, 1U);
|
|
this._isRep[(IntPtr) this._state.Index].Encode(this._rangeEncoder, 0U);
|
|
this._state.UpdateMatch();
|
|
uint len = 2;
|
|
this._lenEncoder.Encode(this._rangeEncoder, len - 2U, posState);
|
|
uint symbol = 63;
|
|
this._posSlotEncoder[(IntPtr) Base.GetLenToPosState(len)].Encode(this._rangeEncoder, symbol);
|
|
int num1 = 30;
|
|
uint num2 = (uint) ((1 << num1) - 1);
|
|
this._rangeEncoder.EncodeDirectBits(num2 >> 4, num1 - 4);
|
|
this._posAlignEncoder.ReverseEncode(this._rangeEncoder, num2 & 15U);
|
|
}
|
|
|
|
private void Flush(uint nowPos)
|
|
{
|
|
this.ReleaseMFStream();
|
|
this.WriteEndMarker(nowPos & this._posStateMask);
|
|
this._rangeEncoder.FlushData();
|
|
this._rangeEncoder.FlushStream();
|
|
}
|
|
|
|
public void CodeOneBlock(out long inSize, out long outSize, out bool finished)
|
|
{
|
|
inSize = 0L;
|
|
outSize = 0L;
|
|
finished = true;
|
|
if (this._inStream != null)
|
|
{
|
|
this._matchFinder.SetStream(this._inStream);
|
|
this._matchFinder.Init();
|
|
this._needReleaseMFStream = true;
|
|
this._inStream = (Stream) null;
|
|
if (this._trainSize > 0U)
|
|
this._matchFinder.Skip(this._trainSize);
|
|
}
|
|
if (this._finished)
|
|
return;
|
|
this._finished = true;
|
|
long nowPos64 = this.nowPos64;
|
|
if (this.nowPos64 == 0L)
|
|
{
|
|
if (this._matchFinder.GetNumAvailableBytes() == 0U)
|
|
{
|
|
this.Flush((uint) this.nowPos64);
|
|
return;
|
|
}
|
|
this.ReadMatchDistances(out uint _, out uint _);
|
|
this._isMatch[(IntPtr) ((this._state.Index << 4) + ((uint) this.nowPos64 & this._posStateMask))].Encode(this._rangeEncoder, 0U);
|
|
this._state.UpdateChar();
|
|
byte indexByte = this._matchFinder.GetIndexByte(-(int) this._additionalOffset);
|
|
this._literalEncoder.GetSubCoder((uint) this.nowPos64, this._previousByte).Encode(this._rangeEncoder, indexByte);
|
|
this._previousByte = indexByte;
|
|
--this._additionalOffset;
|
|
++this.nowPos64;
|
|
}
|
|
if (this._matchFinder.GetNumAvailableBytes() == 0U)
|
|
{
|
|
this.Flush((uint) this.nowPos64);
|
|
}
|
|
else
|
|
{
|
|
do
|
|
{
|
|
do
|
|
{
|
|
uint backRes;
|
|
uint optimum = this.GetOptimum((uint) this.nowPos64, out backRes);
|
|
uint posState = (uint) this.nowPos64 & this._posStateMask;
|
|
uint index1 = (this._state.Index << 4) + posState;
|
|
if (optimum == 1U && backRes == uint.MaxValue)
|
|
{
|
|
this._isMatch[(IntPtr) index1].Encode(this._rangeEncoder, 0U);
|
|
byte indexByte1 = this._matchFinder.GetIndexByte(-(int) this._additionalOffset);
|
|
Encoder.LiteralEncoder.Encoder2 subCoder = this._literalEncoder.GetSubCoder((uint) this.nowPos64, this._previousByte);
|
|
if (!this._state.IsCharState())
|
|
{
|
|
byte indexByte2 = this._matchFinder.GetIndexByte(-(int) this._repDistances[0] - 1 - (int) this._additionalOffset);
|
|
subCoder.EncodeMatched(this._rangeEncoder, indexByte2, indexByte1);
|
|
}
|
|
else
|
|
subCoder.Encode(this._rangeEncoder, indexByte1);
|
|
this._previousByte = indexByte1;
|
|
this._state.UpdateChar();
|
|
}
|
|
else
|
|
{
|
|
this._isMatch[(IntPtr) index1].Encode(this._rangeEncoder, 1U);
|
|
if (backRes < 4U)
|
|
{
|
|
this._isRep[(IntPtr) this._state.Index].Encode(this._rangeEncoder, 1U);
|
|
if (backRes == 0U)
|
|
{
|
|
this._isRepG0[(IntPtr) this._state.Index].Encode(this._rangeEncoder, 0U);
|
|
if (optimum == 1U)
|
|
this._isRep0Long[(IntPtr) index1].Encode(this._rangeEncoder, 0U);
|
|
else
|
|
this._isRep0Long[(IntPtr) index1].Encode(this._rangeEncoder, 1U);
|
|
}
|
|
else
|
|
{
|
|
this._isRepG0[(IntPtr) this._state.Index].Encode(this._rangeEncoder, 1U);
|
|
if (backRes == 1U)
|
|
{
|
|
this._isRepG1[(IntPtr) this._state.Index].Encode(this._rangeEncoder, 0U);
|
|
}
|
|
else
|
|
{
|
|
this._isRepG1[(IntPtr) this._state.Index].Encode(this._rangeEncoder, 1U);
|
|
this._isRepG2[(IntPtr) this._state.Index].Encode(this._rangeEncoder, backRes - 2U);
|
|
}
|
|
}
|
|
if (optimum == 1U)
|
|
{
|
|
this._state.UpdateShortRep();
|
|
}
|
|
else
|
|
{
|
|
this._repMatchLenEncoder.Encode(this._rangeEncoder, optimum - 2U, posState);
|
|
this._state.UpdateRep();
|
|
}
|
|
uint repDistance = this._repDistances[(IntPtr) backRes];
|
|
if (backRes != 0U)
|
|
{
|
|
for (uint index2 = backRes; index2 >= 1U; --index2)
|
|
this._repDistances[(IntPtr) index2] = this._repDistances[(IntPtr) (index2 - 1U)];
|
|
this._repDistances[0] = repDistance;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this._isRep[(IntPtr) this._state.Index].Encode(this._rangeEncoder, 0U);
|
|
this._state.UpdateMatch();
|
|
this._lenEncoder.Encode(this._rangeEncoder, optimum - 2U, posState);
|
|
backRes -= 4U;
|
|
uint posSlot = Encoder.GetPosSlot(backRes);
|
|
this._posSlotEncoder[(IntPtr) Base.GetLenToPosState(optimum)].Encode(this._rangeEncoder, posSlot);
|
|
if (posSlot >= 4U)
|
|
{
|
|
int NumBitLevels = (int) (posSlot >> 1) - 1;
|
|
uint num = (uint) ((2 | (int) posSlot & 1) << NumBitLevels);
|
|
uint symbol = backRes - num;
|
|
if (posSlot < 14U)
|
|
{
|
|
BitTreeEncoder.ReverseEncode(this._posEncoders, (uint) ((int) num - (int) posSlot - 1), this._rangeEncoder, NumBitLevels, symbol);
|
|
}
|
|
else
|
|
{
|
|
this._rangeEncoder.EncodeDirectBits(symbol >> 4, NumBitLevels - 4);
|
|
this._posAlignEncoder.ReverseEncode(this._rangeEncoder, symbol & 15U);
|
|
++this._alignPriceCount;
|
|
}
|
|
}
|
|
uint num1 = backRes;
|
|
for (uint index3 = 3; index3 >= 1U; --index3)
|
|
this._repDistances[(IntPtr) index3] = this._repDistances[(IntPtr) (index3 - 1U)];
|
|
this._repDistances[0] = num1;
|
|
++this._matchPriceCount;
|
|
}
|
|
this._previousByte = this._matchFinder.GetIndexByte((int) optimum - 1 - (int) this._additionalOffset);
|
|
}
|
|
this._additionalOffset -= optimum;
|
|
this.nowPos64 += (long) optimum;
|
|
}
|
|
while (this._additionalOffset != 0U);
|
|
if (this._matchPriceCount >= 128U)
|
|
this.FillDistancesPrices();
|
|
if (this._alignPriceCount >= 16U)
|
|
this.FillAlignPrices();
|
|
inSize = this.nowPos64;
|
|
outSize = this._rangeEncoder.GetProcessedSizeAdd();
|
|
if (this._matchFinder.GetNumAvailableBytes() == 0U)
|
|
{
|
|
this.Flush((uint) this.nowPos64);
|
|
return;
|
|
}
|
|
}
|
|
while (this.nowPos64 - nowPos64 < 4096L);
|
|
this._finished = false;
|
|
finished = false;
|
|
}
|
|
}
|
|
|
|
private void ReleaseMFStream()
|
|
{
|
|
if (this._matchFinder == null || !this._needReleaseMFStream)
|
|
return;
|
|
this._matchFinder.ReleaseStream();
|
|
this._needReleaseMFStream = false;
|
|
}
|
|
|
|
private void SetOutStream(Stream outStream) => this._rangeEncoder.SetStream(outStream);
|
|
|
|
private void ReleaseOutStream() => this._rangeEncoder.ReleaseStream();
|
|
|
|
private void ReleaseStreams()
|
|
{
|
|
this.ReleaseMFStream();
|
|
this.ReleaseOutStream();
|
|
}
|
|
|
|
private void SetStreams(Stream inStream, Stream outStream, long inSize, long outSize)
|
|
{
|
|
this._inStream = inStream;
|
|
this._finished = false;
|
|
this.Create();
|
|
this.SetOutStream(outStream);
|
|
this.Init();
|
|
this.FillDistancesPrices();
|
|
this.FillAlignPrices();
|
|
this._lenEncoder.SetTableSize((uint) ((int) this._numFastBytes + 1 - 2));
|
|
this._lenEncoder.UpdateTables((uint) (1 << this._posStateBits));
|
|
this._repMatchLenEncoder.SetTableSize((uint) ((int) this._numFastBytes + 1 - 2));
|
|
this._repMatchLenEncoder.UpdateTables((uint) (1 << this._posStateBits));
|
|
this.nowPos64 = 0L;
|
|
}
|
|
|
|
public void Code(
|
|
Stream inStream,
|
|
Stream outStream,
|
|
long inSize,
|
|
long outSize,
|
|
ICodeProgress progress)
|
|
{
|
|
this._needReleaseMFStream = false;
|
|
try
|
|
{
|
|
this.SetStreams(inStream, outStream, inSize, outSize);
|
|
while (true)
|
|
{
|
|
long inSize1;
|
|
long outSize1;
|
|
do
|
|
{
|
|
bool finished;
|
|
this.CodeOneBlock(out inSize1, out outSize1, out finished);
|
|
if (finished)
|
|
goto label_3;
|
|
}
|
|
while (progress == null);
|
|
progress.SetProgress(inSize1, outSize1);
|
|
}
|
|
label_3:;
|
|
}
|
|
finally
|
|
{
|
|
this.ReleaseStreams();
|
|
}
|
|
}
|
|
|
|
public void WriteCoderProperties(Stream outStream)
|
|
{
|
|
this.properties[0] = (byte) ((this._posStateBits * 5 + this._numLiteralPosStateBits) * 9 + this._numLiteralContextBits);
|
|
for (int index = 0; index < 4; ++index)
|
|
this.properties[1 + index] = (byte) (this._dictionarySize >> 8 * index & (uint) byte.MaxValue);
|
|
outStream.Write(this.properties, 0, 5);
|
|
}
|
|
|
|
private void FillDistancesPrices()
|
|
{
|
|
for (uint pos = 4; pos < 128U; ++pos)
|
|
{
|
|
uint posSlot = Encoder.GetPosSlot(pos);
|
|
int NumBitLevels = (int) (posSlot >> 1) - 1;
|
|
uint num = (uint) ((2 | (int) posSlot & 1) << NumBitLevels);
|
|
this.tempPrices[(IntPtr) pos] = BitTreeEncoder.ReverseGetPrice(this._posEncoders, (uint) ((int) num - (int) posSlot - 1), NumBitLevels, pos - num);
|
|
}
|
|
for (uint index1 = 0; index1 < 4U; ++index1)
|
|
{
|
|
BitTreeEncoder bitTreeEncoder = this._posSlotEncoder[(IntPtr) index1];
|
|
uint num1 = index1 << 6;
|
|
for (uint symbol = 0; symbol < this._distTableSize; ++symbol)
|
|
this._posSlotPrices[(IntPtr) (num1 + symbol)] = bitTreeEncoder.GetPrice(symbol);
|
|
for (uint index2 = 14; index2 < this._distTableSize; ++index2)
|
|
this._posSlotPrices[(IntPtr) (num1 + index2)] += (uint) ((int) (index2 >> 1) - 1 - 4 << 6);
|
|
uint num2 = index1 * 128U;
|
|
uint pos;
|
|
for (pos = 0U; pos < 4U; ++pos)
|
|
this._distancesPrices[(IntPtr) (num2 + pos)] = this._posSlotPrices[(IntPtr) (num1 + pos)];
|
|
for (; pos < 128U; ++pos)
|
|
this._distancesPrices[(IntPtr) (num2 + pos)] = this._posSlotPrices[(IntPtr) (num1 + Encoder.GetPosSlot(pos))] + this.tempPrices[(IntPtr) pos];
|
|
}
|
|
this._matchPriceCount = 0U;
|
|
}
|
|
|
|
private void FillAlignPrices()
|
|
{
|
|
for (uint symbol = 0; symbol < 16U; ++symbol)
|
|
this._alignPrices[(IntPtr) symbol] = this._posAlignEncoder.ReverseGetPrice(symbol);
|
|
this._alignPriceCount = 0U;
|
|
}
|
|
|
|
private static int FindMatchFinder(string s)
|
|
{
|
|
for (int matchFinder = 0; matchFinder < Encoder.kMatchFinderIDs.Length; ++matchFinder)
|
|
{
|
|
if (s == Encoder.kMatchFinderIDs[matchFinder])
|
|
return matchFinder;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
|
|
{
|
|
for (uint index = 0; (long) index < (long) properties.Length; ++index)
|
|
{
|
|
object property = properties[(IntPtr) index];
|
|
switch (propIDs[(IntPtr) index])
|
|
{
|
|
case CoderPropID.DictionarySize:
|
|
if (!(property is int num1))
|
|
throw new InvalidParamException();
|
|
this._dictionarySize = num1 >= 1 && num1 <= 1073741824 ? (uint) num1 : throw new InvalidParamException();
|
|
int num2 = 0;
|
|
while (num2 < 30 && (long) num1 > (long) (uint) (1 << num2))
|
|
++num2;
|
|
this._distTableSize = (uint) (num2 * 2);
|
|
continue;
|
|
case CoderPropID.PosStateBits:
|
|
if (!(property is int num3))
|
|
throw new InvalidParamException();
|
|
this._posStateBits = num3 >= 0 && num3 <= 4 ? num3 : throw new InvalidParamException();
|
|
this._posStateMask = (uint) ((1 << this._posStateBits) - 1);
|
|
continue;
|
|
case CoderPropID.LitContextBits:
|
|
if (!(property is int num4))
|
|
throw new InvalidParamException();
|
|
this._numLiteralContextBits = num4 >= 0 && num4 <= 8 ? num4 : throw new InvalidParamException();
|
|
continue;
|
|
case CoderPropID.LitPosBits:
|
|
if (!(property is int num5))
|
|
throw new InvalidParamException();
|
|
this._numLiteralPosStateBits = num5 >= 0 && num5 <= 4 ? num5 : throw new InvalidParamException();
|
|
continue;
|
|
case CoderPropID.NumFastBytes:
|
|
if (!(property is int num6))
|
|
throw new InvalidParamException();
|
|
this._numFastBytes = num6 >= 5 && num6 <= 273 ? (uint) num6 : throw new InvalidParamException();
|
|
continue;
|
|
case CoderPropID.MatchFinder:
|
|
if (!(property is string))
|
|
throw new InvalidParamException();
|
|
Encoder.EMatchFinderType matchFinderType = this._matchFinderType;
|
|
int matchFinder = Encoder.FindMatchFinder(((string) property).ToUpper());
|
|
this._matchFinderType = matchFinder >= 0 ? (Encoder.EMatchFinderType) matchFinder : throw new InvalidParamException();
|
|
if (this._matchFinder != null && matchFinderType != this._matchFinderType)
|
|
{
|
|
this._dictionarySizePrev = uint.MaxValue;
|
|
this._matchFinder = (IMatchFinder) null;
|
|
continue;
|
|
}
|
|
continue;
|
|
case CoderPropID.Algorithm:
|
|
continue;
|
|
case CoderPropID.EndMarker:
|
|
if (!(property is bool writeEndMarker))
|
|
throw new InvalidParamException();
|
|
this.SetWriteEndMarkerMode(writeEndMarker);
|
|
continue;
|
|
default:
|
|
throw new InvalidParamException();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetTrainSize(uint trainSize) => this._trainSize = trainSize;
|
|
|
|
private enum EMatchFinderType
|
|
{
|
|
BT2,
|
|
BT4,
|
|
}
|
|
|
|
private class LiteralEncoder
|
|
{
|
|
private Encoder.LiteralEncoder.Encoder2[] m_Coders;
|
|
private int m_NumPrevBits;
|
|
private int m_NumPosBits;
|
|
private uint m_PosMask;
|
|
|
|
public void Create(int numPosBits, int numPrevBits)
|
|
{
|
|
if (this.m_Coders != null && this.m_NumPrevBits == numPrevBits && this.m_NumPosBits == numPosBits)
|
|
return;
|
|
this.m_NumPosBits = numPosBits;
|
|
this.m_PosMask = (uint) ((1 << numPosBits) - 1);
|
|
this.m_NumPrevBits = numPrevBits;
|
|
uint length = (uint) (1 << this.m_NumPrevBits + this.m_NumPosBits);
|
|
this.m_Coders = new Encoder.LiteralEncoder.Encoder2[(IntPtr) length];
|
|
for (uint index = 0; index < length; ++index)
|
|
this.m_Coders[(IntPtr) index].Create();
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
uint num = (uint) (1 << this.m_NumPrevBits + this.m_NumPosBits);
|
|
for (uint index = 0; index < num; ++index)
|
|
this.m_Coders[(IntPtr) index].Init();
|
|
}
|
|
|
|
public Encoder.LiteralEncoder.Encoder2 GetSubCoder(uint pos, byte prevByte) => this.m_Coders[(IntPtr) (uint) ((((int) pos & (int) this.m_PosMask) << this.m_NumPrevBits) + ((int) prevByte >> 8 - this.m_NumPrevBits))];
|
|
|
|
public struct Encoder2
|
|
{
|
|
private BitEncoder[] m_Encoders;
|
|
|
|
public void Create() => this.m_Encoders = new BitEncoder[768];
|
|
|
|
public void Init()
|
|
{
|
|
for (int index = 0; index < 768; ++index)
|
|
this.m_Encoders[index].Init();
|
|
}
|
|
|
|
public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol)
|
|
{
|
|
uint index1 = 1;
|
|
for (int index2 = 7; index2 >= 0; --index2)
|
|
{
|
|
uint symbol1 = (uint) ((int) symbol >> index2 & 1);
|
|
this.m_Encoders[(IntPtr) index1].Encode(rangeEncoder, symbol1);
|
|
index1 = index1 << 1 | symbol1;
|
|
}
|
|
}
|
|
|
|
public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
|
|
{
|
|
uint num1 = 1;
|
|
bool flag = true;
|
|
for (int index1 = 7; index1 >= 0; --index1)
|
|
{
|
|
uint symbol1 = (uint) ((int) symbol >> index1 & 1);
|
|
uint index2 = num1;
|
|
if (flag)
|
|
{
|
|
uint num2 = (uint) ((int) matchByte >> index1 & 1);
|
|
index2 += (uint) (1 + (int) num2 << 8);
|
|
flag = (int) num2 == (int) symbol1;
|
|
}
|
|
this.m_Encoders[(IntPtr) index2].Encode(rangeEncoder, symbol1);
|
|
num1 = num1 << 1 | symbol1;
|
|
}
|
|
}
|
|
|
|
public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
|
|
{
|
|
uint price = 0;
|
|
uint index = 1;
|
|
int num1 = 7;
|
|
if (matchMode)
|
|
{
|
|
for (; num1 >= 0; --num1)
|
|
{
|
|
uint num2 = (uint) ((int) matchByte >> num1 & 1);
|
|
uint symbol1 = (uint) ((int) symbol >> num1 & 1);
|
|
price += this.m_Encoders[(IntPtr) ((uint) (1 + (int) num2 << 8) + index)].GetPrice(symbol1);
|
|
index = index << 1 | symbol1;
|
|
if ((int) num2 != (int) symbol1)
|
|
{
|
|
--num1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
for (; num1 >= 0; --num1)
|
|
{
|
|
uint symbol2 = (uint) ((int) symbol >> num1 & 1);
|
|
price += this.m_Encoders[(IntPtr) index].GetPrice(symbol2);
|
|
index = index << 1 | symbol2;
|
|
}
|
|
return price;
|
|
}
|
|
}
|
|
}
|
|
|
|
private class LenEncoder
|
|
{
|
|
private BitEncoder _choice = new BitEncoder();
|
|
private BitEncoder _choice2 = new BitEncoder();
|
|
private BitTreeEncoder[] _lowCoder = new BitTreeEncoder[new IntPtr(16)];
|
|
private BitTreeEncoder[] _midCoder = new BitTreeEncoder[new IntPtr(16)];
|
|
private BitTreeEncoder _highCoder = new BitTreeEncoder(8);
|
|
|
|
public LenEncoder()
|
|
{
|
|
for (uint index = 0; index < 16U; ++index)
|
|
{
|
|
this._lowCoder[(IntPtr) index] = new BitTreeEncoder(3);
|
|
this._midCoder[(IntPtr) index] = new BitTreeEncoder(3);
|
|
}
|
|
}
|
|
|
|
public void Init(uint numPosStates)
|
|
{
|
|
this._choice.Init();
|
|
this._choice2.Init();
|
|
for (uint index = 0; index < numPosStates; ++index)
|
|
{
|
|
this._lowCoder[(IntPtr) index].Init();
|
|
this._midCoder[(IntPtr) index].Init();
|
|
}
|
|
this._highCoder.Init();
|
|
}
|
|
|
|
public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, uint symbol, uint posState)
|
|
{
|
|
if (symbol < 8U)
|
|
{
|
|
this._choice.Encode(rangeEncoder, 0U);
|
|
this._lowCoder[(IntPtr) posState].Encode(rangeEncoder, symbol);
|
|
}
|
|
else
|
|
{
|
|
symbol -= 8U;
|
|
this._choice.Encode(rangeEncoder, 1U);
|
|
if (symbol < 8U)
|
|
{
|
|
this._choice2.Encode(rangeEncoder, 0U);
|
|
this._midCoder[(IntPtr) posState].Encode(rangeEncoder, symbol);
|
|
}
|
|
else
|
|
{
|
|
this._choice2.Encode(rangeEncoder, 1U);
|
|
this._highCoder.Encode(rangeEncoder, symbol - 8U);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SetPrices(uint posState, uint numSymbols, uint[] prices, uint st)
|
|
{
|
|
uint price0 = this._choice.GetPrice0();
|
|
uint price1 = this._choice.GetPrice1();
|
|
uint num1 = price1 + this._choice2.GetPrice0();
|
|
uint num2 = price1 + this._choice2.GetPrice1();
|
|
uint symbol;
|
|
for (symbol = 0U; symbol < 8U; ++symbol)
|
|
{
|
|
if (symbol >= numSymbols)
|
|
return;
|
|
prices[(IntPtr) (st + symbol)] = price0 + this._lowCoder[(IntPtr) posState].GetPrice(symbol);
|
|
}
|
|
for (; symbol < 16U; ++symbol)
|
|
{
|
|
if (symbol >= numSymbols)
|
|
return;
|
|
prices[(IntPtr) (st + symbol)] = num1 + this._midCoder[(IntPtr) posState].GetPrice(symbol - 8U);
|
|
}
|
|
for (; symbol < numSymbols; ++symbol)
|
|
prices[(IntPtr) (st + symbol)] = num2 + this._highCoder.GetPrice((uint) ((int) symbol - 8 - 8));
|
|
}
|
|
}
|
|
|
|
private class LenPriceTableEncoder : Encoder.LenEncoder
|
|
{
|
|
private uint[] _prices = new uint[new IntPtr(4352)];
|
|
private uint _tableSize;
|
|
private uint[] _counters = new uint[new IntPtr(16)];
|
|
|
|
public void SetTableSize(uint tableSize) => this._tableSize = tableSize;
|
|
|
|
public uint GetPrice(uint symbol, uint posState) => this._prices[(IntPtr) (posState * 272U + symbol)];
|
|
|
|
private void UpdateTable(uint posState)
|
|
{
|
|
this.SetPrices(posState, this._tableSize, this._prices, posState * 272U);
|
|
this._counters[(IntPtr) posState] = this._tableSize;
|
|
}
|
|
|
|
public void UpdateTables(uint numPosStates)
|
|
{
|
|
for (uint posState = 0; posState < numPosStates; ++posState)
|
|
this.UpdateTable(posState);
|
|
}
|
|
|
|
public new void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, uint symbol, uint posState)
|
|
{
|
|
base.Encode(rangeEncoder, symbol, posState);
|
|
if (--this._counters[(IntPtr) posState] != 0U)
|
|
return;
|
|
this.UpdateTable(posState);
|
|
}
|
|
}
|
|
|
|
private class Optimal
|
|
{
|
|
public Base.State State;
|
|
public bool Prev1IsChar;
|
|
public bool Prev2;
|
|
public uint PosPrev2;
|
|
public uint BackPrev2;
|
|
public uint Price;
|
|
public uint PosPrev;
|
|
public uint BackPrev;
|
|
public uint Backs0;
|
|
public uint Backs1;
|
|
public uint Backs2;
|
|
public uint Backs3;
|
|
|
|
public void MakeAsChar()
|
|
{
|
|
this.BackPrev = uint.MaxValue;
|
|
this.Prev1IsChar = false;
|
|
}
|
|
|
|
public void MakeAsShortRep()
|
|
{
|
|
this.BackPrev = 0U;
|
|
this.Prev1IsChar = false;
|
|
}
|
|
|
|
public bool IsShortRep() => this.BackPrev == 0U;
|
|
}
|
|
}
|
|
}
|