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