]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
BaseTools LzmaCompress: Fix GCC warning misleading-indentation
[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
50431b9c
LG
1467 for (len = 3; len < limit && data[len] == data2[len]; len++)\r
1468 {\r
1469 }\r
5ec5a236 1470 \r
30fdf114 1471 {\r
5ec5a236
LG
1472 unsigned state2 = kLiteralNextStates[state];\r
1473 unsigned posState2 = (position + 1) & p->pbMask;\r
1474 UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);\r
30fdf114 1475 {\r
5ec5a236
LG
1476 unsigned offset = cur + len;\r
1477 while (last < offset)\r
1478 p->opt[++last].price = kInfinityPrice;\r
1479 \r
1480 // do\r
1481 {\r
1482 UInt32 price2;\r
1483 COptimal *opt;\r
1484 len--;\r
1485 // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);\r
1486 price2 = price + p->repLenEnc.prices[posState2][len - LZMA_MATCH_LEN_MIN];\r
1487\r
1488 opt = &p->opt[offset];\r
1489 // offset--;\r
1490 if (price2 < opt->price)\r
1491 {\r
1492 opt->price = price2;\r
1493 opt->len = len;\r
1494 opt->dist = 0;\r
1495 opt->extra = 1;\r
1496 }\r
1497 }\r
1498 // while (len >= 3);\r
30fdf114
LG
1499 }\r
1500 }\r
1501 }\r
1502 }\r
1503 \r
1504 startLen = 2; /* speed optimization */\r
1505 {\r
5ec5a236
LG
1506 // ---------- REP ----------\r
1507 unsigned repIndex = 0; // 17.old\r
1508 // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused\r
1509 for (; repIndex < LZMA_NUM_REPS; repIndex++)\r
30fdf114 1510 {\r
5ec5a236
LG
1511 unsigned len;\r
1512 UInt32 price;\r
1513 const Byte *data2 = data - reps[repIndex];\r
1514 if (data[0] != data2[0] || data[1] != data2[1])\r
1515 continue;\r
1516 \r
1517 for (len = 2; len < numAvail && data[len] == data2[len]; len++);\r
1518 \r
1519 // if (len < startLen) continue; // 18.new: speed optimization\r
1520\r
1521 while (last < cur + len)\r
1522 p->opt[++last].price = kInfinityPrice;\r
30fdf114 1523 {\r
5ec5a236
LG
1524 unsigned len2 = len;\r
1525 price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);\r
1526 do\r
1527 {\r
1528 UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)len2 - 2];\r
1529 COptimal *opt = &p->opt[cur + len2];\r
1530 if (price2 < opt->price)\r
1531 {\r
1532 opt->price = price2;\r
1533 opt->len = len2;\r
1534 opt->dist = repIndex;\r
1535 opt->extra = 0;\r
1536 }\r
1537 }\r
1538 while (--len2 >= 2);\r
30fdf114 1539 }\r
c4ab09ef 1540 \r
5ec5a236
LG
1541 if (repIndex == 0) startLen = len + 1; // 17.old\r
1542 // startLen = len + 1; // 18.new\r
1543\r
1544 /* if (_maxMode) */\r
30fdf114 1545 {\r
5ec5a236
LG
1546 // ---------- REP : LIT : REP_0 ----------\r
1547 // numFastBytes + 1 + numFastBytes\r
1548\r
1549 unsigned len2 = len + 1;\r
1550 unsigned limit = len2 + p->numFastBytes;\r
30fdf114
LG
1551 if (limit > numAvailFull)\r
1552 limit = numAvailFull;\r
5ec5a236
LG
1553 \r
1554 for (; len2 < limit && data[len2] == data2[len2]; len2++);\r
1555 \r
1556 len2 -= len;\r
1557 if (len2 >= 3)\r
30fdf114 1558 {\r
5ec5a236
LG
1559 unsigned state2 = kRepNextStates[state];\r
1560 unsigned posState2 = (position + len) & p->pbMask;\r
1561 price +=\r
1562 p->repLenEnc.prices[posState][(size_t)len - 2]\r
1563 + GET_PRICE_0(p->isMatch[state2][posState2])\r
1564 + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),\r
1565 data[len], data2[len], p->ProbPrices);\r
30fdf114 1566 \r
5ec5a236
LG
1567 // state2 = kLiteralNextStates[state2];\r
1568 state2 = kState_LitAfterRep;\r
1569 posState2 = (posState2 + 1) & p->pbMask;\r
1570\r
1571\r
1572 price += GetPrice_Rep_0(p, state2, posState2);\r
30fdf114 1573 {\r
5ec5a236
LG
1574 unsigned offset = cur + len + len2;\r
1575 while (last < offset)\r
1576 p->opt[++last].price = kInfinityPrice;\r
1577 // do\r
30fdf114 1578 {\r
5ec5a236
LG
1579 unsigned price2;\r
1580 COptimal *opt;\r
1581 len2--;\r
1582 // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);\r
1583 price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];\r
1584\r
1585 opt = &p->opt[offset];\r
1586 // offset--;\r
1587 if (price2 < opt->price)\r
1588 {\r
1589 opt->price = price2;\r
1590 opt->len = len2;\r
1591 opt->extra = (CExtra)(len + 1);\r
1592 opt->dist = repIndex;\r
1593 }\r
30fdf114 1594 }\r
5ec5a236 1595 // while (len2 >= 3);\r
30fdf114
LG
1596 }\r
1597 }\r
1598 }\r
5ec5a236 1599 }\r
30fdf114 1600 }\r
5ec5a236
LG
1601\r
1602\r
1603 // ---------- MATCH ----------\r
1604 /* for (unsigned len = 2; len <= newLen; len++) */\r
30fdf114
LG
1605 if (newLen > numAvail)\r
1606 {\r
1607 newLen = numAvail;\r
1608 for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);\r
1609 matches[numPairs] = newLen;\r
1610 numPairs += 2;\r
1611 }\r
5ec5a236 1612 \r
30fdf114
LG
1613 if (newLen >= startLen)\r
1614 {\r
c4ab09ef 1615 UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);\r
5ec5a236
LG
1616 UInt32 dist;\r
1617 unsigned offs, posSlot, len;\r
1618 while (last < cur + newLen)\r
1619 p->opt[++last].price = kInfinityPrice;\r
30fdf114
LG
1620\r
1621 offs = 0;\r
1622 while (startLen > matches[offs])\r
1623 offs += 2;\r
5ec5a236
LG
1624 dist = matches[(size_t)offs + 1];\r
1625 \r
1626 // if (dist >= kNumFullDistances)\r
1627 GetPosSlot2(dist, posSlot);\r
1628 \r
1629 for (len = /*2*/ startLen; ; len++)\r
30fdf114 1630 {\r
5ec5a236 1631 UInt32 price = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];\r
30fdf114 1632 {\r
5ec5a236
LG
1633 COptimal *opt;\r
1634 unsigned lenToPosState = len - 2; lenToPosState = GetLenToPosState2(lenToPosState);\r
1635 if (dist < kNumFullDistances)\r
1636 price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];\r
1637 else\r
1638 price += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[dist & kAlignMask];\r
1639 \r
1640 opt = &p->opt[cur + len];\r
1641 if (price < opt->price)\r
1642 {\r
1643 opt->price = price;\r
1644 opt->len = len;\r
1645 opt->dist = dist + LZMA_NUM_REPS;\r
1646 opt->extra = 0;\r
1647 }\r
c4ab09ef 1648 }\r
30fdf114 1649\r
5ec5a236 1650 if (/*_maxMode && */ len == matches[offs])\r
30fdf114 1651 {\r
5ec5a236
LG
1652 // MATCH : LIT : REP_0\r
1653\r
1654 const Byte *data2 = data - dist - 1;\r
1655 unsigned len2 = len + 1;\r
1656 unsigned limit = len2 + p->numFastBytes;\r
30fdf114
LG
1657 if (limit > numAvailFull)\r
1658 limit = numAvailFull;\r
5ec5a236
LG
1659 \r
1660 for (; len2 < limit && data[len2] == data2[len2]; len2++);\r
1661 \r
1662 len2 -= len;\r
1663 \r
1664 if (len2 >= 3)\r
30fdf114 1665 {\r
5ec5a236
LG
1666 unsigned state2 = kMatchNextStates[state];\r
1667 unsigned posState2 = (position + len) & p->pbMask;\r
1668 unsigned offset;\r
1669 price += GET_PRICE_0(p->isMatch[state2][posState2]);\r
1670 price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),\r
1671 data[len], data2[len], p->ProbPrices);\r
1672\r
1673 // state2 = kLiteralNextStates[state2];\r
1674 state2 = kState_LitAfterMatch;\r
1675\r
1676 posState2 = (posState2 + 1) & p->pbMask;\r
1677 price += GetPrice_Rep_0(p, state2, posState2);\r
1678\r
1679 offset = cur + len + len2;\r
1680 while (last < offset)\r
1681 p->opt[++last].price = kInfinityPrice;\r
1682 // do\r
30fdf114 1683 {\r
5ec5a236 1684 UInt32 price2;\r
c4ab09ef 1685 COptimal *opt;\r
5ec5a236
LG
1686 len2--;\r
1687 // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);\r
1688 price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];\r
30fdf114 1689 opt = &p->opt[offset];\r
5ec5a236
LG
1690 // offset--;\r
1691 if (price2 < opt->price)\r
30fdf114 1692 {\r
5ec5a236
LG
1693 opt->price = price2;\r
1694 opt->len = len2;\r
1695 opt->extra = (CExtra)(len + 1);\r
1696 opt->dist = dist + LZMA_NUM_REPS;\r
30fdf114
LG
1697 }\r
1698 }\r
5ec5a236 1699 // while (len2 >= 3);\r
30fdf114 1700 }\r
5ec5a236 1701 \r
30fdf114
LG
1702 offs += 2;\r
1703 if (offs == numPairs)\r
1704 break;\r
5ec5a236
LG
1705 dist = matches[(size_t)offs + 1];\r
1706 // if (dist >= kNumFullDistances)\r
1707 GetPosSlot2(dist, posSlot);\r
30fdf114
LG
1708 }\r
1709 }\r
1710 }\r
1711 }\r
1712}\r
1713\r
5ec5a236
LG
1714\r
1715\r
30fdf114
LG
1716#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))\r
1717\r
5ec5a236
LG
1718\r
1719\r
1720static unsigned GetOptimumFast(CLzmaEnc *p)\r
30fdf114 1721{\r
5ec5a236
LG
1722 UInt32 numAvail, mainDist;\r
1723 unsigned mainLen, numPairs, repIndex, repLen, i;\r
30fdf114 1724 const Byte *data;\r
30fdf114
LG
1725\r
1726 if (p->additionalOffset == 0)\r
1727 mainLen = ReadMatchDistances(p, &numPairs);\r
1728 else\r
1729 {\r
5ec5a236 1730 mainLen = p->longestMatchLen;\r
30fdf114
LG
1731 numPairs = p->numPairs;\r
1732 }\r
1733\r
1734 numAvail = p->numAvail;\r
5ec5a236 1735 p->backRes = MARK_LIT;\r
30fdf114
LG
1736 if (numAvail < 2)\r
1737 return 1;\r
1738 if (numAvail > LZMA_MATCH_LEN_MAX)\r
1739 numAvail = LZMA_MATCH_LEN_MAX;\r
1740 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
30fdf114 1741 repLen = repIndex = 0;\r
5ec5a236 1742 \r
30fdf114
LG
1743 for (i = 0; i < LZMA_NUM_REPS; i++)\r
1744 {\r
5ec5a236
LG
1745 unsigned len;\r
1746 const Byte *data2 = data - p->reps[i];\r
30fdf114
LG
1747 if (data[0] != data2[0] || data[1] != data2[1])\r
1748 continue;\r
1749 for (len = 2; len < numAvail && data[len] == data2[len]; len++);\r
1750 if (len >= p->numFastBytes)\r
1751 {\r
5ec5a236
LG
1752 p->backRes = i;\r
1753 MOVE_POS(p, len - 1)\r
30fdf114
LG
1754 return len;\r
1755 }\r
1756 if (len > repLen)\r
1757 {\r
1758 repIndex = i;\r
1759 repLen = len;\r
1760 }\r
1761 }\r
1762\r
30fdf114
LG
1763 if (mainLen >= p->numFastBytes)\r
1764 {\r
5ec5a236
LG
1765 p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;\r
1766 MOVE_POS(p, mainLen - 1)\r
30fdf114
LG
1767 return mainLen;\r
1768 }\r
1769\r
1770 mainDist = 0; /* for GCC */\r
5ec5a236 1771 \r
30fdf114
LG
1772 if (mainLen >= 2)\r
1773 {\r
5ec5a236
LG
1774 mainDist = p->matches[(size_t)numPairs - 1];\r
1775 while (numPairs > 2)\r
30fdf114 1776 {\r
5ec5a236
LG
1777 UInt32 dist2;\r
1778 if (mainLen != p->matches[(size_t)numPairs - 4] + 1)\r
1779 break;\r
1780 dist2 = p->matches[(size_t)numPairs - 3];\r
1781 if (!ChangePair(dist2, mainDist))\r
30fdf114
LG
1782 break;\r
1783 numPairs -= 2;\r
5ec5a236
LG
1784 mainLen--;\r
1785 mainDist = dist2;\r
30fdf114
LG
1786 }\r
1787 if (mainLen == 2 && mainDist >= 0x80)\r
1788 mainLen = 1;\r
1789 }\r
1790\r
5ec5a236
LG
1791 if (repLen >= 2)\r
1792 if ( repLen + 1 >= mainLen\r
1793 || (repLen + 2 >= mainLen && mainDist >= (1 << 9))\r
1794 || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))\r
30fdf114 1795 {\r
5ec5a236
LG
1796 p->backRes = repIndex;\r
1797 MOVE_POS(p, repLen - 1)\r
30fdf114
LG
1798 return repLen;\r
1799 }\r
1800 \r
1801 if (mainLen < 2 || numAvail <= 2)\r
1802 return 1;\r
1803\r
30fdf114 1804 {\r
5ec5a236
LG
1805 unsigned len1 = ReadMatchDistances(p, &p->numPairs);\r
1806 p->longestMatchLen = len1;\r
1807 \r
1808 if (len1 >= 2)\r
1809 {\r
1810 UInt32 newDist = p->matches[(size_t)p->numPairs - 1];\r
1811 if ( (len1 >= mainLen && newDist < mainDist)\r
1812 || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))\r
1813 || (len1 > mainLen + 1)\r
1814 || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))\r
1815 return 1;\r
1816 }\r
30fdf114
LG
1817 }\r
1818 \r
1819 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;\r
5ec5a236 1820 \r
30fdf114
LG
1821 for (i = 0; i < LZMA_NUM_REPS; i++)\r
1822 {\r
5ec5a236
LG
1823 unsigned len, limit;\r
1824 const Byte *data2 = data - p->reps[i];\r
30fdf114
LG
1825 if (data[0] != data2[0] || data[1] != data2[1])\r
1826 continue;\r
1827 limit = mainLen - 1;\r
5ec5a236
LG
1828 for (len = 2;; len++)\r
1829 {\r
1830 if (len >= limit)\r
1831 return 1;\r
1832 if (data[len] != data2[len])\r
1833 break;\r
1834 }\r
1835 }\r
1836 \r
1837 p->backRes = mainDist + LZMA_NUM_REPS;\r
1838 if (mainLen != 2)\r
1839 {\r
1840 MOVE_POS(p, mainLen - 2)\r
30fdf114 1841 }\r
30fdf114
LG
1842 return mainLen;\r
1843}\r
1844\r
5ec5a236
LG
1845\r
1846\r
1847\r
1848static void WriteEndMarker(CLzmaEnc *p, unsigned posState)\r
30fdf114 1849{\r
5ec5a236
LG
1850 UInt32 range;\r
1851 range = p->rc.range;\r
1852 {\r
1853 UInt32 ttt, newBound;\r
1854 CLzmaProb *prob = &p->isMatch[p->state][posState];\r
1855 RC_BIT_PRE(&p->rc, prob)\r
1856 RC_BIT_1(&p->rc, prob)\r
1857 prob = &p->isRep[p->state];\r
1858 RC_BIT_PRE(&p->rc, prob)\r
1859 RC_BIT_0(&p->rc, prob)\r
1860 }\r
30fdf114 1861 p->state = kMatchNextStates[p->state];\r
5ec5a236
LG
1862 \r
1863 p->rc.range = range;\r
1864 LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);\r
1865 range = p->rc.range;\r
1866\r
1867 {\r
1868 // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);\r
1869 CLzmaProb *probs = p->posSlotEncoder[0];\r
1870 unsigned m = 1;\r
1871 do\r
1872 {\r
1873 UInt32 ttt, newBound;\r
1874 RC_BIT_PRE(p, probs + m)\r
1875 RC_BIT_1(&p->rc, probs + m);\r
1876 m = (m << 1) + 1;\r
1877 }\r
1878 while (m < (1 << kNumPosSlotBits));\r
1879 }\r
1880 {\r
1881 // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits); UInt32 range = p->range;\r
1882 unsigned numBits = 30 - kNumAlignBits;\r
1883 do\r
1884 {\r
1885 range >>= 1;\r
1886 p->rc.low += range;\r
1887 RC_NORM(&p->rc)\r
1888 }\r
1889 while (--numBits);\r
1890 }\r
1891 \r
1892 {\r
1893 // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);\r
1894 CLzmaProb *probs = p->posAlignEncoder;\r
1895 unsigned m = 1;\r
1896 do\r
1897 {\r
1898 UInt32 ttt, newBound;\r
1899 RC_BIT_PRE(p, probs + m)\r
1900 RC_BIT_1(&p->rc, probs + m);\r
1901 m = (m << 1) + 1;\r
1902 }\r
1903 while (m < kAlignTableSize);\r
1904 }\r
1905 p->rc.range = range;\r
30fdf114
LG
1906}\r
1907\r
5ec5a236 1908\r
30fdf114
LG
1909static SRes CheckErrors(CLzmaEnc *p)\r
1910{\r
1911 if (p->result != SZ_OK)\r
1912 return p->result;\r
1913 if (p->rc.res != SZ_OK)\r
1914 p->result = SZ_ERROR_WRITE;\r
1915 if (p->matchFinderBase.result != SZ_OK)\r
1916 p->result = SZ_ERROR_READ;\r
1917 if (p->result != SZ_OK)\r
1918 p->finished = True;\r
1919 return p->result;\r
1920}\r
1921\r
5ec5a236
LG
1922\r
1923MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)\r
30fdf114
LG
1924{\r
1925 /* ReleaseMFStream(); */\r
1926 p->finished = True;\r
1927 if (p->writeEndMark)\r
1928 WriteEndMarker(p, nowPos & p->pbMask);\r
1929 RangeEnc_FlushData(&p->rc);\r
1930 RangeEnc_FlushStream(&p->rc);\r
1931 return CheckErrors(p);\r
1932}\r
1933\r
5ec5a236
LG
1934\r
1935\r
30fdf114
LG
1936static void FillAlignPrices(CLzmaEnc *p)\r
1937{\r
5ec5a236
LG
1938 unsigned i;\r
1939 const CProbPrice *ProbPrices = p->ProbPrices;\r
1940 const CLzmaProb *probs = p->posAlignEncoder;\r
30fdf114 1941 p->alignPriceCount = 0;\r
5ec5a236
LG
1942 for (i = 0; i < kAlignTableSize / 2; i++)\r
1943 {\r
1944 UInt32 price = 0;\r
1945 unsigned symbol = i;\r
1946 unsigned m = 1;\r
1947 unsigned bit;\r
1948 UInt32 prob;\r
1949 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\r
1950 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\r
1951 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;\r
1952 prob = probs[m];\r
1953 p->alignPrices[i ] = price + GET_PRICEa_0(prob);\r
1954 p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);\r
1955 // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);\r
1956 }\r
30fdf114
LG
1957}\r
1958\r
5ec5a236 1959\r
30fdf114
LG
1960static void FillDistancesPrices(CLzmaEnc *p)\r
1961{\r
1962 UInt32 tempPrices[kNumFullDistances];\r
5ec5a236
LG
1963 unsigned i, lenToPosState;\r
1964\r
1965 const CProbPrice *ProbPrices = p->ProbPrices;\r
1966 p->matchPriceCount = 0;\r
1967\r
30fdf114
LG
1968 for (i = kStartPosModelIndex; i < kNumFullDistances; i++)\r
1969 {\r
5ec5a236
LG
1970 unsigned posSlot = GetPosSlot1(i);\r
1971 unsigned footerBits = ((posSlot >> 1) - 1);\r
1972 unsigned base = ((2 | (posSlot & 1)) << footerBits);\r
1973 // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);\r
1974\r
1975 const CLzmaProb *probs = p->posEncoders + base;\r
1976 UInt32 price = 0;\r
1977 unsigned m = 1;\r
1978 unsigned symbol = i - base;\r
1979 do\r
1980 {\r
1981 unsigned bit = symbol & 1;\r
1982 symbol >>= 1;\r
1983 price += GET_PRICEa(probs[m], bit);\r
1984 m = (m << 1) + bit;\r
1985 }\r
1986 while (--footerBits);\r
1987 tempPrices[i] = price;\r
30fdf114
LG
1988 }\r
1989\r
1990 for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)\r
1991 {\r
5ec5a236 1992 unsigned posSlot;\r
30fdf114
LG
1993 const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];\r
1994 UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];\r
5ec5a236
LG
1995 unsigned distTableSize = p->distTableSize;\r
1996 const CLzmaProb *probs = encoder;\r
1997 for (posSlot = 0; posSlot < distTableSize; posSlot += 2)\r
1998 {\r
1999 // posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);\r
2000 UInt32 price = 0;\r
2001 unsigned bit;\r
2002 unsigned symbol = (posSlot >> 1) + (1 << (kNumPosSlotBits - 1));\r
2003 UInt32 prob;\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 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);\r
2008 bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);\r
2009 prob = probs[(posSlot >> 1) + (1 << (kNumPosSlotBits - 1))];\r
2010 posSlotPrices[posSlot ] = price + GET_PRICEa_0(prob);\r
2011 posSlotPrices[posSlot + 1] = price + GET_PRICEa_1(prob);\r
2012 }\r
2013 for (posSlot = kEndPosModelIndex; posSlot < distTableSize; posSlot++)\r
2014 posSlotPrices[posSlot] += ((UInt32)(((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);\r
30fdf114
LG
2015\r
2016 {\r
2017 UInt32 *distancesPrices = p->distancesPrices[lenToPosState];\r
5ec5a236
LG
2018 {\r
2019 distancesPrices[0] = posSlotPrices[0];\r
2020 distancesPrices[1] = posSlotPrices[1];\r
2021 distancesPrices[2] = posSlotPrices[2];\r
2022 distancesPrices[3] = posSlotPrices[3];\r
2023 }\r
2024 for (i = 4; i < kNumFullDistances; i += 2)\r
2025 {\r
2026 UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];\r
2027 distancesPrices[i ] = slotPrice + tempPrices[i];\r
2028 distancesPrices[i + 1] = slotPrice + tempPrices[i + 1];\r
2029 }\r
30fdf114
LG
2030 }\r
2031 }\r
30fdf114
LG
2032}\r
2033\r
5ec5a236
LG
2034\r
2035\r
30fdf114
LG
2036void LzmaEnc_Construct(CLzmaEnc *p)\r
2037{\r
2038 RangeEnc_Construct(&p->rc);\r
2039 MatchFinder_Construct(&p->matchFinderBase);\r
c4ab09ef
LG
2040 \r
2041 #ifndef _7ZIP_ST\r
30fdf114
LG
2042 MatchFinderMt_Construct(&p->matchFinderMt);\r
2043 p->matchFinderMt.MatchFinder = &p->matchFinderBase;\r
2044 #endif\r
2045\r
2046 {\r
2047 CLzmaEncProps props;\r
2048 LzmaEncProps_Init(&props);\r
2049 LzmaEnc_SetProps(p, &props);\r
2050 }\r
2051\r
2052 #ifndef LZMA_LOG_BSR\r
2053 LzmaEnc_FastPosInit(p->g_FastPos);\r
2054 #endif\r
2055\r
2056 LzmaEnc_InitPriceTables(p->ProbPrices);\r
c4ab09ef
LG
2057 p->litProbs = NULL;\r
2058 p->saveState.litProbs = NULL;\r
5ec5a236 2059\r
30fdf114
LG
2060}\r
2061\r
5ec5a236 2062CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)\r
30fdf114
LG
2063{\r
2064 void *p;\r
5ec5a236 2065 p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));\r
c4ab09ef 2066 if (p)\r
30fdf114
LG
2067 LzmaEnc_Construct((CLzmaEnc *)p);\r
2068 return p;\r
2069}\r
2070\r
5ec5a236 2071void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)\r
30fdf114 2072{\r
5ec5a236
LG
2073 ISzAlloc_Free(alloc, p->litProbs);\r
2074 ISzAlloc_Free(alloc, p->saveState.litProbs);\r
c4ab09ef
LG
2075 p->litProbs = NULL;\r
2076 p->saveState.litProbs = NULL;\r
30fdf114
LG
2077}\r
2078\r
5ec5a236 2079void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114 2080{\r
c4ab09ef 2081 #ifndef _7ZIP_ST\r
30fdf114
LG
2082 MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);\r
2083 #endif\r
c4ab09ef 2084 \r
30fdf114
LG
2085 MatchFinder_Free(&p->matchFinderBase, allocBig);\r
2086 LzmaEnc_FreeLits(p, alloc);\r
2087 RangeEnc_Free(&p->rc, alloc);\r
2088}\r
2089\r
5ec5a236 2090void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114
LG
2091{\r
2092 LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);\r
5ec5a236 2093 ISzAlloc_Free(alloc, p);\r
30fdf114
LG
2094}\r
2095\r
5ec5a236
LG
2096\r
2097static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)\r
30fdf114
LG
2098{\r
2099 UInt32 nowPos32, startPos32;\r
c4ab09ef 2100 if (p->needInit)\r
30fdf114 2101 {\r
30fdf114 2102 p->matchFinder.Init(p->matchFinderObj);\r
c4ab09ef 2103 p->needInit = 0;\r
30fdf114
LG
2104 }\r
2105\r
2106 if (p->finished)\r
2107 return p->result;\r
2108 RINOK(CheckErrors(p));\r
2109\r
2110 nowPos32 = (UInt32)p->nowPos64;\r
2111 startPos32 = nowPos32;\r
2112\r
2113 if (p->nowPos64 == 0)\r
2114 {\r
5ec5a236 2115 unsigned numPairs;\r
30fdf114
LG
2116 Byte curByte;\r
2117 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\r
2118 return Flush(p, nowPos32);\r
2119 ReadMatchDistances(p, &numPairs);\r
5ec5a236
LG
2120 RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);\r
2121 // p->state = kLiteralNextStates[p->state];\r
c4ab09ef 2122 curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);\r
30fdf114
LG
2123 LitEnc_Encode(&p->rc, p->litProbs, curByte);\r
2124 p->additionalOffset--;\r
2125 nowPos32++;\r
2126 }\r
2127\r
2128 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)\r
5ec5a236 2129 \r
30fdf114
LG
2130 for (;;)\r
2131 {\r
5ec5a236
LG
2132 UInt32 dist;\r
2133 unsigned len, posState;\r
2134 UInt32 range, ttt, newBound;\r
2135 CLzmaProb *probs;\r
2136 \r
30fdf114 2137 if (p->fastMode)\r
5ec5a236 2138 len = GetOptimumFast(p);\r
30fdf114 2139 else\r
5ec5a236
LG
2140 {\r
2141 unsigned oci = p->optCur;\r
2142 if (p->optEnd == oci)\r
2143 len = GetOptimum(p, nowPos32);\r
2144 else\r
2145 {\r
2146 const COptimal *opt = &p->opt[oci];\r
2147 len = opt->len;\r
2148 p->backRes = opt->dist;\r
2149 p->optCur = oci + 1;\r
2150 }\r
2151 }\r
2152\r
2153 posState = (unsigned)nowPos32 & p->pbMask;\r
2154 range = p->rc.range;\r
2155 probs = &p->isMatch[p->state][posState];\r
2156 \r
2157 RC_BIT_PRE(&p->rc, probs)\r
2158 \r
2159 dist = p->backRes;\r
30fdf114
LG
2160\r
2161 #ifdef SHOW_STAT2\r
5ec5a236 2162 printf("\n pos = %6X, len = %3u pos = %6u", nowPos32, len, dist);\r
30fdf114
LG
2163 #endif\r
2164\r
5ec5a236 2165 if (dist == MARK_LIT)\r
30fdf114
LG
2166 {\r
2167 Byte curByte;\r
30fdf114 2168 const Byte *data;\r
5ec5a236 2169 unsigned state;\r
30fdf114 2170\r
5ec5a236
LG
2171 RC_BIT_0(&p->rc, probs);\r
2172 p->rc.range = range;\r
30fdf114 2173 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\r
30fdf114 2174 probs = LIT_PROBS(nowPos32, *(data - 1));\r
5ec5a236
LG
2175 curByte = *data;\r
2176 state = p->state;\r
2177 p->state = kLiteralNextStates[state];\r
2178 if (IsLitState(state))\r
30fdf114
LG
2179 LitEnc_Encode(&p->rc, probs, curByte);\r
2180 else\r
5ec5a236 2181 LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));\r
30fdf114
LG
2182 }\r
2183 else\r
2184 {\r
5ec5a236
LG
2185 RC_BIT_1(&p->rc, probs);\r
2186 probs = &p->isRep[p->state];\r
2187 RC_BIT_PRE(&p->rc, probs)\r
2188 \r
2189 if (dist < LZMA_NUM_REPS)\r
30fdf114 2190 {\r
5ec5a236
LG
2191 RC_BIT_1(&p->rc, probs);\r
2192 probs = &p->isRepG0[p->state];\r
2193 RC_BIT_PRE(&p->rc, probs)\r
2194 if (dist == 0)\r
30fdf114 2195 {\r
5ec5a236
LG
2196 RC_BIT_0(&p->rc, probs);\r
2197 probs = &p->isRep0Long[p->state][posState];\r
2198 RC_BIT_PRE(&p->rc, probs)\r
2199 if (len != 1)\r
2200 {\r
2201 RC_BIT_1_BASE(&p->rc, probs);\r
2202 }\r
2203 else\r
2204 {\r
2205 RC_BIT_0_BASE(&p->rc, probs);\r
2206 p->state = kShortRepNextStates[p->state];\r
2207 }\r
30fdf114
LG
2208 }\r
2209 else\r
2210 {\r
5ec5a236
LG
2211 RC_BIT_1(&p->rc, probs);\r
2212 probs = &p->isRepG1[p->state];\r
2213 RC_BIT_PRE(&p->rc, probs)\r
2214 if (dist == 1)\r
2215 {\r
2216 RC_BIT_0_BASE(&p->rc, probs);\r
2217 dist = p->reps[1];\r
2218 }\r
30fdf114
LG
2219 else\r
2220 {\r
5ec5a236
LG
2221 RC_BIT_1(&p->rc, probs);\r
2222 probs = &p->isRepG2[p->state];\r
2223 RC_BIT_PRE(&p->rc, probs)\r
2224 if (dist == 2)\r
2225 {\r
2226 RC_BIT_0_BASE(&p->rc, probs);\r
2227 dist = p->reps[2];\r
2228 }\r
2229 else\r
2230 {\r
2231 RC_BIT_1_BASE(&p->rc, probs);\r
2232 dist = p->reps[3];\r
30fdf114 2233 p->reps[3] = p->reps[2];\r
5ec5a236 2234 }\r
30fdf114
LG
2235 p->reps[2] = p->reps[1];\r
2236 }\r
2237 p->reps[1] = p->reps[0];\r
5ec5a236 2238 p->reps[0] = dist;\r
30fdf114 2239 }\r
5ec5a236
LG
2240\r
2241 RC_NORM(&p->rc)\r
2242\r
2243 p->rc.range = range;\r
2244\r
2245 if (len != 1)\r
30fdf114 2246 {\r
5ec5a236
LG
2247 LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);\r
2248 if (!p->fastMode)\r
2249 if (--p->repLenEnc.counters[posState] == 0)\r
2250 LenPriceEnc_UpdateTable(&p->repLenEnc, posState, &p->repLenProbs, p->ProbPrices);\r
2251\r
30fdf114
LG
2252 p->state = kRepNextStates[p->state];\r
2253 }\r
2254 }\r
2255 else\r
2256 {\r
5ec5a236
LG
2257 unsigned posSlot;\r
2258 RC_BIT_0(&p->rc, probs);\r
2259 p->rc.range = range;\r
30fdf114 2260 p->state = kMatchNextStates[p->state];\r
5ec5a236
LG
2261\r
2262 LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);\r
2263 if (!p->fastMode)\r
2264 if (--p->lenEnc.counters[posState] == 0)\r
2265 LenPriceEnc_UpdateTable(&p->lenEnc, posState, &p->lenProbs, p->ProbPrices);\r
2266\r
2267 dist -= LZMA_NUM_REPS;\r
2268 p->reps[3] = p->reps[2];\r
2269 p->reps[2] = p->reps[1];\r
2270 p->reps[1] = p->reps[0];\r
2271 p->reps[0] = dist + 1;\r
30fdf114 2272 \r
5ec5a236
LG
2273 p->matchPriceCount++;\r
2274 GetPosSlot(dist, posSlot);\r
2275 // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);\r
2276 {\r
2277 UInt32 symbol = posSlot + (1 << kNumPosSlotBits);\r
2278 range = p->rc.range;\r
2279 probs = p->posSlotEncoder[GetLenToPosState(len)];\r
2280 do\r
2281 {\r
2282 CLzmaProb *prob = probs + (symbol >> kNumPosSlotBits);\r
2283 UInt32 bit = (symbol >> (kNumPosSlotBits - 1)) & 1;\r
2284 symbol <<= 1;\r
2285 RC_BIT(&p->rc, prob, bit);\r
2286 }\r
2287 while (symbol < (1 << kNumPosSlotBits * 2));\r
2288 p->rc.range = range;\r
2289 }\r
2290 \r
2291 if (dist >= kStartPosModelIndex)\r
30fdf114 2292 {\r
5ec5a236 2293 unsigned footerBits = ((posSlot >> 1) - 1);\r
30fdf114 2294\r
5ec5a236
LG
2295 if (dist < kNumFullDistances)\r
2296 {\r
2297 unsigned base = ((2 | (posSlot & 1)) << footerBits);\r
2298 RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, dist - base);\r
2299 }\r
30fdf114
LG
2300 else\r
2301 {\r
5ec5a236
LG
2302 UInt32 pos2 = (dist | 0xF) << (32 - footerBits);\r
2303 range = p->rc.range;\r
2304 // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);\r
2305 /*\r
2306 do\r
2307 {\r
2308 range >>= 1;\r
2309 p->rc.low += range & (0 - ((dist >> --footerBits) & 1));\r
2310 RC_NORM(&p->rc)\r
2311 }\r
2312 while (footerBits > kNumAlignBits);\r
2313 */\r
2314 do\r
2315 {\r
2316 range >>= 1;\r
2317 p->rc.low += range & (0 - (pos2 >> 31));\r
2318 pos2 += pos2;\r
2319 RC_NORM(&p->rc)\r
2320 }\r
2321 while (pos2 != 0xF0000000);\r
2322\r
2323\r
2324 // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);\r
2325\r
2326 {\r
2327 unsigned m = 1;\r
2328 unsigned 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; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;\r
2331 bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;\r
2332 bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit);\r
2333 p->rc.range = range;\r
2334 p->alignPriceCount++;\r
2335 }\r
30fdf114
LG
2336 }\r
2337 }\r
30fdf114
LG
2338 }\r
2339 }\r
5ec5a236 2340\r
30fdf114 2341 nowPos32 += len;\r
5ec5a236
LG
2342 p->additionalOffset -= len;\r
2343 \r
30fdf114
LG
2344 if (p->additionalOffset == 0)\r
2345 {\r
2346 UInt32 processed;\r
5ec5a236 2347\r
30fdf114
LG
2348 if (!p->fastMode)\r
2349 {\r
2350 if (p->matchPriceCount >= (1 << 7))\r
2351 FillDistancesPrices(p);\r
2352 if (p->alignPriceCount >= kAlignTableSize)\r
2353 FillAlignPrices(p);\r
2354 }\r
5ec5a236 2355 \r
30fdf114
LG
2356 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)\r
2357 break;\r
2358 processed = nowPos32 - startPos32;\r
5ec5a236
LG
2359 \r
2360 if (maxPackSize)\r
30fdf114 2361 {\r
5ec5a236
LG
2362 if (processed + kNumOpts + 300 >= maxUnpackSize\r
2363 || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)\r
30fdf114
LG
2364 break;\r
2365 }\r
c4ab09ef 2366 else if (processed >= (1 << 17))\r
30fdf114
LG
2367 {\r
2368 p->nowPos64 += nowPos32 - startPos32;\r
2369 return CheckErrors(p);\r
2370 }\r
2371 }\r
2372 }\r
5ec5a236 2373\r
30fdf114
LG
2374 p->nowPos64 += nowPos32 - startPos32;\r
2375 return Flush(p, nowPos32);\r
2376}\r
2377\r
5ec5a236
LG
2378\r
2379\r
30fdf114
LG
2380#define kBigHashDicLimit ((UInt32)1 << 24)\r
2381\r
5ec5a236 2382static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114
LG
2383{\r
2384 UInt32 beforeSize = kNumOpts;\r
30fdf114
LG
2385 if (!RangeEnc_Alloc(&p->rc, alloc))\r
2386 return SZ_ERROR_MEM;\r
c4ab09ef
LG
2387\r
2388 #ifndef _7ZIP_ST\r
2389 p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));\r
30fdf114
LG
2390 #endif\r
2391\r
2392 {\r
2393 unsigned lclp = p->lc + p->lp;\r
c4ab09ef 2394 if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)\r
30fdf114
LG
2395 {\r
2396 LzmaEnc_FreeLits(p, alloc);\r
5ec5a236
LG
2397 p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));\r
2398 p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));\r
c4ab09ef 2399 if (!p->litProbs || !p->saveState.litProbs)\r
30fdf114
LG
2400 {\r
2401 LzmaEnc_FreeLits(p, alloc);\r
2402 return SZ_ERROR_MEM;\r
2403 }\r
2404 p->lclp = lclp;\r
2405 }\r
2406 }\r
2407\r
c4ab09ef 2408 p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);\r
30fdf114
LG
2409\r
2410 if (beforeSize + p->dictSize < keepWindowSize)\r
2411 beforeSize = keepWindowSize - p->dictSize;\r
2412\r
c4ab09ef 2413 #ifndef _7ZIP_ST\r
30fdf114
LG
2414 if (p->mtMode)\r
2415 {\r
5ec5a236
LG
2416 RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,\r
2417 LZMA_MATCH_LEN_MAX\r
2418 + 1 /* 18.04 */\r
2419 , allocBig));\r
30fdf114 2420 p->matchFinderObj = &p->matchFinderMt;\r
5ec5a236
LG
2421 p->matchFinderBase.bigHash = (Byte)(\r
2422 (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);\r
30fdf114
LG
2423 MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);\r
2424 }\r
2425 else\r
2426 #endif\r
2427 {\r
2428 if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))\r
2429 return SZ_ERROR_MEM;\r
2430 p->matchFinderObj = &p->matchFinderBase;\r
2431 MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);\r
2432 }\r
c4ab09ef 2433 \r
30fdf114
LG
2434 return SZ_OK;\r
2435}\r
2436\r
2437void LzmaEnc_Init(CLzmaEnc *p)\r
2438{\r
5ec5a236 2439 unsigned i;\r
30fdf114 2440 p->state = 0;\r
5ec5a236
LG
2441 p->reps[0] =\r
2442 p->reps[1] =\r
2443 p->reps[2] =\r
2444 p->reps[3] = 1;\r
30fdf114
LG
2445\r
2446 RangeEnc_Init(&p->rc);\r
2447\r
5ec5a236
LG
2448 for (i = 0; i < (1 << kNumAlignBits); i++)\r
2449 p->posAlignEncoder[i] = kProbInitValue;\r
30fdf114
LG
2450\r
2451 for (i = 0; i < kNumStates; i++)\r
2452 {\r
5ec5a236 2453 unsigned j;\r
30fdf114
LG
2454 for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)\r
2455 {\r
2456 p->isMatch[i][j] = kProbInitValue;\r
2457 p->isRep0Long[i][j] = kProbInitValue;\r
2458 }\r
2459 p->isRep[i] = kProbInitValue;\r
2460 p->isRepG0[i] = kProbInitValue;\r
2461 p->isRepG1[i] = kProbInitValue;\r
2462 p->isRepG2[i] = kProbInitValue;\r
2463 }\r
2464\r
30fdf114
LG
2465 {\r
2466 for (i = 0; i < kNumLenToPosStates; i++)\r
2467 {\r
2468 CLzmaProb *probs = p->posSlotEncoder[i];\r
5ec5a236 2469 unsigned j;\r
30fdf114
LG
2470 for (j = 0; j < (1 << kNumPosSlotBits); j++)\r
2471 probs[j] = kProbInitValue;\r
2472 }\r
2473 }\r
2474 {\r
5ec5a236 2475 for (i = 0; i < kNumFullDistances; i++)\r
30fdf114
LG
2476 p->posEncoders[i] = kProbInitValue;\r
2477 }\r
2478\r
5ec5a236
LG
2479 {\r
2480 UInt32 num = (UInt32)0x300 << (p->lp + p->lc);\r
2481 UInt32 k;\r
2482 CLzmaProb *probs = p->litProbs;\r
2483 for (k = 0; k < num; k++)\r
2484 probs[k] = kProbInitValue;\r
2485 }\r
30fdf114 2486\r
30fdf114 2487\r
5ec5a236
LG
2488 LenEnc_Init(&p->lenProbs);\r
2489 LenEnc_Init(&p->repLenProbs);\r
2490\r
2491 p->optEnd = 0;\r
2492 p->optCur = 0;\r
30fdf114
LG
2493 p->additionalOffset = 0;\r
2494\r
2495 p->pbMask = (1 << p->pb) - 1;\r
5ec5a236 2496 p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);\r
30fdf114
LG
2497}\r
2498\r
2499void LzmaEnc_InitPrices(CLzmaEnc *p)\r
2500{\r
2501 if (!p->fastMode)\r
2502 {\r
2503 FillDistancesPrices(p);\r
2504 FillAlignPrices(p);\r
2505 }\r
2506\r
2507 p->lenEnc.tableSize =\r
2508 p->repLenEnc.tableSize =\r
2509 p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;\r
5ec5a236
LG
2510 LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);\r
2511 LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);\r
30fdf114
LG
2512}\r
2513\r
5ec5a236 2514static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114 2515{\r
5ec5a236
LG
2516 unsigned i;\r
2517 for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)\r
30fdf114
LG
2518 if (p->dictSize <= ((UInt32)1 << i))\r
2519 break;\r
2520 p->distTableSize = i * 2;\r
2521\r
2522 p->finished = False;\r
2523 p->result = SZ_OK;\r
2524 RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));\r
2525 LzmaEnc_Init(p);\r
2526 LzmaEnc_InitPrices(p);\r
2527 p->nowPos64 = 0;\r
2528 return SZ_OK;\r
2529}\r
2530\r
c4ab09ef 2531static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,\r
5ec5a236 2532 ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114
LG
2533{\r
2534 CLzmaEnc *p = (CLzmaEnc *)pp;\r
c4ab09ef
LG
2535 p->matchFinderBase.stream = inStream;\r
2536 p->needInit = 1;\r
30fdf114
LG
2537 p->rc.outStream = outStream;\r
2538 return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);\r
2539}\r
2540\r
2541SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,\r
2542 ISeqInStream *inStream, UInt32 keepWindowSize,\r
5ec5a236 2543 ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114
LG
2544{\r
2545 CLzmaEnc *p = (CLzmaEnc *)pp;\r
c4ab09ef
LG
2546 p->matchFinderBase.stream = inStream;\r
2547 p->needInit = 1;\r
30fdf114
LG
2548 return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\r
2549}\r
2550\r
2551static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)\r
2552{\r
c4ab09ef
LG
2553 p->matchFinderBase.directInput = 1;\r
2554 p->matchFinderBase.bufferBase = (Byte *)src;\r
2555 p->matchFinderBase.directInputRem = srcLen;\r
30fdf114
LG
2556}\r
2557\r
2558SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,\r
5ec5a236 2559 UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114
LG
2560{\r
2561 CLzmaEnc *p = (CLzmaEnc *)pp;\r
2562 LzmaEnc_SetInputBuf(p, src, srcLen);\r
c4ab09ef
LG
2563 p->needInit = 1;\r
2564\r
5ec5a236 2565 LzmaEnc_SetDataSize(pp, srcLen);\r
30fdf114
LG
2566 return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);\r
2567}\r
2568\r
2569void LzmaEnc_Finish(CLzmaEncHandle pp)\r
2570{\r
c4ab09ef 2571 #ifndef _7ZIP_ST\r
30fdf114
LG
2572 CLzmaEnc *p = (CLzmaEnc *)pp;\r
2573 if (p->mtMode)\r
2574 MatchFinderMt_ReleaseStream(&p->matchFinderMt);\r
2575 #else\r
c4ab09ef 2576 UNUSED_VAR(pp);\r
30fdf114
LG
2577 #endif\r
2578}\r
2579\r
c4ab09ef
LG
2580\r
2581typedef struct\r
30fdf114 2582{\r
5ec5a236 2583 ISeqOutStream vt;\r
30fdf114
LG
2584 Byte *data;\r
2585 SizeT rem;\r
2586 Bool overflow;\r
5ec5a236 2587} CLzmaEnc_SeqOutStreamBuf;\r
30fdf114 2588\r
5ec5a236 2589static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)\r
30fdf114 2590{\r
5ec5a236 2591 CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);\r
30fdf114
LG
2592 if (p->rem < size)\r
2593 {\r
2594 size = p->rem;\r
2595 p->overflow = True;\r
2596 }\r
2597 memcpy(p->data, data, size);\r
2598 p->rem -= size;\r
2599 p->data += size;\r
2600 return size;\r
2601}\r
2602\r
2603\r
2604UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)\r
2605{\r
2606 const CLzmaEnc *p = (CLzmaEnc *)pp;\r
2607 return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);\r
2608}\r
2609\r
c4ab09ef 2610\r
30fdf114
LG
2611const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)\r
2612{\r
2613 const CLzmaEnc *p = (CLzmaEnc *)pp;\r
2614 return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;\r
2615}\r
2616\r
c4ab09ef 2617\r
30fdf114
LG
2618SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,\r
2619 Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)\r
2620{\r
2621 CLzmaEnc *p = (CLzmaEnc *)pp;\r
2622 UInt64 nowPos64;\r
2623 SRes res;\r
5ec5a236 2624 CLzmaEnc_SeqOutStreamBuf outStream;\r
30fdf114 2625\r
5ec5a236 2626 outStream.vt.Write = SeqOutStreamBuf_Write;\r
30fdf114
LG
2627 outStream.data = dest;\r
2628 outStream.rem = *destLen;\r
2629 outStream.overflow = False;\r
2630\r
2631 p->writeEndMark = False;\r
2632 p->finished = False;\r
2633 p->result = SZ_OK;\r
2634\r
2635 if (reInit)\r
2636 LzmaEnc_Init(p);\r
2637 LzmaEnc_InitPrices(p);\r
5ec5a236 2638\r
30fdf114
LG
2639 nowPos64 = p->nowPos64;\r
2640 RangeEnc_Init(&p->rc);\r
5ec5a236
LG
2641 p->rc.outStream = &outStream.vt;\r
2642\r
2643 if (desiredPackSize == 0)\r
2644 return SZ_ERROR_OUTPUT_EOF;\r
30fdf114 2645\r
5ec5a236 2646 res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);\r
30fdf114
LG
2647 \r
2648 *unpackSize = (UInt32)(p->nowPos64 - nowPos64);\r
2649 *destLen -= outStream.rem;\r
2650 if (outStream.overflow)\r
2651 return SZ_ERROR_OUTPUT_EOF;\r
2652\r
2653 return res;\r
2654}\r
2655\r
c4ab09ef
LG
2656\r
2657static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)\r
30fdf114 2658{\r
30fdf114
LG
2659 SRes res = SZ_OK;\r
2660\r
c4ab09ef 2661 #ifndef _7ZIP_ST\r
30fdf114 2662 Byte allocaDummy[0x300];\r
c4ab09ef
LG
2663 allocaDummy[0] = 0;\r
2664 allocaDummy[1] = allocaDummy[0];\r
30fdf114
LG
2665 #endif\r
2666\r
30fdf114
LG
2667 for (;;)\r
2668 {\r
5ec5a236 2669 res = LzmaEnc_CodeOneBlock(p, 0, 0);\r
c4ab09ef 2670 if (res != SZ_OK || p->finished)\r
30fdf114 2671 break;\r
c4ab09ef 2672 if (progress)\r
30fdf114 2673 {\r
5ec5a236 2674 res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));\r
30fdf114
LG
2675 if (res != SZ_OK)\r
2676 {\r
2677 res = SZ_ERROR_PROGRESS;\r
2678 break;\r
2679 }\r
2680 }\r
2681 }\r
c4ab09ef
LG
2682 \r
2683 LzmaEnc_Finish(p);\r
2684\r
2685 /*\r
5ec5a236 2686 if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))\r
c4ab09ef
LG
2687 res = SZ_ERROR_FAIL;\r
2688 }\r
2689 */\r
2690\r
30fdf114
LG
2691 return res;\r
2692}\r
2693\r
c4ab09ef
LG
2694\r
2695SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,\r
5ec5a236 2696 ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
c4ab09ef
LG
2697{\r
2698 RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));\r
2699 return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);\r
2700}\r
2701\r
2702\r
30fdf114
LG
2703SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)\r
2704{\r
2705 CLzmaEnc *p = (CLzmaEnc *)pp;\r
c4ab09ef 2706 unsigned i;\r
30fdf114
LG
2707 UInt32 dictSize = p->dictSize;\r
2708 if (*size < LZMA_PROPS_SIZE)\r
2709 return SZ_ERROR_PARAM;\r
2710 *size = LZMA_PROPS_SIZE;\r
2711 props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);\r
2712\r
c4ab09ef 2713 if (dictSize >= ((UInt32)1 << 22))\r
30fdf114 2714 {\r
c4ab09ef
LG
2715 UInt32 kDictMask = ((UInt32)1 << 20) - 1;\r
2716 if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)\r
2717 dictSize = (dictSize + kDictMask) & ~kDictMask;\r
2718 }\r
2719 else for (i = 11; i <= 30; i++)\r
2720 {\r
2721 if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }\r
2722 if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }\r
30fdf114
LG
2723 }\r
2724\r
2725 for (i = 0; i < 4; i++)\r
2726 props[1 + i] = (Byte)(dictSize >> (8 * i));\r
2727 return SZ_OK;\r
2728}\r
2729\r
c4ab09ef 2730\r
5ec5a236
LG
2731unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)\r
2732{\r
2733 return ((CLzmaEnc *)pp)->writeEndMark;\r
2734}\r
2735\r
2736\r
30fdf114 2737SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
5ec5a236 2738 int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114
LG
2739{\r
2740 SRes res;\r
2741 CLzmaEnc *p = (CLzmaEnc *)pp;\r
2742\r
5ec5a236 2743 CLzmaEnc_SeqOutStreamBuf outStream;\r
30fdf114 2744\r
5ec5a236 2745 outStream.vt.Write = SeqOutStreamBuf_Write;\r
30fdf114
LG
2746 outStream.data = dest;\r
2747 outStream.rem = *destLen;\r
2748 outStream.overflow = False;\r
2749\r
2750 p->writeEndMark = writeEndMark;\r
5ec5a236 2751 p->rc.outStream = &outStream.vt;\r
c4ab09ef
LG
2752\r
2753 res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);\r
2754 \r
2755 if (res == SZ_OK)\r
2756 {\r
2757 res = LzmaEnc_Encode2(p, progress);\r
2758 if (res == SZ_OK && p->nowPos64 != srcLen)\r
2759 res = SZ_ERROR_FAIL;\r
2760 }\r
30fdf114
LG
2761\r
2762 *destLen -= outStream.rem;\r
2763 if (outStream.overflow)\r
2764 return SZ_ERROR_OUTPUT_EOF;\r
2765 return res;\r
2766}\r
2767\r
c4ab09ef 2768\r
30fdf114
LG
2769SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,\r
2770 const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,\r
5ec5a236 2771 ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)\r
30fdf114
LG
2772{\r
2773 CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);\r
2774 SRes res;\r
c4ab09ef 2775 if (!p)\r
30fdf114
LG
2776 return SZ_ERROR_MEM;\r
2777\r
2778 res = LzmaEnc_SetProps(p, props);\r
2779 if (res == SZ_OK)\r
2780 {\r
2781 res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);\r
2782 if (res == SZ_OK)\r
2783 res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,\r
2784 writeEndMark, progress, alloc, allocBig);\r
2785 }\r
2786\r
2787 LzmaEnc_Destroy(p, alloc, allocBig);\r
2788 return res;\r
2789}\r