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