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