Home | History | Annotate | Download | only in C
      1 /* LzmaEnc.c -- LZMA Encoder
      2 2014-12-29 : Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 #include <string.h>
      7 
      8 /* #define SHOW_STAT */
      9 /* #define SHOW_STAT2 */
     10 
     11 #if defined(SHOW_STAT) || defined(SHOW_STAT2)
     12 #include <stdio.h>
     13 #endif
     14 
     15 #include "LzmaEnc.h"
     16 
     17 #include "LzFind.h"
     18 #ifndef _7ZIP_ST
     19 #include "LzFindMt.h"
     20 #endif
     21 
     22 #ifdef SHOW_STAT
     23 static unsigned g_STAT_OFFSET = 0;
     24 #endif
     25 
     26 #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
     27 
     28 #define kBlockSize (9 << 10)
     29 #define kUnpackBlockSize (1 << 18)
     30 #define kMatchArraySize (1 << 21)
     31 #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
     32 
     33 #define kNumMaxDirectBits (31)
     34 
     35 #define kNumTopBits 24
     36 #define kTopValue ((UInt32)1 << kNumTopBits)
     37 
     38 #define kNumBitModelTotalBits 11
     39 #define kBitModelTotal (1 << kNumBitModelTotalBits)
     40 #define kNumMoveBits 5
     41 #define kProbInitValue (kBitModelTotal >> 1)
     42 
     43 #define kNumMoveReducingBits 4
     44 #define kNumBitPriceShiftBits 4
     45 #define kBitPrice (1 << kNumBitPriceShiftBits)
     46 
     47 void LzmaEncProps_Init(CLzmaEncProps *p)
     48 {
     49   p->level = 5;
     50   p->dictSize = p->mc = 0;
     51   p->reduceSize = (UInt64)(Int64)-1;
     52   p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
     53   p->writeEndMark = 0;
     54 }
     55 
     56 void LzmaEncProps_Normalize(CLzmaEncProps *p)
     57 {
     58   int level = p->level;
     59   if (level < 0) level = 5;
     60   p->level = level;
     61   if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
     62   if (p->dictSize > p->reduceSize)
     63   {
     64     unsigned i;
     65     for (i = 11; i <= 30; i++)
     66     {
     67       if ((UInt32)p->reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
     68       if ((UInt32)p->reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
     69     }
     70   }
     71   if (p->lc < 0) p->lc = 3;
     72   if (p->lp < 0) p->lp = 0;
     73   if (p->pb < 0) p->pb = 2;
     74   if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
     75   if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
     76   if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
     77   if (p->numHashBytes < 0) p->numHashBytes = 4;
     78   if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
     79   if (p->numThreads < 0)
     80     p->numThreads =
     81       #ifndef _7ZIP_ST
     82       ((p->btMode && p->algo) ? 2 : 1);
     83       #else
     84       1;
     85       #endif
     86 }
     87 
     88 UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
     89 {
     90   CLzmaEncProps props = *props2;
     91   LzmaEncProps_Normalize(&props);
     92   return props.dictSize;
     93 }
     94 
     95 /* #define LZMA_LOG_BSR */
     96 /* Define it for Intel's CPU */
     97 
     98 
     99 #ifdef LZMA_LOG_BSR
    100 
    101 #define kDicLogSizeMaxCompress 30
    102 
    103 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
    104 
    105 UInt32 GetPosSlot1(UInt32 pos)
    106 {
    107   UInt32 res;
    108   BSR2_RET(pos, res);
    109   return res;
    110 }
    111 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
    112 #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
    113 
    114 #else
    115 
    116 #define kNumLogBits (9 + (int)sizeof(size_t) / 2)
    117 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
    118 
    119 void LzmaEnc_FastPosInit(Byte *g_FastPos)
    120 {
    121   int c = 2, slotFast;
    122   g_FastPos[0] = 0;
    123   g_FastPos[1] = 1;
    124 
    125   for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
    126   {
    127     UInt32 k = (1 << ((slotFast >> 1) - 1));
    128     UInt32 j;
    129     for (j = 0; j < k; j++, c++)
    130       g_FastPos[c] = (Byte)slotFast;
    131   }
    132 }
    133 
    134 #define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
    135   (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
    136   res = p->g_FastPos[pos >> i] + (i * 2); }
    137 /*
    138 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
    139   p->g_FastPos[pos >> 6] + 12 : \
    140   p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
    141 */
    142 
    143 #define GetPosSlot1(pos) p->g_FastPos[pos]
    144 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
    145 #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
    146 
    147 #endif
    148 
    149 
    150 #define LZMA_NUM_REPS 4
    151 
    152 typedef unsigned CState;
    153 
    154 typedef struct
    155 {
    156   UInt32 price;
    157 
    158   CState state;
    159   int prev1IsChar;
    160   int prev2;
    161 
    162   UInt32 posPrev2;
    163   UInt32 backPrev2;
    164 
    165   UInt32 posPrev;
    166   UInt32 backPrev;
    167   UInt32 backs[LZMA_NUM_REPS];
    168 } COptimal;
    169 
    170 #define kNumOpts (1 << 12)
    171 
    172 #define kNumLenToPosStates 4
    173 #define kNumPosSlotBits 6
    174 #define kDicLogSizeMin 0
    175 #define kDicLogSizeMax 32
    176 #define kDistTableSizeMax (kDicLogSizeMax * 2)
    177 
    178 
    179 #define kNumAlignBits 4
    180 #define kAlignTableSize (1 << kNumAlignBits)
    181 #define kAlignMask (kAlignTableSize - 1)
    182 
    183 #define kStartPosModelIndex 4
    184 #define kEndPosModelIndex 14
    185 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
    186 
    187 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
    188 
    189 #ifdef _LZMA_PROB32
    190 #define CLzmaProb UInt32
    191 #else
    192 #define CLzmaProb UInt16
    193 #endif
    194 
    195 #define LZMA_PB_MAX 4
    196 #define LZMA_LC_MAX 8
    197 #define LZMA_LP_MAX 4
    198 
    199 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
    200 
    201 
    202 #define kLenNumLowBits 3
    203 #define kLenNumLowSymbols (1 << kLenNumLowBits)
    204 #define kLenNumMidBits 3
    205 #define kLenNumMidSymbols (1 << kLenNumMidBits)
    206 #define kLenNumHighBits 8
    207 #define kLenNumHighSymbols (1 << kLenNumHighBits)
    208 
    209 #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
    210 
    211 #define LZMA_MATCH_LEN_MIN 2
    212 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
    213 
    214 #define kNumStates 12
    215 
    216 typedef struct
    217 {
    218   CLzmaProb choice;
    219   CLzmaProb choice2;
    220   CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
    221   CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
    222   CLzmaProb high[kLenNumHighSymbols];
    223 } CLenEnc;
    224 
    225 typedef struct
    226 {
    227   CLenEnc p;
    228   UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
    229   UInt32 tableSize;
    230   UInt32 counters[LZMA_NUM_PB_STATES_MAX];
    231 } CLenPriceEnc;
    232 
    233 typedef struct
    234 {
    235   UInt32 range;
    236   Byte cache;
    237   UInt64 low;
    238   UInt64 cacheSize;
    239   Byte *buf;
    240   Byte *bufLim;
    241   Byte *bufBase;
    242   ISeqOutStream *outStream;
    243   UInt64 processed;
    244   SRes res;
    245 } CRangeEnc;
    246 
    247 typedef struct
    248 {
    249   CLzmaProb *litProbs;
    250 
    251   CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
    252   CLzmaProb isRep[kNumStates];
    253   CLzmaProb isRepG0[kNumStates];
    254   CLzmaProb isRepG1[kNumStates];
    255   CLzmaProb isRepG2[kNumStates];
    256   CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
    257 
    258   CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
    259   CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
    260   CLzmaProb posAlignEncoder[1 << kNumAlignBits];
    261 
    262   CLenPriceEnc lenEnc;
    263   CLenPriceEnc repLenEnc;
    264 
    265   UInt32 reps[LZMA_NUM_REPS];
    266   UInt32 state;
    267 } CSaveState;
    268 
    269 typedef struct
    270 {
    271   IMatchFinder matchFinder;
    272   void *matchFinderObj;
    273 
    274   #ifndef _7ZIP_ST
    275   Bool mtMode;
    276   CMatchFinderMt matchFinderMt;
    277   #endif
    278 
    279   CMatchFinder matchFinderBase;
    280 
    281   #ifndef _7ZIP_ST
    282   Byte pad[128];
    283   #endif
    284 
    285   UInt32 optimumEndIndex;
    286   UInt32 optimumCurrentIndex;
    287 
    288   UInt32 longestMatchLength;
    289   UInt32 numPairs;
    290   UInt32 numAvail;
    291   COptimal opt[kNumOpts];
    292 
    293   #ifndef LZMA_LOG_BSR
    294   Byte g_FastPos[1 << kNumLogBits];
    295   #endif
    296 
    297   UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
    298   UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
    299   UInt32 numFastBytes;
    300   UInt32 additionalOffset;
    301   UInt32 reps[LZMA_NUM_REPS];
    302   UInt32 state;
    303 
    304   UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
    305   UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
    306   UInt32 alignPrices[kAlignTableSize];
    307   UInt32 alignPriceCount;
    308 
    309   UInt32 distTableSize;
    310 
    311   unsigned lc, lp, pb;
    312   unsigned lpMask, pbMask;
    313 
    314   CLzmaProb *litProbs;
    315 
    316   CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
    317   CLzmaProb isRep[kNumStates];
    318   CLzmaProb isRepG0[kNumStates];
    319   CLzmaProb isRepG1[kNumStates];
    320   CLzmaProb isRepG2[kNumStates];
    321   CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
    322 
    323   CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
    324   CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
    325   CLzmaProb posAlignEncoder[1 << kNumAlignBits];
    326 
    327   CLenPriceEnc lenEnc;
    328   CLenPriceEnc repLenEnc;
    329 
    330   unsigned lclp;
    331 
    332   Bool fastMode;
    333 
    334   CRangeEnc rc;
    335 
    336   Bool writeEndMark;
    337   UInt64 nowPos64;
    338   UInt32 matchPriceCount;
    339   Bool finished;
    340   Bool multiThread;
    341 
    342   SRes result;
    343   UInt32 dictSize;
    344 
    345   int needInit;
    346 
    347   CSaveState saveState;
    348 } CLzmaEnc;
    349 
    350 void LzmaEnc_SaveState(CLzmaEncHandle pp)
    351 {
    352   CLzmaEnc *p = (CLzmaEnc *)pp;
    353   CSaveState *dest = &p->saveState;
    354   int i;
    355   dest->lenEnc = p->lenEnc;
    356   dest->repLenEnc = p->repLenEnc;
    357   dest->state = p->state;
    358 
    359   for (i = 0; i < kNumStates; i++)
    360   {
    361     memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
    362     memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
    363   }
    364   for (i = 0; i < kNumLenToPosStates; i++)
    365     memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
    366   memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
    367   memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
    368   memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
    369   memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
    370   memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
    371   memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
    372   memcpy(dest->reps, p->reps, sizeof(p->reps));
    373   memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
    374 }
    375 
    376 void LzmaEnc_RestoreState(CLzmaEncHandle pp)
    377 {
    378   CLzmaEnc *dest = (CLzmaEnc *)pp;
    379   const CSaveState *p = &dest->saveState;
    380   int i;
    381   dest->lenEnc = p->lenEnc;
    382   dest->repLenEnc = p->repLenEnc;
    383   dest->state = p->state;
    384 
    385   for (i = 0; i < kNumStates; i++)
    386   {
    387     memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
    388     memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
    389   }
    390   for (i = 0; i < kNumLenToPosStates; i++)
    391     memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
    392   memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
    393   memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
    394   memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
    395   memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
    396   memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
    397   memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
    398   memcpy(dest->reps, p->reps, sizeof(p->reps));
    399   memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
    400 }
    401 
    402 SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
    403 {
    404   CLzmaEnc *p = (CLzmaEnc *)pp;
    405   CLzmaEncProps props = *props2;
    406   LzmaEncProps_Normalize(&props);
    407 
    408   if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
    409       props.dictSize > ((UInt32)1 << kDicLogSizeMaxCompress) || props.dictSize > ((UInt32)1 << 30))
    410     return SZ_ERROR_PARAM;
    411   p->dictSize = props.dictSize;
    412   {
    413     unsigned fb = props.fb;
    414     if (fb < 5)
    415       fb = 5;
    416     if (fb > LZMA_MATCH_LEN_MAX)
    417       fb = LZMA_MATCH_LEN_MAX;
    418     p->numFastBytes = fb;
    419   }
    420   p->lc = props.lc;
    421   p->lp = props.lp;
    422   p->pb = props.pb;
    423   p->fastMode = (props.algo == 0);
    424   p->matchFinderBase.btMode = props.btMode;
    425   {
    426     UInt32 numHashBytes = 4;
    427     if (props.btMode)
    428     {
    429       if (props.numHashBytes < 2)
    430         numHashBytes = 2;
    431       else if (props.numHashBytes < 4)
    432         numHashBytes = props.numHashBytes;
    433     }
    434     p->matchFinderBase.numHashBytes = numHashBytes;
    435   }
    436 
    437   p->matchFinderBase.cutValue = props.mc;
    438 
    439   p->writeEndMark = props.writeEndMark;
    440 
    441   #ifndef _7ZIP_ST
    442   /*
    443   if (newMultiThread != _multiThread)
    444   {
    445     ReleaseMatchFinder();
    446     _multiThread = newMultiThread;
    447   }
    448   */
    449   p->multiThread = (props.numThreads > 1);
    450   #endif
    451 
    452   return SZ_OK;
    453 }
    454 
    455 static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
    456 static const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
    457 static const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
    458 static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
    459 
    460 #define IsCharState(s) ((s) < 7)
    461 
    462 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
    463 
    464 #define kInfinityPrice (1 << 30)
    465 
    466 static void RangeEnc_Construct(CRangeEnc *p)
    467 {
    468   p->outStream = 0;
    469   p->bufBase = 0;
    470 }
    471 
    472 #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
    473 
    474 #define RC_BUF_SIZE (1 << 16)
    475 static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
    476 {
    477   if (p->bufBase == 0)
    478   {
    479     p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
    480     if (p->bufBase == 0)
    481       return 0;
    482     p->bufLim = p->bufBase + RC_BUF_SIZE;
    483   }
    484   return 1;
    485 }
    486 
    487 static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
    488 {
    489   alloc->Free(alloc, p->bufBase);
    490   p->bufBase = 0;
    491 }
    492 
    493 static void RangeEnc_Init(CRangeEnc *p)
    494 {
    495   /* Stream.Init(); */
    496   p->low = 0;
    497   p->range = 0xFFFFFFFF;
    498   p->cacheSize = 1;
    499   p->cache = 0;
    500 
    501   p->buf = p->bufBase;
    502 
    503   p->processed = 0;
    504   p->res = SZ_OK;
    505 }
    506 
    507 static void RangeEnc_FlushStream(CRangeEnc *p)
    508 {
    509   size_t num;
    510   if (p->res != SZ_OK)
    511     return;
    512   num = p->buf - p->bufBase;
    513   if (num != p->outStream->Write(p->outStream, p->bufBase, num))
    514     p->res = SZ_ERROR_WRITE;
    515   p->processed += num;
    516   p->buf = p->bufBase;
    517 }
    518 
    519 static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
    520 {
    521   if ((UInt32)p->low < (UInt32)0xFF000000 || (unsigned)(p->low >> 32) != 0)
    522   {
    523     Byte temp = p->cache;
    524     do
    525     {
    526       Byte *buf = p->buf;
    527       *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
    528       p->buf = buf;
    529       if (buf == p->bufLim)
    530         RangeEnc_FlushStream(p);
    531       temp = 0xFF;
    532     }
    533     while (--p->cacheSize != 0);
    534     p->cache = (Byte)((UInt32)p->low >> 24);
    535   }
    536   p->cacheSize++;
    537   p->low = (UInt32)p->low << 8;
    538 }
    539 
    540 static void RangeEnc_FlushData(CRangeEnc *p)
    541 {
    542   int i;
    543   for (i = 0; i < 5; i++)
    544     RangeEnc_ShiftLow(p);
    545 }
    546 
    547 static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, unsigned numBits)
    548 {
    549   do
    550   {
    551     p->range >>= 1;
    552     p->low += p->range & (0 - ((value >> --numBits) & 1));
    553     if (p->range < kTopValue)
    554     {
    555       p->range <<= 8;
    556       RangeEnc_ShiftLow(p);
    557     }
    558   }
    559   while (numBits != 0);
    560 }
    561 
    562 static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
    563 {
    564   UInt32 ttt = *prob;
    565   UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
    566   if (symbol == 0)
    567   {
    568     p->range = newBound;
    569     ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
    570   }
    571   else
    572   {
    573     p->low += newBound;
    574     p->range -= newBound;
    575     ttt -= ttt >> kNumMoveBits;
    576   }
    577   *prob = (CLzmaProb)ttt;
    578   if (p->range < kTopValue)
    579   {
    580     p->range <<= 8;
    581     RangeEnc_ShiftLow(p);
    582   }
    583 }
    584 
    585 static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
    586 {
    587   symbol |= 0x100;
    588   do
    589   {
    590     RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
    591     symbol <<= 1;
    592   }
    593   while (symbol < 0x10000);
    594 }
    595 
    596 static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
    597 {
    598   UInt32 offs = 0x100;
    599   symbol |= 0x100;
    600   do
    601   {
    602     matchByte <<= 1;
    603     RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
    604     symbol <<= 1;
    605     offs &= ~(matchByte ^ symbol);
    606   }
    607   while (symbol < 0x10000);
    608 }
    609 
    610 void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
    611 {
    612   UInt32 i;
    613   for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
    614   {
    615     const int kCyclesBits = kNumBitPriceShiftBits;
    616     UInt32 w = i;
    617     UInt32 bitCount = 0;
    618     int j;
    619     for (j = 0; j < kCyclesBits; j++)
    620     {
    621       w = w * w;
    622       bitCount <<= 1;
    623       while (w >= ((UInt32)1 << 16))
    624       {
    625         w >>= 1;
    626         bitCount++;
    627       }
    628     }
    629     ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
    630   }
    631 }
    632 
    633 
    634 #define GET_PRICE(prob, symbol) \
    635   p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
    636 
    637 #define GET_PRICEa(prob, symbol) \
    638   ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
    639 
    640 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
    641 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
    642 
    643 #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
    644 #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
    645 
    646 static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
    647 {
    648   UInt32 price = 0;
    649   symbol |= 0x100;
    650   do
    651   {
    652     price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
    653     symbol <<= 1;
    654   }
    655   while (symbol < 0x10000);
    656   return price;
    657 }
    658 
    659 static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
    660 {
    661   UInt32 price = 0;
    662   UInt32 offs = 0x100;
    663   symbol |= 0x100;
    664   do
    665   {
    666     matchByte <<= 1;
    667     price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
    668     symbol <<= 1;
    669     offs &= ~(matchByte ^ symbol);
    670   }
    671   while (symbol < 0x10000);
    672   return price;
    673 }
    674 
    675 
    676 static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
    677 {
    678   UInt32 m = 1;
    679   int i;
    680   for (i = numBitLevels; i != 0;)
    681   {
    682     UInt32 bit;
    683     i--;
    684     bit = (symbol >> i) & 1;
    685     RangeEnc_EncodeBit(rc, probs + m, bit);
    686     m = (m << 1) | bit;
    687   }
    688 }
    689 
    690 static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
    691 {
    692   UInt32 m = 1;
    693   int i;
    694   for (i = 0; i < numBitLevels; i++)
    695   {
    696     UInt32 bit = symbol & 1;
    697     RangeEnc_EncodeBit(rc, probs + m, bit);
    698     m = (m << 1) | bit;
    699     symbol >>= 1;
    700   }
    701 }
    702 
    703 static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
    704 {
    705   UInt32 price = 0;
    706   symbol |= (1 << numBitLevels);
    707   while (symbol != 1)
    708   {
    709     price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
    710     symbol >>= 1;
    711   }
    712   return price;
    713 }
    714 
    715 static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
    716 {
    717   UInt32 price = 0;
    718   UInt32 m = 1;
    719   int i;
    720   for (i = numBitLevels; i != 0; i--)
    721   {
    722     UInt32 bit = symbol & 1;
    723     symbol >>= 1;
    724     price += GET_PRICEa(probs[m], bit);
    725     m = (m << 1) | bit;
    726   }
    727   return price;
    728 }
    729 
    730 
    731 static void LenEnc_Init(CLenEnc *p)
    732 {
    733   unsigned i;
    734   p->choice = p->choice2 = kProbInitValue;
    735   for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
    736     p->low[i] = kProbInitValue;
    737   for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
    738     p->mid[i] = kProbInitValue;
    739   for (i = 0; i < kLenNumHighSymbols; i++)
    740     p->high[i] = kProbInitValue;
    741 }
    742 
    743 static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
    744 {
    745   if (symbol < kLenNumLowSymbols)
    746   {
    747     RangeEnc_EncodeBit(rc, &p->choice, 0);
    748     RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
    749   }
    750   else
    751   {
    752     RangeEnc_EncodeBit(rc, &p->choice, 1);
    753     if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
    754     {
    755       RangeEnc_EncodeBit(rc, &p->choice2, 0);
    756       RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
    757     }
    758     else
    759     {
    760       RangeEnc_EncodeBit(rc, &p->choice2, 1);
    761       RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
    762     }
    763   }
    764 }
    765 
    766 static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
    767 {
    768   UInt32 a0 = GET_PRICE_0a(p->choice);
    769   UInt32 a1 = GET_PRICE_1a(p->choice);
    770   UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
    771   UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
    772   UInt32 i = 0;
    773   for (i = 0; i < kLenNumLowSymbols; i++)
    774   {
    775     if (i >= numSymbols)
    776       return;
    777     prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
    778   }
    779   for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
    780   {
    781     if (i >= numSymbols)
    782       return;
    783     prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
    784   }
    785   for (; i < numSymbols; i++)
    786     prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
    787 }
    788 
    789 static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
    790 {
    791   LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
    792   p->counters[posState] = p->tableSize;
    793 }
    794 
    795 static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
    796 {
    797   UInt32 posState;
    798   for (posState = 0; posState < numPosStates; posState++)
    799     LenPriceEnc_UpdateTable(p, posState, ProbPrices);
    800 }
    801 
    802 static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
    803 {
    804   LenEnc_Encode(&p->p, rc, symbol, posState);
    805   if (updatePrice)
    806     if (--p->counters[posState] == 0)
    807       LenPriceEnc_UpdateTable(p, posState, ProbPrices);
    808 }
    809 
    810 
    811 
    812 
    813 static void MovePos(CLzmaEnc *p, UInt32 num)
    814 {
    815   #ifdef SHOW_STAT
    816   g_STAT_OFFSET += num;
    817   printf("\n MovePos %d", num);
    818   #endif
    819 
    820   if (num != 0)
    821   {
    822     p->additionalOffset += num;
    823     p->matchFinder.Skip(p->matchFinderObj, num);
    824   }
    825 }
    826 
    827 static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
    828 {
    829   UInt32 lenRes = 0, numPairs;
    830   p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
    831   numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
    832 
    833   #ifdef SHOW_STAT
    834   printf("\n i = %d numPairs = %d    ", g_STAT_OFFSET, numPairs / 2);
    835   g_STAT_OFFSET++;
    836   {
    837     UInt32 i;
    838     for (i = 0; i < numPairs; i += 2)
    839       printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);
    840   }
    841   #endif
    842 
    843   if (numPairs > 0)
    844   {
    845     lenRes = p->matches[numPairs - 2];
    846     if (lenRes == p->numFastBytes)
    847     {
    848       const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
    849       UInt32 distance = p->matches[numPairs - 1] + 1;
    850       UInt32 numAvail = p->numAvail;
    851       if (numAvail > LZMA_MATCH_LEN_MAX)
    852         numAvail = LZMA_MATCH_LEN_MAX;
    853       {
    854         const Byte *pby2 = pby - distance;
    855         for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
    856       }
    857     }
    858   }
    859   p->additionalOffset++;
    860   *numDistancePairsRes = numPairs;
    861   return lenRes;
    862 }
    863 
    864 
    865 #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
    866 #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
    867 #define IsShortRep(p) ((p)->backPrev == 0)
    868 
    869 static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
    870 {
    871   return
    872     GET_PRICE_0(p->isRepG0[state]) +
    873     GET_PRICE_0(p->isRep0Long[state][posState]);
    874 }
    875 
    876 static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
    877 {
    878   UInt32 price;
    879   if (repIndex == 0)
    880   {
    881     price = GET_PRICE_0(p->isRepG0[state]);
    882     price += GET_PRICE_1(p->isRep0Long[state][posState]);
    883   }
    884   else
    885   {
    886     price = GET_PRICE_1(p->isRepG0[state]);
    887     if (repIndex == 1)
    888       price += GET_PRICE_0(p->isRepG1[state]);
    889     else
    890     {
    891       price += GET_PRICE_1(p->isRepG1[state]);
    892       price += GET_PRICE(p->isRepG2[state], repIndex - 2);
    893     }
    894   }
    895   return price;
    896 }
    897 
    898 static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
    899 {
    900   return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
    901     GetPureRepPrice(p, repIndex, state, posState);
    902 }
    903 
    904 static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
    905 {
    906   UInt32 posMem = p->opt[cur].posPrev;
    907   UInt32 backMem = p->opt[cur].backPrev;
    908   p->optimumEndIndex = cur;
    909   do
    910   {
    911     if (p->opt[cur].prev1IsChar)
    912     {
    913       MakeAsChar(&p->opt[posMem])
    914       p->opt[posMem].posPrev = posMem - 1;
    915       if (p->opt[cur].prev2)
    916       {
    917         p->opt[posMem - 1].prev1IsChar = False;
    918         p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
    919         p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
    920       }
    921     }
    922     {
    923       UInt32 posPrev = posMem;
    924       UInt32 backCur = backMem;
    925 
    926       backMem = p->opt[posPrev].backPrev;
    927       posMem = p->opt[posPrev].posPrev;
    928 
    929       p->opt[posPrev].backPrev = backCur;
    930       p->opt[posPrev].posPrev = cur;
    931       cur = posPrev;
    932     }
    933   }
    934   while (cur != 0);
    935   *backRes = p->opt[0].backPrev;
    936   p->optimumCurrentIndex  = p->opt[0].posPrev;
    937   return p->optimumCurrentIndex;
    938 }
    939 
    940 #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
    941 
    942 static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
    943 {
    944   UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
    945   UInt32 matchPrice, repMatchPrice, normalMatchPrice;
    946   UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
    947   UInt32 *matches;
    948   const Byte *data;
    949   Byte curByte, matchByte;
    950   if (p->optimumEndIndex != p->optimumCurrentIndex)
    951   {
    952     const COptimal *opt = &p->opt[p->optimumCurrentIndex];
    953     UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
    954     *backRes = opt->backPrev;
    955     p->optimumCurrentIndex = opt->posPrev;
    956     return lenRes;
    957   }
    958   p->optimumCurrentIndex = p->optimumEndIndex = 0;
    959 
    960   if (p->additionalOffset == 0)
    961     mainLen = ReadMatchDistances(p, &numPairs);
    962   else
    963   {
    964     mainLen = p->longestMatchLength;
    965     numPairs = p->numPairs;
    966   }
    967 
    968   numAvail = p->numAvail;
    969   if (numAvail < 2)
    970   {
    971     *backRes = (UInt32)(-1);
    972     return 1;
    973   }
    974   if (numAvail > LZMA_MATCH_LEN_MAX)
    975     numAvail = LZMA_MATCH_LEN_MAX;
    976 
    977   data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
    978   repMaxIndex = 0;
    979   for (i = 0; i < LZMA_NUM_REPS; i++)
    980   {
    981     UInt32 lenTest;
    982     const Byte *data2;
    983     reps[i] = p->reps[i];
    984     data2 = data - (reps[i] + 1);
    985     if (data[0] != data2[0] || data[1] != data2[1])
    986     {
    987       repLens[i] = 0;
    988       continue;
    989     }
    990     for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
    991     repLens[i] = lenTest;
    992     if (lenTest > repLens[repMaxIndex])
    993       repMaxIndex = i;
    994   }
    995   if (repLens[repMaxIndex] >= p->numFastBytes)
    996   {
    997     UInt32 lenRes;
    998     *backRes = repMaxIndex;
    999     lenRes = repLens[repMaxIndex];
   1000     MovePos(p, lenRes - 1);
   1001     return lenRes;
   1002   }
   1003 
   1004   matches = p->matches;
   1005   if (mainLen >= p->numFastBytes)
   1006   {
   1007     *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
   1008     MovePos(p, mainLen - 1);
   1009     return mainLen;
   1010   }
   1011   curByte = *data;
   1012   matchByte = *(data - (reps[0] + 1));
   1013 
   1014   if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
   1015   {
   1016     *backRes = (UInt32)-1;
   1017     return 1;
   1018   }
   1019 
   1020   p->opt[0].state = (CState)p->state;
   1021 
   1022   posState = (position & p->pbMask);
   1023 
   1024   {
   1025     const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
   1026     p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
   1027         (!IsCharState(p->state) ?
   1028           LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
   1029           LitEnc_GetPrice(probs, curByte, p->ProbPrices));
   1030   }
   1031 
   1032   MakeAsChar(&p->opt[1]);
   1033 
   1034   matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
   1035   repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
   1036 
   1037   if (matchByte == curByte)
   1038   {
   1039     UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
   1040     if (shortRepPrice < p->opt[1].price)
   1041     {
   1042       p->opt[1].price = shortRepPrice;
   1043       MakeAsShortRep(&p->opt[1]);
   1044     }
   1045   }
   1046   lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
   1047 
   1048   if (lenEnd < 2)
   1049   {
   1050     *backRes = p->opt[1].backPrev;
   1051     return 1;
   1052   }
   1053 
   1054   p->opt[1].posPrev = 0;
   1055   for (i = 0; i < LZMA_NUM_REPS; i++)
   1056     p->opt[0].backs[i] = reps[i];
   1057 
   1058   len = lenEnd;
   1059   do
   1060     p->opt[len--].price = kInfinityPrice;
   1061   while (len >= 2);
   1062 
   1063   for (i = 0; i < LZMA_NUM_REPS; i++)
   1064   {
   1065     UInt32 repLen = repLens[i];
   1066     UInt32 price;
   1067     if (repLen < 2)
   1068       continue;
   1069     price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
   1070     do
   1071     {
   1072       UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
   1073       COptimal *opt = &p->opt[repLen];
   1074       if (curAndLenPrice < opt->price)
   1075       {
   1076         opt->price = curAndLenPrice;
   1077         opt->posPrev = 0;
   1078         opt->backPrev = i;
   1079         opt->prev1IsChar = False;
   1080       }
   1081     }
   1082     while (--repLen >= 2);
   1083   }
   1084 
   1085   normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
   1086 
   1087   len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
   1088   if (len <= mainLen)
   1089   {
   1090     UInt32 offs = 0;
   1091     while (len > matches[offs])
   1092       offs += 2;
   1093     for (; ; len++)
   1094     {
   1095       COptimal *opt;
   1096       UInt32 distance = matches[offs + 1];
   1097 
   1098       UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
   1099       UInt32 lenToPosState = GetLenToPosState(len);
   1100       if (distance < kNumFullDistances)
   1101         curAndLenPrice += p->distancesPrices[lenToPosState][distance];
   1102       else
   1103       {
   1104         UInt32 slot;
   1105         GetPosSlot2(distance, slot);
   1106         curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
   1107       }
   1108       opt = &p->opt[len];
   1109       if (curAndLenPrice < opt->price)
   1110       {
   1111         opt->price = curAndLenPrice;
   1112         opt->posPrev = 0;
   1113         opt->backPrev = distance + LZMA_NUM_REPS;
   1114         opt->prev1IsChar = False;
   1115       }
   1116       if (len == matches[offs])
   1117       {
   1118         offs += 2;
   1119         if (offs == numPairs)
   1120           break;
   1121       }
   1122     }
   1123   }
   1124 
   1125   cur = 0;
   1126 
   1127     #ifdef SHOW_STAT2
   1128     if (position >= 0)
   1129     {
   1130       unsigned i;
   1131       printf("\n pos = %4X", position);
   1132       for (i = cur; i <= lenEnd; i++)
   1133       printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
   1134     }
   1135     #endif
   1136 
   1137   for (;;)
   1138   {
   1139     UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
   1140     UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
   1141     Bool nextIsChar;
   1142     Byte curByte, matchByte;
   1143     const Byte *data;
   1144     COptimal *curOpt;
   1145     COptimal *nextOpt;
   1146 
   1147     cur++;
   1148     if (cur == lenEnd)
   1149       return Backward(p, backRes, cur);
   1150 
   1151     newLen = ReadMatchDistances(p, &numPairs);
   1152     if (newLen >= p->numFastBytes)
   1153     {
   1154       p->numPairs = numPairs;
   1155       p->longestMatchLength = newLen;
   1156       return Backward(p, backRes, cur);
   1157     }
   1158     position++;
   1159     curOpt = &p->opt[cur];
   1160     posPrev = curOpt->posPrev;
   1161     if (curOpt->prev1IsChar)
   1162     {
   1163       posPrev--;
   1164       if (curOpt->prev2)
   1165       {
   1166         state = p->opt[curOpt->posPrev2].state;
   1167         if (curOpt->backPrev2 < LZMA_NUM_REPS)
   1168           state = kRepNextStates[state];
   1169         else
   1170           state = kMatchNextStates[state];
   1171       }
   1172       else
   1173         state = p->opt[posPrev].state;
   1174       state = kLiteralNextStates[state];
   1175     }
   1176     else
   1177       state = p->opt[posPrev].state;
   1178     if (posPrev == cur - 1)
   1179     {
   1180       if (IsShortRep(curOpt))
   1181         state = kShortRepNextStates[state];
   1182       else
   1183         state = kLiteralNextStates[state];
   1184     }
   1185     else
   1186     {
   1187       UInt32 pos;
   1188       const COptimal *prevOpt;
   1189       if (curOpt->prev1IsChar && curOpt->prev2)
   1190       {
   1191         posPrev = curOpt->posPrev2;
   1192         pos = curOpt->backPrev2;
   1193         state = kRepNextStates[state];
   1194       }
   1195       else
   1196       {
   1197         pos = curOpt->backPrev;
   1198         if (pos < LZMA_NUM_REPS)
   1199           state = kRepNextStates[state];
   1200         else
   1201           state = kMatchNextStates[state];
   1202       }
   1203       prevOpt = &p->opt[posPrev];
   1204       if (pos < LZMA_NUM_REPS)
   1205       {
   1206         UInt32 i;
   1207         reps[0] = prevOpt->backs[pos];
   1208         for (i = 1; i <= pos; i++)
   1209           reps[i] = prevOpt->backs[i - 1];
   1210         for (; i < LZMA_NUM_REPS; i++)
   1211           reps[i] = prevOpt->backs[i];
   1212       }
   1213       else
   1214       {
   1215         UInt32 i;
   1216         reps[0] = (pos - LZMA_NUM_REPS);
   1217         for (i = 1; i < LZMA_NUM_REPS; i++)
   1218           reps[i] = prevOpt->backs[i - 1];
   1219       }
   1220     }
   1221     curOpt->state = (CState)state;
   1222 
   1223     curOpt->backs[0] = reps[0];
   1224     curOpt->backs[1] = reps[1];
   1225     curOpt->backs[2] = reps[2];
   1226     curOpt->backs[3] = reps[3];
   1227 
   1228     curPrice = curOpt->price;
   1229     nextIsChar = False;
   1230     data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
   1231     curByte = *data;
   1232     matchByte = *(data - (reps[0] + 1));
   1233 
   1234     posState = (position & p->pbMask);
   1235 
   1236     curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
   1237     {
   1238       const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
   1239       curAnd1Price +=
   1240         (!IsCharState(state) ?
   1241           LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
   1242           LitEnc_GetPrice(probs, curByte, p->ProbPrices));
   1243     }
   1244 
   1245     nextOpt = &p->opt[cur + 1];
   1246 
   1247     if (curAnd1Price < nextOpt->price)
   1248     {
   1249       nextOpt->price = curAnd1Price;
   1250       nextOpt->posPrev = cur;
   1251       MakeAsChar(nextOpt);
   1252       nextIsChar = True;
   1253     }
   1254 
   1255     matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
   1256     repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
   1257 
   1258     if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
   1259     {
   1260       UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
   1261       if (shortRepPrice <= nextOpt->price)
   1262       {
   1263         nextOpt->price = shortRepPrice;
   1264         nextOpt->posPrev = cur;
   1265         MakeAsShortRep(nextOpt);
   1266         nextIsChar = True;
   1267       }
   1268     }
   1269     numAvailFull = p->numAvail;
   1270     {
   1271       UInt32 temp = kNumOpts - 1 - cur;
   1272       if (temp < numAvailFull)
   1273         numAvailFull = temp;
   1274     }
   1275 
   1276     if (numAvailFull < 2)
   1277       continue;
   1278     numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
   1279 
   1280     if (!nextIsChar && matchByte != curByte) /* speed optimization */
   1281     {
   1282       /* try Literal + rep0 */
   1283       UInt32 temp;
   1284       UInt32 lenTest2;
   1285       const Byte *data2 = data - (reps[0] + 1);
   1286       UInt32 limit = p->numFastBytes + 1;
   1287       if (limit > numAvailFull)
   1288         limit = numAvailFull;
   1289 
   1290       for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
   1291       lenTest2 = temp - 1;
   1292       if (lenTest2 >= 2)
   1293       {
   1294         UInt32 state2 = kLiteralNextStates[state];
   1295         UInt32 posStateNext = (position + 1) & p->pbMask;
   1296         UInt32 nextRepMatchPrice = curAnd1Price +
   1297             GET_PRICE_1(p->isMatch[state2][posStateNext]) +
   1298             GET_PRICE_1(p->isRep[state2]);
   1299         /* for (; lenTest2 >= 2; lenTest2--) */
   1300         {
   1301           UInt32 curAndLenPrice;
   1302           COptimal *opt;
   1303           UInt32 offset = cur + 1 + lenTest2;
   1304           while (lenEnd < offset)
   1305             p->opt[++lenEnd].price = kInfinityPrice;
   1306           curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
   1307           opt = &p->opt[offset];
   1308           if (curAndLenPrice < opt->price)
   1309           {
   1310             opt->price = curAndLenPrice;
   1311             opt->posPrev = cur + 1;
   1312             opt->backPrev = 0;
   1313             opt->prev1IsChar = True;
   1314             opt->prev2 = False;
   1315           }
   1316         }
   1317       }
   1318     }
   1319 
   1320     startLen = 2; /* speed optimization */
   1321     {
   1322     UInt32 repIndex;
   1323     for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
   1324     {
   1325       UInt32 lenTest;
   1326       UInt32 lenTestTemp;
   1327       UInt32 price;
   1328       const Byte *data2 = data - (reps[repIndex] + 1);
   1329       if (data[0] != data2[0] || data[1] != data2[1])
   1330         continue;
   1331       for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
   1332       while (lenEnd < cur + lenTest)
   1333         p->opt[++lenEnd].price = kInfinityPrice;
   1334       lenTestTemp = lenTest;
   1335       price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
   1336       do
   1337       {
   1338         UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
   1339         COptimal *opt = &p->opt[cur + lenTest];
   1340         if (curAndLenPrice < opt->price)
   1341         {
   1342           opt->price = curAndLenPrice;
   1343           opt->posPrev = cur;
   1344           opt->backPrev = repIndex;
   1345           opt->prev1IsChar = False;
   1346         }
   1347       }
   1348       while (--lenTest >= 2);
   1349       lenTest = lenTestTemp;
   1350 
   1351       if (repIndex == 0)
   1352         startLen = lenTest + 1;
   1353 
   1354       /* if (_maxMode) */
   1355         {
   1356           UInt32 lenTest2 = lenTest + 1;
   1357           UInt32 limit = lenTest2 + p->numFastBytes;
   1358           UInt32 nextRepMatchPrice;
   1359           if (limit > numAvailFull)
   1360             limit = numAvailFull;
   1361           for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
   1362           lenTest2 -= lenTest + 1;
   1363           if (lenTest2 >= 2)
   1364           {
   1365             UInt32 state2 = kRepNextStates[state];
   1366             UInt32 posStateNext = (position + lenTest) & p->pbMask;
   1367             UInt32 curAndLenCharPrice =
   1368                 price + p->repLenEnc.prices[posState][lenTest - 2] +
   1369                 GET_PRICE_0(p->isMatch[state2][posStateNext]) +
   1370                 LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
   1371                     data[lenTest], data2[lenTest], p->ProbPrices);
   1372             state2 = kLiteralNextStates[state2];
   1373             posStateNext = (position + lenTest + 1) & p->pbMask;
   1374             nextRepMatchPrice = curAndLenCharPrice +
   1375                 GET_PRICE_1(p->isMatch[state2][posStateNext]) +
   1376                 GET_PRICE_1(p->isRep[state2]);
   1377 
   1378             /* for (; lenTest2 >= 2; lenTest2--) */
   1379             {
   1380               UInt32 curAndLenPrice;
   1381               COptimal *opt;
   1382               UInt32 offset = cur + lenTest + 1 + lenTest2;
   1383               while (lenEnd < offset)
   1384                 p->opt[++lenEnd].price = kInfinityPrice;
   1385               curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
   1386               opt = &p->opt[offset];
   1387               if (curAndLenPrice < opt->price)
   1388               {
   1389                 opt->price = curAndLenPrice;
   1390                 opt->posPrev = cur + lenTest + 1;
   1391                 opt->backPrev = 0;
   1392                 opt->prev1IsChar = True;
   1393                 opt->prev2 = True;
   1394                 opt->posPrev2 = cur;
   1395                 opt->backPrev2 = repIndex;
   1396               }
   1397             }
   1398           }
   1399         }
   1400     }
   1401     }
   1402     /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
   1403     if (newLen > numAvail)
   1404     {
   1405       newLen = numAvail;
   1406       for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
   1407       matches[numPairs] = newLen;
   1408       numPairs += 2;
   1409     }
   1410     if (newLen >= startLen)
   1411     {
   1412       UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
   1413       UInt32 offs, curBack, posSlot;
   1414       UInt32 lenTest;
   1415       while (lenEnd < cur + newLen)
   1416         p->opt[++lenEnd].price = kInfinityPrice;
   1417 
   1418       offs = 0;
   1419       while (startLen > matches[offs])
   1420         offs += 2;
   1421       curBack = matches[offs + 1];
   1422       GetPosSlot2(curBack, posSlot);
   1423       for (lenTest = /*2*/ startLen; ; lenTest++)
   1424       {
   1425         UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
   1426         UInt32 lenToPosState = GetLenToPosState(lenTest);
   1427         COptimal *opt;
   1428         if (curBack < kNumFullDistances)
   1429           curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
   1430         else
   1431           curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
   1432 
   1433         opt = &p->opt[cur + lenTest];
   1434         if (curAndLenPrice < opt->price)
   1435         {
   1436           opt->price = curAndLenPrice;
   1437           opt->posPrev = cur;
   1438           opt->backPrev = curBack + LZMA_NUM_REPS;
   1439           opt->prev1IsChar = False;
   1440         }
   1441 
   1442         if (/*_maxMode && */lenTest == matches[offs])
   1443         {
   1444           /* Try Match + Literal + Rep0 */
   1445           const Byte *data2 = data - (curBack + 1);
   1446           UInt32 lenTest2 = lenTest + 1;
   1447           UInt32 limit = lenTest2 + p->numFastBytes;
   1448           UInt32 nextRepMatchPrice;
   1449           if (limit > numAvailFull)
   1450             limit = numAvailFull;
   1451           for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
   1452           lenTest2 -= lenTest + 1;
   1453           if (lenTest2 >= 2)
   1454           {
   1455             UInt32 state2 = kMatchNextStates[state];
   1456             UInt32 posStateNext = (position + lenTest) & p->pbMask;
   1457             UInt32 curAndLenCharPrice = curAndLenPrice +
   1458                 GET_PRICE_0(p->isMatch[state2][posStateNext]) +
   1459                 LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
   1460                     data[lenTest], data2[lenTest], p->ProbPrices);
   1461             state2 = kLiteralNextStates[state2];
   1462             posStateNext = (posStateNext + 1) & p->pbMask;
   1463             nextRepMatchPrice = curAndLenCharPrice +
   1464                 GET_PRICE_1(p->isMatch[state2][posStateNext]) +
   1465                 GET_PRICE_1(p->isRep[state2]);
   1466 
   1467             /* for (; lenTest2 >= 2; lenTest2--) */
   1468             {
   1469               UInt32 offset = cur + lenTest + 1 + lenTest2;
   1470               UInt32 curAndLenPrice;
   1471               COptimal *opt;
   1472               while (lenEnd < offset)
   1473                 p->opt[++lenEnd].price = kInfinityPrice;
   1474               curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
   1475               opt = &p->opt[offset];
   1476               if (curAndLenPrice < opt->price)
   1477               {
   1478                 opt->price = curAndLenPrice;
   1479                 opt->posPrev = cur + lenTest + 1;
   1480                 opt->backPrev = 0;
   1481                 opt->prev1IsChar = True;
   1482                 opt->prev2 = True;
   1483                 opt->posPrev2 = cur;
   1484                 opt->backPrev2 = curBack + LZMA_NUM_REPS;
   1485               }
   1486             }
   1487           }
   1488           offs += 2;
   1489           if (offs == numPairs)
   1490             break;
   1491           curBack = matches[offs + 1];
   1492           if (curBack >= kNumFullDistances)
   1493             GetPosSlot2(curBack, posSlot);
   1494         }
   1495       }
   1496     }
   1497   }
   1498 }
   1499 
   1500 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
   1501 
   1502 static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
   1503 {
   1504   UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
   1505   const Byte *data;
   1506   const UInt32 *matches;
   1507 
   1508   if (p->additionalOffset == 0)
   1509     mainLen = ReadMatchDistances(p, &numPairs);
   1510   else
   1511   {
   1512     mainLen = p->longestMatchLength;
   1513     numPairs = p->numPairs;
   1514   }
   1515 
   1516   numAvail = p->numAvail;
   1517   *backRes = (UInt32)-1;
   1518   if (numAvail < 2)
   1519     return 1;
   1520   if (numAvail > LZMA_MATCH_LEN_MAX)
   1521     numAvail = LZMA_MATCH_LEN_MAX;
   1522   data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
   1523 
   1524   repLen = repIndex = 0;
   1525   for (i = 0; i < LZMA_NUM_REPS; i++)
   1526   {
   1527     UInt32 len;
   1528     const Byte *data2 = data - (p->reps[i] + 1);
   1529     if (data[0] != data2[0] || data[1] != data2[1])
   1530       continue;
   1531     for (len = 2; len < numAvail && data[len] == data2[len]; len++);
   1532     if (len >= p->numFastBytes)
   1533     {
   1534       *backRes = i;
   1535       MovePos(p, len - 1);
   1536       return len;
   1537     }
   1538     if (len > repLen)
   1539     {
   1540       repIndex = i;
   1541       repLen = len;
   1542     }
   1543   }
   1544 
   1545   matches = p->matches;
   1546   if (mainLen >= p->numFastBytes)
   1547   {
   1548     *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
   1549     MovePos(p, mainLen - 1);
   1550     return mainLen;
   1551   }
   1552 
   1553   mainDist = 0; /* for GCC */
   1554   if (mainLen >= 2)
   1555   {
   1556     mainDist = matches[numPairs - 1];
   1557     while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
   1558     {
   1559       if (!ChangePair(matches[numPairs - 3], mainDist))
   1560         break;
   1561       numPairs -= 2;
   1562       mainLen = matches[numPairs - 2];
   1563       mainDist = matches[numPairs - 1];
   1564     }
   1565     if (mainLen == 2 && mainDist >= 0x80)
   1566       mainLen = 1;
   1567   }
   1568 
   1569   if (repLen >= 2 && (
   1570         (repLen + 1 >= mainLen) ||
   1571         (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
   1572         (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
   1573   {
   1574     *backRes = repIndex;
   1575     MovePos(p, repLen - 1);
   1576     return repLen;
   1577   }
   1578 
   1579   if (mainLen < 2 || numAvail <= 2)
   1580     return 1;
   1581 
   1582   p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
   1583   if (p->longestMatchLength >= 2)
   1584   {
   1585     UInt32 newDistance = matches[p->numPairs - 1];
   1586     if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
   1587         (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
   1588         (p->longestMatchLength > mainLen + 1) ||
   1589         (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
   1590       return 1;
   1591   }
   1592 
   1593   data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
   1594   for (i = 0; i < LZMA_NUM_REPS; i++)
   1595   {
   1596     UInt32 len, limit;
   1597     const Byte *data2 = data - (p->reps[i] + 1);
   1598     if (data[0] != data2[0] || data[1] != data2[1])
   1599       continue;
   1600     limit = mainLen - 1;
   1601     for (len = 2; len < limit && data[len] == data2[len]; len++);
   1602     if (len >= limit)
   1603       return 1;
   1604   }
   1605   *backRes = mainDist + LZMA_NUM_REPS;
   1606   MovePos(p, mainLen - 2);
   1607   return mainLen;
   1608 }
   1609 
   1610 static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
   1611 {
   1612   UInt32 len;
   1613   RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
   1614   RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
   1615   p->state = kMatchNextStates[p->state];
   1616   len = LZMA_MATCH_LEN_MIN;
   1617   LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
   1618   RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
   1619   RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
   1620   RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
   1621 }
   1622 
   1623 static SRes CheckErrors(CLzmaEnc *p)
   1624 {
   1625   if (p->result != SZ_OK)
   1626     return p->result;
   1627   if (p->rc.res != SZ_OK)
   1628     p->result = SZ_ERROR_WRITE;
   1629   if (p->matchFinderBase.result != SZ_OK)
   1630     p->result = SZ_ERROR_READ;
   1631   if (p->result != SZ_OK)
   1632     p->finished = True;
   1633   return p->result;
   1634 }
   1635 
   1636 static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
   1637 {
   1638   /* ReleaseMFStream(); */
   1639   p->finished = True;
   1640   if (p->writeEndMark)
   1641     WriteEndMarker(p, nowPos & p->pbMask);
   1642   RangeEnc_FlushData(&p->rc);
   1643   RangeEnc_FlushStream(&p->rc);
   1644   return CheckErrors(p);
   1645 }
   1646 
   1647 static void FillAlignPrices(CLzmaEnc *p)
   1648 {
   1649   UInt32 i;
   1650   for (i = 0; i < kAlignTableSize; i++)
   1651     p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
   1652   p->alignPriceCount = 0;
   1653 }
   1654 
   1655 static void FillDistancesPrices(CLzmaEnc *p)
   1656 {
   1657   UInt32 tempPrices[kNumFullDistances];
   1658   UInt32 i, lenToPosState;
   1659   for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
   1660   {
   1661     UInt32 posSlot = GetPosSlot1(i);
   1662     UInt32 footerBits = ((posSlot >> 1) - 1);
   1663     UInt32 base = ((2 | (posSlot & 1)) << footerBits);
   1664     tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
   1665   }
   1666 
   1667   for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
   1668   {
   1669     UInt32 posSlot;
   1670     const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
   1671     UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
   1672     for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
   1673       posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
   1674     for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
   1675       posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
   1676 
   1677     {
   1678       UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
   1679       UInt32 i;
   1680       for (i = 0; i < kStartPosModelIndex; i++)
   1681         distancesPrices[i] = posSlotPrices[i];
   1682       for (; i < kNumFullDistances; i++)
   1683         distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
   1684     }
   1685   }
   1686   p->matchPriceCount = 0;
   1687 }
   1688 
   1689 void LzmaEnc_Construct(CLzmaEnc *p)
   1690 {
   1691   RangeEnc_Construct(&p->rc);
   1692   MatchFinder_Construct(&p->matchFinderBase);
   1693   #ifndef _7ZIP_ST
   1694   MatchFinderMt_Construct(&p->matchFinderMt);
   1695   p->matchFinderMt.MatchFinder = &p->matchFinderBase;
   1696   #endif
   1697 
   1698   {
   1699     CLzmaEncProps props;
   1700     LzmaEncProps_Init(&props);
   1701     LzmaEnc_SetProps(p, &props);
   1702   }
   1703 
   1704   #ifndef LZMA_LOG_BSR
   1705   LzmaEnc_FastPosInit(p->g_FastPos);
   1706   #endif
   1707 
   1708   LzmaEnc_InitPriceTables(p->ProbPrices);
   1709   p->litProbs = 0;
   1710   p->saveState.litProbs = 0;
   1711 }
   1712 
   1713 CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
   1714 {
   1715   void *p;
   1716   p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
   1717   if (p != 0)
   1718     LzmaEnc_Construct((CLzmaEnc *)p);
   1719   return p;
   1720 }
   1721 
   1722 void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
   1723 {
   1724   alloc->Free(alloc, p->litProbs);
   1725   alloc->Free(alloc, p->saveState.litProbs);
   1726   p->litProbs = 0;
   1727   p->saveState.litProbs = 0;
   1728 }
   1729 
   1730 void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
   1731 {
   1732   #ifndef _7ZIP_ST
   1733   MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
   1734   #endif
   1735   MatchFinder_Free(&p->matchFinderBase, allocBig);
   1736   LzmaEnc_FreeLits(p, alloc);
   1737   RangeEnc_Free(&p->rc, alloc);
   1738 }
   1739 
   1740 void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
   1741 {
   1742   LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
   1743   alloc->Free(alloc, p);
   1744 }
   1745 
   1746 static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
   1747 {
   1748   UInt32 nowPos32, startPos32;
   1749   if (p->needInit)
   1750   {
   1751     p->matchFinder.Init(p->matchFinderObj);
   1752     p->needInit = 0;
   1753   }
   1754 
   1755   if (p->finished)
   1756     return p->result;
   1757   RINOK(CheckErrors(p));
   1758 
   1759   nowPos32 = (UInt32)p->nowPos64;
   1760   startPos32 = nowPos32;
   1761 
   1762   if (p->nowPos64 == 0)
   1763   {
   1764     UInt32 numPairs;
   1765     Byte curByte;
   1766     if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
   1767       return Flush(p, nowPos32);
   1768     ReadMatchDistances(p, &numPairs);
   1769     RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
   1770     p->state = kLiteralNextStates[p->state];
   1771     curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
   1772     LitEnc_Encode(&p->rc, p->litProbs, curByte);
   1773     p->additionalOffset--;
   1774     nowPos32++;
   1775   }
   1776 
   1777   if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
   1778   for (;;)
   1779   {
   1780     UInt32 pos, len, posState;
   1781 
   1782     if (p->fastMode)
   1783       len = GetOptimumFast(p, &pos);
   1784     else
   1785       len = GetOptimum(p, nowPos32, &pos);
   1786 
   1787     #ifdef SHOW_STAT2
   1788     printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);
   1789     #endif
   1790 
   1791     posState = nowPos32 & p->pbMask;
   1792     if (len == 1 && pos == (UInt32)-1)
   1793     {
   1794       Byte curByte;
   1795       CLzmaProb *probs;
   1796       const Byte *data;
   1797 
   1798       RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
   1799       data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
   1800       curByte = *data;
   1801       probs = LIT_PROBS(nowPos32, *(data - 1));
   1802       if (IsCharState(p->state))
   1803         LitEnc_Encode(&p->rc, probs, curByte);
   1804       else
   1805         LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
   1806       p->state = kLiteralNextStates[p->state];
   1807     }
   1808     else
   1809     {
   1810       RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
   1811       if (pos < LZMA_NUM_REPS)
   1812       {
   1813         RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
   1814         if (pos == 0)
   1815         {
   1816           RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
   1817           RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
   1818         }
   1819         else
   1820         {
   1821           UInt32 distance = p->reps[pos];
   1822           RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
   1823           if (pos == 1)
   1824             RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
   1825           else
   1826           {
   1827             RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
   1828             RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
   1829             if (pos == 3)
   1830               p->reps[3] = p->reps[2];
   1831             p->reps[2] = p->reps[1];
   1832           }
   1833           p->reps[1] = p->reps[0];
   1834           p->reps[0] = distance;
   1835         }
   1836         if (len == 1)
   1837           p->state = kShortRepNextStates[p->state];
   1838         else
   1839         {
   1840           LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
   1841           p->state = kRepNextStates[p->state];
   1842         }
   1843       }
   1844       else
   1845       {
   1846         UInt32 posSlot;
   1847         RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
   1848         p->state = kMatchNextStates[p->state];
   1849         LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
   1850         pos -= LZMA_NUM_REPS;
   1851         GetPosSlot(pos, posSlot);
   1852         RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
   1853 
   1854         if (posSlot >= kStartPosModelIndex)
   1855         {
   1856           UInt32 footerBits = ((posSlot >> 1) - 1);
   1857           UInt32 base = ((2 | (posSlot & 1)) << footerBits);
   1858           UInt32 posReduced = pos - base;
   1859 
   1860           if (posSlot < kEndPosModelIndex)
   1861             RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
   1862           else
   1863           {
   1864             RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
   1865             RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
   1866             p->alignPriceCount++;
   1867           }
   1868         }
   1869         p->reps[3] = p->reps[2];
   1870         p->reps[2] = p->reps[1];
   1871         p->reps[1] = p->reps[0];
   1872         p->reps[0] = pos;
   1873         p->matchPriceCount++;
   1874       }
   1875     }
   1876     p->additionalOffset -= len;
   1877     nowPos32 += len;
   1878     if (p->additionalOffset == 0)
   1879     {
   1880       UInt32 processed;
   1881       if (!p->fastMode)
   1882       {
   1883         if (p->matchPriceCount >= (1 << 7))
   1884           FillDistancesPrices(p);
   1885         if (p->alignPriceCount >= kAlignTableSize)
   1886           FillAlignPrices(p);
   1887       }
   1888       if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
   1889         break;
   1890       processed = nowPos32 - startPos32;
   1891       if (useLimits)
   1892       {
   1893         if (processed + kNumOpts + 300 >= maxUnpackSize ||
   1894             RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
   1895           break;
   1896       }
   1897       else if (processed >= (1 << 15))
   1898       {
   1899         p->nowPos64 += nowPos32 - startPos32;
   1900         return CheckErrors(p);
   1901       }
   1902     }
   1903   }
   1904   p->nowPos64 += nowPos32 - startPos32;
   1905   return Flush(p, nowPos32);
   1906 }
   1907 
   1908 #define kBigHashDicLimit ((UInt32)1 << 24)
   1909 
   1910 static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
   1911 {
   1912   UInt32 beforeSize = kNumOpts;
   1913   if (!RangeEnc_Alloc(&p->rc, alloc))
   1914     return SZ_ERROR_MEM;
   1915   #ifndef _7ZIP_ST
   1916   p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
   1917   #endif
   1918 
   1919   {
   1920     unsigned lclp = p->lc + p->lp;
   1921     if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
   1922     {
   1923       LzmaEnc_FreeLits(p, alloc);
   1924       p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
   1925       p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
   1926       if (p->litProbs == 0 || p->saveState.litProbs == 0)
   1927       {
   1928         LzmaEnc_FreeLits(p, alloc);
   1929         return SZ_ERROR_MEM;
   1930       }
   1931       p->lclp = lclp;
   1932     }
   1933   }
   1934 
   1935   p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
   1936 
   1937   if (beforeSize + p->dictSize < keepWindowSize)
   1938     beforeSize = keepWindowSize - p->dictSize;
   1939 
   1940   #ifndef _7ZIP_ST
   1941   if (p->mtMode)
   1942   {
   1943     RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
   1944     p->matchFinderObj = &p->matchFinderMt;
   1945     MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
   1946   }
   1947   else
   1948   #endif
   1949   {
   1950     if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
   1951       return SZ_ERROR_MEM;
   1952     p->matchFinderObj = &p->matchFinderBase;
   1953     MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
   1954   }
   1955   return SZ_OK;
   1956 }
   1957 
   1958 void LzmaEnc_Init(CLzmaEnc *p)
   1959 {
   1960   UInt32 i;
   1961   p->state = 0;
   1962   for (i = 0 ; i < LZMA_NUM_REPS; i++)
   1963     p->reps[i] = 0;
   1964 
   1965   RangeEnc_Init(&p->rc);
   1966 
   1967 
   1968   for (i = 0; i < kNumStates; i++)
   1969   {
   1970     UInt32 j;
   1971     for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
   1972     {
   1973       p->isMatch[i][j] = kProbInitValue;
   1974       p->isRep0Long[i][j] = kProbInitValue;
   1975     }
   1976     p->isRep[i] = kProbInitValue;
   1977     p->isRepG0[i] = kProbInitValue;
   1978     p->isRepG1[i] = kProbInitValue;
   1979     p->isRepG2[i] = kProbInitValue;
   1980   }
   1981 
   1982   {
   1983     UInt32 num = 0x300 << (p->lp + p->lc);
   1984     for (i = 0; i < num; i++)
   1985       p->litProbs[i] = kProbInitValue;
   1986   }
   1987 
   1988   {
   1989     for (i = 0; i < kNumLenToPosStates; i++)
   1990     {
   1991       CLzmaProb *probs = p->posSlotEncoder[i];
   1992       UInt32 j;
   1993       for (j = 0; j < (1 << kNumPosSlotBits); j++)
   1994         probs[j] = kProbInitValue;
   1995     }
   1996   }
   1997   {
   1998     for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
   1999       p->posEncoders[i] = kProbInitValue;
   2000   }
   2001 
   2002   LenEnc_Init(&p->lenEnc.p);
   2003   LenEnc_Init(&p->repLenEnc.p);
   2004 
   2005   for (i = 0; i < (1 << kNumAlignBits); i++)
   2006     p->posAlignEncoder[i] = kProbInitValue;
   2007 
   2008   p->optimumEndIndex = 0;
   2009   p->optimumCurrentIndex = 0;
   2010   p->additionalOffset = 0;
   2011 
   2012   p->pbMask = (1 << p->pb) - 1;
   2013   p->lpMask = (1 << p->lp) - 1;
   2014 }
   2015 
   2016 void LzmaEnc_InitPrices(CLzmaEnc *p)
   2017 {
   2018   if (!p->fastMode)
   2019   {
   2020     FillDistancesPrices(p);
   2021     FillAlignPrices(p);
   2022   }
   2023 
   2024   p->lenEnc.tableSize =
   2025   p->repLenEnc.tableSize =
   2026       p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
   2027   LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
   2028   LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
   2029 }
   2030 
   2031 static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
   2032 {
   2033   UInt32 i;
   2034   for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
   2035     if (p->dictSize <= ((UInt32)1 << i))
   2036       break;
   2037   p->distTableSize = i * 2;
   2038 
   2039   p->finished = False;
   2040   p->result = SZ_OK;
   2041   RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
   2042   LzmaEnc_Init(p);
   2043   LzmaEnc_InitPrices(p);
   2044   p->nowPos64 = 0;
   2045   return SZ_OK;
   2046 }
   2047 
   2048 static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
   2049     ISzAlloc *alloc, ISzAlloc *allocBig)
   2050 {
   2051   CLzmaEnc *p = (CLzmaEnc *)pp;
   2052   p->matchFinderBase.stream = inStream;
   2053   p->needInit = 1;
   2054   p->rc.outStream = outStream;
   2055   return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
   2056 }
   2057 
   2058 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
   2059     ISeqInStream *inStream, UInt32 keepWindowSize,
   2060     ISzAlloc *alloc, ISzAlloc *allocBig)
   2061 {
   2062   CLzmaEnc *p = (CLzmaEnc *)pp;
   2063   p->matchFinderBase.stream = inStream;
   2064   p->needInit = 1;
   2065   return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
   2066 }
   2067 
   2068 static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
   2069 {
   2070   p->matchFinderBase.directInput = 1;
   2071   p->matchFinderBase.bufferBase = (Byte *)src;
   2072   p->matchFinderBase.directInputRem = srcLen;
   2073 }
   2074 
   2075 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
   2076     UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
   2077 {
   2078   CLzmaEnc *p = (CLzmaEnc *)pp;
   2079   LzmaEnc_SetInputBuf(p, src, srcLen);
   2080   p->needInit = 1;
   2081 
   2082   return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
   2083 }
   2084 
   2085 void LzmaEnc_Finish(CLzmaEncHandle pp)
   2086 {
   2087   #ifndef _7ZIP_ST
   2088   CLzmaEnc *p = (CLzmaEnc *)pp;
   2089   if (p->mtMode)
   2090     MatchFinderMt_ReleaseStream(&p->matchFinderMt);
   2091   #else
   2092   pp = pp;
   2093   #endif
   2094 }
   2095 
   2096 typedef struct
   2097 {
   2098   ISeqOutStream funcTable;
   2099   Byte *data;
   2100   SizeT rem;
   2101   Bool overflow;
   2102 } CSeqOutStreamBuf;
   2103 
   2104 static size_t MyWrite(void *pp, const void *data, size_t size)
   2105 {
   2106   CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
   2107   if (p->rem < size)
   2108   {
   2109     size = p->rem;
   2110     p->overflow = True;
   2111   }
   2112   memcpy(p->data, data, size);
   2113   p->rem -= size;
   2114   p->data += size;
   2115   return size;
   2116 }
   2117 
   2118 
   2119 UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
   2120 {
   2121   const CLzmaEnc *p = (CLzmaEnc *)pp;
   2122   return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
   2123 }
   2124 
   2125 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
   2126 {
   2127   const CLzmaEnc *p = (CLzmaEnc *)pp;
   2128   return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
   2129 }
   2130 
   2131 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
   2132     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
   2133 {
   2134   CLzmaEnc *p = (CLzmaEnc *)pp;
   2135   UInt64 nowPos64;
   2136   SRes res;
   2137   CSeqOutStreamBuf outStream;
   2138 
   2139   outStream.funcTable.Write = MyWrite;
   2140   outStream.data = dest;
   2141   outStream.rem = *destLen;
   2142   outStream.overflow = False;
   2143 
   2144   p->writeEndMark = False;
   2145   p->finished = False;
   2146   p->result = SZ_OK;
   2147 
   2148   if (reInit)
   2149     LzmaEnc_Init(p);
   2150   LzmaEnc_InitPrices(p);
   2151   nowPos64 = p->nowPos64;
   2152   RangeEnc_Init(&p->rc);
   2153   p->rc.outStream = &outStream.funcTable;
   2154 
   2155   res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
   2156 
   2157   *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
   2158   *destLen -= outStream.rem;
   2159   if (outStream.overflow)
   2160     return SZ_ERROR_OUTPUT_EOF;
   2161 
   2162   return res;
   2163 }
   2164 
   2165 static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
   2166 {
   2167   SRes res = SZ_OK;
   2168 
   2169   #ifndef _7ZIP_ST
   2170   Byte allocaDummy[0x300];
   2171   allocaDummy[0] = 0;
   2172   allocaDummy[1] = allocaDummy[0];
   2173   #endif
   2174 
   2175   for (;;)
   2176   {
   2177     res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
   2178     if (res != SZ_OK || p->finished != 0)
   2179       break;
   2180     if (progress != 0)
   2181     {
   2182       res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
   2183       if (res != SZ_OK)
   2184       {
   2185         res = SZ_ERROR_PROGRESS;
   2186         break;
   2187       }
   2188     }
   2189   }
   2190   LzmaEnc_Finish(p);
   2191   return res;
   2192 }
   2193 
   2194 SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
   2195     ISzAlloc *alloc, ISzAlloc *allocBig)
   2196 {
   2197   RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
   2198   return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
   2199 }
   2200 
   2201 SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
   2202 {
   2203   CLzmaEnc *p = (CLzmaEnc *)pp;
   2204   int i;
   2205   UInt32 dictSize = p->dictSize;
   2206   if (*size < LZMA_PROPS_SIZE)
   2207     return SZ_ERROR_PARAM;
   2208   *size = LZMA_PROPS_SIZE;
   2209   props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
   2210 
   2211   for (i = 11; i <= 30; i++)
   2212   {
   2213     if (dictSize <= ((UInt32)2 << i))
   2214     {
   2215       dictSize = (2 << i);
   2216       break;
   2217     }
   2218     if (dictSize <= ((UInt32)3 << i))
   2219     {
   2220       dictSize = (3 << i);
   2221       break;
   2222     }
   2223   }
   2224 
   2225   for (i = 0; i < 4; i++)
   2226     props[1 + i] = (Byte)(dictSize >> (8 * i));
   2227   return SZ_OK;
   2228 }
   2229 
   2230 SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
   2231     int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
   2232 {
   2233   SRes res;
   2234   CLzmaEnc *p = (CLzmaEnc *)pp;
   2235 
   2236   CSeqOutStreamBuf outStream;
   2237 
   2238   LzmaEnc_SetInputBuf(p, src, srcLen);
   2239 
   2240   outStream.funcTable.Write = MyWrite;
   2241   outStream.data = dest;
   2242   outStream.rem = *destLen;
   2243   outStream.overflow = False;
   2244 
   2245   p->writeEndMark = writeEndMark;
   2246 
   2247   p->rc.outStream = &outStream.funcTable;
   2248   res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
   2249   if (res == SZ_OK)
   2250     res = LzmaEnc_Encode2(p, progress);
   2251 
   2252   *destLen -= outStream.rem;
   2253   if (outStream.overflow)
   2254     return SZ_ERROR_OUTPUT_EOF;
   2255   return res;
   2256 }
   2257 
   2258 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
   2259     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
   2260     ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
   2261 {
   2262   CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
   2263   SRes res;
   2264   if (p == 0)
   2265     return SZ_ERROR_MEM;
   2266 
   2267   res = LzmaEnc_SetProps(p, props);
   2268   if (res == SZ_OK)
   2269   {
   2270     res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
   2271     if (res == SZ_OK)
   2272       res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
   2273           writeEndMark, progress, alloc, allocBig);
   2274   }
   2275 
   2276   LzmaEnc_Destroy(p, alloc, allocBig);
   2277   return res;
   2278 }
   2279