• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* LzmaEnc.c -- LZMA Encoder
2 2021-11-18: 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 "CpuArch.h"
16 #include "LzmaEnc.h"
17 
18 #include "LzFind.h"
19 #ifndef _7ZIP_ST
20 #include "LzFindMt.h"
21 #endif
22 
23 /* the following LzmaEnc_* declarations is internal LZMA interface for LZMA2 encoder */
24 
25 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
26     ISzAllocPtr alloc, ISzAllocPtr allocBig);
27 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
28     UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);
29 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
30     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
31 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
32 void LzmaEnc_Finish(CLzmaEncHandle pp);
33 void LzmaEnc_SaveState(CLzmaEncHandle pp);
34 void LzmaEnc_RestoreState(CLzmaEncHandle pp);
35 
36 #ifdef SHOW_STAT
37 static unsigned g_STAT_OFFSET = 0;
38 #endif
39 
40 /* for good normalization speed we still reserve 256 MB before 4 GB range */
41 #define kLzmaMaxHistorySize ((UInt32)15 << 28)
42 
43 #define kNumTopBits 24
44 #define kTopValue ((UInt32)1 << kNumTopBits)
45 
46 #define kNumBitModelTotalBits 11
47 #define kBitModelTotal (1 << kNumBitModelTotalBits)
48 #define kNumMoveBits 5
49 #define kProbInitValue (kBitModelTotal >> 1)
50 
51 #define kNumMoveReducingBits 4
52 #define kNumBitPriceShiftBits 4
53 // #define kBitPrice (1 << kNumBitPriceShiftBits)
54 
55 #define REP_LEN_COUNT 64
56 
LzmaEncProps_Init(CLzmaEncProps * p)57 void LzmaEncProps_Init(CLzmaEncProps *p)
58 {
59   p->level = 5;
60   p->dictSize = p->mc = 0;
61   p->reduceSize = (UInt64)(Int64)-1;
62   p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
63   p->writeEndMark = 0;
64   p->affinity = 0;
65 }
66 
LzmaEncProps_Normalize(CLzmaEncProps * p)67 void LzmaEncProps_Normalize(CLzmaEncProps *p)
68 {
69   int level = p->level;
70   if (level < 0) level = 5;
71   p->level = level;
72 
73   if (p->dictSize == 0)
74     p->dictSize =
75       ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
76       ( level <= 6 ? ((UInt32)1 << (level + 19)) :
77       ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
78       )));
79 
80   if (p->dictSize > p->reduceSize)
81   {
82     UInt32 v = (UInt32)p->reduceSize;
83     const UInt32 kReduceMin = ((UInt32)1 << 12);
84     if (v < kReduceMin)
85       v = kReduceMin;
86     if (p->dictSize > v)
87       p->dictSize = v;
88   }
89 
90   if (p->lc < 0) p->lc = 3;
91   if (p->lp < 0) p->lp = 0;
92   if (p->pb < 0) p->pb = 2;
93 
94   if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
95   if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
96   if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
97   if (p->numHashBytes < 0) p->numHashBytes = (p->btMode ? 4 : 5);
98   if (p->mc == 0) p->mc = (16 + ((unsigned)p->fb >> 1)) >> (p->btMode ? 0 : 1);
99 
100   if (p->numThreads < 0)
101     p->numThreads =
102       #ifndef _7ZIP_ST
103       ((p->btMode && p->algo) ? 2 : 1);
104       #else
105       1;
106       #endif
107 }
108 
LzmaEncProps_GetDictSize(const CLzmaEncProps * props2)109 UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
110 {
111   CLzmaEncProps props = *props2;
112   LzmaEncProps_Normalize(&props);
113   return props.dictSize;
114 }
115 
116 
117 /*
118 x86/x64:
119 
120 BSR:
121   IF (SRC == 0) ZF = 1, DEST is undefined;
122                   AMD : DEST is unchanged;
123   IF (SRC != 0) ZF = 0; DEST is index of top non-zero bit
124   BSR is slow in some processors
125 
126 LZCNT:
127   IF (SRC  == 0) CF = 1, DEST is size_in_bits_of_register(src) (32 or 64)
128   IF (SRC  != 0) CF = 0, DEST = num_lead_zero_bits
129   IF (DEST == 0) ZF = 1;
130 
131 LZCNT works only in new processors starting from Haswell.
132 if LZCNT is not supported by processor, then it's executed as BSR.
133 LZCNT can be faster than BSR, if supported.
134 */
135 
136 // #define LZMA_LOG_BSR
137 
138 #if defined(MY_CPU_ARM_OR_ARM64) /* || defined(MY_CPU_X86_OR_AMD64) */
139 
140   #if (defined(__clang__) && (__clang_major__ >= 6)) \
141       || (defined(__GNUC__) && (__GNUC__ >= 6))
142       #define LZMA_LOG_BSR
143   #elif defined(_MSC_VER) && (_MSC_VER >= 1300)
144     // #if defined(MY_CPU_ARM_OR_ARM64)
145       #define LZMA_LOG_BSR
146     // #endif
147   #endif
148 #endif
149 
150 // #include <intrin.h>
151 
152 #ifdef LZMA_LOG_BSR
153 
154 #if defined(__clang__) \
155     || defined(__GNUC__)
156 
157 /*
158   C code:                  : (30 - __builtin_clz(x))
159     gcc9/gcc10 for x64 /x86  : 30 - (bsr(x) xor 31)
160     clang10 for x64          : 31 + (bsr(x) xor -32)
161 */
162 
163   #define MY_clz(x)  ((unsigned)__builtin_clz(x))
164   // __lzcnt32
165   // __builtin_ia32_lzcnt_u32
166 
167 #else  // #if defined(_MSC_VER)
168 
169   #ifdef MY_CPU_ARM_OR_ARM64
170 
171     #define MY_clz  _CountLeadingZeros
172 
173   #else // if defined(MY_CPU_X86_OR_AMD64)
174 
175     // #define MY_clz  __lzcnt  // we can use lzcnt (unsupported by old CPU)
176     // _BitScanReverse code is not optimal for some MSVC compilers
177     #define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); zz--; \
178       res = (zz + zz) + (pos >> zz); }
179 
180   #endif // MY_CPU_X86_OR_AMD64
181 
182 #endif // _MSC_VER
183 
184 
185 #ifndef BSR2_RET
186 
187     #define BSR2_RET(pos, res) { unsigned zz = 30 - MY_clz(pos); \
188       res = (zz + zz) + (pos >> zz); }
189 
190 #endif
191 
192 
193 unsigned GetPosSlot1(UInt32 pos);
GetPosSlot1(UInt32 pos)194 unsigned GetPosSlot1(UInt32 pos)
195 {
196   unsigned res;
197   BSR2_RET(pos, res);
198   return res;
199 }
200 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
201 #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
202 
203 
204 #else // ! LZMA_LOG_BSR
205 
206 #define kNumLogBits (11 + sizeof(size_t) / 8 * 3)
207 
208 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
209 
LzmaEnc_FastPosInit(Byte * g_FastPos)210 static void LzmaEnc_FastPosInit(Byte *g_FastPos)
211 {
212   unsigned slot;
213   g_FastPos[0] = 0;
214   g_FastPos[1] = 1;
215   g_FastPos += 2;
216 
217   for (slot = 2; slot < kNumLogBits * 2; slot++)
218   {
219     size_t k = ((size_t)1 << ((slot >> 1) - 1));
220     size_t j;
221     for (j = 0; j < k; j++)
222       g_FastPos[j] = (Byte)slot;
223     g_FastPos += k;
224   }
225 }
226 
227 /* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
228 /*
229 #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
230   (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
231   res = p->g_FastPos[pos >> zz] + (zz * 2); }
232 */
233 
234 /*
235 #define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
236   (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
237   res = p->g_FastPos[pos >> zz] + (zz * 2); }
238 */
239 
240 #define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
241   res = p->g_FastPos[pos >> zz] + (zz * 2); }
242 
243 /*
244 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
245   p->g_FastPos[pos >> 6] + 12 : \
246   p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
247 */
248 
249 #define GetPosSlot1(pos) p->g_FastPos[pos]
250 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
251 #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
252 
253 #endif // LZMA_LOG_BSR
254 
255 
256 #define LZMA_NUM_REPS 4
257 
258 typedef UInt16 CState;
259 typedef UInt16 CExtra;
260 
261 typedef struct
262 {
263   UInt32 price;
264   CState state;
265   CExtra extra;
266       // 0   : normal
267       // 1   : LIT : MATCH
268       // > 1 : MATCH (extra-1) : LIT : REP0 (len)
269   UInt32 len;
270   UInt32 dist;
271   UInt32 reps[LZMA_NUM_REPS];
272 } COptimal;
273 
274 
275 // 18.06
276 #define kNumOpts (1 << 11)
277 #define kPackReserve (kNumOpts * 8)
278 // #define kNumOpts (1 << 12)
279 // #define kPackReserve (1 + kNumOpts * 2)
280 
281 #define kNumLenToPosStates 4
282 #define kNumPosSlotBits 6
283 // #define kDicLogSizeMin 0
284 #define kDicLogSizeMax 32
285 #define kDistTableSizeMax (kDicLogSizeMax * 2)
286 
287 #define kNumAlignBits 4
288 #define kAlignTableSize (1 << kNumAlignBits)
289 #define kAlignMask (kAlignTableSize - 1)
290 
291 #define kStartPosModelIndex 4
292 #define kEndPosModelIndex 14
293 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
294 
295 typedef
296 #ifdef _LZMA_PROB32
297   UInt32
298 #else
299   UInt16
300 #endif
301   CLzmaProb;
302 
303 #define LZMA_PB_MAX 4
304 #define LZMA_LC_MAX 8
305 #define LZMA_LP_MAX 4
306 
307 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
308 
309 #define kLenNumLowBits 3
310 #define kLenNumLowSymbols (1 << kLenNumLowBits)
311 #define kLenNumHighBits 8
312 #define kLenNumHighSymbols (1 << kLenNumHighBits)
313 #define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
314 
315 #define LZMA_MATCH_LEN_MIN 2
316 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
317 
318 #define kNumStates 12
319 
320 
321 typedef struct
322 {
323   CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
324   CLzmaProb high[kLenNumHighSymbols];
325 } CLenEnc;
326 
327 
328 typedef struct
329 {
330   unsigned tableSize;
331   UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
332   // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2];
333   // UInt32 prices2[kLenNumSymbolsTotal];
334 } CLenPriceEnc;
335 
336 #define GET_PRICE_LEN(p, posState, len) \
337     ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN])
338 
339 /*
340 #define GET_PRICE_LEN(p, posState, len) \
341     ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9)))
342 */
343 
344 typedef struct
345 {
346   UInt32 range;
347   unsigned cache;
348   UInt64 low;
349   UInt64 cacheSize;
350   Byte *buf;
351   Byte *bufLim;
352   Byte *bufBase;
353   ISeqOutStream *outStream;
354   UInt64 processed;
355   SRes res;
356 } CRangeEnc;
357 
358 
359 typedef struct
360 {
361   CLzmaProb *litProbs;
362 
363   unsigned state;
364   UInt32 reps[LZMA_NUM_REPS];
365 
366   CLzmaProb posAlignEncoder[1 << kNumAlignBits];
367   CLzmaProb isRep[kNumStates];
368   CLzmaProb isRepG0[kNumStates];
369   CLzmaProb isRepG1[kNumStates];
370   CLzmaProb isRepG2[kNumStates];
371   CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
372   CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
373 
374   CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
375   CLzmaProb posEncoders[kNumFullDistances];
376 
377   CLenEnc lenProbs;
378   CLenEnc repLenProbs;
379 
380 } CSaveState;
381 
382 
383 typedef UInt32 CProbPrice;
384 
385 
386 typedef struct
387 {
388   void *matchFinderObj;
389   IMatchFinder2 matchFinder;
390 
391   unsigned optCur;
392   unsigned optEnd;
393 
394   unsigned longestMatchLen;
395   unsigned numPairs;
396   UInt32 numAvail;
397 
398   unsigned state;
399   unsigned numFastBytes;
400   unsigned additionalOffset;
401   UInt32 reps[LZMA_NUM_REPS];
402   unsigned lpMask, pbMask;
403   CLzmaProb *litProbs;
404   CRangeEnc rc;
405 
406   UInt32 backRes;
407 
408   unsigned lc, lp, pb;
409   unsigned lclp;
410 
411   BoolInt fastMode;
412   BoolInt writeEndMark;
413   BoolInt finished;
414   BoolInt multiThread;
415   BoolInt needInit;
416   // BoolInt _maxMode;
417 
418   UInt64 nowPos64;
419 
420   unsigned matchPriceCount;
421   // unsigned alignPriceCount;
422   int repLenEncCounter;
423 
424   unsigned distTableSize;
425 
426   UInt32 dictSize;
427   SRes result;
428 
429   #ifndef _7ZIP_ST
430   BoolInt mtMode;
431   // begin of CMatchFinderMt is used in LZ thread
432   CMatchFinderMt matchFinderMt;
433   // end of CMatchFinderMt is used in BT and HASH threads
434   // #else
435   // CMatchFinder matchFinderBase;
436   #endif
437   CMatchFinder matchFinderBase;
438 
439 
440   // we suppose that we have 8-bytes alignment after CMatchFinder
441 
442   #ifndef _7ZIP_ST
443   Byte pad[128];
444   #endif
445 
446   // LZ thread
447   CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
448 
449   // we want {len , dist} pairs to be 8-bytes aligned in matches array
450   UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2];
451 
452   // we want 8-bytes alignment here
453   UInt32 alignPrices[kAlignTableSize];
454   UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
455   UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
456 
457   CLzmaProb posAlignEncoder[1 << kNumAlignBits];
458   CLzmaProb isRep[kNumStates];
459   CLzmaProb isRepG0[kNumStates];
460   CLzmaProb isRepG1[kNumStates];
461   CLzmaProb isRepG2[kNumStates];
462   CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
463   CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
464   CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
465   CLzmaProb posEncoders[kNumFullDistances];
466 
467   CLenEnc lenProbs;
468   CLenEnc repLenProbs;
469 
470   #ifndef LZMA_LOG_BSR
471   Byte g_FastPos[1 << kNumLogBits];
472   #endif
473 
474   CLenPriceEnc lenEnc;
475   CLenPriceEnc repLenEnc;
476 
477   COptimal opt[kNumOpts];
478 
479   CSaveState saveState;
480 
481   // BoolInt mf_Failure;
482   #ifndef _7ZIP_ST
483   Byte pad2[128];
484   #endif
485 } CLzmaEnc;
486 
487 
488 #define MFB (p->matchFinderBase)
489 /*
490 #ifndef _7ZIP_ST
491 #define MFB (p->matchFinderMt.MatchFinder)
492 #endif
493 */
494 
495 #define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));
496 
LzmaEnc_SaveState(CLzmaEncHandle pp)497 void LzmaEnc_SaveState(CLzmaEncHandle pp)
498 {
499   CLzmaEnc *p = (CLzmaEnc *)pp;
500   CSaveState *dest = &p->saveState;
501 
502   dest->state = p->state;
503 
504   dest->lenProbs = p->lenProbs;
505   dest->repLenProbs = p->repLenProbs;
506 
507   COPY_ARR(dest, p, reps);
508 
509   COPY_ARR(dest, p, posAlignEncoder);
510   COPY_ARR(dest, p, isRep);
511   COPY_ARR(dest, p, isRepG0);
512   COPY_ARR(dest, p, isRepG1);
513   COPY_ARR(dest, p, isRepG2);
514   COPY_ARR(dest, p, isMatch);
515   COPY_ARR(dest, p, isRep0Long);
516   COPY_ARR(dest, p, posSlotEncoder);
517   COPY_ARR(dest, p, posEncoders);
518 
519   memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
520 }
521 
522 
LzmaEnc_RestoreState(CLzmaEncHandle pp)523 void LzmaEnc_RestoreState(CLzmaEncHandle pp)
524 {
525   CLzmaEnc *dest = (CLzmaEnc *)pp;
526   const CSaveState *p = &dest->saveState;
527 
528   dest->state = p->state;
529 
530   dest->lenProbs = p->lenProbs;
531   dest->repLenProbs = p->repLenProbs;
532 
533   COPY_ARR(dest, p, reps);
534 
535   COPY_ARR(dest, p, posAlignEncoder);
536   COPY_ARR(dest, p, isRep);
537   COPY_ARR(dest, p, isRepG0);
538   COPY_ARR(dest, p, isRepG1);
539   COPY_ARR(dest, p, isRepG2);
540   COPY_ARR(dest, p, isMatch);
541   COPY_ARR(dest, p, isRep0Long);
542   COPY_ARR(dest, p, posSlotEncoder);
543   COPY_ARR(dest, p, posEncoders);
544 
545   memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
546 }
547 
548 
549 
LzmaEnc_SetProps(CLzmaEncHandle pp,const CLzmaEncProps * props2)550 SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
551 {
552   CLzmaEnc *p = (CLzmaEnc *)pp;
553   CLzmaEncProps props = *props2;
554   LzmaEncProps_Normalize(&props);
555 
556   if (props.lc > LZMA_LC_MAX
557       || props.lp > LZMA_LP_MAX
558       || props.pb > LZMA_PB_MAX)
559     return SZ_ERROR_PARAM;
560 
561 
562   if (props.dictSize > kLzmaMaxHistorySize)
563     props.dictSize = kLzmaMaxHistorySize;
564 
565   #ifndef LZMA_LOG_BSR
566   {
567     const UInt64 dict64 = props.dictSize;
568     if (dict64 > ((UInt64)1 << kDicLogSizeMaxCompress))
569       return SZ_ERROR_PARAM;
570   }
571   #endif
572 
573   p->dictSize = props.dictSize;
574   {
575     unsigned fb = (unsigned)props.fb;
576     if (fb < 5)
577       fb = 5;
578     if (fb > LZMA_MATCH_LEN_MAX)
579       fb = LZMA_MATCH_LEN_MAX;
580     p->numFastBytes = fb;
581   }
582   p->lc = (unsigned)props.lc;
583   p->lp = (unsigned)props.lp;
584   p->pb = (unsigned)props.pb;
585   p->fastMode = (props.algo == 0);
586   // p->_maxMode = True;
587   MFB.btMode = (Byte)(props.btMode ? 1 : 0);
588   {
589     unsigned numHashBytes = 4;
590     if (props.btMode)
591     {
592            if (props.numHashBytes <  2) numHashBytes = 2;
593       else if (props.numHashBytes <  4) numHashBytes = (unsigned)props.numHashBytes;
594     }
595     if (props.numHashBytes >= 5) numHashBytes = 5;
596 
597     MFB.numHashBytes = numHashBytes;
598   }
599 
600   MFB.cutValue = props.mc;
601 
602   p->writeEndMark = (BoolInt)props.writeEndMark;
603 
604   #ifndef _7ZIP_ST
605   /*
606   if (newMultiThread != _multiThread)
607   {
608     ReleaseMatchFinder();
609     _multiThread = newMultiThread;
610   }
611   */
612   p->multiThread = (props.numThreads > 1);
613   p->matchFinderMt.btSync.affinity =
614   p->matchFinderMt.hashSync.affinity = props.affinity;
615   #endif
616 
617   return SZ_OK;
618 }
619 
620 
LzmaEnc_SetDataSize(CLzmaEncHandle pp,UInt64 expectedDataSiize)621 void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
622 {
623   CLzmaEnc *p = (CLzmaEnc *)pp;
624   MFB.expectedDataSize = expectedDataSiize;
625 }
626 
627 
628 #define kState_Start 0
629 #define kState_LitAfterMatch 4
630 #define kState_LitAfterRep   5
631 #define kState_MatchAfterLit 7
632 #define kState_RepAfterLit   8
633 
634 static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
635 static const Byte kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
636 static const Byte kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
637 static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
638 
639 #define IsLitState(s) ((s) < 7)
640 #define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
641 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
642 
643 #define kInfinityPrice (1 << 30)
644 
RangeEnc_Construct(CRangeEnc * p)645 static void RangeEnc_Construct(CRangeEnc *p)
646 {
647   p->outStream = NULL;
648   p->bufBase = NULL;
649 }
650 
651 #define RangeEnc_GetProcessed(p)       (        (p)->processed + (size_t)((p)->buf - (p)->bufBase) +         (p)->cacheSize)
652 #define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + (size_t)((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
653 
654 #define RC_BUF_SIZE (1 << 16)
655 
RangeEnc_Alloc(CRangeEnc * p,ISzAllocPtr alloc)656 static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
657 {
658   if (!p->bufBase)
659   {
660     p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
661     if (!p->bufBase)
662       return 0;
663     p->bufLim = p->bufBase + RC_BUF_SIZE;
664   }
665   return 1;
666 }
667 
RangeEnc_Free(CRangeEnc * p,ISzAllocPtr alloc)668 static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
669 {
670   ISzAlloc_Free(alloc, p->bufBase);
671   p->bufBase = NULL;
672 }
673 
RangeEnc_Init(CRangeEnc * p)674 static void RangeEnc_Init(CRangeEnc *p)
675 {
676   p->range = 0xFFFFFFFF;
677   p->cache = 0;
678   p->low = 0;
679   p->cacheSize = 0;
680 
681   p->buf = p->bufBase;
682 
683   p->processed = 0;
684   p->res = SZ_OK;
685 }
686 
RangeEnc_FlushStream(CRangeEnc * p)687 MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
688 {
689   const size_t num = (size_t)(p->buf - p->bufBase);
690   if (p->res == SZ_OK)
691   {
692     if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
693       p->res = SZ_ERROR_WRITE;
694   }
695   p->processed += num;
696   p->buf = p->bufBase;
697 }
698 
RangeEnc_ShiftLow(CRangeEnc * p)699 MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
700 {
701   UInt32 low = (UInt32)p->low;
702   unsigned high = (unsigned)(p->low >> 32);
703   p->low = (UInt32)(low << 8);
704   if (low < (UInt32)0xFF000000 || high != 0)
705   {
706     {
707       Byte *buf = p->buf;
708       *buf++ = (Byte)(p->cache + high);
709       p->cache = (unsigned)(low >> 24);
710       p->buf = buf;
711       if (buf == p->bufLim)
712         RangeEnc_FlushStream(p);
713       if (p->cacheSize == 0)
714         return;
715     }
716     high += 0xFF;
717     for (;;)
718     {
719       Byte *buf = p->buf;
720       *buf++ = (Byte)(high);
721       p->buf = buf;
722       if (buf == p->bufLim)
723         RangeEnc_FlushStream(p);
724       if (--p->cacheSize == 0)
725         return;
726     }
727   }
728   p->cacheSize++;
729 }
730 
RangeEnc_FlushData(CRangeEnc * p)731 static void RangeEnc_FlushData(CRangeEnc *p)
732 {
733   int i;
734   for (i = 0; i < 5; i++)
735     RangeEnc_ShiftLow(p);
736 }
737 
738 #define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
739 
740 #define RC_BIT_PRE(p, prob) \
741   ttt = *(prob); \
742   newBound = (range >> kNumBitModelTotalBits) * ttt;
743 
744 // #define _LZMA_ENC_USE_BRANCH
745 
746 #ifdef _LZMA_ENC_USE_BRANCH
747 
748 #define RC_BIT(p, prob, bit) { \
749   RC_BIT_PRE(p, prob) \
750   if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
751   else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
752   *(prob) = (CLzmaProb)ttt; \
753   RC_NORM(p) \
754   }
755 
756 #else
757 
758 #define RC_BIT(p, prob, bit) { \
759   UInt32 mask; \
760   RC_BIT_PRE(p, prob) \
761   mask = 0 - (UInt32)bit; \
762   range &= mask; \
763   mask &= newBound; \
764   range -= mask; \
765   (p)->low += mask; \
766   mask = (UInt32)bit - 1; \
767   range += newBound & mask; \
768   mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
769   mask += ((1 << kNumMoveBits) - 1); \
770   ttt += (UInt32)((Int32)(mask - ttt) >> kNumMoveBits); \
771   *(prob) = (CLzmaProb)ttt; \
772   RC_NORM(p) \
773   }
774 
775 #endif
776 
777 
778 
779 
780 #define RC_BIT_0_BASE(p, prob) \
781   range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
782 
783 #define RC_BIT_1_BASE(p, prob) \
784   range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
785 
786 #define RC_BIT_0(p, prob) \
787   RC_BIT_0_BASE(p, prob) \
788   RC_NORM(p)
789 
790 #define RC_BIT_1(p, prob) \
791   RC_BIT_1_BASE(p, prob) \
792   RC_NORM(p)
793 
RangeEnc_EncodeBit_0(CRangeEnc * p,CLzmaProb * prob)794 static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
795 {
796   UInt32 range, ttt, newBound;
797   range = p->range;
798   RC_BIT_PRE(p, prob)
799   RC_BIT_0(p, prob)
800   p->range = range;
801 }
802 
LitEnc_Encode(CRangeEnc * p,CLzmaProb * probs,UInt32 sym)803 static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym)
804 {
805   UInt32 range = p->range;
806   sym |= 0x100;
807   do
808   {
809     UInt32 ttt, newBound;
810     // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1);
811     CLzmaProb *prob = probs + (sym >> 8);
812     UInt32 bit = (sym >> 7) & 1;
813     sym <<= 1;
814     RC_BIT(p, prob, bit);
815   }
816   while (sym < 0x10000);
817   p->range = range;
818 }
819 
LitEnc_EncodeMatched(CRangeEnc * p,CLzmaProb * probs,UInt32 sym,UInt32 matchByte)820 static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte)
821 {
822   UInt32 range = p->range;
823   UInt32 offs = 0x100;
824   sym |= 0x100;
825   do
826   {
827     UInt32 ttt, newBound;
828     CLzmaProb *prob;
829     UInt32 bit;
830     matchByte <<= 1;
831     // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1);
832     prob = probs + (offs + (matchByte & offs) + (sym >> 8));
833     bit = (sym >> 7) & 1;
834     sym <<= 1;
835     offs &= ~(matchByte ^ sym);
836     RC_BIT(p, prob, bit);
837   }
838   while (sym < 0x10000);
839   p->range = range;
840 }
841 
842 
843 
LzmaEnc_InitPriceTables(CProbPrice * ProbPrices)844 static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
845 {
846   UInt32 i;
847   for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
848   {
849     const unsigned kCyclesBits = kNumBitPriceShiftBits;
850     UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
851     unsigned bitCount = 0;
852     unsigned j;
853     for (j = 0; j < kCyclesBits; j++)
854     {
855       w = w * w;
856       bitCount <<= 1;
857       while (w >= ((UInt32)1 << 16))
858       {
859         w >>= 1;
860         bitCount++;
861       }
862     }
863     ProbPrices[i] = (CProbPrice)(((unsigned)kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
864     // printf("\n%3d: %5d", i, ProbPrices[i]);
865   }
866 }
867 
868 
869 #define GET_PRICE(prob, bit) \
870   p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
871 
872 #define GET_PRICEa(prob, bit) \
873      ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
874 
875 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
876 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
877 
878 #define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
879 #define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
880 
881 
LitEnc_GetPrice(const CLzmaProb * probs,UInt32 sym,const CProbPrice * ProbPrices)882 static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices)
883 {
884   UInt32 price = 0;
885   sym |= 0x100;
886   do
887   {
888     unsigned bit = sym & 1;
889     sym >>= 1;
890     price += GET_PRICEa(probs[sym], bit);
891   }
892   while (sym >= 2);
893   return price;
894 }
895 
896 
LitEnc_Matched_GetPrice(const CLzmaProb * probs,UInt32 sym,UInt32 matchByte,const CProbPrice * ProbPrices)897 static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices)
898 {
899   UInt32 price = 0;
900   UInt32 offs = 0x100;
901   sym |= 0x100;
902   do
903   {
904     matchByte <<= 1;
905     price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1);
906     sym <<= 1;
907     offs &= ~(matchByte ^ sym);
908   }
909   while (sym < 0x10000);
910   return price;
911 }
912 
913 
RcTree_ReverseEncode(CRangeEnc * rc,CLzmaProb * probs,unsigned numBits,unsigned sym)914 static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym)
915 {
916   UInt32 range = rc->range;
917   unsigned m = 1;
918   do
919   {
920     UInt32 ttt, newBound;
921     unsigned bit = sym & 1;
922     // RangeEnc_EncodeBit(rc, probs + m, bit);
923     sym >>= 1;
924     RC_BIT(rc, probs + m, bit);
925     m = (m << 1) | bit;
926   }
927   while (--numBits);
928   rc->range = range;
929 }
930 
931 
932 
LenEnc_Init(CLenEnc * p)933 static void LenEnc_Init(CLenEnc *p)
934 {
935   unsigned i;
936   for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
937     p->low[i] = kProbInitValue;
938   for (i = 0; i < kLenNumHighSymbols; i++)
939     p->high[i] = kProbInitValue;
940 }
941 
LenEnc_Encode(CLenEnc * p,CRangeEnc * rc,unsigned sym,unsigned posState)942 static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState)
943 {
944   UInt32 range, ttt, newBound;
945   CLzmaProb *probs = p->low;
946   range = rc->range;
947   RC_BIT_PRE(rc, probs);
948   if (sym >= kLenNumLowSymbols)
949   {
950     RC_BIT_1(rc, probs);
951     probs += kLenNumLowSymbols;
952     RC_BIT_PRE(rc, probs);
953     if (sym >= kLenNumLowSymbols * 2)
954     {
955       RC_BIT_1(rc, probs);
956       rc->range = range;
957       // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2);
958       LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2);
959       return;
960     }
961     sym -= kLenNumLowSymbols;
962   }
963 
964   // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym);
965   {
966     unsigned m;
967     unsigned bit;
968     RC_BIT_0(rc, probs);
969     probs += (posState << (1 + kLenNumLowBits));
970     bit = (sym >> 2)    ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
971     bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
972     bit =  sym       & 1; RC_BIT(rc, probs + m, bit);
973     rc->range = range;
974   }
975 }
976 
SetPrices_3(const CLzmaProb * probs,UInt32 startPrice,UInt32 * prices,const CProbPrice * ProbPrices)977 static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
978 {
979   unsigned i;
980   for (i = 0; i < 8; i += 2)
981   {
982     UInt32 price = startPrice;
983     UInt32 prob;
984     price += GET_PRICEa(probs[1           ], (i >> 2));
985     price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
986     prob = probs[4 + (i >> 1)];
987     prices[i    ] = price + GET_PRICEa_0(prob);
988     prices[i + 1] = price + GET_PRICEa_1(prob);
989   }
990 }
991 
992 
LenPriceEnc_UpdateTables(CLenPriceEnc * p,unsigned numPosStates,const CLenEnc * enc,const CProbPrice * ProbPrices)993 MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables(
994     CLenPriceEnc *p,
995     unsigned numPosStates,
996     const CLenEnc *enc,
997     const CProbPrice *ProbPrices)
998 {
999   UInt32 b;
1000 
1001   {
1002     unsigned prob = enc->low[0];
1003     UInt32 a, c;
1004     unsigned posState;
1005     b = GET_PRICEa_1(prob);
1006     a = GET_PRICEa_0(prob);
1007     c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
1008     for (posState = 0; posState < numPosStates; posState++)
1009     {
1010       UInt32 *prices = p->prices[posState];
1011       const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
1012       SetPrices_3(probs, a, prices, ProbPrices);
1013       SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices);
1014     }
1015   }
1016 
1017   /*
1018   {
1019     unsigned i;
1020     UInt32 b;
1021     a = GET_PRICEa_0(enc->low[0]);
1022     for (i = 0; i < kLenNumLowSymbols; i++)
1023       p->prices2[i] = a;
1024     a = GET_PRICEa_1(enc->low[0]);
1025     b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
1026     for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++)
1027       p->prices2[i] = b;
1028     a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
1029   }
1030   */
1031 
1032   // p->counter = numSymbols;
1033   // p->counter = 64;
1034 
1035   {
1036     unsigned i = p->tableSize;
1037 
1038     if (i > kLenNumLowSymbols * 2)
1039     {
1040       const CLzmaProb *probs = enc->high;
1041       UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2;
1042       i -= kLenNumLowSymbols * 2 - 1;
1043       i >>= 1;
1044       b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
1045       do
1046       {
1047         /*
1048         p->prices2[i] = a +
1049         // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
1050         LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices);
1051         */
1052         // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices);
1053         unsigned sym = --i + (1 << (kLenNumHighBits - 1));
1054         UInt32 price = b;
1055         do
1056         {
1057           unsigned bit = sym & 1;
1058           sym >>= 1;
1059           price += GET_PRICEa(probs[sym], bit);
1060         }
1061         while (sym >= 2);
1062 
1063         {
1064           unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];
1065           prices[(size_t)i * 2    ] = price + GET_PRICEa_0(prob);
1066           prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);
1067         }
1068       }
1069       while (i);
1070 
1071       {
1072         unsigned posState;
1073         size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);
1074         for (posState = 1; posState < numPosStates; posState++)
1075           memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
1076       }
1077     }
1078   }
1079 }
1080 
1081 /*
1082   #ifdef SHOW_STAT
1083   g_STAT_OFFSET += num;
1084   printf("\n MovePos %u", num);
1085   #endif
1086 */
1087 
1088 #define MOVE_POS(p, num) { \
1089     p->additionalOffset += (num); \
1090     p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }
1091 
1092 
ReadMatchDistances(CLzmaEnc * p,unsigned * numPairsRes)1093 static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
1094 {
1095   unsigned numPairs;
1096 
1097   p->additionalOffset++;
1098   p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
1099   {
1100     const UInt32 *d = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
1101     // if (!d) { p->mf_Failure = True; *numPairsRes = 0;  return 0; }
1102     numPairs = (unsigned)(d - p->matches);
1103   }
1104   *numPairsRes = numPairs;
1105 
1106   #ifdef SHOW_STAT
1107   printf("\n i = %u numPairs = %u    ", g_STAT_OFFSET, numPairs / 2);
1108   g_STAT_OFFSET++;
1109   {
1110     unsigned i;
1111     for (i = 0; i < numPairs; i += 2)
1112       printf("%2u %6u   | ", p->matches[i], p->matches[i + 1]);
1113   }
1114   #endif
1115 
1116   if (numPairs == 0)
1117     return 0;
1118   {
1119     const unsigned len = p->matches[(size_t)numPairs - 2];
1120     if (len != p->numFastBytes)
1121       return len;
1122     {
1123       UInt32 numAvail = p->numAvail;
1124       if (numAvail > LZMA_MATCH_LEN_MAX)
1125         numAvail = LZMA_MATCH_LEN_MAX;
1126       {
1127         const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1128         const Byte *p2 = p1 + len;
1129         const ptrdiff_t dif = (ptrdiff_t)-1 - (ptrdiff_t)p->matches[(size_t)numPairs - 1];
1130         const Byte *lim = p1 + numAvail;
1131         for (; p2 != lim && *p2 == p2[dif]; p2++)
1132         {}
1133         return (unsigned)(p2 - p1);
1134       }
1135     }
1136   }
1137 }
1138 
1139 #define MARK_LIT ((UInt32)(Int32)-1)
1140 
1141 #define MakeAs_Lit(p)       { (p)->dist = MARK_LIT; (p)->extra = 0; }
1142 #define MakeAs_ShortRep(p)  { (p)->dist = 0; (p)->extra = 0; }
1143 #define IsShortRep(p)       ((p)->dist == 0)
1144 
1145 
1146 #define GetPrice_ShortRep(p, state, posState) \
1147   ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
1148 
1149 #define GetPrice_Rep_0(p, state, posState) ( \
1150     GET_PRICE_1(p->isMatch[state][posState]) \
1151   + GET_PRICE_1(p->isRep0Long[state][posState])) \
1152   + GET_PRICE_1(p->isRep[state]) \
1153   + GET_PRICE_0(p->isRepG0[state])
1154 
1155 MY_FORCE_INLINE
GetPrice_PureRep(const CLzmaEnc * p,unsigned repIndex,size_t state,size_t posState)1156 static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
1157 {
1158   UInt32 price;
1159   UInt32 prob = p->isRepG0[state];
1160   if (repIndex == 0)
1161   {
1162     price = GET_PRICE_0(prob);
1163     price += GET_PRICE_1(p->isRep0Long[state][posState]);
1164   }
1165   else
1166   {
1167     price = GET_PRICE_1(prob);
1168     prob = p->isRepG1[state];
1169     if (repIndex == 1)
1170       price += GET_PRICE_0(prob);
1171     else
1172     {
1173       price += GET_PRICE_1(prob);
1174       price += GET_PRICE(p->isRepG2[state], repIndex - 2);
1175     }
1176   }
1177   return price;
1178 }
1179 
1180 
Backward(CLzmaEnc * p,unsigned cur)1181 static unsigned Backward(CLzmaEnc *p, unsigned cur)
1182 {
1183   unsigned wr = cur + 1;
1184   p->optEnd = wr;
1185 
1186   for (;;)
1187   {
1188     UInt32 dist = p->opt[cur].dist;
1189     unsigned len = (unsigned)p->opt[cur].len;
1190     unsigned extra = (unsigned)p->opt[cur].extra;
1191     cur -= len;
1192 
1193     if (extra)
1194     {
1195       wr--;
1196       p->opt[wr].len = (UInt32)len;
1197       cur -= extra;
1198       len = extra;
1199       if (extra == 1)
1200       {
1201         p->opt[wr].dist = dist;
1202         dist = MARK_LIT;
1203       }
1204       else
1205       {
1206         p->opt[wr].dist = 0;
1207         len--;
1208         wr--;
1209         p->opt[wr].dist = MARK_LIT;
1210         p->opt[wr].len = 1;
1211       }
1212     }
1213 
1214     if (cur == 0)
1215     {
1216       p->backRes = dist;
1217       p->optCur = wr;
1218       return len;
1219     }
1220 
1221     wr--;
1222     p->opt[wr].dist = dist;
1223     p->opt[wr].len = (UInt32)len;
1224   }
1225 }
1226 
1227 
1228 
1229 #define LIT_PROBS(pos, prevByte) \
1230   (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))
1231 
1232 
GetOptimum(CLzmaEnc * p,UInt32 position)1233 static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
1234 {
1235   unsigned last, cur;
1236   UInt32 reps[LZMA_NUM_REPS];
1237   unsigned repLens[LZMA_NUM_REPS];
1238   UInt32 *matches;
1239 
1240   {
1241     UInt32 numAvail;
1242     unsigned numPairs, mainLen, repMaxIndex, i, posState;
1243     UInt32 matchPrice, repMatchPrice;
1244     const Byte *data;
1245     Byte curByte, matchByte;
1246 
1247     p->optCur = p->optEnd = 0;
1248 
1249     if (p->additionalOffset == 0)
1250       mainLen = ReadMatchDistances(p, &numPairs);
1251     else
1252     {
1253       mainLen = p->longestMatchLen;
1254       numPairs = p->numPairs;
1255     }
1256 
1257     numAvail = p->numAvail;
1258     if (numAvail < 2)
1259     {
1260       p->backRes = MARK_LIT;
1261       return 1;
1262     }
1263     if (numAvail > LZMA_MATCH_LEN_MAX)
1264       numAvail = LZMA_MATCH_LEN_MAX;
1265 
1266     data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1267     repMaxIndex = 0;
1268 
1269     for (i = 0; i < LZMA_NUM_REPS; i++)
1270     {
1271       unsigned len;
1272       const Byte *data2;
1273       reps[i] = p->reps[i];
1274       data2 = data - reps[i];
1275       if (data[0] != data2[0] || data[1] != data2[1])
1276       {
1277         repLens[i] = 0;
1278         continue;
1279       }
1280       for (len = 2; len < numAvail && data[len] == data2[len]; len++)
1281       {}
1282       repLens[i] = len;
1283       if (len > repLens[repMaxIndex])
1284         repMaxIndex = i;
1285       if (len == LZMA_MATCH_LEN_MAX) // 21.03 : optimization
1286         break;
1287     }
1288 
1289     if (repLens[repMaxIndex] >= p->numFastBytes)
1290     {
1291       unsigned len;
1292       p->backRes = (UInt32)repMaxIndex;
1293       len = repLens[repMaxIndex];
1294       MOVE_POS(p, len - 1)
1295       return len;
1296     }
1297 
1298     matches = p->matches;
1299     #define MATCHES  matches
1300     // #define MATCHES  p->matches
1301 
1302     if (mainLen >= p->numFastBytes)
1303     {
1304       p->backRes = MATCHES[(size_t)numPairs - 1] + LZMA_NUM_REPS;
1305       MOVE_POS(p, mainLen - 1)
1306       return mainLen;
1307     }
1308 
1309     curByte = *data;
1310     matchByte = *(data - reps[0]);
1311 
1312     last = repLens[repMaxIndex];
1313     if (last <= mainLen)
1314       last = mainLen;
1315 
1316     if (last < 2 && curByte != matchByte)
1317     {
1318       p->backRes = MARK_LIT;
1319       return 1;
1320     }
1321 
1322     p->opt[0].state = (CState)p->state;
1323 
1324     posState = (position & p->pbMask);
1325 
1326     {
1327       const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1328       p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
1329         (!IsLitState(p->state) ?
1330           LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
1331           LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1332     }
1333 
1334     MakeAs_Lit(&p->opt[1]);
1335 
1336     matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
1337     repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
1338 
1339     // 18.06
1340     if (matchByte == curByte && repLens[0] == 0)
1341     {
1342       UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
1343       if (shortRepPrice < p->opt[1].price)
1344       {
1345         p->opt[1].price = shortRepPrice;
1346         MakeAs_ShortRep(&p->opt[1]);
1347       }
1348       if (last < 2)
1349       {
1350         p->backRes = p->opt[1].dist;
1351         return 1;
1352       }
1353     }
1354 
1355     p->opt[1].len = 1;
1356 
1357     p->opt[0].reps[0] = reps[0];
1358     p->opt[0].reps[1] = reps[1];
1359     p->opt[0].reps[2] = reps[2];
1360     p->opt[0].reps[3] = reps[3];
1361 
1362     // ---------- REP ----------
1363 
1364     for (i = 0; i < LZMA_NUM_REPS; i++)
1365     {
1366       unsigned repLen = repLens[i];
1367       UInt32 price;
1368       if (repLen < 2)
1369         continue;
1370       price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
1371       do
1372       {
1373         UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen);
1374         COptimal *opt = &p->opt[repLen];
1375         if (price2 < opt->price)
1376         {
1377           opt->price = price2;
1378           opt->len = (UInt32)repLen;
1379           opt->dist = (UInt32)i;
1380           opt->extra = 0;
1381         }
1382       }
1383       while (--repLen >= 2);
1384     }
1385 
1386 
1387     // ---------- MATCH ----------
1388     {
1389       unsigned len = repLens[0] + 1;
1390       if (len <= mainLen)
1391       {
1392         unsigned offs = 0;
1393         UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
1394 
1395         if (len < 2)
1396           len = 2;
1397         else
1398           while (len > MATCHES[offs])
1399             offs += 2;
1400 
1401         for (; ; len++)
1402         {
1403           COptimal *opt;
1404           UInt32 dist = MATCHES[(size_t)offs + 1];
1405           UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
1406           unsigned lenToPosState = GetLenToPosState(len);
1407 
1408           if (dist < kNumFullDistances)
1409             price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
1410           else
1411           {
1412             unsigned slot;
1413             GetPosSlot2(dist, slot);
1414             price += p->alignPrices[dist & kAlignMask];
1415             price += p->posSlotPrices[lenToPosState][slot];
1416           }
1417 
1418           opt = &p->opt[len];
1419 
1420           if (price < opt->price)
1421           {
1422             opt->price = price;
1423             opt->len = (UInt32)len;
1424             opt->dist = dist + LZMA_NUM_REPS;
1425             opt->extra = 0;
1426           }
1427 
1428           if (len == MATCHES[offs])
1429           {
1430             offs += 2;
1431             if (offs == numPairs)
1432               break;
1433           }
1434         }
1435       }
1436     }
1437 
1438 
1439     cur = 0;
1440 
1441     #ifdef SHOW_STAT2
1442     /* if (position >= 0) */
1443     {
1444       unsigned i;
1445       printf("\n pos = %4X", position);
1446       for (i = cur; i <= last; i++)
1447       printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
1448     }
1449     #endif
1450   }
1451 
1452 
1453 
1454   // ---------- Optimal Parsing ----------
1455 
1456   for (;;)
1457   {
1458     unsigned numAvail;
1459     UInt32 numAvailFull;
1460     unsigned newLen, numPairs, prev, state, posState, startLen;
1461     UInt32 litPrice, matchPrice, repMatchPrice;
1462     BoolInt nextIsLit;
1463     Byte curByte, matchByte;
1464     const Byte *data;
1465     COptimal *curOpt, *nextOpt;
1466 
1467     if (++cur == last)
1468       break;
1469 
1470     // 18.06
1471     if (cur >= kNumOpts - 64)
1472     {
1473       unsigned j, best;
1474       UInt32 price = p->opt[cur].price;
1475       best = cur;
1476       for (j = cur + 1; j <= last; j++)
1477       {
1478         UInt32 price2 = p->opt[j].price;
1479         if (price >= price2)
1480         {
1481           price = price2;
1482           best = j;
1483         }
1484       }
1485       {
1486         unsigned delta = best - cur;
1487         if (delta != 0)
1488         {
1489           MOVE_POS(p, delta);
1490         }
1491       }
1492       cur = best;
1493       break;
1494     }
1495 
1496     newLen = ReadMatchDistances(p, &numPairs);
1497 
1498     if (newLen >= p->numFastBytes)
1499     {
1500       p->numPairs = numPairs;
1501       p->longestMatchLen = newLen;
1502       break;
1503     }
1504 
1505     curOpt = &p->opt[cur];
1506 
1507     position++;
1508 
1509     // we need that check here, if skip_items in p->opt are possible
1510     /*
1511     if (curOpt->price >= kInfinityPrice)
1512       continue;
1513     */
1514 
1515     prev = cur - curOpt->len;
1516 
1517     if (curOpt->len == 1)
1518     {
1519       state = (unsigned)p->opt[prev].state;
1520       if (IsShortRep(curOpt))
1521         state = kShortRepNextStates[state];
1522       else
1523         state = kLiteralNextStates[state];
1524     }
1525     else
1526     {
1527       const COptimal *prevOpt;
1528       UInt32 b0;
1529       UInt32 dist = curOpt->dist;
1530 
1531       if (curOpt->extra)
1532       {
1533         prev -= (unsigned)curOpt->extra;
1534         state = kState_RepAfterLit;
1535         if (curOpt->extra == 1)
1536           state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit);
1537       }
1538       else
1539       {
1540         state = (unsigned)p->opt[prev].state;
1541         if (dist < LZMA_NUM_REPS)
1542           state = kRepNextStates[state];
1543         else
1544           state = kMatchNextStates[state];
1545       }
1546 
1547       prevOpt = &p->opt[prev];
1548       b0 = prevOpt->reps[0];
1549 
1550       if (dist < LZMA_NUM_REPS)
1551       {
1552         if (dist == 0)
1553         {
1554           reps[0] = b0;
1555           reps[1] = prevOpt->reps[1];
1556           reps[2] = prevOpt->reps[2];
1557           reps[3] = prevOpt->reps[3];
1558         }
1559         else
1560         {
1561           reps[1] = b0;
1562           b0 = prevOpt->reps[1];
1563           if (dist == 1)
1564           {
1565             reps[0] = b0;
1566             reps[2] = prevOpt->reps[2];
1567             reps[3] = prevOpt->reps[3];
1568           }
1569           else
1570           {
1571             reps[2] = b0;
1572             reps[0] = prevOpt->reps[dist];
1573             reps[3] = prevOpt->reps[dist ^ 1];
1574           }
1575         }
1576       }
1577       else
1578       {
1579         reps[0] = (dist - LZMA_NUM_REPS + 1);
1580         reps[1] = b0;
1581         reps[2] = prevOpt->reps[1];
1582         reps[3] = prevOpt->reps[2];
1583       }
1584     }
1585 
1586     curOpt->state = (CState)state;
1587     curOpt->reps[0] = reps[0];
1588     curOpt->reps[1] = reps[1];
1589     curOpt->reps[2] = reps[2];
1590     curOpt->reps[3] = reps[3];
1591 
1592     data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1593     curByte = *data;
1594     matchByte = *(data - reps[0]);
1595 
1596     posState = (position & p->pbMask);
1597 
1598     /*
1599     The order of Price checks:
1600        <  LIT
1601        <= SHORT_REP
1602        <  LIT : REP_0
1603        <  REP    [ : LIT : REP_0 ]
1604        <  MATCH  [ : LIT : REP_0 ]
1605     */
1606 
1607     {
1608       UInt32 curPrice = curOpt->price;
1609       unsigned prob = p->isMatch[state][posState];
1610       matchPrice = curPrice + GET_PRICE_1(prob);
1611       litPrice = curPrice + GET_PRICE_0(prob);
1612     }
1613 
1614     nextOpt = &p->opt[(size_t)cur + 1];
1615     nextIsLit = False;
1616 
1617     // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice)
1618     // 18.new.06
1619     if ((nextOpt->price < kInfinityPrice
1620         // && !IsLitState(state)
1621         && matchByte == curByte)
1622         || litPrice > nextOpt->price
1623         )
1624       litPrice = 0;
1625     else
1626     {
1627       const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1628       litPrice += (!IsLitState(state) ?
1629           LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
1630           LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1631 
1632       if (litPrice < nextOpt->price)
1633       {
1634         nextOpt->price = litPrice;
1635         nextOpt->len = 1;
1636         MakeAs_Lit(nextOpt);
1637         nextIsLit = True;
1638       }
1639     }
1640 
1641     repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
1642 
1643     numAvailFull = p->numAvail;
1644     {
1645       unsigned temp = kNumOpts - 1 - cur;
1646       if (numAvailFull > temp)
1647         numAvailFull = (UInt32)temp;
1648     }
1649 
1650     // 18.06
1651     // ---------- SHORT_REP ----------
1652     if (IsLitState(state)) // 18.new
1653     if (matchByte == curByte)
1654     if (repMatchPrice < nextOpt->price) // 18.new
1655     // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1))
1656     if (
1657         // nextOpt->price >= kInfinityPrice ||
1658         nextOpt->len < 2   // we can check nextOpt->len, if skip items are not allowed in p->opt
1659         || (nextOpt->dist != 0
1660             // && nextOpt->extra <= 1 // 17.old
1661             )
1662         )
1663     {
1664       UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
1665       // if (shortRepPrice <= nextOpt->price) // 17.old
1666       if (shortRepPrice < nextOpt->price)  // 18.new
1667       {
1668         nextOpt->price = shortRepPrice;
1669         nextOpt->len = 1;
1670         MakeAs_ShortRep(nextOpt);
1671         nextIsLit = False;
1672       }
1673     }
1674 
1675     if (numAvailFull < 2)
1676       continue;
1677     numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
1678 
1679     // numAvail <= p->numFastBytes
1680 
1681     // ---------- LIT : REP_0 ----------
1682 
1683     if (!nextIsLit
1684         && litPrice != 0 // 18.new
1685         && matchByte != curByte
1686         && numAvailFull > 2)
1687     {
1688       const Byte *data2 = data - reps[0];
1689       if (data[1] == data2[1] && data[2] == data2[2])
1690       {
1691         unsigned len;
1692         unsigned limit = p->numFastBytes + 1;
1693         if (limit > numAvailFull)
1694           limit = numAvailFull;
1695         for (len = 3; len < limit && data[len] == data2[len]; len++)
1696         {}
1697 
1698         {
1699           unsigned state2 = kLiteralNextStates[state];
1700           unsigned posState2 = (position + 1) & p->pbMask;
1701           UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
1702           {
1703             unsigned offset = cur + len;
1704 
1705             if (last < offset)
1706               last = offset;
1707 
1708             // do
1709             {
1710               UInt32 price2;
1711               COptimal *opt;
1712               len--;
1713               // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
1714               price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len);
1715 
1716               opt = &p->opt[offset];
1717               // offset--;
1718               if (price2 < opt->price)
1719               {
1720                 opt->price = price2;
1721                 opt->len = (UInt32)len;
1722                 opt->dist = 0;
1723                 opt->extra = 1;
1724               }
1725             }
1726             // while (len >= 3);
1727           }
1728         }
1729       }
1730     }
1731 
1732     startLen = 2; /* speed optimization */
1733 
1734     {
1735       // ---------- REP ----------
1736       unsigned repIndex = 0; // 17.old
1737       // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused
1738       for (; repIndex < LZMA_NUM_REPS; repIndex++)
1739       {
1740         unsigned len;
1741         UInt32 price;
1742         const Byte *data2 = data - reps[repIndex];
1743         if (data[0] != data2[0] || data[1] != data2[1])
1744           continue;
1745 
1746         for (len = 2; len < numAvail && data[len] == data2[len]; len++)
1747         {}
1748 
1749         // if (len < startLen) continue; // 18.new: speed optimization
1750 
1751         {
1752           unsigned offset = cur + len;
1753           if (last < offset)
1754             last = offset;
1755         }
1756         {
1757           unsigned len2 = len;
1758           price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
1759           do
1760           {
1761             UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2);
1762             COptimal *opt = &p->opt[cur + len2];
1763             if (price2 < opt->price)
1764             {
1765               opt->price = price2;
1766               opt->len = (UInt32)len2;
1767               opt->dist = (UInt32)repIndex;
1768               opt->extra = 0;
1769             }
1770           }
1771           while (--len2 >= 2);
1772         }
1773 
1774         if (repIndex == 0) startLen = len + 1;  // 17.old
1775         // startLen = len + 1; // 18.new
1776 
1777         /* if (_maxMode) */
1778         {
1779           // ---------- REP : LIT : REP_0 ----------
1780           // numFastBytes + 1 + numFastBytes
1781 
1782           unsigned len2 = len + 1;
1783           unsigned limit = len2 + p->numFastBytes;
1784           if (limit > numAvailFull)
1785             limit = numAvailFull;
1786 
1787           len2 += 2;
1788           if (len2 <= limit)
1789           if (data[len2 - 2] == data2[len2 - 2])
1790           if (data[len2 - 1] == data2[len2 - 1])
1791           {
1792             unsigned state2 = kRepNextStates[state];
1793             unsigned posState2 = (position + len) & p->pbMask;
1794             price += GET_PRICE_LEN(&p->repLenEnc, posState, len)
1795                 + GET_PRICE_0(p->isMatch[state2][posState2])
1796                 + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
1797                     data[len], data2[len], p->ProbPrices);
1798 
1799             // state2 = kLiteralNextStates[state2];
1800             state2 = kState_LitAfterRep;
1801             posState2 = (posState2 + 1) & p->pbMask;
1802 
1803 
1804             price += GetPrice_Rep_0(p, state2, posState2);
1805 
1806           for (; len2 < limit && data[len2] == data2[len2]; len2++)
1807           {}
1808 
1809           len2 -= len;
1810           // if (len2 >= 3)
1811           {
1812             {
1813               unsigned offset = cur + len + len2;
1814 
1815               if (last < offset)
1816                 last = offset;
1817               // do
1818               {
1819                 UInt32 price2;
1820                 COptimal *opt;
1821                 len2--;
1822                 // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
1823                 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
1824 
1825                 opt = &p->opt[offset];
1826                 // offset--;
1827                 if (price2 < opt->price)
1828                 {
1829                   opt->price = price2;
1830                   opt->len = (UInt32)len2;
1831                   opt->extra = (CExtra)(len + 1);
1832                   opt->dist = (UInt32)repIndex;
1833                 }
1834               }
1835               // while (len2 >= 3);
1836             }
1837           }
1838           }
1839         }
1840       }
1841     }
1842 
1843 
1844     // ---------- MATCH ----------
1845     /* for (unsigned len = 2; len <= newLen; len++) */
1846     if (newLen > numAvail)
1847     {
1848       newLen = numAvail;
1849       for (numPairs = 0; newLen > MATCHES[numPairs]; numPairs += 2);
1850       MATCHES[numPairs] = (UInt32)newLen;
1851       numPairs += 2;
1852     }
1853 
1854     // startLen = 2; /* speed optimization */
1855 
1856     if (newLen >= startLen)
1857     {
1858       UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
1859       UInt32 dist;
1860       unsigned offs, posSlot, len;
1861 
1862       {
1863         unsigned offset = cur + newLen;
1864         if (last < offset)
1865           last = offset;
1866       }
1867 
1868       offs = 0;
1869       while (startLen > MATCHES[offs])
1870         offs += 2;
1871       dist = MATCHES[(size_t)offs + 1];
1872 
1873       // if (dist >= kNumFullDistances)
1874       GetPosSlot2(dist, posSlot);
1875 
1876       for (len = /*2*/ startLen; ; len++)
1877       {
1878         UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
1879         {
1880           COptimal *opt;
1881           unsigned lenNorm = len - 2;
1882           lenNorm = GetLenToPosState2(lenNorm);
1883           if (dist < kNumFullDistances)
1884             price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)];
1885           else
1886             price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask];
1887 
1888           opt = &p->opt[cur + len];
1889           if (price < opt->price)
1890           {
1891             opt->price = price;
1892             opt->len = (UInt32)len;
1893             opt->dist = dist + LZMA_NUM_REPS;
1894             opt->extra = 0;
1895           }
1896         }
1897 
1898         if (len == MATCHES[offs])
1899         {
1900           // if (p->_maxMode) {
1901           // MATCH : LIT : REP_0
1902 
1903           const Byte *data2 = data - dist - 1;
1904           unsigned len2 = len + 1;
1905           unsigned limit = len2 + p->numFastBytes;
1906           if (limit > numAvailFull)
1907             limit = numAvailFull;
1908 
1909           len2 += 2;
1910           if (len2 <= limit)
1911           if (data[len2 - 2] == data2[len2 - 2])
1912           if (data[len2 - 1] == data2[len2 - 1])
1913           {
1914           for (; len2 < limit && data[len2] == data2[len2]; len2++)
1915           {}
1916 
1917           len2 -= len;
1918 
1919           // if (len2 >= 3)
1920           {
1921             unsigned state2 = kMatchNextStates[state];
1922             unsigned posState2 = (position + len) & p->pbMask;
1923             unsigned offset;
1924             price += GET_PRICE_0(p->isMatch[state2][posState2]);
1925             price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
1926                     data[len], data2[len], p->ProbPrices);
1927 
1928             // state2 = kLiteralNextStates[state2];
1929             state2 = kState_LitAfterMatch;
1930 
1931             posState2 = (posState2 + 1) & p->pbMask;
1932             price += GetPrice_Rep_0(p, state2, posState2);
1933 
1934             offset = cur + len + len2;
1935 
1936             if (last < offset)
1937               last = offset;
1938             // do
1939             {
1940               UInt32 price2;
1941               COptimal *opt;
1942               len2--;
1943               // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
1944               price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
1945               opt = &p->opt[offset];
1946               // offset--;
1947               if (price2 < opt->price)
1948               {
1949                 opt->price = price2;
1950                 opt->len = (UInt32)len2;
1951                 opt->extra = (CExtra)(len + 1);
1952                 opt->dist = dist + LZMA_NUM_REPS;
1953               }
1954             }
1955             // while (len2 >= 3);
1956           }
1957 
1958           }
1959 
1960           offs += 2;
1961           if (offs == numPairs)
1962             break;
1963           dist = MATCHES[(size_t)offs + 1];
1964           // if (dist >= kNumFullDistances)
1965             GetPosSlot2(dist, posSlot);
1966         }
1967       }
1968     }
1969   }
1970 
1971   do
1972     p->opt[last].price = kInfinityPrice;
1973   while (--last);
1974 
1975   return Backward(p, cur);
1976 }
1977 
1978 
1979 
1980 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
1981 
1982 
1983 
GetOptimumFast(CLzmaEnc * p)1984 static unsigned GetOptimumFast(CLzmaEnc *p)
1985 {
1986   UInt32 numAvail, mainDist;
1987   unsigned mainLen, numPairs, repIndex, repLen, i;
1988   const Byte *data;
1989 
1990   if (p->additionalOffset == 0)
1991     mainLen = ReadMatchDistances(p, &numPairs);
1992   else
1993   {
1994     mainLen = p->longestMatchLen;
1995     numPairs = p->numPairs;
1996   }
1997 
1998   numAvail = p->numAvail;
1999   p->backRes = MARK_LIT;
2000   if (numAvail < 2)
2001     return 1;
2002   // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused
2003   if (numAvail > LZMA_MATCH_LEN_MAX)
2004     numAvail = LZMA_MATCH_LEN_MAX;
2005   data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
2006   repLen = repIndex = 0;
2007 
2008   for (i = 0; i < LZMA_NUM_REPS; i++)
2009   {
2010     unsigned len;
2011     const Byte *data2 = data - p->reps[i];
2012     if (data[0] != data2[0] || data[1] != data2[1])
2013       continue;
2014     for (len = 2; len < numAvail && data[len] == data2[len]; len++)
2015     {}
2016     if (len >= p->numFastBytes)
2017     {
2018       p->backRes = (UInt32)i;
2019       MOVE_POS(p, len - 1)
2020       return len;
2021     }
2022     if (len > repLen)
2023     {
2024       repIndex = i;
2025       repLen = len;
2026     }
2027   }
2028 
2029   if (mainLen >= p->numFastBytes)
2030   {
2031     p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
2032     MOVE_POS(p, mainLen - 1)
2033     return mainLen;
2034   }
2035 
2036   mainDist = 0; /* for GCC */
2037 
2038   if (mainLen >= 2)
2039   {
2040     mainDist = p->matches[(size_t)numPairs - 1];
2041     while (numPairs > 2)
2042     {
2043       UInt32 dist2;
2044       if (mainLen != p->matches[(size_t)numPairs - 4] + 1)
2045         break;
2046       dist2 = p->matches[(size_t)numPairs - 3];
2047       if (!ChangePair(dist2, mainDist))
2048         break;
2049       numPairs -= 2;
2050       mainLen--;
2051       mainDist = dist2;
2052     }
2053     if (mainLen == 2 && mainDist >= 0x80)
2054       mainLen = 1;
2055   }
2056 
2057   if (repLen >= 2)
2058     if (    repLen + 1 >= mainLen
2059         || (repLen + 2 >= mainLen && mainDist >= (1 << 9))
2060         || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
2061   {
2062     p->backRes = (UInt32)repIndex;
2063     MOVE_POS(p, repLen - 1)
2064     return repLen;
2065   }
2066 
2067   if (mainLen < 2 || numAvail <= 2)
2068     return 1;
2069 
2070   {
2071     unsigned len1 = ReadMatchDistances(p, &p->numPairs);
2072     p->longestMatchLen = len1;
2073 
2074     if (len1 >= 2)
2075     {
2076       UInt32 newDist = p->matches[(size_t)p->numPairs - 1];
2077       if (   (len1 >= mainLen && newDist < mainDist)
2078           || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))
2079           || (len1 >  mainLen + 1)
2080           || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))
2081         return 1;
2082     }
2083   }
2084 
2085   data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
2086 
2087   for (i = 0; i < LZMA_NUM_REPS; i++)
2088   {
2089     unsigned len, limit;
2090     const Byte *data2 = data - p->reps[i];
2091     if (data[0] != data2[0] || data[1] != data2[1])
2092       continue;
2093     limit = mainLen - 1;
2094     for (len = 2;; len++)
2095     {
2096       if (len >= limit)
2097         return 1;
2098       if (data[len] != data2[len])
2099         break;
2100     }
2101   }
2102 
2103   p->backRes = mainDist + LZMA_NUM_REPS;
2104   if (mainLen != 2)
2105   {
2106     MOVE_POS(p, mainLen - 2)
2107   }
2108   return mainLen;
2109 }
2110 
2111 
2112 
2113 
WriteEndMarker(CLzmaEnc * p,unsigned posState)2114 static void WriteEndMarker(CLzmaEnc *p, unsigned posState)
2115 {
2116   UInt32 range;
2117   range = p->rc.range;
2118   {
2119     UInt32 ttt, newBound;
2120     CLzmaProb *prob = &p->isMatch[p->state][posState];
2121     RC_BIT_PRE(&p->rc, prob)
2122     RC_BIT_1(&p->rc, prob)
2123     prob = &p->isRep[p->state];
2124     RC_BIT_PRE(&p->rc, prob)
2125     RC_BIT_0(&p->rc, prob)
2126   }
2127   p->state = kMatchNextStates[p->state];
2128 
2129   p->rc.range = range;
2130   LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);
2131   range = p->rc.range;
2132 
2133   {
2134     // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);
2135     CLzmaProb *probs = p->posSlotEncoder[0];
2136     unsigned m = 1;
2137     do
2138     {
2139       UInt32 ttt, newBound;
2140       RC_BIT_PRE(p, probs + m)
2141       RC_BIT_1(&p->rc, probs + m);
2142       m = (m << 1) + 1;
2143     }
2144     while (m < (1 << kNumPosSlotBits));
2145   }
2146   {
2147     // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits);    UInt32 range = p->range;
2148     unsigned numBits = 30 - kNumAlignBits;
2149     do
2150     {
2151       range >>= 1;
2152       p->rc.low += range;
2153       RC_NORM(&p->rc)
2154     }
2155     while (--numBits);
2156   }
2157 
2158   {
2159     // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
2160     CLzmaProb *probs = p->posAlignEncoder;
2161     unsigned m = 1;
2162     do
2163     {
2164       UInt32 ttt, newBound;
2165       RC_BIT_PRE(p, probs + m)
2166       RC_BIT_1(&p->rc, probs + m);
2167       m = (m << 1) + 1;
2168     }
2169     while (m < kAlignTableSize);
2170   }
2171   p->rc.range = range;
2172 }
2173 
2174 
CheckErrors(CLzmaEnc * p)2175 static SRes CheckErrors(CLzmaEnc *p)
2176 {
2177   if (p->result != SZ_OK)
2178     return p->result;
2179   if (p->rc.res != SZ_OK)
2180     p->result = SZ_ERROR_WRITE;
2181 
2182   #ifndef _7ZIP_ST
2183   if (
2184       // p->mf_Failure ||
2185         (p->mtMode &&
2186           ( // p->matchFinderMt.failure_LZ_LZ ||
2187             p->matchFinderMt.failure_LZ_BT))
2188      )
2189   {
2190     p->result = MY_HRES_ERROR__INTERNAL_ERROR;
2191     // printf("\nCheckErrors p->matchFinderMt.failureLZ\n");
2192   }
2193   #endif
2194 
2195   if (MFB.result != SZ_OK)
2196     p->result = SZ_ERROR_READ;
2197 
2198   if (p->result != SZ_OK)
2199     p->finished = True;
2200   return p->result;
2201 }
2202 
2203 
Flush(CLzmaEnc * p,UInt32 nowPos)2204 MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
2205 {
2206   /* ReleaseMFStream(); */
2207   p->finished = True;
2208   if (p->writeEndMark)
2209     WriteEndMarker(p, nowPos & p->pbMask);
2210   RangeEnc_FlushData(&p->rc);
2211   RangeEnc_FlushStream(&p->rc);
2212   return CheckErrors(p);
2213 }
2214 
2215 
FillAlignPrices(CLzmaEnc * p)2216 MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p)
2217 {
2218   unsigned i;
2219   const CProbPrice *ProbPrices = p->ProbPrices;
2220   const CLzmaProb *probs = p->posAlignEncoder;
2221   // p->alignPriceCount = 0;
2222   for (i = 0; i < kAlignTableSize / 2; i++)
2223   {
2224     UInt32 price = 0;
2225     unsigned sym = i;
2226     unsigned m = 1;
2227     unsigned bit;
2228     UInt32 prob;
2229     bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
2230     bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
2231     bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
2232     prob = probs[m];
2233     p->alignPrices[i    ] = price + GET_PRICEa_0(prob);
2234     p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
2235     // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
2236   }
2237 }
2238 
2239 
FillDistancesPrices(CLzmaEnc * p)2240 MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)
2241 {
2242   // int y; for (y = 0; y < 100; y++) {
2243 
2244   UInt32 tempPrices[kNumFullDistances];
2245   unsigned i, lps;
2246 
2247   const CProbPrice *ProbPrices = p->ProbPrices;
2248   p->matchPriceCount = 0;
2249 
2250   for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++)
2251   {
2252     unsigned posSlot = GetPosSlot1(i);
2253     unsigned footerBits = (posSlot >> 1) - 1;
2254     unsigned base = ((2 | (posSlot & 1)) << footerBits);
2255     const CLzmaProb *probs = p->posEncoders + (size_t)base * 2;
2256     // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
2257     UInt32 price = 0;
2258     unsigned m = 1;
2259     unsigned sym = i;
2260     unsigned offset = (unsigned)1 << footerBits;
2261     base += i;
2262 
2263     if (footerBits)
2264     do
2265     {
2266       unsigned bit = sym & 1;
2267       sym >>= 1;
2268       price += GET_PRICEa(probs[m], bit);
2269       m = (m << 1) + bit;
2270     }
2271     while (--footerBits);
2272 
2273     {
2274       unsigned prob = probs[m];
2275       tempPrices[base         ] = price + GET_PRICEa_0(prob);
2276       tempPrices[base + offset] = price + GET_PRICEa_1(prob);
2277     }
2278   }
2279 
2280   for (lps = 0; lps < kNumLenToPosStates; lps++)
2281   {
2282     unsigned slot;
2283     unsigned distTableSize2 = (p->distTableSize + 1) >> 1;
2284     UInt32 *posSlotPrices = p->posSlotPrices[lps];
2285     const CLzmaProb *probs = p->posSlotEncoder[lps];
2286 
2287     for (slot = 0; slot < distTableSize2; slot++)
2288     {
2289       // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices);
2290       UInt32 price;
2291       unsigned bit;
2292       unsigned sym = slot + (1 << (kNumPosSlotBits - 1));
2293       unsigned prob;
2294       bit = sym & 1; sym >>= 1; price  = GET_PRICEa(probs[sym], bit);
2295       bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2296       bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2297       bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2298       bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
2299       prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))];
2300       posSlotPrices[(size_t)slot * 2    ] = price + GET_PRICEa_0(prob);
2301       posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob);
2302     }
2303 
2304     {
2305       UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
2306       for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++)
2307       {
2308         posSlotPrices[(size_t)slot * 2    ] += delta;
2309         posSlotPrices[(size_t)slot * 2 + 1] += delta;
2310         delta += ((UInt32)1 << kNumBitPriceShiftBits);
2311       }
2312     }
2313 
2314     {
2315       UInt32 *dp = p->distancesPrices[lps];
2316 
2317       dp[0] = posSlotPrices[0];
2318       dp[1] = posSlotPrices[1];
2319       dp[2] = posSlotPrices[2];
2320       dp[3] = posSlotPrices[3];
2321 
2322       for (i = 4; i < kNumFullDistances; i += 2)
2323       {
2324         UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
2325         dp[i    ] = slotPrice + tempPrices[i];
2326         dp[i + 1] = slotPrice + tempPrices[i + 1];
2327       }
2328     }
2329   }
2330   // }
2331 }
2332 
2333 
2334 
LzmaEnc_Construct(CLzmaEnc * p)2335 static void LzmaEnc_Construct(CLzmaEnc *p)
2336 {
2337   RangeEnc_Construct(&p->rc);
2338   MatchFinder_Construct(&MFB);
2339 
2340   #ifndef _7ZIP_ST
2341   p->matchFinderMt.MatchFinder = &MFB;
2342   MatchFinderMt_Construct(&p->matchFinderMt);
2343   #endif
2344 
2345   {
2346     CLzmaEncProps props;
2347     LzmaEncProps_Init(&props);
2348     LzmaEnc_SetProps(p, &props);
2349   }
2350 
2351   #ifndef LZMA_LOG_BSR
2352   LzmaEnc_FastPosInit(p->g_FastPos);
2353   #endif
2354 
2355   LzmaEnc_InitPriceTables(p->ProbPrices);
2356   p->litProbs = NULL;
2357   p->saveState.litProbs = NULL;
2358 }
2359 
LzmaEnc_Create(ISzAllocPtr alloc)2360 CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
2361 {
2362   void *p;
2363   p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
2364   if (p)
2365     LzmaEnc_Construct((CLzmaEnc *)p);
2366   return p;
2367 }
2368 
LzmaEnc_FreeLits(CLzmaEnc * p,ISzAllocPtr alloc)2369 static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
2370 {
2371   ISzAlloc_Free(alloc, p->litProbs);
2372   ISzAlloc_Free(alloc, p->saveState.litProbs);
2373   p->litProbs = NULL;
2374   p->saveState.litProbs = NULL;
2375 }
2376 
LzmaEnc_Destruct(CLzmaEnc * p,ISzAllocPtr alloc,ISzAllocPtr allocBig)2377 static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2378 {
2379   #ifndef _7ZIP_ST
2380   MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
2381   #endif
2382 
2383   MatchFinder_Free(&MFB, allocBig);
2384   LzmaEnc_FreeLits(p, alloc);
2385   RangeEnc_Free(&p->rc, alloc);
2386 }
2387 
LzmaEnc_Destroy(CLzmaEncHandle p,ISzAllocPtr alloc,ISzAllocPtr allocBig)2388 void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2389 {
2390   LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
2391   ISzAlloc_Free(alloc, p);
2392 }
2393 
2394 
2395 MY_NO_INLINE
LzmaEnc_CodeOneBlock(CLzmaEnc * p,UInt32 maxPackSize,UInt32 maxUnpackSize)2396 static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
2397 {
2398   UInt32 nowPos32, startPos32;
2399   if (p->needInit)
2400   {
2401     #ifndef _7ZIP_ST
2402     if (p->mtMode)
2403     {
2404       RINOK(MatchFinderMt_InitMt(&p->matchFinderMt));
2405     }
2406     #endif
2407     p->matchFinder.Init(p->matchFinderObj);
2408     p->needInit = 0;
2409   }
2410 
2411   if (p->finished)
2412     return p->result;
2413   RINOK(CheckErrors(p));
2414 
2415   nowPos32 = (UInt32)p->nowPos64;
2416   startPos32 = nowPos32;
2417 
2418   if (p->nowPos64 == 0)
2419   {
2420     unsigned numPairs;
2421     Byte curByte;
2422     if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
2423       return Flush(p, nowPos32);
2424     ReadMatchDistances(p, &numPairs);
2425     RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);
2426     // p->state = kLiteralNextStates[p->state];
2427     curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
2428     LitEnc_Encode(&p->rc, p->litProbs, curByte);
2429     p->additionalOffset--;
2430     nowPos32++;
2431   }
2432 
2433   if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
2434 
2435   for (;;)
2436   {
2437     UInt32 dist;
2438     unsigned len, posState;
2439     UInt32 range, ttt, newBound;
2440     CLzmaProb *probs;
2441 
2442     if (p->fastMode)
2443       len = GetOptimumFast(p);
2444     else
2445     {
2446       unsigned oci = p->optCur;
2447       if (p->optEnd == oci)
2448         len = GetOptimum(p, nowPos32);
2449       else
2450       {
2451         const COptimal *opt = &p->opt[oci];
2452         len = opt->len;
2453         p->backRes = opt->dist;
2454         p->optCur = oci + 1;
2455       }
2456     }
2457 
2458     posState = (unsigned)nowPos32 & p->pbMask;
2459     range = p->rc.range;
2460     probs = &p->isMatch[p->state][posState];
2461 
2462     RC_BIT_PRE(&p->rc, probs)
2463 
2464     dist = p->backRes;
2465 
2466     #ifdef SHOW_STAT2
2467     printf("\n pos = %6X, len = %3u  pos = %6u", nowPos32, len, dist);
2468     #endif
2469 
2470     if (dist == MARK_LIT)
2471     {
2472       Byte curByte;
2473       const Byte *data;
2474       unsigned state;
2475 
2476       RC_BIT_0(&p->rc, probs);
2477       p->rc.range = range;
2478       data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2479       probs = LIT_PROBS(nowPos32, *(data - 1));
2480       curByte = *data;
2481       state = p->state;
2482       p->state = kLiteralNextStates[state];
2483       if (IsLitState(state))
2484         LitEnc_Encode(&p->rc, probs, curByte);
2485       else
2486         LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));
2487     }
2488     else
2489     {
2490       RC_BIT_1(&p->rc, probs);
2491       probs = &p->isRep[p->state];
2492       RC_BIT_PRE(&p->rc, probs)
2493 
2494       if (dist < LZMA_NUM_REPS)
2495       {
2496         RC_BIT_1(&p->rc, probs);
2497         probs = &p->isRepG0[p->state];
2498         RC_BIT_PRE(&p->rc, probs)
2499         if (dist == 0)
2500         {
2501           RC_BIT_0(&p->rc, probs);
2502           probs = &p->isRep0Long[p->state][posState];
2503           RC_BIT_PRE(&p->rc, probs)
2504           if (len != 1)
2505           {
2506             RC_BIT_1_BASE(&p->rc, probs);
2507           }
2508           else
2509           {
2510             RC_BIT_0_BASE(&p->rc, probs);
2511             p->state = kShortRepNextStates[p->state];
2512           }
2513         }
2514         else
2515         {
2516           RC_BIT_1(&p->rc, probs);
2517           probs = &p->isRepG1[p->state];
2518           RC_BIT_PRE(&p->rc, probs)
2519           if (dist == 1)
2520           {
2521             RC_BIT_0_BASE(&p->rc, probs);
2522             dist = p->reps[1];
2523           }
2524           else
2525           {
2526             RC_BIT_1(&p->rc, probs);
2527             probs = &p->isRepG2[p->state];
2528             RC_BIT_PRE(&p->rc, probs)
2529             if (dist == 2)
2530             {
2531               RC_BIT_0_BASE(&p->rc, probs);
2532               dist = p->reps[2];
2533             }
2534             else
2535             {
2536               RC_BIT_1_BASE(&p->rc, probs);
2537               dist = p->reps[3];
2538               p->reps[3] = p->reps[2];
2539             }
2540             p->reps[2] = p->reps[1];
2541           }
2542           p->reps[1] = p->reps[0];
2543           p->reps[0] = dist;
2544         }
2545 
2546         RC_NORM(&p->rc)
2547 
2548         p->rc.range = range;
2549 
2550         if (len != 1)
2551         {
2552           LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
2553           --p->repLenEncCounter;
2554           p->state = kRepNextStates[p->state];
2555         }
2556       }
2557       else
2558       {
2559         unsigned posSlot;
2560         RC_BIT_0(&p->rc, probs);
2561         p->rc.range = range;
2562         p->state = kMatchNextStates[p->state];
2563 
2564         LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
2565         // --p->lenEnc.counter;
2566 
2567         dist -= LZMA_NUM_REPS;
2568         p->reps[3] = p->reps[2];
2569         p->reps[2] = p->reps[1];
2570         p->reps[1] = p->reps[0];
2571         p->reps[0] = dist + 1;
2572 
2573         p->matchPriceCount++;
2574         GetPosSlot(dist, posSlot);
2575         // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
2576         {
2577           UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits);
2578           range = p->rc.range;
2579           probs = p->posSlotEncoder[GetLenToPosState(len)];
2580           do
2581           {
2582             CLzmaProb *prob = probs + (sym >> kNumPosSlotBits);
2583             UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1;
2584             sym <<= 1;
2585             RC_BIT(&p->rc, prob, bit);
2586           }
2587           while (sym < (1 << kNumPosSlotBits * 2));
2588           p->rc.range = range;
2589         }
2590 
2591         if (dist >= kStartPosModelIndex)
2592         {
2593           unsigned footerBits = ((posSlot >> 1) - 1);
2594 
2595           if (dist < kNumFullDistances)
2596           {
2597             unsigned base = ((2 | (posSlot & 1)) << footerBits);
2598             RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */));
2599           }
2600           else
2601           {
2602             UInt32 pos2 = (dist | 0xF) << (32 - footerBits);
2603             range = p->rc.range;
2604             // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
2605             /*
2606             do
2607             {
2608               range >>= 1;
2609               p->rc.low += range & (0 - ((dist >> --footerBits) & 1));
2610               RC_NORM(&p->rc)
2611             }
2612             while (footerBits > kNumAlignBits);
2613             */
2614             do
2615             {
2616               range >>= 1;
2617               p->rc.low += range & (0 - (pos2 >> 31));
2618               pos2 += pos2;
2619               RC_NORM(&p->rc)
2620             }
2621             while (pos2 != 0xF0000000);
2622 
2623 
2624             // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
2625 
2626             {
2627               unsigned m = 1;
2628               unsigned bit;
2629               bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
2630               bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
2631               bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
2632               bit = dist & 1;             RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
2633               p->rc.range = range;
2634               // p->alignPriceCount++;
2635             }
2636           }
2637         }
2638       }
2639     }
2640 
2641     nowPos32 += (UInt32)len;
2642     p->additionalOffset -= len;
2643 
2644     if (p->additionalOffset == 0)
2645     {
2646       UInt32 processed;
2647 
2648       if (!p->fastMode)
2649       {
2650         /*
2651         if (p->alignPriceCount >= 16) // kAlignTableSize
2652           FillAlignPrices(p);
2653         if (p->matchPriceCount >= 128)
2654           FillDistancesPrices(p);
2655         if (p->lenEnc.counter <= 0)
2656           LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
2657         */
2658         if (p->matchPriceCount >= 64)
2659         {
2660           FillAlignPrices(p);
2661           // { int y; for (y = 0; y < 100; y++) {
2662           FillDistancesPrices(p);
2663           // }}
2664           LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
2665         }
2666         if (p->repLenEncCounter <= 0)
2667         {
2668           p->repLenEncCounter = REP_LEN_COUNT;
2669           LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
2670         }
2671       }
2672 
2673       if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
2674         break;
2675       processed = nowPos32 - startPos32;
2676 
2677       if (maxPackSize)
2678       {
2679         if (processed + kNumOpts + 300 >= maxUnpackSize
2680             || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)
2681           break;
2682       }
2683       else if (processed >= (1 << 17))
2684       {
2685         p->nowPos64 += nowPos32 - startPos32;
2686         return CheckErrors(p);
2687       }
2688     }
2689   }
2690 
2691   p->nowPos64 += nowPos32 - startPos32;
2692   return Flush(p, nowPos32);
2693 }
2694 
2695 
2696 
2697 #define kBigHashDicLimit ((UInt32)1 << 24)
2698 
LzmaEnc_Alloc(CLzmaEnc * p,UInt32 keepWindowSize,ISzAllocPtr alloc,ISzAllocPtr allocBig)2699 static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2700 {
2701   UInt32 beforeSize = kNumOpts;
2702   UInt32 dictSize;
2703 
2704   if (!RangeEnc_Alloc(&p->rc, alloc))
2705     return SZ_ERROR_MEM;
2706 
2707   #ifndef _7ZIP_ST
2708   p->mtMode = (p->multiThread && !p->fastMode && (MFB.btMode != 0));
2709   #endif
2710 
2711   {
2712     unsigned lclp = p->lc + p->lp;
2713     if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
2714     {
2715       LzmaEnc_FreeLits(p, alloc);
2716       p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
2717       p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
2718       if (!p->litProbs || !p->saveState.litProbs)
2719       {
2720         LzmaEnc_FreeLits(p, alloc);
2721         return SZ_ERROR_MEM;
2722       }
2723       p->lclp = lclp;
2724     }
2725   }
2726 
2727   MFB.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
2728 
2729 
2730   dictSize = p->dictSize;
2731   if (dictSize == ((UInt32)2 << 30) ||
2732       dictSize == ((UInt32)3 << 30))
2733   {
2734     /* 21.03 : here we reduce the dictionary for 2 reasons:
2735        1) we don't want 32-bit back_distance matches in decoder for 2 GB dictionary.
2736        2) we want to elimate useless last MatchFinder_Normalize3() for corner cases,
2737           where data size is aligned for 1 GB: 5/6/8 GB.
2738           That reducing must be >= 1 for such corner cases. */
2739     dictSize -= 1;
2740   }
2741 
2742   if (beforeSize + dictSize < keepWindowSize)
2743     beforeSize = keepWindowSize - dictSize;
2744 
2745   /* in worst case we can look ahead for
2746         max(LZMA_MATCH_LEN_MAX, numFastBytes + 1 + numFastBytes) bytes.
2747      we send larger value for (keepAfter) to MantchFinder_Create():
2748         (numFastBytes + LZMA_MATCH_LEN_MAX + 1)
2749   */
2750 
2751   #ifndef _7ZIP_ST
2752   if (p->mtMode)
2753   {
2754     RINOK(MatchFinderMt_Create(&p->matchFinderMt, dictSize, beforeSize,
2755         p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 18.04 */
2756         , allocBig));
2757     p->matchFinderObj = &p->matchFinderMt;
2758     MFB.bigHash = (Byte)(
2759         (p->dictSize > kBigHashDicLimit && MFB.hashMask >= 0xFFFFFF) ? 1 : 0);
2760     MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
2761   }
2762   else
2763   #endif
2764   {
2765     if (!MatchFinder_Create(&MFB, dictSize, beforeSize,
2766         p->numFastBytes, LZMA_MATCH_LEN_MAX + 1 /* 21.03 */
2767         , allocBig))
2768       return SZ_ERROR_MEM;
2769     p->matchFinderObj = &MFB;
2770     MatchFinder_CreateVTable(&MFB, &p->matchFinder);
2771   }
2772 
2773   return SZ_OK;
2774 }
2775 
LzmaEnc_Init(CLzmaEnc * p)2776 static void LzmaEnc_Init(CLzmaEnc *p)
2777 {
2778   unsigned i;
2779   p->state = 0;
2780   p->reps[0] =
2781   p->reps[1] =
2782   p->reps[2] =
2783   p->reps[3] = 1;
2784 
2785   RangeEnc_Init(&p->rc);
2786 
2787   for (i = 0; i < (1 << kNumAlignBits); i++)
2788     p->posAlignEncoder[i] = kProbInitValue;
2789 
2790   for (i = 0; i < kNumStates; i++)
2791   {
2792     unsigned j;
2793     for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
2794     {
2795       p->isMatch[i][j] = kProbInitValue;
2796       p->isRep0Long[i][j] = kProbInitValue;
2797     }
2798     p->isRep[i] = kProbInitValue;
2799     p->isRepG0[i] = kProbInitValue;
2800     p->isRepG1[i] = kProbInitValue;
2801     p->isRepG2[i] = kProbInitValue;
2802   }
2803 
2804   {
2805     for (i = 0; i < kNumLenToPosStates; i++)
2806     {
2807       CLzmaProb *probs = p->posSlotEncoder[i];
2808       unsigned j;
2809       for (j = 0; j < (1 << kNumPosSlotBits); j++)
2810         probs[j] = kProbInitValue;
2811     }
2812   }
2813   {
2814     for (i = 0; i < kNumFullDistances; i++)
2815       p->posEncoders[i] = kProbInitValue;
2816   }
2817 
2818   {
2819     UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
2820     UInt32 k;
2821     CLzmaProb *probs = p->litProbs;
2822     for (k = 0; k < num; k++)
2823       probs[k] = kProbInitValue;
2824   }
2825 
2826 
2827   LenEnc_Init(&p->lenProbs);
2828   LenEnc_Init(&p->repLenProbs);
2829 
2830   p->optEnd = 0;
2831   p->optCur = 0;
2832 
2833   {
2834     for (i = 0; i < kNumOpts; i++)
2835       p->opt[i].price = kInfinityPrice;
2836   }
2837 
2838   p->additionalOffset = 0;
2839 
2840   p->pbMask = ((unsigned)1 << p->pb) - 1;
2841   p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
2842 
2843   // p->mf_Failure = False;
2844 }
2845 
2846 
LzmaEnc_InitPrices(CLzmaEnc * p)2847 static void LzmaEnc_InitPrices(CLzmaEnc *p)
2848 {
2849   if (!p->fastMode)
2850   {
2851     FillDistancesPrices(p);
2852     FillAlignPrices(p);
2853   }
2854 
2855   p->lenEnc.tableSize =
2856   p->repLenEnc.tableSize =
2857       p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
2858 
2859   p->repLenEncCounter = REP_LEN_COUNT;
2860 
2861   LenPriceEnc_UpdateTables(&p->lenEnc, (unsigned)1 << p->pb, &p->lenProbs, p->ProbPrices);
2862   LenPriceEnc_UpdateTables(&p->repLenEnc, (unsigned)1 << p->pb, &p->repLenProbs, p->ProbPrices);
2863 }
2864 
LzmaEnc_AllocAndInit(CLzmaEnc * p,UInt32 keepWindowSize,ISzAllocPtr alloc,ISzAllocPtr allocBig)2865 static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2866 {
2867   unsigned i;
2868   for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)
2869     if (p->dictSize <= ((UInt32)1 << i))
2870       break;
2871   p->distTableSize = i * 2;
2872 
2873   p->finished = False;
2874   p->result = SZ_OK;
2875   RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
2876   LzmaEnc_Init(p);
2877   LzmaEnc_InitPrices(p);
2878   p->nowPos64 = 0;
2879   return SZ_OK;
2880 }
2881 
LzmaEnc_Prepare(CLzmaEncHandle pp,ISeqOutStream * outStream,ISeqInStream * inStream,ISzAllocPtr alloc,ISzAllocPtr allocBig)2882 static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
2883     ISzAllocPtr alloc, ISzAllocPtr allocBig)
2884 {
2885   CLzmaEnc *p = (CLzmaEnc *)pp;
2886   MFB.stream = inStream;
2887   p->needInit = 1;
2888   p->rc.outStream = outStream;
2889   return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
2890 }
2891 
LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,ISeqInStream * inStream,UInt32 keepWindowSize,ISzAllocPtr alloc,ISzAllocPtr allocBig)2892 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
2893     ISeqInStream *inStream, UInt32 keepWindowSize,
2894     ISzAllocPtr alloc, ISzAllocPtr allocBig)
2895 {
2896   CLzmaEnc *p = (CLzmaEnc *)pp;
2897   MFB.stream = inStream;
2898   p->needInit = 1;
2899   return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2900 }
2901 
LzmaEnc_SetInputBuf(CLzmaEnc * p,const Byte * src,SizeT srcLen)2902 static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
2903 {
2904   MFB.directInput = 1;
2905   MFB.bufferBase = (Byte *)src;
2906   MFB.directInputRem = srcLen;
2907 }
2908 
LzmaEnc_MemPrepare(CLzmaEncHandle pp,const Byte * src,SizeT srcLen,UInt32 keepWindowSize,ISzAllocPtr alloc,ISzAllocPtr allocBig)2909 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
2910     UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2911 {
2912   CLzmaEnc *p = (CLzmaEnc *)pp;
2913   LzmaEnc_SetInputBuf(p, src, srcLen);
2914   p->needInit = 1;
2915 
2916   LzmaEnc_SetDataSize(pp, srcLen);
2917   return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2918 }
2919 
LzmaEnc_Finish(CLzmaEncHandle pp)2920 void LzmaEnc_Finish(CLzmaEncHandle pp)
2921 {
2922   #ifndef _7ZIP_ST
2923   CLzmaEnc *p = (CLzmaEnc *)pp;
2924   if (p->mtMode)
2925     MatchFinderMt_ReleaseStream(&p->matchFinderMt);
2926   #else
2927   UNUSED_VAR(pp);
2928   #endif
2929 }
2930 
2931 
2932 typedef struct
2933 {
2934   ISeqOutStream vt;
2935   Byte *data;
2936   SizeT rem;
2937   BoolInt overflow;
2938 } CLzmaEnc_SeqOutStreamBuf;
2939 
SeqOutStreamBuf_Write(const ISeqOutStream * pp,const void * data,size_t size)2940 static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
2941 {
2942   CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);
2943   if (p->rem < size)
2944   {
2945     size = p->rem;
2946     p->overflow = True;
2947   }
2948   if (size != 0)
2949   {
2950     memcpy(p->data, data, size);
2951     p->rem -= size;
2952     p->data += size;
2953   }
2954   return size;
2955 }
2956 
2957 
2958 /*
2959 UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
2960 {
2961   const CLzmaEnc *p = (CLzmaEnc *)pp;
2962   return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
2963 }
2964 */
2965 
LzmaEnc_GetCurBuf(CLzmaEncHandle pp)2966 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
2967 {
2968   const CLzmaEnc *p = (CLzmaEnc *)pp;
2969   return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2970 }
2971 
2972 
LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp,BoolInt reInit,Byte * dest,size_t * destLen,UInt32 desiredPackSize,UInt32 * unpackSize)2973 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
2974     Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
2975 {
2976   CLzmaEnc *p = (CLzmaEnc *)pp;
2977   UInt64 nowPos64;
2978   SRes res;
2979   CLzmaEnc_SeqOutStreamBuf outStream;
2980 
2981   outStream.vt.Write = SeqOutStreamBuf_Write;
2982   outStream.data = dest;
2983   outStream.rem = *destLen;
2984   outStream.overflow = False;
2985 
2986   p->writeEndMark = False;
2987   p->finished = False;
2988   p->result = SZ_OK;
2989 
2990   if (reInit)
2991     LzmaEnc_Init(p);
2992   LzmaEnc_InitPrices(p);
2993 
2994   nowPos64 = p->nowPos64;
2995   RangeEnc_Init(&p->rc);
2996   p->rc.outStream = &outStream.vt;
2997 
2998   if (desiredPackSize == 0)
2999     return SZ_ERROR_OUTPUT_EOF;
3000 
3001   res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
3002 
3003   *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
3004   *destLen -= outStream.rem;
3005   if (outStream.overflow)
3006     return SZ_ERROR_OUTPUT_EOF;
3007 
3008   return res;
3009 }
3010 
3011 
3012 MY_NO_INLINE
LzmaEnc_Encode2(CLzmaEnc * p,ICompressProgress * progress)3013 static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
3014 {
3015   SRes res = SZ_OK;
3016 
3017   #ifndef _7ZIP_ST
3018   Byte allocaDummy[0x300];
3019   allocaDummy[0] = 0;
3020   allocaDummy[1] = allocaDummy[0];
3021   #endif
3022 
3023   for (;;)
3024   {
3025     res = LzmaEnc_CodeOneBlock(p, 0, 0);
3026     if (res != SZ_OK || p->finished)
3027       break;
3028     if (progress)
3029     {
3030       res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
3031       if (res != SZ_OK)
3032       {
3033         res = SZ_ERROR_PROGRESS;
3034         break;
3035       }
3036     }
3037   }
3038 
3039   LzmaEnc_Finish(p);
3040 
3041   /*
3042   if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&MFB))
3043     res = SZ_ERROR_FAIL;
3044   }
3045   */
3046 
3047   return res;
3048 }
3049 
3050 
LzmaEnc_Encode(CLzmaEncHandle pp,ISeqOutStream * outStream,ISeqInStream * inStream,ICompressProgress * progress,ISzAllocPtr alloc,ISzAllocPtr allocBig)3051 SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
3052     ISzAllocPtr alloc, ISzAllocPtr allocBig)
3053 {
3054   RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
3055   return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
3056 }
3057 
3058 
LzmaEnc_WriteProperties(CLzmaEncHandle pp,Byte * props,SizeT * size)3059 SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
3060 {
3061   if (*size < LZMA_PROPS_SIZE)
3062     return SZ_ERROR_PARAM;
3063   *size = LZMA_PROPS_SIZE;
3064   {
3065     const CLzmaEnc *p = (const CLzmaEnc *)pp;
3066     const UInt32 dictSize = p->dictSize;
3067     UInt32 v;
3068     props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
3069 
3070     // we write aligned dictionary value to properties for lzma decoder
3071     if (dictSize >= ((UInt32)1 << 21))
3072     {
3073       const UInt32 kDictMask = ((UInt32)1 << 20) - 1;
3074       v = (dictSize + kDictMask) & ~kDictMask;
3075       if (v < dictSize)
3076         v = dictSize;
3077     }
3078     else
3079     {
3080       unsigned i = 11 * 2;
3081       do
3082       {
3083         v = (UInt32)(2 + (i & 1)) << (i >> 1);
3084         i++;
3085       }
3086       while (v < dictSize);
3087     }
3088 
3089     SetUi32(props + 1, v);
3090     return SZ_OK;
3091   }
3092 }
3093 
3094 
LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)3095 unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)
3096 {
3097   return (unsigned)((CLzmaEnc *)pp)->writeEndMark;
3098 }
3099 
3100 
LzmaEnc_MemEncode(CLzmaEncHandle pp,Byte * dest,SizeT * destLen,const Byte * src,SizeT srcLen,int writeEndMark,ICompressProgress * progress,ISzAllocPtr alloc,ISzAllocPtr allocBig)3101 SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
3102     int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
3103 {
3104   SRes res;
3105   CLzmaEnc *p = (CLzmaEnc *)pp;
3106 
3107   CLzmaEnc_SeqOutStreamBuf outStream;
3108 
3109   outStream.vt.Write = SeqOutStreamBuf_Write;
3110   outStream.data = dest;
3111   outStream.rem = *destLen;
3112   outStream.overflow = False;
3113 
3114   p->writeEndMark = writeEndMark;
3115   p->rc.outStream = &outStream.vt;
3116 
3117   res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
3118 
3119   if (res == SZ_OK)
3120   {
3121     res = LzmaEnc_Encode2(p, progress);
3122     if (res == SZ_OK && p->nowPos64 != srcLen)
3123       res = SZ_ERROR_FAIL;
3124   }
3125 
3126   *destLen -= outStream.rem;
3127   if (outStream.overflow)
3128     return SZ_ERROR_OUTPUT_EOF;
3129   return res;
3130 }
3131 
3132 
LzmaEncode(Byte * dest,SizeT * destLen,const Byte * src,SizeT srcLen,const CLzmaEncProps * props,Byte * propsEncoded,SizeT * propsSize,int writeEndMark,ICompressProgress * progress,ISzAllocPtr alloc,ISzAllocPtr allocBig)3133 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
3134     const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
3135     ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
3136 {
3137   CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
3138   SRes res;
3139   if (!p)
3140     return SZ_ERROR_MEM;
3141 
3142   res = LzmaEnc_SetProps(p, props);
3143   if (res == SZ_OK)
3144   {
3145     res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
3146     if (res == SZ_OK)
3147       res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
3148           writeEndMark, progress, alloc, allocBig);
3149   }
3150 
3151   LzmaEnc_Destroy(p, alloc, allocBig);
3152   return res;
3153 }
3154 
3155 
3156 /*
3157 #ifndef _7ZIP_ST
3158 void LzmaEnc_GetLzThreads(CLzmaEncHandle pp, HANDLE lz_threads[2])
3159 {
3160   const CLzmaEnc *p = (CLzmaEnc *)pp;
3161   lz_threads[0] = p->matchFinderMt.hashSync.thread;
3162   lz_threads[1] = p->matchFinderMt.btSync.thread;
3163 }
3164 #endif
3165 */
3166