📄 lzmaencoder.cs
字号:
// LzmaEncoder.cs
using System;
namespace SevenZip.Compression.LZMA
{
using RangeCoder;
public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
{
enum EMatchFinderType
{
BT2,
BT4,
BT4B
};
static string[] kMatchFinderIDs =
{
"BT2",
"BT4",
"BT4B",
};
static int FindMatchFinder(string s)
{
for (int m = 0; m < kMatchFinderIDs.Length; m++)
if (s == kMatchFinderIDs[m])
return m;
return -1;
}
const UInt32 kIfinityPrice = 0xFFFFFFF;
static Byte[] g_FastPos = new Byte[1024];
static Encoder()
{
const Byte kFastSlots = 20;
int c = 2;
g_FastPos[0] = 0;
g_FastPos[1] = 1;
for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
{
UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1));
for (UInt32 j = 0; j < k; j++, c++)
g_FastPos[c] = slotFast;
}
}
static UInt32 GetPosSlot(UInt32 pos)
{
if (pos < (1 << 10))
return g_FastPos[pos];
if (pos < (1 << 19))
return (UInt32)(g_FastPos[pos >> 9] + 18);
return (UInt32)(g_FastPos[pos >> 18] + 36);
}
static UInt32 GetPosSlot2(UInt32 pos)
{
if (pos < (1 << 16))
return (UInt32)(g_FastPos[pos >> 6] + 12);
if (pos < (1 << 25))
return (UInt32)(g_FastPos[pos >> 15] + 30);
return (UInt32)(g_FastPos[pos >> 24] + 48);
}
Base.State _state = new Base.State();
Byte _previousByte;
UInt32[] _repDistances = new UInt32[Base.kNumRepDistances];
void BaseInit()
{
_state.Init();
_previousByte = 0;
for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
_repDistances[i] = 0;
}
const int kDefaultDictionaryLogSize = 20;
const UInt32 kNumFastBytesDefault = 0x20;
class LiteralEncoder
{
public struct Encoder2
{
BitEncoder[] m_Encoders;
public void Create() { m_Encoders = new BitEncoder[0x300]; }
public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); }
public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)
{
uint context = 1;
for (int i = 7; i >= 0; i--)
{
uint bit = (uint)((symbol >> i) & 1);
m_Encoders[context].Encode(rangeEncoder, bit);
context = (context << 1) | bit;
}
}
public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
{
uint context = 1;
bool same = true;
for (int i = 7; i >= 0; i--)
{
uint bit = (uint)((symbol >> i) & 1);
uint state = context;
if (same)
{
uint matchBit = (uint)((matchByte >> i) & 1);
state += ((1 + matchBit) << 8);
same = (matchBit == bit);
}
m_Encoders[state].Encode(rangeEncoder, bit);
context = (context << 1) | bit;
}
}
public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
{
uint price = 0;
uint context = 1;
int i = 7;
if (matchMode)
{
for (; i >= 0; i--)
{
uint matchBit = (uint)(matchByte >> i) & 1;
uint bit = (uint)(symbol >> i) & 1;
price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);
context = (context << 1) | bit;
if (matchBit != bit)
{
i--;
break;
}
}
}
for (; i >= 0; i--)
{
uint bit = (uint)(symbol >> i) & 1;
price += m_Encoders[context].GetPrice(bit);
context = (context << 1) | bit;
}
return price;
}
}
Encoder2[] m_Coders;
int m_NumPrevBits;
int m_NumPosBits;
uint m_PosMask;
public void Create(int numPosBits, int numPrevBits)
{
if (m_Coders != null && m_NumPrevBits == numPrevBits &&
m_NumPosBits == numPosBits)
return;
m_NumPosBits = numPosBits;
m_PosMask = ((uint)1 << numPosBits) - 1;
m_NumPrevBits = numPrevBits;
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
m_Coders = new Encoder2[numStates];
for (uint i = 0; i < numStates; i++)
m_Coders[i].Create();
}
public void Init()
{
uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
for (uint i = 0; i < numStates; i++)
m_Coders[i].Init();
}
uint GetState(uint pos, byte prevByte)
{ return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)
{ return m_Coders[GetState(pos, prevByte)]; }
}
class LenEncoder
{
RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder();
RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder();
RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumLowBits
RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; // kNumMidBits
RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits);
public LenEncoder()
{
for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
{
_lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits);
_midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits);
}
}
public void Init(UInt32 numPosStates)
{
_choice.Init();
_choice2.Init();
for (UInt32 posState = 0; posState < numPosStates; posState++)
{
_lowCoder[posState].Init();
_midCoder[posState].Init();
}
_highCoder.Init();
}
public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
{
if (symbol < Base.kNumLowLenSymbols)
{
_choice.Encode(rangeEncoder, 0);
_lowCoder[posState].Encode(rangeEncoder, symbol);
}
else
{
symbol -= Base.kNumLowLenSymbols;
_choice.Encode(rangeEncoder, 1);
if (symbol < Base.kNumMidLenSymbols)
{
_choice2.Encode(rangeEncoder, 0);
_midCoder[posState].Encode(rangeEncoder, symbol);
}
else
{
_choice2.Encode(rangeEncoder, 1);
_highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
}
}
}
public UInt32 GetPrice(UInt32 symbol, UInt32 posState)
{
UInt32 price = 0;
if (symbol < Base.kNumLowLenSymbols)
{
price += _choice.GetPrice0();
price += _lowCoder[posState].GetPrice(symbol);
}
else
{
symbol -= Base.kNumLowLenSymbols;
price += _choice.GetPrice1();
if (symbol < Base.kNumMidLenSymbols)
{
price += _choice2.GetPrice0();
price += _midCoder[posState].GetPrice(symbol);
}
else
{
price += _choice2.GetPrice1();
price += _highCoder.GetPrice(symbol - Base.kNumMidLenSymbols);
}
}
return price;
}
};
const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
class LenPriceTableEncoder : LenEncoder
{
UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
UInt32 _tableSize;
UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];
public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
public new UInt32 GetPrice(UInt32 symbol, UInt32 posState)
{
return _prices[(symbol << Base.kNumPosStatesBitsEncodingMax) + posState];
}
void UpdateTable(UInt32 posState)
{
for (UInt32 len = 0; len < _tableSize; len++)
_prices[(len << Base.kNumPosStatesBitsEncodingMax) + posState] = base.GetPrice(len, posState);
_counters[posState] = _tableSize;
}
public void UpdateTables(UInt32 numPosStates)
{
for (UInt32 posState = 0; posState < numPosStates; posState++)
UpdateTable(posState);
}
public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
{
base.Encode(rangeEncoder, symbol, posState);
if (--_counters[posState] == 0)
UpdateTable(posState);
}
}
const UInt32 kNumOpts = 1 << 12;
class Optimal
{
public Base.State State;
public bool Prev1IsChar;
public bool Prev2;
public UInt32 PosPrev2;
public UInt32 BackPrev2;
public UInt32 Price;
public UInt32 PosPrev; // posNext;
public UInt32 BackPrev;
// public UInt32 []Backs = new UInt32[Base.kNumRepDistances];
public UInt32 Backs0;
public UInt32 Backs1;
public UInt32 Backs2;
public UInt32 Backs3;
public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }
public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
public bool IsShortRep() { return (BackPrev == 0); }
};
Optimal[] _optimum = new Optimal[kNumOpts];
LZ.IMatchFinder _matchFinder = null; // test it
RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();
RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates];
RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates];
RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates];
RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates];
RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits
RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits);
LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
LiteralEncoder _literalEncoder = new LiteralEncoder();
UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen + 1];
bool _fastMode = false;
bool _maxMode = false;
UInt32 _numFastBytes = kNumFastBytesDefault;
UInt32 _longestMatchLength;
UInt32 _additionalOffset;
UInt32 _optimumEndIndex;
UInt32 _optimumCurrentIndex;
bool _longestMatchWasFound;
UInt32[] _posSlotPrices = new UInt32[Base.kDistTableSizeMax << Base.kNumLenToPosStatesBits];
UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];
UInt32 _alignPriceCount;
UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2);
int _posStateBits = 2;
UInt32 _posStateMask = (4 - 1);
int _numLiteralPosStateBits = 0;
int _numLiteralContextBits = 3;
UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize);
UInt32 _dictionarySizePrev = 0xFFFFFFFF;
UInt32 _numFastBytesPrev = 0xFFFFFFFF;
Int64 lastPosSlotFillingPos;
Int64 nowPos64;
bool _finished;
System.IO.Stream _inStream;
EMatchFinderType _matchFinderType = EMatchFinderType.BT4;
bool _writeEndMark;
bool _needReleaseMFStream;
void Create()
{
// _rangeEncoder.Create(1 << 20);
if (_matchFinder == null)
{
LZ.BinTree bt = new LZ.BinTree();
int numHashBytes = 4;
bool big = false;
switch (_matchFinderType)
{
case EMatchFinderType.BT2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -