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