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