update libchdr
[pcsx_rearmed.git] / deps / libchdr / deps / lzma-22.01 / src / LzmaEnc.c
CommitLineData
9e052883 1/* LzmaEnc.c -- LZMA Encoder\r
22022-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
25SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,\r
26 ISzAllocPtr alloc, ISzAllocPtr allocBig);\r
27SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,\r
28 UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig);\r
29SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,\r
30 Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);\r
31const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);\r
32void LzmaEnc_Finish(CLzmaEncHandle pp);\r
33void LzmaEnc_SaveState(CLzmaEncHandle pp);\r
34void LzmaEnc_RestoreState(CLzmaEncHandle pp);\r
35\r
36#ifdef SHOW_STAT\r
37static 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
57void 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
67void 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
109UInt32 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
118x86/x64:\r
119\r
120BSR:\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
126LZCNT:\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
131LZCNT works only in new processors starting from Haswell.\r
132if LZCNT is not supported by processor, then it's executed as BSR.\r
133LZCNT 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
193unsigned GetPosSlot1(UInt32 pos);\r
194unsigned 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
210static 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
258typedef UInt16 CState;\r
259typedef UInt16 CExtra;\r
260\r
261typedef 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
295typedef\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
321typedef 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
328typedef 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
344typedef 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
359typedef 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
383typedef UInt32 CProbPrice;\r
384\r
385\r
386typedef 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
497void 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
523void 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
550SRes 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
621void 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
634static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};\r
635static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};\r
636static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};\r
637static 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
645static 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
656static 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
668static 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
674static 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
687MY_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
699MY_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
731static 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
794static 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
803static 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
820static 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
844static 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
882static 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
897static 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
914static 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
933static 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
942static 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
977static 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
993MY_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
1093static 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
1155MY_FORCE_INLINE\r
1156static 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
1181static 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
1233static 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
1984static 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
2114static 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
2175static 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
2204MY_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
2216MY_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
2240MY_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
2335static 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
2360CLzmaEncHandle 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
2369static 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
2377static 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
2388void 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
2395MY_NO_INLINE\r
2396static 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
2699static 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
2776static 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
2847static 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
2865static 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
2882static 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
2892SRes 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
2902static 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
2909SRes 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
2920void 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
2932typedef 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
2940static 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
2959UInt32 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
2966const 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
2974SRes 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
3009MY_NO_INLINE\r
3010static 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
3048SRes 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
3056SRes 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
3092unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)\r
3093{\r
3094 return (unsigned)((CLzmaEnc *)pp)->writeEndMark;\r
3095}\r
3096\r
3097\r
3098SRes 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
3130SRes 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
3155void 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