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