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