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