Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "LZMAEncoder.h"
  2. #include "MatchFinder.h"
  3.  
  4. const byte kLiteralNextStates[kNumStates] = {0,0,0,0,1,2,3,4,5,6,4,5};
  5. const byte kMatchNextStates[kNumStates] = {7,7,7,7,7,7,7,10,10,10,10,10};
  6. const byte kRepNextStates[kNumStates] = {8,8,8,8,8,8,8,11,11,11,11,11};
  7. const byte kShortRepNextStates[kNumStates] = {9,9,9,9,9,9,9,11,11,11,11,11};
  8.  
  9. static CState _state;
  10. static byte _previousByte;
  11. static unsigned _repDistances[kNumRepDistances];
  12.  
  13. static COptimal _optimum[kNumOpts];
  14. static CMyBitEncoder _isMatch[kNumStates][kNumPosStatesEncodingMax];
  15. static CMyBitEncoder _isRep[kNumStates];
  16. static CMyBitEncoder _isRepG0[kNumStates];
  17. static CMyBitEncoder _isRepG1[kNumStates];
  18. static CMyBitEncoder _isRepG2[kNumStates];
  19. static CMyBitEncoder _isRep0Long[kNumStates][kNumPosStatesEncodingMax];
  20. static NRangeCoder_CBitTreeEncoder _posSlotEncoder[kNumLenToPosStates];
  21. static CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];
  22. static NRangeCoder_CBitTreeEncoder _posAlignEncoder;
  23. static NLength_CPriceTableEncoder _lenEncoder;
  24. static NLength_CPriceTableEncoder _repMatchLenEncoder;
  25. static CLiteralEncoder _literalEncoder;
  26. static unsigned _matchDistances[kMatchMaxLen+1];
  27. static unsigned _numFastBytes;
  28. static unsigned _longestMatchLength;
  29. static unsigned _additionalOffset;
  30. static unsigned _optimumEndIndex;
  31. static unsigned _optimumCurrentIndex;
  32. static bool _longestMatchWasFound;
  33. static unsigned _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
  34. static unsigned _distancesPrices[kNumLenToPosStates][kNumFullDistances];
  35. static unsigned _alignPrices[kAlignTableSize];
  36. static unsigned _alignPriceCount;
  37. static unsigned _distTableSize;
  38. static unsigned _posStateBits;
  39. static unsigned _posStateMask;
  40. static unsigned _numLiteralPosStateBits;
  41. static unsigned _numLiteralContextBits;
  42. static unsigned _dictionarySize;
  43. static uint64 lastPosSlotFillingPos;
  44. static uint64 nowPos64;
  45. static bool _finished;
  46. static bool _writeEndMark;
  47.  
  48. static byte g_FastPos[1024];
  49.  
  50. // must be called before work
  51. static void FastPosInit(void)
  52. {
  53.         int c = 2;
  54.         int slotFast;
  55.         unsigned j,k;
  56.         g_FastPos[0] = 0;
  57.         g_FastPos[1] = 1;
  58.         for (slotFast = 2; slotFast < 20; slotFast++)
  59.         {
  60.                 k = (1 << ((slotFast >> 1) - 1));
  61.                 for (j=0;j<k;j++) g_FastPos[c++] = slotFast;
  62.         }
  63. }
  64. static unsigned GetPosSlot(unsigned pos)
  65. {
  66.         if (pos < (1<<10))
  67.                 return g_FastPos[pos];
  68.         if (pos < (1<<19))
  69.                 return g_FastPos[pos>>9]+18;
  70.         return g_FastPos[pos>>18]+36;
  71. }
  72. static unsigned GetPosSlot2(unsigned pos)
  73. {
  74.         if (pos < (1<<16))
  75.                 return g_FastPos[pos>>6]+12;
  76.         if (pos < (1<<25))
  77.                 return g_FastPos[pos>>15]+30;
  78.         return g_FastPos[pos>>24]+48;
  79. }
  80.  
  81. unsigned pack_length;
  82. unsigned pack_pos;
  83. const byte* curin;
  84. byte* curout;
  85.  
  86. static void NLength_CEncoder_Init(NLength_CEncoder*e, unsigned numPosStates)
  87. {
  88.         unsigned posState;
  89.         CMyBitEncoder_Init(e->_choice);
  90.         CMyBitEncoder_Init(e->_choice2);
  91.         for (posState=0;posState<numPosStates;posState++)
  92.         {
  93.                 CBitTreeEncoder_Init(&e->_lowCoder[posState],kNumLowBits);
  94.                 CBitTreeEncoder_Init(&e->_midCoder[posState],kNumMidBits);
  95.         }
  96.         CBitTreeEncoder_Init(&e->_highCoder,kNumHighBits);
  97. }
  98.  
  99. static void NLength_CEncoder_Encode(NLength_CEncoder*e, unsigned symbol, unsigned posState)
  100. {
  101.         if (symbol < kNumLowSymbols)
  102.         {
  103.                 CMyBitEncoder_Encode(&e->_choice,0);
  104.                 CBitTreeEncoder_Encode(&e->_lowCoder[posState],symbol);
  105.         }
  106.         else
  107.         {
  108.                 CMyBitEncoder_Encode(&e->_choice,1);
  109.                 if (symbol < kNumLowSymbols + kNumMidSymbols)
  110.                 {
  111.                         CMyBitEncoder_Encode(&e->_choice2,0);
  112.                         CBitTreeEncoder_Encode(&e->_midCoder[posState],symbol-kNumLowSymbols);
  113.                 }
  114.                 else
  115.                 {
  116.                         CMyBitEncoder_Encode(&e->_choice2,1);
  117.                         CBitTreeEncoder_Encode(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols);
  118.                 }
  119.         }
  120. }
  121.  
  122. static unsigned NLength_CEncoder_GetPrice(NLength_CEncoder*e, unsigned symbol, unsigned posState)
  123. {
  124.         unsigned price;
  125.         if (symbol < kNumLowSymbols)
  126.                 return CMyBitEncoder_GetPrice0(&e->_choice) +
  127.                         CBitTreeEncoder_GetPrice(&e->_lowCoder[posState],symbol);
  128.         price = CMyBitEncoder_GetPrice1(&e->_choice);
  129.         if (symbol < kNumLowSymbols + kNumMidSymbols)
  130.         {
  131.                 price += CMyBitEncoder_GetPrice0(&e->_choice2);
  132.                 price += CBitTreeEncoder_GetPrice(&e->_midCoder[posState],symbol-kNumLowSymbols);
  133.         }
  134.         else
  135.         {
  136.                 price += CMyBitEncoder_GetPrice1(&e->_choice2);
  137.                 price += CBitTreeEncoder_GetPrice(&e->_highCoder,symbol-kNumLowSymbols-kNumMidSymbols);
  138.         }
  139.         return price;
  140. }
  141.  
  142. static void CPriceTableEncoder_SetTableSize(NLength_CPriceTableEncoder*pte,unsigned tableSize)
  143. {pte->_tableSize = tableSize;}
  144. static unsigned CPriceTableEncoder_GetPrice(NLength_CPriceTableEncoder*pte,unsigned symbol,unsigned posState)
  145. {return pte->_prices[symbol][posState];}
  146. static void CPriceTableEncoder_UpdateTable(NLength_CPriceTableEncoder*pte,unsigned posState)
  147. {
  148.         unsigned len;
  149.         for (len=0;len<pte->_tableSize;len++)
  150.                 pte->_prices[len][posState] = NLength_CEncoder_GetPrice(&pte->base,len,posState);
  151.         pte->_counters[posState] = pte->_tableSize;
  152. }
  153. static void CPriceTableEncoder_UpdateTables(NLength_CPriceTableEncoder*pte,unsigned numPosStates)
  154. {
  155.         unsigned posState;
  156.         for (posState=0;posState<numPosStates;posState++)
  157.                 CPriceTableEncoder_UpdateTable(pte,posState);
  158. }
  159. static void CPriceTableEncoder_Encode(NLength_CPriceTableEncoder*pte, unsigned symbol, unsigned posState)
  160. {
  161.         NLength_CEncoder_Encode(&pte->base,symbol,posState);
  162.         if (--pte->_counters[posState] == 0)
  163.                 CPriceTableEncoder_UpdateTable(pte,posState);
  164. }
  165.  
  166. static void CBaseState_Init(void)
  167. {
  168.         unsigned i;
  169.         CState_Init(_state);
  170.         _previousByte = 0;
  171.         for (i=0;i<kNumRepDistances;i++)
  172.                 _repDistances[i] = 0;
  173. }
  174.  
  175. static void CLiteralEncoder2_Init(CLiteralEncoder2 le)
  176. {
  177.         int i;
  178.         for (i=0;i<0x300;i++)
  179.                 CMyBitEncoder_Init(le[i]);
  180. }
  181.  
  182. static void CLiteralEncoder2_Encode(CLiteralEncoder2 le, byte symbol)
  183. {
  184.         unsigned context = 1;
  185.         int i;
  186.         unsigned bit;
  187.         for (i=8;i--;)
  188.         {
  189.                 bit = (symbol >> i) & 1;
  190.                 CMyBitEncoder_Encode(&le[context],bit);
  191.                 context = (context << 1) | bit;
  192.         }
  193. }
  194.  
  195. static void CLiteralEncoder2_EncodeMatched(CLiteralEncoder2 le, byte matchByte, byte symbol)
  196. {
  197.         unsigned context = 1;
  198.         int i;
  199.         unsigned bit,matchBit;
  200.         for (i=8;i--;)
  201.         {
  202.                 bit = (symbol >> i) & 1;
  203.                 matchBit = (matchByte >> i) & 1;
  204.                 CMyBitEncoder_Encode(&le[0x100 + (matchBit<<8) + context],bit);
  205.                 context = (context << 1) | bit;
  206.                 if (matchBit != bit)
  207.                 {
  208.                         while (i--)
  209.                         {
  210.                                 bit = (symbol >> i) & 1;
  211.                                 CMyBitEncoder_Encode(&le[context],bit);
  212.                                 context = (context << 1) | bit;
  213.                         }
  214.                         break;
  215.                 }
  216.         }
  217. }
  218.  
  219. static unsigned CLiteralEncoder2_GetPrice(CLiteralEncoder2 le, bool matchMode, byte matchByte, byte symbol)
  220. {
  221.         unsigned price = 0;
  222.         unsigned context = 1;
  223.         unsigned bit,matchBit;
  224.         int i = 8;
  225.         if (matchMode)
  226.         {
  227.                 do
  228.                 {
  229.                         i--;
  230.                         matchBit = (matchByte >> i) & 1;
  231.                         bit = (symbol >> i) & 1;
  232.                         price += CMyBitEncoder_GetPrice(&le[0x100 + (matchBit<<8) + context],bit);
  233.                         context = (context << 1) | bit;
  234.                         if (matchBit != bit)
  235.                                 break;
  236.                 } while (i);
  237.         }
  238.         while (i--)
  239.         {
  240.                 bit = (symbol >> i) & 1;
  241.                 price += CMyBitEncoder_GetPrice(&le[context],bit);
  242.                 context = (context << 1) | bit;
  243.         }
  244.         return price;
  245. }
  246.  
  247. static void WriteEndMarker(unsigned posState)
  248. {
  249.         unsigned posSlot;
  250.         if (!_writeEndMark)
  251.                 return;
  252.         CMyBitEncoder_Encode(&_isMatch[_state][posState],1);
  253.         CMyBitEncoder_Encode(&_isRep[_state],0);
  254.         CState_UpdateMatch(_state);
  255.         CPriceTableEncoder_Encode(&_lenEncoder,0,posState);
  256.         posSlot = (1<<kNumPosSlotBits) - 1;
  257.         CBitTreeEncoder_Encode(&_posSlotEncoder[GetLenToPosState(kMatchMinLen)],posSlot);
  258.         RangeEncoder_EncodeDirectBits(((1<<30)-1)>>kNumAlignBits,30-kNumAlignBits);
  259.         CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,((1<<30)-1) & kAlignMask);
  260. }
  261.  
  262. static void CEncoder_Flush(void)
  263. {
  264.         WriteEndMarker((unsigned)nowPos64 & _posStateMask);
  265.         RangeEncoder_FlushData();
  266. }
  267.  
  268. static void CLiteralEncoder_Create(CLiteralEncoder*le, byte** memory, int numPosBits, int numPrevBits)
  269. {
  270.         unsigned numStates;
  271.         le->_coders = (CLiteralEncoder2*)*memory;
  272.         numStates = 1 << (numPosBits+numPrevBits);
  273.         *memory = (byte*)(le->_coders + numStates);
  274.         le->_numPosBits = numPosBits;
  275.         le->_posMask = (1<<numPosBits) - 1;
  276.         le->_numPrevBits = numPrevBits;
  277. }
  278.  
  279. static void CLiteralEncoder_Init(CLiteralEncoder*le)
  280. {
  281.         unsigned numStates,i;
  282.         numStates = 1 << (le->_numPosBits + le->_numPrevBits);
  283.         for (i=0;i<numStates;i++)
  284.                 CLiteralEncoder2_Init(le->_coders[i]);
  285. }
  286.  
  287. static unsigned CLiteralEncoder_GetState(CLiteralEncoder*le,unsigned pos,byte prevByte)
  288. {return ((pos&le->_posMask)<<le->_numPrevBits)+(prevByte>>(8-le->_numPrevBits));}
  289. static CLiteralEncoder2* CLiteralEncoder_GetSubCoder(CLiteralEncoder*le,unsigned pos,byte prevByte)
  290. {return &le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)];}
  291.  
  292. static unsigned CLiteralEncoder_GetPrice(CLiteralEncoder*le,unsigned pos,byte prevByte,
  293.         bool matchMode, byte matchByte, byte symbol)
  294. {
  295.         return CLiteralEncoder2_GetPrice(le->_coders[CLiteralEncoder_GetState(le,pos,prevByte)],
  296.                 matchMode, matchByte, symbol);
  297. }
  298.  
  299. static void CEncoder_Create(void*workmem)
  300. {
  301.         byte* workpos = (byte*)workmem;
  302.         /* align on dword boundary */
  303.         unsigned a;
  304.         a = (unsigned)workpos & 3;
  305.         if (a) workpos += 4-a;
  306.         /* sizeof(CLiteralEncoder2) * (1<<(numPosBits+numPrevBits)) for literal encoders */
  307.         /* = 0xC00 * 8 = 0x6000 with current settings */
  308.         CLiteralEncoder_Create(&_literalEncoder,&workpos,_numLiteralPosStateBits,_numLiteralContextBits);
  309.         /* (dictsize+0x1223)*1.5+256 for LZ input window */
  310.         /* (0x140400 + (dictsize+1)*2) * 4 for match finder hash */
  311.         MatchFinder_Create(_dictionarySize,kNumOpts,_numFastBytes,
  312.                 kMatchMaxLen*2+1-_numFastBytes,&workpos);
  313.         /* total 0x508C3C + dictsize*9.5 */
  314.         /* plus max 6 bytes for alignment */
  315. }
  316.  
  317. static void CEncoder_Init(void)
  318. {
  319.         int i;
  320.         unsigned j;
  321.         CBaseState_Init();
  322.         RangeEncoder_Init();
  323.         for (i=0;i<kNumStates;i++)
  324.         {
  325.                 for (j=0;j<=_posStateMask;j++)
  326.                 {
  327.                         CMyBitEncoder_Init(_isMatch[i][j]);
  328.                         CMyBitEncoder_Init(_isRep0Long[i][j]);
  329.                 }
  330.                 CMyBitEncoder_Init(_isRep[i]);
  331.                 CMyBitEncoder_Init(_isRepG0[i]);
  332.                 CMyBitEncoder_Init(_isRepG1[i]);
  333.                 CMyBitEncoder_Init(_isRepG2[i]);
  334.         }
  335.         CLiteralEncoder_Init(&_literalEncoder);
  336.         for (i=0;i<kNumLenToPosStates;i++)
  337.                 CBitTreeEncoder_Init(_posSlotEncoder+i,kNumPosSlotBits);
  338.         for (i=0;i<kNumFullDistances-kEndPosModelIndex;i++)
  339.                 CMyBitEncoder_Init(_posEncoders[i]);
  340.         CPriceTableEncoder_Init(_lenEncoder, 1<<_posStateBits);
  341.         CPriceTableEncoder_Init(_repMatchLenEncoder,1<<_posStateBits);
  342.         CBitTreeEncoder_Init(&_posAlignEncoder,kNumAlignBits);
  343.         _longestMatchWasFound = false;
  344.         _optimumEndIndex = 0;
  345.         _optimumCurrentIndex = 0;
  346.         _additionalOffset = 0;
  347. }
  348.  
  349. static void MovePos(unsigned num)
  350. {
  351.         for (;num--;)
  352.         {
  353.                 DummyLongestMatch();
  354.                 MatchFinder_MovePos();
  355.                 _additionalOffset++;
  356.         }
  357. }
  358.  
  359. static unsigned Backward(unsigned* backRes, unsigned cur)
  360. {
  361.         unsigned posMem,backMem;
  362.         unsigned posPrev,backCur;
  363.         _optimumEndIndex = cur;
  364.         posMem = _optimum[cur].PosPrev;
  365.         backMem = _optimum[cur].BackPrev;
  366.         do
  367.         {
  368.                 if (_optimum[cur].Prev1IsChar)
  369.                 {
  370.                         COptimal_MakeAsChar(&_optimum[posMem]);
  371.                         _optimum[posMem].PosPrev = posMem-1;
  372.                         if (_optimum[cur].Prev2)
  373.                         {
  374.                                 _optimum[posMem-1].Prev1IsChar = false;
  375.                                 _optimum[posMem-1].PosPrev = _optimum[cur].PosPrev2;
  376.                                 _optimum[posMem-1].BackPrev = _optimum[cur].BackPrev2;
  377.                         }
  378.                 }
  379.                 posPrev = posMem;
  380.                 backCur = backMem;
  381.                 backMem = _optimum[posPrev].BackPrev;
  382.                 posMem = _optimum[posPrev].PosPrev;
  383.                 _optimum[posPrev].BackPrev = backCur;
  384.                 _optimum[posPrev].PosPrev = cur;
  385.                 cur = posPrev;
  386.         } while (cur);
  387.         *backRes = _optimum[0].BackPrev;
  388.         _optimumCurrentIndex = _optimum[0].PosPrev;
  389.         return _optimumCurrentIndex;
  390. }
  391.  
  392. static unsigned ReadMatchDistances(void)
  393. {
  394.         unsigned res;
  395.         res = GetLongestMatch(_matchDistances);
  396.         if (res == _numFastBytes)
  397.                 res += GetMatchLen(res,_matchDistances[res],kMatchMaxLen-res);
  398.         _additionalOffset++;
  399.         MatchFinder_MovePos();
  400.         return res;
  401. }
  402.  
  403. static void FillPosSlotPrices(void)
  404. {
  405.         unsigned lenToPosState,posSlot;
  406.         for (lenToPosState=0;lenToPosState<kNumLenToPosStates;lenToPosState++)
  407.         {
  408.                 for (posSlot=0;posSlot<kEndPosModelIndex && posSlot<_distTableSize;posSlot++)
  409.                         _posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot);
  410.                 for (;posSlot<_distTableSize;posSlot++)
  411.                         _posSlotPrices[lenToPosState][posSlot] = CBitTreeEncoder_GetPrice(&_posSlotEncoder[lenToPosState],posSlot) +
  412.                                 (((posSlot>>1)-1-kNumAlignBits)<<kNumBitPriceShiftBits);
  413.         }
  414. }
  415.  
  416. static void FillDistancesPrices(void)
  417. {
  418.         unsigned lenToPosState,i;
  419.         unsigned posSlot,footerBits,base;
  420.         for (lenToPosState=0;lenToPosState<kNumLenToPosStates;lenToPosState++)
  421.         {
  422.                 for (i=0;i<kStartPosModelIndex;i++)
  423.                         _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i];
  424.                 for (;i<kNumFullDistances;i++)
  425.                 {
  426.                         posSlot = GetPosSlot(i);
  427.                         footerBits = ((posSlot>>1)-1);
  428.                         base = (2|(posSlot&1))<<footerBits;
  429.                         _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] +
  430.                                 ReverseBitTreeGetPrice(_posEncoders+base-posSlot-1,footerBits,i-base);
  431.                 }
  432.         }
  433. }
  434.  
  435. static void FillAlignPrices(void)
  436. {
  437.         unsigned i;
  438.         for (i=0;i<kAlignTableSize;i++)
  439.                 _alignPrices[i] = CBitTreeEncoder_ReverseGetPrice(&_posAlignEncoder,i);
  440.         _alignPriceCount = kAlignTableSize;
  441. }
  442.  
  443. static unsigned GetRepLen1Price(CState state, unsigned posState)
  444. {
  445.         return CMyBitEncoder_GetPrice0(&_isRepG0[state]) +
  446.                 CMyBitEncoder_GetPrice0(&_isRep0Long[state][posState]);
  447. }
  448. static unsigned GetRepPrice(unsigned repIndex, unsigned len, CState state, unsigned posState)
  449. {
  450.         unsigned price;
  451.         price = CPriceTableEncoder_GetPrice(&_repMatchLenEncoder,len-kMatchMinLen,posState);
  452.         if (!repIndex)
  453.         {
  454.                 price += CMyBitEncoder_GetPrice0(&_isRepG0[state]);
  455.                 price += CMyBitEncoder_GetPrice1(&_isRep0Long[state][posState]);
  456.         }
  457.         else
  458.         {
  459.                 price += CMyBitEncoder_GetPrice1(&_isRepG0[state]);
  460.                 if (repIndex == 1)
  461.                         price += CMyBitEncoder_GetPrice0(&_isRepG1[state]);
  462.                 else
  463.                 {
  464.                         price += CMyBitEncoder_GetPrice1(&_isRepG1[state]);
  465.                         price += CMyBitEncoder_GetPrice(&_isRepG2[state],repIndex-2);
  466.                 }
  467.         }
  468.         return price;
  469. }
  470. static unsigned GetPosLenPrice(unsigned pos, unsigned len, unsigned posState)
  471. {
  472.         unsigned price,lenToPosState;
  473.         if (len==2 && pos>=0x80)
  474.                 return kIfinityPrice;
  475.         lenToPosState = GetLenToPosState(len);
  476.         if (pos < kNumFullDistances)
  477.                 price = _distancesPrices[lenToPosState][pos];
  478.         else
  479.                 price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
  480.                         _alignPrices[pos & kAlignMask];
  481.         return price + CPriceTableEncoder_GetPrice(&_lenEncoder,len-kMatchMinLen,posState);
  482. }
  483.  
  484. static void GetOptimum(unsigned position,unsigned*backRes,unsigned*lenRes)
  485. {
  486.         int lenMain,lenEnd;
  487.         COptimal* opt,*prevOpt;
  488.         int reps[kNumRepDistances];
  489.         int repLens[kNumRepDistances];
  490.         int repIndex,repMaxIndex;
  491.         int i,len,repLen,lenTest,newLen,lenTestTemp,lenTest2;
  492.         int posState,posStateNext;
  493.         byte currentByte,matchByte;
  494.         unsigned matchPrice,repMatchPrice,shortRepPrice,normalMatchPrice,curAndLenPrice,curPrice,curAnd1Price,curAndLenCharPrice;
  495.         unsigned nextMatchPrice,nextRepMatchPrice;
  496.         int cur,posPrev,pos;
  497.         CState state,state2;
  498.         const byte* data;
  499.         bool nextIsChar;
  500.         int numAvailableBytesFull,numAvailableBytes;
  501.         int backOffset,offset;
  502.         int limit;
  503.         if (_optimumEndIndex != _optimumCurrentIndex)
  504.         {
  505.                 opt = &_optimum[_optimumCurrentIndex];
  506.                 *lenRes = opt->PosPrev - _optimumCurrentIndex;
  507.                 *backRes = opt->BackPrev;
  508.                 _optimumCurrentIndex = opt->PosPrev;
  509.                 return;
  510.         }
  511.         _optimumCurrentIndex = _optimumEndIndex = 0;
  512.         if (!_longestMatchWasFound)
  513.                 lenMain = ReadMatchDistances();
  514.         else
  515.         {
  516.                 lenMain = _longestMatchLength;
  517.                 _longestMatchWasFound = false;
  518.         }
  519.         for (i=0;i<kNumRepDistances;i++)
  520.         {
  521.                 reps[i] = _repDistances[i];
  522.                 repLens[i] = GetMatchLen(0-1,reps[i],kMatchMaxLen);
  523.                 if (i==0 || repLens[i] > repLens[repMaxIndex])
  524.                         repMaxIndex = i;
  525.         }
  526.         if (repLens[repMaxIndex] >= _numFastBytes)
  527.         {
  528.                 *backRes = repMaxIndex;
  529.                 *lenRes = repLens[repMaxIndex];
  530.                 MovePos(*lenRes-1);
  531.                 return;
  532.         }
  533.         if (lenMain >= _numFastBytes)
  534.         {
  535.                 *backRes = _matchDistances[_numFastBytes]+kNumRepDistances;
  536.                 *lenRes = lenMain;
  537.                 MovePos(lenMain-1);
  538.                 return;
  539.         }
  540.         currentByte = GetIndexByte(0-1);
  541.         _optimum[0].State = _state;
  542.         matchByte = GetIndexByte(0-_repDistances[0]-2);
  543.         posState = position & _posStateMask;
  544.         _optimum[1].Price = CMyBitEncoder_GetPrice0(&_isMatch[_state][posState]) +
  545.                 CLiteralEncoder_GetPrice(&_literalEncoder,position,_previousByte,
  546.                 (bool)!CState_IsCharState(_state),matchByte,currentByte);
  547.         COptimal_MakeAsChar(&_optimum[1]);
  548.         _optimum[1].PosPrev = 0;
  549.         for (i=0;i<kNumRepDistances;i++)
  550.                 _optimum[0].Backs[i] = reps[i];
  551.         matchPrice = CMyBitEncoder_GetPrice1(&_isMatch[_state][posState]);
  552.         repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[_state]);
  553.         if (matchByte == currentByte)
  554.         {
  555.                 shortRepPrice = repMatchPrice + GetRepLen1Price(_state,posState);
  556.                 if (shortRepPrice < _optimum[1].Price)
  557.                 {
  558.                         _optimum[1].Price = shortRepPrice;
  559.                         COptimal_MakeAsShortRep(&_optimum[1]);
  560.                 }
  561.         }
  562.         if (lenMain < 2)
  563.         {
  564.                 *backRes = _optimum[1].BackPrev;
  565.                 *lenRes = 1;
  566.                 return;
  567.         }
  568.         normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[_state]);
  569.         if (lenMain <= repLens[repMaxIndex])
  570.                 lenMain = 0;
  571.         for (len=2;len<=lenMain;len++)
  572.         {
  573.                 _optimum[len].PosPrev = 0;
  574.                 _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances;
  575.                 _optimum[len].Price = normalMatchPrice + GetPosLenPrice(_matchDistances[len],len,posState);
  576.                 _optimum[len].Prev1IsChar = false;
  577.         }
  578.         if (lenMain < repLens[repMaxIndex])
  579.                 lenMain = repLens[repMaxIndex];
  580.         for (;len<=lenMain;len++)
  581.                 _optimum[len].Price = kIfinityPrice;
  582.         for (i=0;i<kNumRepDistances;i++)
  583.         {
  584.                 repLen = repLens[i];
  585.                 for (lenTest=2;lenTest<=repLen;lenTest++)
  586.                 {
  587.                         curAndLenPrice = repMatchPrice + GetRepPrice(i,lenTest,_state,posState);
  588.                         opt = &_optimum[lenTest];
  589.                         if (curAndLenPrice < opt->Price)
  590.                         {
  591.                                 opt->Price = curAndLenPrice;
  592.                                 opt->PosPrev = 0;
  593.                                 opt->BackPrev = i;
  594.                                 opt->Prev1IsChar = false;
  595.                         }
  596.                 }
  597.         }
  598.         cur=0;
  599.         lenEnd = lenMain;
  600.         while (1)
  601.         {
  602.                 cur++;
  603.                 if (cur==lenEnd)
  604.                 {
  605.                         *lenRes = Backward(backRes,cur);
  606.                         return;
  607.                 }
  608.                 position++;
  609.                 opt = &_optimum[cur];
  610.                 posPrev = opt->PosPrev;
  611.                 if (opt->Prev1IsChar)
  612.                 {
  613.                         posPrev--;
  614.                         if (opt->Prev2)
  615.                         {
  616.                                 state = _optimum[opt->PosPrev2].State;
  617.                                 if (opt->BackPrev2 < kNumRepDistances)
  618.                                         CState_UpdateRep(state);
  619.                                 else
  620.                                         CState_UpdateMatch(state);
  621.                         }
  622.                         else
  623.                                 state = _optimum[posPrev].State;
  624.                         CState_UpdateChar(state);
  625.                 }
  626.                 else
  627.                         state = _optimum[posPrev].State;
  628.                 if (posPrev == cur-1)
  629.                 {
  630.                         if (COptimal_IsShortRep(opt))
  631.                                 CState_UpdateShortRep(state);
  632.                         else
  633.                                 CState_UpdateChar(state);
  634.                 }
  635.                 else
  636.                 {
  637.                         if (opt->Prev1IsChar && opt->Prev2)
  638.                         {
  639.                                 posPrev = opt->PosPrev2;
  640.                                 pos = opt->BackPrev2;
  641.                                 CState_UpdateRep(state);
  642.                         }
  643.                         else
  644.                         {
  645.                                 pos = opt->BackPrev;
  646.                                 if (pos < kNumRepDistances)
  647.                                         CState_UpdateRep(state);
  648.                                 else
  649.                                         CState_UpdateMatch(state);
  650.                         }
  651.                         prevOpt = &_optimum[posPrev];
  652.                         if (pos < kNumRepDistances)
  653.                         {
  654.                                 reps[0] = prevOpt->Backs[pos];
  655.                                 for (i=1;i<=pos;i++)
  656.                                         reps[i] = prevOpt->Backs[i-1];
  657.                                 for (;i<kNumRepDistances;i++)
  658.                                         reps[i] = prevOpt->Backs[i];
  659.                         }
  660.                         else
  661.                         {
  662.                                 reps[0] = pos-kNumRepDistances;
  663.                                 for (i=1;i<kNumRepDistances;i++)
  664.                                         reps[i] = prevOpt->Backs[i-1];
  665.                         }
  666.                 }
  667.                 opt->State = state;
  668.                 for (i=0;i<kNumRepDistances;i++)
  669.                         opt->Backs[i] = reps[i];
  670.                 newLen = ReadMatchDistances();
  671.                 if (newLen >= _numFastBytes)
  672.                 {
  673.                         _longestMatchLength = newLen;
  674.                         _longestMatchWasFound = true;
  675.                         *lenRes = Backward(backRes,cur);
  676.                         return;
  677.                 }
  678.                 curPrice = opt->Price;
  679.                 data = GetPointerToCurrentPos()-1;
  680.                 currentByte = *data;
  681.                 matchByte = data[-1-reps[0]];
  682.                 posState = position & _posStateMask;
  683.                 curAnd1Price = curPrice + CMyBitEncoder_GetPrice0(&_isMatch[state][posState]) +
  684.                         CLiteralEncoder_GetPrice(&_literalEncoder,position,data[-1],(bool)!CState_IsCharState(state),matchByte,currentByte);
  685.                 opt = &_optimum[cur+1];
  686.                 nextIsChar = false;
  687.                 if (curAnd1Price < opt->Price)
  688.                 {
  689.                         opt->Price = curAnd1Price;
  690.                         opt->PosPrev = cur;
  691.                         COptimal_MakeAsChar(opt);
  692.                         nextIsChar = true;
  693.                 }
  694.                 matchPrice = curPrice + CMyBitEncoder_GetPrice1(&_isMatch[state][posState]);
  695.                 repMatchPrice = matchPrice + CMyBitEncoder_GetPrice1(&_isRep[state]);
  696.                 if (matchByte == currentByte && !(opt->PosPrev<cur && !opt->BackPrev))
  697.                 {
  698.                         shortRepPrice = repMatchPrice + GetRepLen1Price(state,posState);
  699.                         if (shortRepPrice <= opt->Price)
  700.                         {
  701.                                 opt->Price = shortRepPrice;
  702.                                 opt->PosPrev = cur;
  703.                                 COptimal_MakeAsShortRep(opt);
  704.                         }
  705.                 }
  706.                 numAvailableBytesFull = GetNumAvailableBytes()+1;
  707.                 if (numAvailableBytesFull > kNumOpts-1-cur)
  708.                         numAvailableBytesFull = kNumOpts-1-cur;
  709.                 numAvailableBytes = numAvailableBytesFull;
  710.                 if (numAvailableBytes < 2)
  711.                         continue;
  712.                 if (numAvailableBytes > _numFastBytes)
  713.                         numAvailableBytes = _numFastBytes;
  714.                 if (numAvailableBytes >= 3 && !nextIsChar)
  715.                 {
  716.                         // try Literal + rep0
  717.                         int temp;
  718.                         backOffset = reps[0]+1;
  719.                         for (temp=1;temp<numAvailableBytes;temp++)
  720.                                 if (data[temp]!=data[temp-backOffset])
  721.                                         break;
  722.                         lenTest = temp-1;
  723.                         if (lenTest>=2)
  724.                         {
  725.                                 int posStateNext;
  726.                                 unsigned nextRepMatchPrice;
  727.                                 state2 = state;
  728.                                 CState_UpdateChar(state2);
  729.                                 posStateNext = (position+1) & _posStateMask;
  730.                                 nextRepMatchPrice = curAnd1Price +
  731.                                         CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]) +
  732.                                         CMyBitEncoder_GetPrice1(&_isRep[state2]);
  733.                                 while (lenEnd < cur+1+lenTest)
  734.                                         _optimum[++lenEnd].Price = kIfinityPrice;
  735.                                 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest,state2,posStateNext);
  736.                                 opt = &_optimum[cur+1+lenTest];
  737.                                 if (curAndLenPrice < opt->Price)
  738.                                 {
  739.                                         opt->Price = curAndLenPrice;
  740.                                         opt->PosPrev = cur+1;
  741.                                         opt->BackPrev = 0;
  742.                                         opt->Prev1IsChar = true;
  743.                                         opt->Prev2 = false;
  744.                                 }
  745.                         }
  746.                 }
  747.                 for (repIndex=0;repIndex<kNumRepDistances;repIndex++)
  748.                 {
  749.                         backOffset = reps[repIndex]+1;
  750.                         if (data[0] != data[0-backOffset] ||
  751.                                 data[1] != data[1-backOffset])
  752.                                 continue;
  753.                         for (lenTest=2;lenTest<numAvailableBytes;lenTest++)
  754.                                 if (data[lenTest]!=data[lenTest-backOffset])
  755.                                         break;
  756.                         lenTestTemp = lenTest;
  757.                         do
  758.                         {
  759.                                 while (lenEnd < cur+lenTest)
  760.                                         _optimum[++lenEnd].Price = kIfinityPrice;
  761.                                 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState);
  762.                                 opt = &_optimum[cur+lenTest];
  763.                                 if (curAndLenPrice < opt->Price)
  764.                                 {
  765.                                         opt->Price = curAndLenPrice;
  766.                                         opt->PosPrev = cur;
  767.                                         opt->BackPrev = repIndex;
  768.                                         opt->Prev1IsChar = false;
  769.                                 }
  770.                         } while (--lenTest>=2);
  771.                         lenTest = lenTestTemp;
  772.                         lenTest2 = lenTest+1;
  773.                         limit = lenTest2 + _numFastBytes;
  774.                         if (limit > numAvailableBytesFull)
  775.                                 limit = numAvailableBytesFull;
  776.                         for (;lenTest2<limit;lenTest2++)
  777.                                 if (data[lenTest2] != data[lenTest2-backOffset])
  778.                                         break;
  779.                         lenTest2 -= lenTest+1;
  780.                         if (lenTest2 >= 2)
  781.                         {
  782.                                 unsigned nextMatchPrice,nextRepMatchPrice;
  783.                                 int offset;
  784.                                 state2 = state;
  785.                                 CState_UpdateRep(state2);
  786.                                 posStateNext = (position+lenTest)&_posStateMask;
  787.                                 curAndLenCharPrice = repMatchPrice + GetRepPrice(repIndex,lenTest,state,posState) +
  788.                                         CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) +
  789.                                         CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]);
  790.                                 CState_UpdateChar(state2);
  791.                                 posStateNext = (position+lenTest+1)&_posStateMask;
  792.                                 nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]);
  793.                                 nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]);
  794.                                 offset = lenTest+1+lenTest2;
  795.                                 while (lenEnd<cur+offset)
  796.                                         _optimum[++lenEnd].Price = kIfinityPrice;
  797.                                 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext);
  798.                                 opt = &_optimum[cur+offset];
  799.                                 if (curAndLenPrice < opt->Price)
  800.                                 {
  801.                                         opt->Price = curAndLenPrice;
  802.                                         opt->PosPrev = cur+lenTest+1;
  803.                                         opt->BackPrev = 0;
  804.                                         opt->Prev1IsChar = true;
  805.                                         opt->Prev2 = true;
  806.                                         opt->PosPrev2 = cur;
  807.                                         opt->BackPrev2 = repIndex;
  808.                                 }
  809.                         }
  810.                 }
  811.                 if (newLen > numAvailableBytes)
  812.                         newLen = numAvailableBytes;
  813.                 if (newLen >= 2)
  814.                 {
  815.                         if (newLen==2 && _matchDistances[2] >= 0x80)
  816.                                 continue;
  817.                         normalMatchPrice = matchPrice + CMyBitEncoder_GetPrice0(&_isRep[state]);
  818.                         while (lenEnd < cur+newLen)
  819.                                 _optimum[++lenEnd].Price = kIfinityPrice;
  820.                         for (lenTest=newLen;lenTest>=2;lenTest--)
  821.                         {
  822.                                 backOffset = _matchDistances[lenTest];
  823.                                 curAndLenPrice = normalMatchPrice + GetPosLenPrice(backOffset,lenTest,posState);
  824.                                 opt = &_optimum[cur+lenTest];
  825.                                 if (curAndLenPrice < opt->Price)
  826.                                 {
  827.                                         opt->Price = curAndLenPrice;
  828.                                         opt->PosPrev = cur;
  829.                                         opt->BackPrev = backOffset+kNumRepDistances;
  830.                                         opt->Prev1IsChar = false;
  831.                                 }
  832.                                 if (lenTest==newLen || backOffset!=_matchDistances[lenTest+1])
  833.                                 {
  834.                                         // Try Match + Literal + Rep0
  835.                                         backOffset++;
  836.                                         lenTest2 = lenTest+1;
  837.                                         limit = lenTest2+_numFastBytes;
  838.                                         if (limit > numAvailableBytesFull)
  839.                                                 limit = numAvailableBytesFull;
  840.                                         for (;lenTest2<limit;lenTest2++)
  841.                                                 if (data[lenTest2]!=data[lenTest2-backOffset])
  842.                                                         break;
  843.                                         lenTest2 -= lenTest+1;
  844.                                         if (lenTest2 >= 2)
  845.                                         {
  846.                                                 state2 = state;
  847.                                                 CState_UpdateMatch(state2);
  848.                                                 posStateNext = (position+lenTest)&_posStateMask;
  849.                                                 curAndLenCharPrice = curAndLenPrice + CMyBitEncoder_GetPrice0(&_isMatch[state2][posStateNext]) +
  850.                                                         CLiteralEncoder_GetPrice(&_literalEncoder,position+lenTest,data[lenTest-1],true,data[lenTest-backOffset],data[lenTest]);
  851.                                                 CState_UpdateChar(state2);
  852.                                                 posStateNext = (position+lenTest+1)&_posStateMask;
  853.                                                 nextMatchPrice = curAndLenCharPrice + CMyBitEncoder_GetPrice1(&_isMatch[state2][posStateNext]);
  854.                                                 nextRepMatchPrice = nextMatchPrice + CMyBitEncoder_GetPrice1(&_isRep[state2]);
  855.                                                 offset = lenTest+1+lenTest2;
  856.                                                 while (lenEnd<cur+offset)
  857.                                                         _optimum[++lenEnd].Price = kIfinityPrice;
  858.                                                 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0,lenTest2,state2,posStateNext);
  859.                                                 opt = &_optimum[cur+offset];
  860.                                                 if (curAndLenPrice < opt->Price)
  861.                                                 {
  862.                                                         opt->Price = curAndLenPrice;
  863.                                                         opt->PosPrev = cur+lenTest+1;
  864.                                                         opt->BackPrev = 0;
  865.                                                         opt->Prev1IsChar = true;
  866.                                                         opt->Prev2 = true;
  867.                                                         opt->PosPrev2 = cur;
  868.                                                         opt->BackPrev2 = backOffset - 1 + kNumRepDistances;
  869.                                                 }
  870.                                         }
  871.                                 }
  872.                         }
  873.                 }
  874.         }
  875. }
  876.  
  877. static bool CodeOneBlock(void)
  878. {
  879.         unsigned posState;
  880.         byte curByte,matchByte;
  881.         unsigned pos,len,distance,i;
  882.         unsigned posSlot,lenToPosState;
  883.         CLiteralEncoder2* subCoder;
  884.         uint64 progressPosValuePrev;
  885.  
  886.         if (_finished)
  887.                 return false;
  888.         _finished = true;
  889.         progressPosValuePrev = nowPos64;
  890.         if (nowPos64 == 0)
  891.         {
  892.                 if (GetNumAvailableBytes() == 0)
  893.                 {
  894.                         CEncoder_Flush();
  895.                         return false;
  896.                 }
  897.                 ReadMatchDistances();
  898.                 posState = (unsigned)nowPos64 & _posStateMask;
  899.                 CMyBitEncoder_Encode(&_isMatch[_state][posState],0);
  900.                 CState_UpdateChar(_state);
  901.                 curByte = GetIndexByte(0 - _additionalOffset);
  902.                 CLiteralEncoder2_Encode(
  903.                         *CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64,_previousByte),
  904.                         curByte);
  905.                 _previousByte = curByte;
  906.                 _additionalOffset--;
  907.                 nowPos64++;
  908.         }
  909.         if (GetNumAvailableBytes() == 0)
  910.         {
  911.                 CEncoder_Flush();
  912.                 return false;
  913.         }
  914.         for (;;)
  915.         {
  916.                 posState = (unsigned)nowPos64 & _posStateMask;
  917.                 GetOptimum((unsigned)nowPos64,&pos,&len);
  918.                 if (len==1 && pos==0xFFFFFFFF)
  919.                 {
  920.                         CMyBitEncoder_Encode(&_isMatch[_state][posState],0);
  921.                         curByte = GetIndexByte(0-_additionalOffset);
  922.                         subCoder = CLiteralEncoder_GetSubCoder(&_literalEncoder,(unsigned)nowPos64,
  923.                                 _previousByte);
  924.                         if (!CState_IsCharState(_state))
  925.                         {
  926.                                 matchByte = GetIndexByte(0-_repDistances[0]-1-_additionalOffset);
  927.                                 CLiteralEncoder2_EncodeMatched(*subCoder,matchByte,curByte);
  928.                         }
  929.                         else
  930.                                 CLiteralEncoder2_Encode(*subCoder,curByte);
  931.                         CState_UpdateChar(_state);
  932.                         _previousByte = curByte;
  933.                 }
  934.                 else
  935.                 {
  936.                         CMyBitEncoder_Encode(&_isMatch[_state][posState],1);
  937.                         if (pos < kNumRepDistances)
  938.                         {
  939.                                 CMyBitEncoder_Encode(&_isRep[_state],1);
  940.                                 if (pos==0)
  941.                                 {
  942.                                         CMyBitEncoder_Encode(&_isRepG0[_state],0);
  943.                                         CMyBitEncoder_Encode(&_isRep0Long[_state][posState],
  944.                                                 (len==1) ? 0 : 1);
  945.                                 }
  946.                                 else
  947.                                 {
  948.                                         CMyBitEncoder_Encode(&_isRepG0[_state],1);
  949.                                         if (pos==1)
  950.                                                 CMyBitEncoder_Encode(&_isRepG1[_state],0);
  951.                                         else
  952.                                         {
  953.                                                 CMyBitEncoder_Encode(&_isRepG1[_state],1);
  954.                                                 CMyBitEncoder_Encode(&_isRepG2[_state],pos-2);
  955.                                         }
  956.                                 }
  957.                                 if (len==1)
  958.                                         CState_UpdateShortRep(_state);
  959.                                 else
  960.                                 {
  961.                                         CPriceTableEncoder_Encode(&_repMatchLenEncoder,len-kMatchMinLen,posState);
  962.                                         CState_UpdateRep(_state);
  963.                                 }
  964.                                 distance = _repDistances[pos];
  965.                                 if (pos)
  966.                                 {
  967.                                         for (i=pos;i;i--)
  968.                                                 _repDistances[i] = _repDistances[i-1];
  969.                                         _repDistances[0] = distance;
  970.                                 }
  971.                         }
  972.                         else
  973.                         {
  974.                                 CMyBitEncoder_Encode(&_isRep[_state],0);
  975.                                 CState_UpdateMatch(_state);
  976.                                 CPriceTableEncoder_Encode(&_lenEncoder,len-kMatchMinLen,posState);
  977.                                 pos -= kNumRepDistances;
  978.                                 posSlot = GetPosSlot(pos);
  979.                                 lenToPosState = GetLenToPosState(len);
  980.                                 CBitTreeEncoder_Encode(&_posSlotEncoder[lenToPosState],posSlot);
  981.                                 if (posSlot >= kStartPosModelIndex)
  982.                                 {
  983.                                         unsigned footerBits;
  984.                                         unsigned base,posReduced;
  985.                                         footerBits = (posSlot>>1)-1;
  986.                                         base = (2 | (posSlot&1)) << footerBits;
  987.                                         posReduced = pos-base;
  988.                                         if (posSlot < kEndPosModelIndex)
  989.                                                 ReverseBitTreeEncode(_posEncoders+base-posSlot-1,
  990.                                                         footerBits,posReduced);
  991.                                         else
  992.                                         {
  993.                                                 RangeEncoder_EncodeDirectBits(posReduced>>kNumAlignBits,footerBits-kNumAlignBits);
  994.                                                 CBitTreeEncoder_ReverseEncode(&_posAlignEncoder,posReduced&kAlignMask);
  995.                                                 if (--_alignPriceCount == 0)
  996.                                                         FillAlignPrices();
  997.                                         }
  998.                                 }
  999.                                 distance = pos;
  1000.                                 for (i=kNumRepDistances-1;i;i--)
  1001.                                         _repDistances[i] = _repDistances[i-1];
  1002.                                 _repDistances[0] = distance;
  1003.                         }
  1004.                         _previousByte = GetIndexByte(len-1-_additionalOffset);
  1005.                 }
  1006.                 _additionalOffset -= len;
  1007.                 nowPos64 += len;
  1008.                 if (nowPos64 - lastPosSlotFillingPos >= (1<<9))
  1009.                 {
  1010.                         FillPosSlotPrices();
  1011.                         FillDistancesPrices();
  1012.                         lastPosSlotFillingPos = nowPos64;
  1013.                 }
  1014.                 if (!_additionalOffset)
  1015.                 {
  1016.                         if (GetNumAvailableBytes() == 0)
  1017.                         {
  1018.                                 CEncoder_Flush();
  1019.                                 return false;
  1020.                         }
  1021.                         if (nowPos64 - progressPosValuePrev >= (1<<12))
  1022.                         {
  1023.                                 _finished = false;
  1024.                                 return true;
  1025.                         }
  1026.                 }
  1027.         }
  1028. }
  1029.  
  1030. extern void __stdcall lzma_set_dict_size(
  1031.         unsigned logdictsize)
  1032. {
  1033.         _dictionarySize = 1 << logdictsize;
  1034.         _distTableSize = logdictsize*2;
  1035. }
  1036.  
  1037. extern unsigned __stdcall lzma_compress(
  1038.         const void* source,
  1039.         void* destination,
  1040.         unsigned length,
  1041.         void* workmem)
  1042. {
  1043.         FastPosInit();
  1044.         //memset(&encoder,0,sizeof(encoder));
  1045.         //memset(&rangeEncoder,0,sizeof(rangeEncoder));
  1046.         // CEncoder::CEncoder, CEncoder::SetCoderProperties
  1047.         _numFastBytes = 128;
  1048. #ifdef FOR_KERPACK
  1049.         _posStateBits = 0;
  1050.         _posStateMask = 0;
  1051. #else
  1052.         _posStateBits = 2;
  1053.         _posStateMask = 3;
  1054. #endif
  1055.         _numLiteralContextBits = 3;
  1056.         _numLiteralPosStateBits = 0;
  1057.         _writeEndMark = false;
  1058.         // CEncoder::Code - яюхїрыш!
  1059.         _finished = false;
  1060.         CEncoder_Create(workmem);
  1061.         CEncoder_Init();
  1062.         FillPosSlotPrices();
  1063.         FillDistancesPrices();
  1064.         FillAlignPrices();
  1065.         CPriceTableEncoder_SetTableSize(&_lenEncoder,_numFastBytes+1-kMatchMinLen);
  1066.         CPriceTableEncoder_UpdateTables(&_lenEncoder,1<<_posStateBits);
  1067.         CPriceTableEncoder_SetTableSize(&_repMatchLenEncoder,_numFastBytes+1-kMatchMinLen);
  1068.         CPriceTableEncoder_UpdateTables(&_repMatchLenEncoder,1<<_posStateBits);
  1069.         lastPosSlotFillingPos = 0;
  1070.         nowPos64 = 0;
  1071.         pack_length = length;
  1072.         pack_pos = 0;
  1073.         curin = (const byte*)source;
  1074.         curout = (byte*)destination;
  1075.         MatchFinder_Init();
  1076.         while (CodeOneBlock()) ;
  1077.         return curout - (byte*)destination;
  1078. }
  1079.