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