123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797 |
- using System;
- using System.IO;
- using SharpCompress.Compressors.LZMA.LZ;
- using SharpCompress.Compressors.LZMA.RangeCoder;
- namespace SharpCompress.Compressors.LZMA
- {
- internal class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
- {
- private enum EMatchFinderType
- {
- Bt2,
- Bt4
- }
- private const UInt32 K_IFINITY_PRICE = 0xFFFFFFF;
- private static readonly Byte[] G_FAST_POS = new Byte[1 << 11];
- static Encoder()
- {
- const Byte kFastSlots = 22;
- int c = 2;
- G_FAST_POS[0] = 0;
- G_FAST_POS[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_FAST_POS[c] = slotFast;
- }
- }
- }
- private static UInt32 GetPosSlot(UInt32 pos)
- {
- if (pos < (1 << 11))
- {
- return G_FAST_POS[pos];
- }
- if (pos < (1 << 21))
- {
- return (UInt32)(G_FAST_POS[pos >> 10] + 20);
- }
- return (UInt32)(G_FAST_POS[pos >> 20] + 40);
- }
- private static UInt32 GetPosSlot2(UInt32 pos)
- {
- if (pos < (1 << 17))
- {
- return (UInt32)(G_FAST_POS[pos >> 6] + 12);
- }
- if (pos < (1 << 27))
- {
- return (UInt32)(G_FAST_POS[pos >> 16] + 32);
- }
- return (UInt32)(G_FAST_POS[pos >> 26] + 52);
- }
- private Base.State _state = new Base.State();
- private Byte _previousByte;
- private readonly UInt32[] _repDistances = new UInt32[Base.K_NUM_REP_DISTANCES];
- private void BaseInit()
- {
- _state.Init();
- _previousByte = 0;
- for (UInt32 i = 0; i < Base.K_NUM_REP_DISTANCES; i++)
- {
- _repDistances[i] = 0;
- }
- }
- private const int K_DEFAULT_DICTIONARY_LOG_SIZE = 22;
- private const UInt32 K_NUM_FAST_BYTES_DEFAULT = 0x20;
- private class LiteralEncoder
- {
- public struct Encoder2
- {
- private BitEncoder[] _encoders;
- public void Create()
- {
- _encoders = new BitEncoder[0x300];
- }
- public void Init()
- {
- for (int i = 0; i < 0x300; i++)
- {
- _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);
- _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);
- }
- _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 += _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 += _encoders[context].GetPrice(bit);
- context = (context << 1) | bit;
- }
- return price;
- }
- }
- private Encoder2[] _coders;
- private int _numPrevBits;
- private int _numPosBits;
- private uint _posMask;
- public void Create(int numPosBits, int numPrevBits)
- {
- if (_coders != null && _numPrevBits == numPrevBits && _numPosBits == numPosBits)
- {
- return;
- }
- _numPosBits = numPosBits;
- _posMask = ((uint)1 << numPosBits) - 1;
- _numPrevBits = numPrevBits;
- uint numStates = (uint)1 << (_numPrevBits + _numPosBits);
- _coders = new Encoder2[numStates];
- for (uint i = 0; i < numStates; i++)
- {
- _coders[i].Create();
- }
- }
- public void Init()
- {
- uint numStates = (uint)1 << (_numPrevBits + _numPosBits);
- for (uint i = 0; i < numStates; i++)
- {
- _coders[i].Init();
- }
- }
- public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)
- {
- return _coders[((pos & _posMask) << _numPrevBits) + (uint)(prevByte >> (8 - _numPrevBits))];
- }
- }
- private class LenEncoder
- {
- private BitEncoder _choice = new BitEncoder();
- private BitEncoder _choice2 = new BitEncoder();
- private readonly BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.K_NUM_POS_STATES_ENCODING_MAX];
- private readonly BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.K_NUM_POS_STATES_ENCODING_MAX];
- private BitTreeEncoder _highCoder = new BitTreeEncoder(Base.K_NUM_HIGH_LEN_BITS);
- public LenEncoder()
- {
- for (UInt32 posState = 0; posState < Base.K_NUM_POS_STATES_ENCODING_MAX; posState++)
- {
- _lowCoder[posState] = new BitTreeEncoder(Base.K_NUM_LOW_LEN_BITS);
- _midCoder[posState] = new BitTreeEncoder(Base.K_NUM_MID_LEN_BITS);
- }
- }
- 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.K_NUM_LOW_LEN_SYMBOLS)
- {
- _choice.Encode(rangeEncoder, 0);
- _lowCoder[posState].Encode(rangeEncoder, symbol);
- }
- else
- {
- symbol -= Base.K_NUM_LOW_LEN_SYMBOLS;
- _choice.Encode(rangeEncoder, 1);
- if (symbol < Base.K_NUM_MID_LEN_SYMBOLS)
- {
- _choice2.Encode(rangeEncoder, 0);
- _midCoder[posState].Encode(rangeEncoder, symbol);
- }
- else
- {
- _choice2.Encode(rangeEncoder, 1);
- _highCoder.Encode(rangeEncoder, symbol - Base.K_NUM_MID_LEN_SYMBOLS);
- }
- }
- }
- public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)
- {
- UInt32 a0 = _choice.GetPrice0();
- UInt32 a1 = _choice.GetPrice1();
- UInt32 b0 = a1 + _choice2.GetPrice0();
- UInt32 b1 = a1 + _choice2.GetPrice1();
- UInt32 i = 0;
- for (i = 0; i < Base.K_NUM_LOW_LEN_SYMBOLS; i++)
- {
- if (i >= numSymbols)
- {
- return;
- }
- prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
- }
- for (; i < Base.K_NUM_LOW_LEN_SYMBOLS + Base.K_NUM_MID_LEN_SYMBOLS; i++)
- {
- if (i >= numSymbols)
- {
- return;
- }
- prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.K_NUM_LOW_LEN_SYMBOLS);
- }
- for (; i < numSymbols; i++)
- {
- prices[st + i] = b1 + _highCoder.GetPrice(i - Base.K_NUM_LOW_LEN_SYMBOLS - Base.K_NUM_MID_LEN_SYMBOLS);
- }
- }
- }
- private const UInt32 K_NUM_LEN_SPEC_SYMBOLS = Base.K_NUM_LOW_LEN_SYMBOLS + Base.K_NUM_MID_LEN_SYMBOLS;
- private class LenPriceTableEncoder : LenEncoder
- {
- private readonly UInt32[] _prices = new UInt32[Base.K_NUM_LEN_SYMBOLS << Base.K_NUM_POS_STATES_BITS_ENCODING_MAX];
- private UInt32 _tableSize;
- private readonly UInt32[] _counters = new UInt32[Base.K_NUM_POS_STATES_ENCODING_MAX];
- public void SetTableSize(UInt32 tableSize)
- {
- _tableSize = tableSize;
- }
- public UInt32 GetPrice(UInt32 symbol, UInt32 posState)
- {
- return _prices[posState * Base.K_NUM_LEN_SYMBOLS + symbol];
- }
- private void UpdateTable(UInt32 posState)
- {
- SetPrices(posState, _tableSize, _prices, posState * Base.K_NUM_LEN_SYMBOLS);
- _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);
- }
- }
- }
- private const UInt32 K_NUM_OPTS = 1 << 12;
- private class Optimal
- {
- public Base.State _state;
- public bool _prev1IsChar;
- public bool _prev2;
- public UInt32 _posPrev2;
- public UInt32 _backPrev2;
- public UInt32 _price;
- public UInt32 _posPrev;
- public UInt32 _backPrev;
- 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);
- }
- }
- private readonly Optimal[] _optimum = new Optimal[K_NUM_OPTS];
- private BinTree _matchFinder;
- private readonly RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();
- private readonly BitEncoder[] _isMatch =
- new BitEncoder[Base.K_NUM_STATES << Base.K_NUM_POS_STATES_BITS_MAX];
- private readonly BitEncoder[] _isRep = new BitEncoder[Base.K_NUM_STATES];
- private readonly BitEncoder[] _isRepG0 = new BitEncoder[Base.K_NUM_STATES];
- private readonly BitEncoder[] _isRepG1 = new BitEncoder[Base.K_NUM_STATES];
- private readonly BitEncoder[] _isRepG2 = new BitEncoder[Base.K_NUM_STATES];
- private readonly BitEncoder[] _isRep0Long =
- new BitEncoder[Base.K_NUM_STATES << Base.K_NUM_POS_STATES_BITS_MAX];
- private readonly BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.K_NUM_LEN_TO_POS_STATES];
- private readonly BitEncoder[] _posEncoders =
- new BitEncoder[Base.K_NUM_FULL_DISTANCES - Base.K_END_POS_MODEL_INDEX];
- private BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.K_NUM_ALIGN_BITS);
- private readonly LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
- private readonly LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
- private readonly LiteralEncoder _literalEncoder = new LiteralEncoder();
- private readonly UInt32[] _matchDistances = new UInt32[Base.K_MATCH_MAX_LEN * 2 + 2];
- private UInt32 _numFastBytes = K_NUM_FAST_BYTES_DEFAULT;
- private UInt32 _longestMatchLength;
- private UInt32 _numDistancePairs;
- private UInt32 _additionalOffset;
- private UInt32 _optimumEndIndex;
- private UInt32 _optimumCurrentIndex;
- private bool _longestMatchWasFound;
- private readonly UInt32[] _posSlotPrices = new UInt32[1 << (Base.K_NUM_POS_SLOT_BITS + Base.K_NUM_LEN_TO_POS_STATES_BITS)];
- private readonly UInt32[] _distancesPrices = new UInt32[Base.K_NUM_FULL_DISTANCES << Base.K_NUM_LEN_TO_POS_STATES_BITS];
- private readonly UInt32[] _alignPrices = new UInt32[Base.K_ALIGN_TABLE_SIZE];
- private UInt32 _alignPriceCount;
- private UInt32 _distTableSize = (K_DEFAULT_DICTIONARY_LOG_SIZE * 2);
- private int _posStateBits = 2;
- private UInt32 _posStateMask = (4 - 1);
- private int _numLiteralPosStateBits;
- private int _numLiteralContextBits = 3;
- private UInt32 _dictionarySize = (1 << K_DEFAULT_DICTIONARY_LOG_SIZE);
- private UInt32 _dictionarySizePrev = 0xFFFFFFFF;
- private UInt32 _numFastBytesPrev = 0xFFFFFFFF;
- private Int64 _nowPos64;
- private bool _finished;
- private Stream _inStream;
- private EMatchFinderType _matchFinderType = EMatchFinderType.Bt4;
- private bool _writeEndMark;
- private bool _needReleaseMfStream;
- private bool _processingMode;
- private void Create()
- {
- if (_matchFinder == null)
- {
- BinTree bt = new BinTree();
- int numHashBytes = 4;
- if (_matchFinderType == EMatchFinderType.Bt2)
- {
- numHashBytes = 2;
- }
- bt.SetType(numHashBytes);
- _matchFinder = bt;
- }
- _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
- if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
- {
- return;
- }
- _matchFinder.Create(_dictionarySize, K_NUM_OPTS, _numFastBytes, Base.K_MATCH_MAX_LEN + 1 + K_NUM_OPTS);
- _dictionarySizePrev = _dictionarySize;
- _numFastBytesPrev = _numFastBytes;
- }
- public Encoder()
- {
- for (int i = 0; i < K_NUM_OPTS; i++)
- {
- _optimum[i] = new Optimal();
- }
- for (int i = 0; i < Base.K_NUM_LEN_TO_POS_STATES; i++)
- {
- _posSlotEncoder[i] = new BitTreeEncoder(Base.K_NUM_POS_SLOT_BITS);
- }
- }
- private void SetWriteEndMarkerMode(bool writeEndMarker)
- {
- _writeEndMark = writeEndMarker;
- }
- private void Init()
- {
- BaseInit();
- _rangeEncoder.Init();
- uint i;
- for (i = 0; i < Base.K_NUM_STATES; i++)
- {
- for (uint j = 0; j <= _posStateMask; j++)
- {
- uint complexState = (i << Base.K_NUM_POS_STATES_BITS_MAX) + 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.K_NUM_LEN_TO_POS_STATES; i++)
- {
- _posSlotEncoder[i].Init();
- }
- for (i = 0; i < Base.K_NUM_FULL_DISTANCES - Base.K_END_POS_MODEL_INDEX; i++)
- {
- _posEncoders[i].Init();
- }
- _lenEncoder.Init((UInt32)1 << _posStateBits);
- _repMatchLenEncoder.Init((UInt32)1 << _posStateBits);
- _posAlignEncoder.Init();
- _longestMatchWasFound = false;
- _optimumEndIndex = 0;
- _optimumCurrentIndex = 0;
- _additionalOffset = 0;
- }
- private void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)
- {
- lenRes = 0;
- numDistancePairs = _matchFinder.GetMatches(_matchDistances);
- if (numDistancePairs > 0)
- {
- lenRes = _matchDistances[numDistancePairs - 2];
- if (lenRes == _numFastBytes)
- {
- lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],
- Base.K_MATCH_MAX_LEN - lenRes);
- }
- }
- _additionalOffset++;
- }
- private void MovePos(UInt32 num)
- {
- if (num > 0)
- {
- _matchFinder.Skip(num);
- _additionalOffset += num;
- }
- }
- private UInt32 GetRepLen1Price(Base.State state, UInt32 posState)
- {
- return _isRepG0[state._index].GetPrice0() +
- _isRep0Long[(state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].GetPrice0();
- }
- private UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)
- {
- UInt32 price;
- if (repIndex == 0)
- {
- price = _isRepG0[state._index].GetPrice0();
- price += _isRep0Long[(state._index << Base.K_NUM_POS_STATES_BITS_MAX) + 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;
- }
- private UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)
- {
- UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.K_MATCH_MIN_LEN, posState);
- return price + GetPureRepPrice(repIndex, state, posState);
- }
- private UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)
- {
- UInt32 price;
- UInt32 lenToPosState = Base.GetLenToPosState(len);
- if (pos < Base.K_NUM_FULL_DISTANCES)
- {
- price = _distancesPrices[(lenToPosState * Base.K_NUM_FULL_DISTANCES) + pos];
- }
- else
- {
- price = _posSlotPrices[(lenToPosState << Base.K_NUM_POS_SLOT_BITS) + GetPosSlot2(pos)] +
- _alignPrices[pos & Base.K_ALIGN_MASK];
- }
- return price + _lenEncoder.GetPrice(len - Base.K_MATCH_MIN_LEN, posState);
- }
- private 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;
- }
- private readonly UInt32[] _reps = new UInt32[Base.K_NUM_REP_DISTANCES];
- private readonly UInt32[] _repLens = new UInt32[Base.K_NUM_REP_DISTANCES];
- private 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 = _optimumEndIndex = 0;
- UInt32 lenMain, numDistancePairs;
- if (!_longestMatchWasFound)
- {
- ReadMatchDistances(out lenMain, out numDistancePairs);
- }
- else
- {
- lenMain = _longestMatchLength;
- numDistancePairs = _numDistancePairs;
- _longestMatchWasFound = false;
- }
- UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
- if (numAvailableBytes < 2)
- {
- backRes = 0xFFFFFFFF;
- return 1;
- }
- if (numAvailableBytes > Base.K_MATCH_MAX_LEN)
- {
- numAvailableBytes = Base.K_MATCH_MAX_LEN;
- }
- UInt32 repMaxIndex = 0;
- UInt32 i;
- for (i = 0; i < Base.K_NUM_REP_DISTANCES; i++)
- {
- _reps[i] = _repDistances[i];
- _repLens[i] = _matchFinder.GetMatchLen(0 - 1, _reps[i], Base.K_MATCH_MAX_LEN);
- if (_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[numDistancePairs - 1] + Base.K_NUM_REP_DISTANCES;
- MovePos(lenMain - 1);
- return lenMain;
- }
- Byte currentByte = _matchFinder.GetIndexByte(0 - 1);
- Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));
- if (lenMain < 2 && currentByte != matchByte && _repLens[repMaxIndex] < 2)
- {
- backRes = 0xFFFFFFFF;
- return 1;
- }
- _optimum[0]._state = _state;
- UInt32 posState = (position & _posStateMask);
- _optimum[1]._price = _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].GetPrice0() +
- _literalEncoder.GetSubCoder(position, _previousByte)
- .GetPrice(!_state.IsCharState(), matchByte, currentByte);
- _optimum[1].MakeAsChar();
- UInt32 matchPrice = _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + 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();
- }
- }
- UInt32 lenEnd = ((lenMain >= _repLens[repMaxIndex]) ? lenMain : _repLens[repMaxIndex]);
- if (lenEnd < 2)
- {
- backRes = _optimum[1]._backPrev;
- return 1;
- }
- _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 len = lenEnd;
- do
- {
- _optimum[len--]._price = K_IFINITY_PRICE;
- }
- while (len >= 2);
- for (i = 0; i < Base.K_NUM_REP_DISTANCES; i++)
- {
- UInt32 repLen = _repLens[i];
- if (repLen < 2)
- {
- continue;
- }
- UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
- do
- {
- UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
- Optimal optimum = _optimum[repLen];
- if (curAndLenPrice < optimum._price)
- {
- optimum._price = curAndLenPrice;
- optimum._posPrev = 0;
- optimum._backPrev = i;
- optimum._prev1IsChar = false;
- }
- }
- while (--repLen >= 2);
- }
- UInt32 normalMatchPrice = matchPrice + _isRep[_state._index].GetPrice0();
- len = ((_repLens[0] >= 2) ? _repLens[0] + 1 : 2);
- if (len <= lenMain)
- {
- UInt32 offs = 0;
- while (len > _matchDistances[offs])
- {
- offs += 2;
- }
- for (;; len++)
- {
- UInt32 distance = _matchDistances[offs + 1];
- UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
- Optimal optimum = _optimum[len];
- if (curAndLenPrice < optimum._price)
- {
- optimum._price = curAndLenPrice;
- optimum._posPrev = 0;
- optimum._backPrev = distance + Base.K_NUM_REP_DISTANCES;
- optimum._prev1IsChar = false;
- }
- if (len == _matchDistances[offs])
- {
- offs += 2;
- if (offs == numDistancePairs)
- {
- break;
- }
- }
- }
- }
- UInt32 cur = 0;
- while (true)
- {
- cur++;
- if (cur == lenEnd)
- {
- return Backward(out backRes, cur);
- }
- UInt32 newLen;
- ReadMatchDistances(out newLen, out numDistancePairs);
- if (newLen >= _numFastBytes)
- {
- _numDistancePairs = numDistancePairs;
- _longestMatchLength = newLen;
- _longestMatchWasFound = true;
- 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.K_NUM_REP_DISTANCES)
- {
- 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.K_NUM_REP_DISTANCES)
- {
- state.UpdateRep();
- }
- else
- {
- state.UpdateMatch();
- }
- }
- Optimal opt = _optimum[posPrev];
- if (pos < Base.K_NUM_REP_DISTANCES)
- {
- 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.K_NUM_REP_DISTANCES);
- _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 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.K_NUM_POS_STATES_BITS_MAX) + 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.K_NUM_POS_STATES_BITS_MAX) + 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 = true;
- }
- }
- UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
- numAvailableBytesFull = Math.Min(K_NUM_OPTS - 1 - cur, numAvailableBytesFull);
- numAvailableBytes = numAvailableBytesFull;
- if (numAvailableBytes < 2)
- {
- continue;
- }
- if (numAvailableBytes > _numFastBytes)
- {
- numAvailableBytes = _numFastBytes;
- }
- if (!nextIsChar && matchByte != currentByte)
- {
- // try Literal + rep0
- UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);
- UInt32 lenTest2 = _matchFinder.GetMatchLen(0, _reps[0], t);
- if (lenTest2 >= 2)
- {
- Base.State state2 = state;
- state2.UpdateChar();
- UInt32 posStateNext = (position + 1) & _posStateMask;
- UInt32 nextRepMatchPrice = curAnd1Price +
- _isMatch[(state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + posStateNext]
- .GetPrice1() +
- _isRep[state2._index].GetPrice1();
- {
- UInt32 offset = cur + 1 + lenTest2;
- while (lenEnd < offset)
- {
- _optimum[++lenEnd]._price = K_IFINITY_PRICE;
- }
- UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
- 0, lenTest2, state2, posStateNext);
- Optimal optimum = _optimum[offset];
- if (curAndLenPrice < optimum._price)
- {
- optimum._price = curAndLenPrice;
- optimum._posPrev = cur + 1;
- optimum._backPrev = 0;
- optimum._prev1IsChar = true;
- optimum._prev2 = false;
- }
- }
- }
- }
- UInt32 startLen = 2; // speed optimization
- for (UInt32 repIndex = 0; repIndex < Base.K_NUM_REP_DISTANCES; repIndex++)
- {
- UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, _reps[repIndex], numAvailableBytes);
- if (lenTest < 2)
- {
- continue;
- }
- UInt32 lenTestTemp = lenTest;
- do
- {
- while (lenEnd < cur + lenTest)
- {
- _optimum[++lenEnd]._price = K_IFINITY_PRICE;
- }
- 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 (repIndex == 0)
- {
- startLen = lenTest + 1;
- }
- // if (_maxMode)
- if (lenTest < numAvailableBytesFull)
- {
- UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
- UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, _reps[repIndex], t);
- 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.K_NUM_POS_STATES_BITS_MAX) + posStateNext].GetPrice0() +
- _literalEncoder.GetSubCoder(position + lenTest,
- _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1))
- .GetPrice(true,
- _matchFinder.GetIndexByte(
- (Int32)lenTest - 1 - (Int32)(_reps[repIndex] + 1)),
- _matchFinder.GetIndexByte((Int32)lenTest - 1));
- state2.UpdateChar();
- posStateNext = (position + lenTest + 1) & _posStateMask;
- UInt32 nextMatchPrice = curAndLenCharPrice +
- _isMatch[(state2._index << Base.K_NUM_POS_STATES_BITS_MAX) + 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 = K_IFINITY_PRICE;
- }
- 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;
- }
- }
- }
- }
- }
- if (newLen > numAvailableBytes)
- {
- newLen = numAvailableBytes;
- for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2)
- {
- ;
- }
- _matchDistances[numDistancePairs] = newLen;
- numDistancePairs += 2;
- }
- if (newLen >= startLen)
- {
- normalMatchPrice = matchPrice + _isRep[state._index].GetPrice0();
- while (lenEnd < cur + newLen)
- {
- _optimum[++lenEnd]._price = K_IFINITY_PRICE;
- }
- UInt32 offs = 0;
- while (startLen > _matchDistances[offs])
- {
- offs += 2;
- }
- for (UInt32 lenTest = startLen;; lenTest++)
- {
- UInt32 curBack = _matchDistances[offs + 1];
- 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.K_NUM_REP_DISTANCES;
- optimum._prev1IsChar = false;
- }
- if (lenTest == _matchDistances[offs])
- {
- if (lenTest < numAvailableBytesFull)
- {
- UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
- UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);
- if (lenTest2 >= 2)
- {
- Base.State state2 = state;
- state2.UpdateMatch();
- UInt32 posStateNext = (position + lenTest) & _posStateMask;
- UInt32 curAndLenCharPrice = curAndLenPrice +
- _isMatch[
- (state2._index << Base.K_NUM_POS_STATES_BITS_MAX) +
- 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.K_NUM_POS_STATES_BITS_MAX) +
- posStateNext].GetPrice1();
- UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2._index].GetPrice1();
- UInt32 offset = lenTest + 1 + lenTest2;
- while (lenEnd < cur + offset)
- {
- _optimum[++lenEnd]._price = K_IFINITY_PRICE;
- }
- 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.K_NUM_REP_DISTANCES;
- }
- }
- }
- offs += 2;
- if (offs == numDistancePairs)
- {
- break;
- }
- }
- }
- }
- }
- }
- private bool ChangePair(UInt32 smallDist, UInt32 bigDist)
- {
- const int kDif = 7;
- return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
- }
- private void WriteEndMarker(UInt32 posState)
- {
- if (!_writeEndMark)
- {
- return;
- }
- _isMatch[(_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + posState].Encode(_rangeEncoder, 1);
- _isRep[_state._index].Encode(_rangeEncoder, 0);
- _state.UpdateMatch();
- UInt32 len = Base.K_MATCH_MIN_LEN;
- _lenEncoder.Encode(_rangeEncoder, len - Base.K_MATCH_MIN_LEN, posState);
- UInt32 posSlot = (1 << Base.K_NUM_POS_SLOT_BITS) - 1;
- UInt32 lenToPosState = Base.GetLenToPosState(len);
- _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
- int footerBits = 30;
- UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
- _rangeEncoder.EncodeDirectBits(posReduced >> Base.K_NUM_ALIGN_BITS, footerBits - Base.K_NUM_ALIGN_BITS);
- _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.K_ALIGN_MASK);
- }
- private 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);
- _needReleaseMfStream = true;
- _inStream = null;
- }
- if (_finished)
- {
- return;
- }
- _finished = true;
- Int64 progressPosValuePrev = _nowPos64;
- if (_nowPos64 == 0)
- {
- if (_trainSize > 0)
- {
- for (; _trainSize > 0 && (!_processingMode || !_matchFinder.IsDataStarved); _trainSize--)
- {
- _matchFinder.Skip(1);
- }
- if (_trainSize == 0)
- {
- _previousByte = _matchFinder.GetIndexByte(-1);
- }
- }
- if (_processingMode && _matchFinder.IsDataStarved)
- {
- _finished = false;
- return;
- }
- 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.K_NUM_POS_STATES_BITS_MAX) + 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 (_processingMode && _matchFinder.IsDataStarved)
- {
- _finished = false;
- return;
- }
- if (_matchFinder.GetNumAvailableBytes() == 0)
- {
- Flush((UInt32)_nowPos64);
- return;
- }
- while (true)
- {
- if (_processingMode && _matchFinder.IsDataStarved)
- {
- _finished = false;
- return;
- }
- UInt32 pos;
- UInt32 len = GetOptimum((UInt32)_nowPos64, out pos);
- UInt32 posState = ((UInt32)_nowPos64) & _posStateMask;
- UInt32 complexState = (_state._index << Base.K_NUM_POS_STATES_BITS_MAX) + 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.K_NUM_REP_DISTANCES)
- {
- _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.K_MATCH_MIN_LEN, 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.K_MATCH_MIN_LEN, posState);
- pos -= Base.K_NUM_REP_DISTANCES;
- UInt32 posSlot = GetPosSlot(pos);
- UInt32 lenToPosState = Base.GetLenToPosState(len);
- _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
- if (posSlot >= Base.K_START_POS_MODEL_INDEX)
- {
- int footerBits = (int)((posSlot >> 1) - 1);
- UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
- UInt32 posReduced = pos - baseVal;
- if (posSlot < Base.K_END_POS_MODEL_INDEX)
- {
- BitTreeEncoder.ReverseEncode(_posEncoders,
- baseVal - posSlot - 1, _rangeEncoder, footerBits,
- posReduced);
- }
- else
- {
- _rangeEncoder.EncodeDirectBits(posReduced >> Base.K_NUM_ALIGN_BITS,
- footerBits - Base.K_NUM_ALIGN_BITS);
- _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.K_ALIGN_MASK);
- _alignPriceCount++;
- }
- }
- UInt32 distance = pos;
- for (UInt32 i = Base.K_NUM_REP_DISTANCES - 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.K_ALIGN_TABLE_SIZE)
- {
- FillAlignPrices();
- }
- inSize = _nowPos64;
- outSize = _rangeEncoder.GetProcessedSizeAdd();
- if (_processingMode && _matchFinder.IsDataStarved)
- {
- _finished = false;
- return;
- }
- if (_matchFinder.GetNumAvailableBytes() == 0)
- {
- Flush((UInt32)_nowPos64);
- return;
- }
- if (_nowPos64 - progressPosValuePrev >= (1 << 12))
- {
- _finished = false;
- finished = false;
- return;
- }
- }
- }
- }
- private void ReleaseMfStream()
- {
- if (_matchFinder != null && _needReleaseMfStream)
- {
- _matchFinder.ReleaseStream();
- _needReleaseMfStream = false;
- }
- }
- private void SetOutStream(Stream outStream)
- {
- _rangeEncoder.SetStream(outStream);
- }
- private void ReleaseOutStream()
- {
- _rangeEncoder.ReleaseStream();
- }
- private void ReleaseStreams()
- {
- ReleaseMfStream();
- ReleaseOutStream();
- }
- public void SetStreams(Stream inStream, Stream outStream,
- Int64 inSize, Int64 outSize)
- {
- _inStream = inStream;
- _finished = false;
- Create();
- SetOutStream(outStream);
- Init();
- _matchFinder.Init();
- // if (!_fastMode)
- {
- FillDistancesPrices();
- FillAlignPrices();
- }
- _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.K_MATCH_MIN_LEN);
- _lenEncoder.UpdateTables((UInt32)1 << _posStateBits);
- _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.K_MATCH_MIN_LEN);
- _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);
- _nowPos64 = 0;
- }
- public void Code(Stream inStream, Stream outStream,
- Int64 inSize, Int64 outSize, ICodeProgress progress)
- {
- _needReleaseMfStream = false;
- _processingMode = 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();
- }
- }
- public long Code(Stream inStream, bool final)
- {
- _matchFinder.SetStream(inStream);
- _processingMode = !final;
- try
- {
- while (true)
- {
- Int64 processedInSize;
- Int64 processedOutSize;
- bool finished;
- CodeOneBlock(out processedInSize, out processedOutSize, out finished);
- if (finished)
- {
- return processedInSize;
- }
- }
- }
- finally
- {
- _matchFinder.ReleaseStream();
- if (final)
- {
- ReleaseStreams();
- }
- }
- }
- public void Train(Stream trainStream)
- {
- if (_nowPos64 > 0)
- {
- throw new InvalidOperationException();
- }
- _trainSize = (uint)trainStream.Length;
- if (_trainSize > 0)
- {
- _matchFinder.SetStream(trainStream);
- for (; _trainSize > 0 && !_matchFinder.IsDataStarved; _trainSize--)
- {
- _matchFinder.Skip(1);
- }
- if (_trainSize == 0)
- {
- _previousByte = _matchFinder.GetIndexByte(-1);
- }
- _matchFinder.ReleaseStream();
- }
- }
- private const int K_PROP_SIZE = 5;
- private readonly Byte[] _properties = new Byte[K_PROP_SIZE];
- public void WriteCoderProperties(Stream outStream)
- {
- _properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
- for (int i = 0; i < 4; i++)
- {
- _properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF);
- }
- outStream.Write(_properties, 0, K_PROP_SIZE);
- }
- private readonly UInt32[] _tempPrices = new UInt32[Base.K_NUM_FULL_DISTANCES];
- private UInt32 _matchPriceCount;
- private void FillDistancesPrices()
- {
- for (UInt32 i = Base.K_START_POS_MODEL_INDEX; i < Base.K_NUM_FULL_DISTANCES; 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.K_NUM_LEN_TO_POS_STATES; lenToPosState++)
- {
- UInt32 posSlot;
- BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
- UInt32 st = (lenToPosState << Base.K_NUM_POS_SLOT_BITS);
- for (posSlot = 0; posSlot < _distTableSize; posSlot++)
- {
- _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
- }
- for (posSlot = Base.K_END_POS_MODEL_INDEX; posSlot < _distTableSize; posSlot++)
- {
- _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.K_NUM_ALIGN_BITS) <<
- BitEncoder.K_NUM_BIT_PRICE_SHIFT_BITS);
- }
- UInt32 st2 = lenToPosState * Base.K_NUM_FULL_DISTANCES;
- UInt32 i;
- for (i = 0; i < Base.K_START_POS_MODEL_INDEX; i++)
- {
- _distancesPrices[st2 + i] = _posSlotPrices[st + i];
- }
- for (; i < Base.K_NUM_FULL_DISTANCES; i++)
- {
- _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + _tempPrices[i];
- }
- }
- _matchPriceCount = 0;
- }
- private void FillAlignPrices()
- {
- for (UInt32 i = 0; i < Base.K_ALIGN_TABLE_SIZE; i++)
- {
- _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
- }
- _alignPriceCount = 0;
- }
- private static readonly string[] K_MATCH_FINDER_I_DS =
- {
- "BT2",
- "BT4"
- };
- private static int FindMatchFinder(string s)
- {
- for (int m = 0; m < K_MATCH_FINDER_I_DS.Length; m++)
- {
- if (s == K_MATCH_FINDER_I_DS[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.K_MATCH_MAX_LEN)
- {
- 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.K_DIC_LOG_SIZE_MIN) ||
- 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.K_NUM_POS_STATES_BITS_ENCODING_MAX)
- {
- throw new InvalidParamException();
- }
- _posStateBits = v;
- _posStateMask = (((UInt32)1) << _posStateBits) - 1;
- break;
- }
- case CoderPropId.LitPosBits:
- {
- if (!(prop is Int32))
- {
- throw new InvalidParamException();
- }
- Int32 v = (Int32)prop;
- if (v < 0 || v > Base.K_NUM_LIT_POS_STATES_BITS_ENCODING_MAX)
- {
- throw new InvalidParamException();
- }
- _numLiteralPosStateBits = v;
- break;
- }
- case CoderPropId.LitContextBits:
- {
- if (!(prop is Int32))
- {
- throw new InvalidParamException();
- }
- Int32 v = (Int32)prop;
- if (v < 0 || v > Base.K_NUM_LIT_CONTEXT_BITS_MAX)
- {
- throw new InvalidParamException();
- }
- ;
- _numLiteralContextBits = v;
- break;
- }
- case CoderPropId.EndMarker:
- {
- if (!(prop is Boolean))
- {
- throw new InvalidParamException();
- }
- SetWriteEndMarkerMode((Boolean)prop);
- break;
- }
- default:
- throw new InvalidParamException();
- }
- }
- }
- private uint _trainSize;
- public void SetTrainSize(uint trainSize)
- {
- _trainSize = trainSize;
- }
- }
- }
|