1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
27 /* LzmaEnc.c -- LZMA Encoder
28 2008-10-04 : Igor Pavlov : Public domain */
29 #include "vogl_core.h"
32 /* #define SHOW_STAT */
33 /* #define SHOW_STAT2 */
35 #if defined(SHOW_STAT) || defined(SHOW_STAT2)
39 #include "lzma_LzmaEnc.h"
41 #include "lzma_LzFind.h"
43 #include "lzma_LzFindMt.h"
53 #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
55 #define kBlockSize (9 << 10)
56 #define kUnpackBlockSize (1 << 18)
57 #define kMatchArraySize (1 << 21)
58 #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
60 #define kNumMaxDirectBits (31)
62 #define kNumTopBits 24
63 #define kTopValue ((UInt32)1 << kNumTopBits)
65 #define kNumBitModelTotalBits 11
66 #define kBitModelTotal (1 << kNumBitModelTotalBits)
67 #define kNumMoveBits 5
68 #define kProbInitValue (kBitModelTotal >> 1)
70 #define kNumMoveReducingBits 4
71 #define kNumBitPriceShiftBits 4
72 #define kBitPrice (1 << kNumBitPriceShiftBits)
74 void LzmaEncProps_Init(CLzmaEncProps *p)
77 p->dictSize = p->mc = 0;
78 p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
82 void LzmaEncProps_Normalize(CLzmaEncProps *p)
89 p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
97 p->algo = (level < 5 ? 0 : 1);
99 p->fb = (level < 7 ? 32 : 64);
101 p->btMode = (p->algo == 0 ? 0 : 1);
102 if (p->numHashBytes < 0)
105 p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
106 if (p->numThreads < 0)
107 p->numThreads = ((p->btMode && p->algo) ? 2 : 1);
110 UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
112 CLzmaEncProps props = *props2;
113 LzmaEncProps_Normalize(&props);
114 return props.dictSize;
117 /* #define LZMA_LOG_BSR */
118 /* Define it for Intel's CPU */
122 #define kDicLogSizeMaxCompress 30
124 #define BSR2_RET(pos, res) \
127 _BitScanReverse(&i, (pos)); \
128 res = (i + i) + ((pos >> (i - 1)) & 1); \
131 UInt32 GetPosSlot1(UInt32 pos)
137 #define GetPosSlot2(pos, res) \
139 BSR2_RET(pos, res); \
141 #define GetPosSlot(pos, res) \
146 BSR2_RET(pos, res); \
151 #define kNumLogBits (9 + (int)sizeof(size_t) / 2)
152 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
154 void LzmaEnc_FastPosInit(Byte *g_FastPos)
160 for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
162 UInt32 k = (1 << ((slotFast >> 1) - 1));
164 for (j = 0; j < k; j++, c++)
165 g_FastPos[c] = (Byte)slotFast;
169 #define BSR2_RET(pos, res) \
171 UInt32 i = 6 + ((kNumLogBits - 1) & (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
172 res = p->g_FastPos[pos >> i] + (i * 2); \
175 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
176 p->g_FastPos[pos >> 6] + 12 : \
177 p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
180 #define GetPosSlot1(pos) p->g_FastPos[pos]
181 #define GetPosSlot2(pos, res) \
183 BSR2_RET(pos, res); \
185 #define GetPosSlot(pos, res) \
187 if (pos < kNumFullDistances) \
188 res = p->g_FastPos[pos]; \
190 BSR2_RET(pos, res); \
195 #define LZMA_NUM_REPS 4
197 typedef unsigned CState;
199 typedef struct _COptimal
212 UInt32 backs[LZMA_NUM_REPS];
215 #define kNumOpts (1 << 12)
217 #define kNumLenToPosStates 4
218 #define kNumPosSlotBits 6
219 #define kDicLogSizeMin 0
220 #define kDicLogSizeMax 32
221 #define kDistTableSizeMax (kDicLogSizeMax * 2)
223 #define kNumAlignBits 4
224 #define kAlignTableSize (1 << kNumAlignBits)
225 #define kAlignMask (kAlignTableSize - 1)
227 #define kStartPosModelIndex 4
228 #define kEndPosModelIndex 14
229 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
231 #define kNumFullDistances (1 << (kEndPosModelIndex / 2))
234 #define CLzmaProb UInt32
236 #define CLzmaProb UInt16
239 #define LZMA_PB_MAX 4
240 #define LZMA_LC_MAX 8
241 #define LZMA_LP_MAX 4
243 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
245 #define kLenNumLowBits 3
246 #define kLenNumLowSymbols (1 << kLenNumLowBits)
247 #define kLenNumMidBits 3
248 #define kLenNumMidSymbols (1 << kLenNumMidBits)
249 #define kLenNumHighBits 8
250 #define kLenNumHighSymbols (1 << kLenNumHighBits)
252 #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
254 #define LZMA_MATCH_LEN_MIN 2
255 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
257 #define kNumStates 12
263 CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
264 CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
265 CLzmaProb high[kLenNumHighSymbols];
271 UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
273 UInt32 counters[LZMA_NUM_PB_STATES_MAX];
276 typedef struct _CRangeEnc
285 ISeqOutStream *outStream;
290 typedef struct _CSeqInStreamBuf
292 ISeqInStream funcTable;
297 static SRes MyRead(void *pp, void *data, size_t *size)
299 size_t curSize = *size;
300 CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
301 if (p->rem < curSize)
303 memcpy(data, p->data, curSize);
314 CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
315 CLzmaProb isRep[kNumStates];
316 CLzmaProb isRepG0[kNumStates];
317 CLzmaProb isRepG1[kNumStates];
318 CLzmaProb isRepG2[kNumStates];
319 CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
321 CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
322 CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
323 CLzmaProb posAlignEncoder[1 << kNumAlignBits];
326 CLenPriceEnc repLenEnc;
328 UInt32 reps[LZMA_NUM_REPS];
332 typedef struct _CLzmaEnc
334 IMatchFinder matchFinder;
335 void *matchFinderObj;
337 #ifdef COMPRESS_MF_MT
339 CMatchFinderMt matchFinderMt;
342 CMatchFinder matchFinderBase;
344 #ifdef COMPRESS_MF_MT
348 UInt32 optimumEndIndex;
349 UInt32 optimumCurrentIndex;
351 UInt32 longestMatchLength;
354 COptimal opt[kNumOpts];
357 Byte g_FastPos[1 << kNumLogBits];
360 UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
361 UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
363 UInt32 additionalOffset;
364 UInt32 reps[LZMA_NUM_REPS];
367 UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
368 UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
369 UInt32 alignPrices[kAlignTableSize];
370 UInt32 alignPriceCount;
372 UInt32 distTableSize;
375 unsigned lpMask, pbMask;
379 CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
380 CLzmaProb isRep[kNumStates];
381 CLzmaProb isRepG0[kNumStates];
382 CLzmaProb isRepG1[kNumStates];
383 CLzmaProb isRepG2[kNumStates];
384 CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
386 CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
387 CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
388 CLzmaProb posAlignEncoder[1 << kNumAlignBits];
391 CLenPriceEnc repLenEnc;
401 UInt32 matchPriceCount;
407 UInt32 matchFinderCycles;
409 ISeqInStream *inStream;
410 CSeqInStreamBuf seqBufInStream;
412 CSaveState saveState;
415 void LzmaEnc_SaveState(CLzmaEncHandle pp)
417 CLzmaEnc *p = (CLzmaEnc *)pp;
418 CSaveState *dest = &p->saveState;
420 dest->lenEnc = p->lenEnc;
421 dest->repLenEnc = p->repLenEnc;
422 dest->state = p->state;
424 for (i = 0; i < kNumStates; i++)
426 memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
427 memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
429 for (i = 0; i < kNumLenToPosStates; i++)
430 memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
431 memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
432 memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
433 memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
434 memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
435 memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
436 memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
437 memcpy(dest->reps, p->reps, sizeof(p->reps));
438 memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
441 void LzmaEnc_RestoreState(CLzmaEncHandle pp)
443 CLzmaEnc *dest = (CLzmaEnc *)pp;
444 const CSaveState *p = &dest->saveState;
446 dest->lenEnc = p->lenEnc;
447 dest->repLenEnc = p->repLenEnc;
448 dest->state = p->state;
450 for (i = 0; i < kNumStates; i++)
452 memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
453 memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
455 for (i = 0; i < kNumLenToPosStates; i++)
456 memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
457 memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
458 memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
459 memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
460 memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
461 memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
462 memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
463 memcpy(dest->reps, p->reps, sizeof(p->reps));
464 memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
467 SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
469 CLzmaEnc *p = (CLzmaEnc *)pp;
470 CLzmaEncProps props = *props2;
471 LzmaEncProps_Normalize(&props);
473 if (props.lc > LZMA_LC_MAX ||
474 props.lp > LZMA_LP_MAX ||
475 props.pb > LZMA_PB_MAX ||
476 props.dictSize > (1U << kDicLogSizeMaxCompress) ||
477 props.dictSize > (1 << 30))
478 return SZ_ERROR_PARAM;
479 p->dictSize = props.dictSize;
480 p->matchFinderCycles = props.mc;
482 unsigned fb = props.fb;
485 if (fb > LZMA_MATCH_LEN_MAX)
486 fb = LZMA_MATCH_LEN_MAX;
487 p->numFastBytes = fb;
492 p->fastMode = (props.algo == 0);
493 p->matchFinderBase.btMode = props.btMode;
495 UInt32 numHashBytes = 4;
498 if (props.numHashBytes < 2)
500 else if (props.numHashBytes < 4)
501 numHashBytes = props.numHashBytes;
503 p->matchFinderBase.numHashBytes = numHashBytes;
506 p->matchFinderBase.cutValue = props.mc;
508 p->writeEndMark = props.writeEndMark;
510 #ifdef COMPRESS_MF_MT
512 if (newMultiThread != _multiThread)
514 ReleaseMatchFinder();
515 _multiThread = newMultiThread;
518 p->multiThread = (props.numThreads > 1);
524 static const int kLiteralNextStates[kNumStates] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
525 static const int kMatchNextStates[kNumStates] = { 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 };
526 static const int kRepNextStates[kNumStates] = { 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11 };
527 static const int kShortRepNextStates[kNumStates] = { 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11 };
529 #define IsCharState(s) ((s) < 7)
531 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
533 #define kInfinityPrice (1 << 30)
535 static void RangeEnc_Construct(CRangeEnc *p)
541 #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
543 #define RC_BUF_SIZE (1 << 16)
544 static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
548 p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
551 p->bufLim = p->bufBase + RC_BUF_SIZE;
556 static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
558 alloc->Free(alloc, p->bufBase);
562 static void RangeEnc_Init(CRangeEnc *p)
566 p->range = 0xFFFFFFFF;
576 static void RangeEnc_FlushStream(CRangeEnc *p)
581 num = p->buf - p->bufBase;
582 if (num != p->outStream->Write(p->outStream, p->bufBase, num))
583 p->res = SZ_ERROR_WRITE;
588 static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
590 if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
592 Byte temp = p->cache;
596 *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
598 if (buf == p->bufLim)
599 RangeEnc_FlushStream(p);
601 } while (--p->cacheSize != 0);
602 p->cache = (Byte)((UInt32)p->low >> 24);
605 p->low = (UInt32)p->low << 8;
608 static void RangeEnc_FlushData(CRangeEnc *p)
611 for (i = 0; i < 5; i++)
612 RangeEnc_ShiftLow(p);
615 static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
620 p->low += p->range & (0 - ((value >> --numBits) & 1));
621 if (p->range < kTopValue)
624 RangeEnc_ShiftLow(p);
626 } while (numBits != 0);
629 static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
632 UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
636 ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
641 p->range -= newBound;
642 ttt -= ttt >> kNumMoveBits;
644 *prob = (CLzmaProb)ttt;
645 if (p->range < kTopValue)
648 RangeEnc_ShiftLow(p);
652 static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
657 RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
659 } while (symbol < 0x10000);
662 static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
669 RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
671 offs &= ~(matchByte ^ symbol);
672 } while (symbol < 0x10000);
675 void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
678 for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
680 const int kCyclesBits = kNumBitPriceShiftBits;
684 for (j = 0; j < kCyclesBits; j++)
688 while (w >= ((UInt32)1 << 16))
694 ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
698 #define GET_PRICE(prob, symbol) \
699 p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
701 #define GET_PRICEa(prob, symbol) \
702 ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
704 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
705 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
707 #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
708 #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
710 static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
716 price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
718 } while (symbol < 0x10000);
722 static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
730 price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
732 offs &= ~(matchByte ^ symbol);
733 } while (symbol < 0x10000);
737 static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
741 for (i = numBitLevels; i != 0;)
745 bit = (symbol >> i) & 1;
746 RangeEnc_EncodeBit(rc, probs + m, bit);
751 static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
755 for (i = 0; i < numBitLevels; i++)
757 UInt32 bit = symbol & 1;
758 RangeEnc_EncodeBit(rc, probs + m, bit);
764 static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
767 symbol |= (1 << numBitLevels);
770 price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
776 static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
781 for (i = numBitLevels; i != 0; i--)
783 UInt32 bit = symbol & 1;
785 price += GET_PRICEa(probs[m], bit);
791 static void LenEnc_Init(CLenEnc *p)
794 p->choice = p->choice2 = kProbInitValue;
795 for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
796 p->low[i] = kProbInitValue;
797 for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
798 p->mid[i] = kProbInitValue;
799 for (i = 0; i < kLenNumHighSymbols; i++)
800 p->high[i] = kProbInitValue;
803 static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
805 if (symbol < kLenNumLowSymbols)
807 RangeEnc_EncodeBit(rc, &p->choice, 0);
808 RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
812 RangeEnc_EncodeBit(rc, &p->choice, 1);
813 if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
815 RangeEnc_EncodeBit(rc, &p->choice2, 0);
816 RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
820 RangeEnc_EncodeBit(rc, &p->choice2, 1);
821 RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
826 static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
828 UInt32 a0 = GET_PRICE_0a(p->choice);
829 UInt32 a1 = GET_PRICE_1a(p->choice);
830 UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
831 UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
833 for (i = 0; i < kLenNumLowSymbols; i++)
837 prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
839 for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
843 prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
845 for (; i < numSymbols; i++)
846 prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
849 static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
851 LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
852 p->counters[posState] = p->tableSize;
855 static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
858 for (posState = 0; posState < numPosStates; posState++)
859 LenPriceEnc_UpdateTable(p, posState, ProbPrices);
862 static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
864 LenEnc_Encode(&p->p, rc, symbol, posState);
866 if (--p->counters[posState] == 0)
867 LenPriceEnc_UpdateTable(p, posState, ProbPrices);
870 static void MovePos(CLzmaEnc *p, UInt32 num)
874 printf("\n MovePos %d", num);
878 p->additionalOffset += num;
879 p->matchFinder.Skip(p->matchFinderObj, num);
883 static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
885 UInt32 lenRes = 0, numPairs;
886 p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
887 numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
889 printf("\n i = %d numPairs = %d ", ttt, numPairs / 2);
893 for (i = 0; i < numPairs; i += 2)
894 printf("%2d %6d | ", p->matches[i], p->matches[i + 1]);
899 lenRes = p->matches[numPairs - 2];
900 if (lenRes == p->numFastBytes)
902 const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
903 UInt32 distance = p->matches[numPairs - 1] + 1;
904 UInt32 numAvail = p->numAvail;
905 if (numAvail > LZMA_MATCH_LEN_MAX)
906 numAvail = LZMA_MATCH_LEN_MAX;
908 const Byte *pby2 = pby - distance;
909 for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++)
914 p->additionalOffset++;
915 *numDistancePairsRes = numPairs;
919 #define MakeAsChar(p) \
920 (p)->backPrev = (UInt32)(-1); \
921 (p)->prev1IsChar = False;
922 #define MakeAsShortRep(p) \
924 (p)->prev1IsChar = False;
925 #define IsShortRep(p) ((p)->backPrev == 0)
927 static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
929 return GET_PRICE_0(p->isRepG0[state]) +
930 GET_PRICE_0(p->isRep0Long[state][posState]);
933 static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
938 price = GET_PRICE_0(p->isRepG0[state]);
939 price += GET_PRICE_1(p->isRep0Long[state][posState]);
943 price = GET_PRICE_1(p->isRepG0[state]);
945 price += GET_PRICE_0(p->isRepG1[state]);
948 price += GET_PRICE_1(p->isRepG1[state]);
949 price += GET_PRICE(p->isRepG2[state], repIndex - 2);
955 static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
957 return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
958 GetPureRepPrice(p, repIndex, state, posState);
961 static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
963 UInt32 posMem = p->opt[cur].posPrev;
964 UInt32 backMem = p->opt[cur].backPrev;
965 p->optimumEndIndex = cur;
968 if (p->opt[cur].prev1IsChar)
970 MakeAsChar(&p->opt[posMem])
971 p->opt[posMem].posPrev = posMem - 1;
972 if (p->opt[cur].prev2)
974 p->opt[posMem - 1].prev1IsChar = False;
975 p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
976 p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
980 UInt32 posPrev = posMem;
981 UInt32 backCur = backMem;
983 backMem = p->opt[posPrev].backPrev;
984 posMem = p->opt[posPrev].posPrev;
986 p->opt[posPrev].backPrev = backCur;
987 p->opt[posPrev].posPrev = cur;
991 *backRes = p->opt[0].backPrev;
992 p->optimumCurrentIndex = p->opt[0].posPrev;
993 return p->optimumCurrentIndex;
996 #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
998 static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
1000 UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
1001 UInt32 matchPrice, repMatchPrice, normalMatchPrice;
1002 UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
1005 Byte curByte, matchByte;
1006 if (p->optimumEndIndex != p->optimumCurrentIndex)
1008 const COptimal *opt = &p->opt[p->optimumCurrentIndex];
1009 UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
1010 *backRes = opt->backPrev;
1011 p->optimumCurrentIndex = opt->posPrev;
1014 p->optimumCurrentIndex = p->optimumEndIndex = 0;
1016 if (p->additionalOffset == 0)
1017 mainLen = ReadMatchDistances(p, &numPairs);
1020 mainLen = p->longestMatchLength;
1021 numPairs = p->numPairs;
1024 numAvail = p->numAvail;
1027 *backRes = (UInt32)(-1);
1030 if (numAvail > LZMA_MATCH_LEN_MAX)
1031 numAvail = LZMA_MATCH_LEN_MAX;
1033 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1035 for (i = 0; i < LZMA_NUM_REPS; i++)
1039 reps[i] = p->reps[i];
1040 data2 = data - (reps[i] + 1);
1041 if (data[0] != data2[0] || data[1] != data2[1])
1046 for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++)
1048 repLens[i] = lenTest;
1049 if (lenTest > repLens[repMaxIndex])
1052 if (repLens[repMaxIndex] >= p->numFastBytes)
1055 *backRes = repMaxIndex;
1056 lenRes = repLens[repMaxIndex];
1057 MovePos(p, lenRes - 1);
1061 matches = p->matches;
1062 if (mainLen >= p->numFastBytes)
1064 *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
1065 MovePos(p, mainLen - 1);
1069 matchByte = *(data - (reps[0] + 1));
1071 if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
1073 *backRes = (UInt32) - 1;
1077 p->opt[0].state = (CState)p->state;
1079 posState = (position & p->pbMask);
1082 const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1083 p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
1084 (!IsCharState(p->state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1087 MakeAsChar(&p->opt[1]);
1089 matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
1090 repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
1092 if (matchByte == curByte)
1094 UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
1095 if (shortRepPrice < p->opt[1].price)
1097 p->opt[1].price = shortRepPrice;
1098 MakeAsShortRep(&p->opt[1]);
1101 lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
1105 *backRes = p->opt[1].backPrev;
1109 p->opt[1].posPrev = 0;
1110 for (i = 0; i < LZMA_NUM_REPS; i++)
1111 p->opt[0].backs[i] = reps[i];
1115 p->opt[len--].price = kInfinityPrice;
1118 for (i = 0; i < LZMA_NUM_REPS; i++)
1120 UInt32 repLen = repLens[i];
1124 price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
1127 UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
1128 COptimal *opt = &p->opt[repLen];
1129 if (curAndLenPrice < opt->price)
1131 opt->price = curAndLenPrice;
1134 opt->prev1IsChar = False;
1136 } while (--repLen >= 2);
1139 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
1141 len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
1145 while (len > matches[offs])
1150 UInt32 distance = matches[offs + 1];
1152 UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
1153 UInt32 lenToPosState = GetLenToPosState(len);
1154 if (distance < kNumFullDistances)
1155 curAndLenPrice += p->distancesPrices[lenToPosState][distance];
1159 GetPosSlot2(distance, slot);
1160 curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
1163 if (curAndLenPrice < opt->price)
1165 opt->price = curAndLenPrice;
1167 opt->backPrev = distance + LZMA_NUM_REPS;
1168 opt->prev1IsChar = False;
1170 if (len == matches[offs])
1173 if (offs == numPairs)
1185 printf("\n pos = %4X", position);
1186 for (i = cur; i <= lenEnd; i++)
1187 printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
1193 UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
1194 UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
1196 Byte curByte, matchByte;
1203 return Backward(p, backRes, cur);
1205 newLen = ReadMatchDistances(p, &numPairs);
1206 if (newLen >= p->numFastBytes)
1208 p->numPairs = numPairs;
1209 p->longestMatchLength = newLen;
1210 return Backward(p, backRes, cur);
1213 curOpt = &p->opt[cur];
1214 posPrev = curOpt->posPrev;
1215 if (curOpt->prev1IsChar)
1220 state = p->opt[curOpt->posPrev2].state;
1221 if (curOpt->backPrev2 < LZMA_NUM_REPS)
1222 state = kRepNextStates[state];
1224 state = kMatchNextStates[state];
1227 state = p->opt[posPrev].state;
1228 state = kLiteralNextStates[state];
1231 state = p->opt[posPrev].state;
1232 if (posPrev == cur - 1)
1234 if (IsShortRep(curOpt))
1235 state = kShortRepNextStates[state];
1237 state = kLiteralNextStates[state];
1242 const COptimal *prevOpt;
1243 if (curOpt->prev1IsChar && curOpt->prev2)
1245 posPrev = curOpt->posPrev2;
1246 pos = curOpt->backPrev2;
1247 state = kRepNextStates[state];
1251 pos = curOpt->backPrev;
1252 if (pos < LZMA_NUM_REPS)
1253 state = kRepNextStates[state];
1255 state = kMatchNextStates[state];
1257 prevOpt = &p->opt[posPrev];
1258 if (pos < LZMA_NUM_REPS)
1261 reps[0] = prevOpt->backs[pos];
1262 for (i = 1; i <= pos; i++)
1263 reps[i] = prevOpt->backs[i - 1];
1264 for (; i < LZMA_NUM_REPS; i++)
1265 reps[i] = prevOpt->backs[i];
1270 reps[0] = (pos - LZMA_NUM_REPS);
1271 for (i = 1; i < LZMA_NUM_REPS; i++)
1272 reps[i] = prevOpt->backs[i - 1];
1275 curOpt->state = (CState)state;
1277 curOpt->backs[0] = reps[0];
1278 curOpt->backs[1] = reps[1];
1279 curOpt->backs[2] = reps[2];
1280 curOpt->backs[3] = reps[3];
1282 curPrice = curOpt->price;
1284 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1286 matchByte = *(data - (reps[0] + 1));
1288 posState = (position & p->pbMask);
1290 curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
1292 const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1294 (!IsCharState(state) ? LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) : LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1297 nextOpt = &p->opt[cur + 1];
1299 if (curAnd1Price < nextOpt->price)
1301 nextOpt->price = curAnd1Price;
1302 nextOpt->posPrev = cur;
1303 MakeAsChar(nextOpt);
1307 matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
1308 repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
1310 if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
1312 UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
1313 if (shortRepPrice <= nextOpt->price)
1315 nextOpt->price = shortRepPrice;
1316 nextOpt->posPrev = cur;
1317 MakeAsShortRep(nextOpt);
1321 numAvailFull = p->numAvail;
1323 UInt32 temp = kNumOpts - 1 - cur;
1324 if (temp < numAvailFull)
1325 numAvailFull = temp;
1328 if (numAvailFull < 2)
1330 numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
1332 if (!nextIsChar && matchByte != curByte) /* speed optimization */
1334 /* try Literal + rep0 */
1337 const Byte *data2 = data - (reps[0] + 1);
1338 UInt32 limit = p->numFastBytes + 1;
1339 if (limit > numAvailFull)
1340 limit = numAvailFull;
1342 for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++)
1344 lenTest2 = temp - 1;
1347 UInt32 state2 = kLiteralNextStates[state];
1348 UInt32 posStateNext = (position + 1) & p->pbMask;
1349 UInt32 nextRepMatchPrice = curAnd1Price +
1350 GET_PRICE_1(p->isMatch[state2][posStateNext]) +
1351 GET_PRICE_1(p->isRep[state2]);
1352 /* for (; lenTest2 >= 2; lenTest2--) */
1354 UInt32 curAndLenPrice;
1356 UInt32 offset = cur + 1 + lenTest2;
1357 while (lenEnd < offset)
1358 p->opt[++lenEnd].price = kInfinityPrice;
1359 curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
1360 opt = &p->opt[offset];
1361 if (curAndLenPrice < opt->price)
1363 opt->price = curAndLenPrice;
1364 opt->posPrev = cur + 1;
1366 opt->prev1IsChar = True;
1373 startLen = 2; /* speed optimization */
1376 for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
1381 const Byte *data2 = data - (reps[repIndex] + 1);
1382 if (data[0] != data2[0] || data[1] != data2[1])
1384 for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++)
1386 while (lenEnd < cur + lenTest)
1387 p->opt[++lenEnd].price = kInfinityPrice;
1388 lenTestTemp = lenTest;
1389 price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
1392 UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
1393 COptimal *opt = &p->opt[cur + lenTest];
1394 if (curAndLenPrice < opt->price)
1396 opt->price = curAndLenPrice;
1398 opt->backPrev = repIndex;
1399 opt->prev1IsChar = False;
1401 } while (--lenTest >= 2);
1402 lenTest = lenTestTemp;
1405 startLen = lenTest + 1;
1409 UInt32 lenTest2 = lenTest + 1;
1410 UInt32 limit = lenTest2 + p->numFastBytes;
1411 UInt32 nextRepMatchPrice;
1412 if (limit > numAvailFull)
1413 limit = numAvailFull;
1414 for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++)
1416 lenTest2 -= lenTest + 1;
1419 UInt32 state2 = kRepNextStates[state];
1420 UInt32 posStateNext = (position + lenTest) & p->pbMask;
1421 UInt32 curAndLenCharPrice =
1422 price + p->repLenEnc.prices[posState][lenTest - 2] +
1423 GET_PRICE_0(p->isMatch[state2][posStateNext]) +
1424 LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
1425 data[lenTest], data2[lenTest], p->ProbPrices);
1426 state2 = kLiteralNextStates[state2];
1427 posStateNext = (position + lenTest + 1) & p->pbMask;
1428 nextRepMatchPrice = curAndLenCharPrice +
1429 GET_PRICE_1(p->isMatch[state2][posStateNext]) +
1430 GET_PRICE_1(p->isRep[state2]);
1432 /* for (; lenTest2 >= 2; lenTest2--) */
1434 UInt32 curAndLenPrice;
1436 UInt32 offset = cur + lenTest + 1 + lenTest2;
1437 while (lenEnd < offset)
1438 p->opt[++lenEnd].price = kInfinityPrice;
1439 curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
1440 opt = &p->opt[offset];
1441 if (curAndLenPrice < opt->price)
1443 opt->price = curAndLenPrice;
1444 opt->posPrev = cur + lenTest + 1;
1446 opt->prev1IsChar = True;
1448 opt->posPrev2 = cur;
1449 opt->backPrev2 = repIndex;
1456 /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
1457 if (newLen > numAvail)
1460 for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2)
1462 matches[numPairs] = newLen;
1465 if (newLen >= startLen)
1467 UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
1468 UInt32 offs, curBack, posSlot;
1470 while (lenEnd < cur + newLen)
1471 p->opt[++lenEnd].price = kInfinityPrice;
1474 while (startLen > matches[offs])
1476 curBack = matches[offs + 1];
1477 GetPosSlot2(curBack, posSlot);
1478 for (lenTest = /*2*/ startLen;; lenTest++)
1480 UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
1481 UInt32 lenToPosState = GetLenToPosState(lenTest);
1483 if (curBack < kNumFullDistances)
1484 curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
1486 curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
1488 opt = &p->opt[cur + lenTest];
1489 if (curAndLenPrice < opt->price)
1491 opt->price = curAndLenPrice;
1493 opt->backPrev = curBack + LZMA_NUM_REPS;
1494 opt->prev1IsChar = False;
1497 if (/*_maxMode && */ lenTest == matches[offs])
1499 /* Try Match + Literal + Rep0 */
1500 const Byte *data2 = data - (curBack + 1);
1501 UInt32 lenTest2 = lenTest + 1;
1502 UInt32 limit = lenTest2 + p->numFastBytes;
1503 UInt32 nextRepMatchPrice;
1504 if (limit > numAvailFull)
1505 limit = numAvailFull;
1506 for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++)
1508 lenTest2 -= lenTest + 1;
1511 UInt32 state2 = kMatchNextStates[state];
1512 UInt32 posStateNext = (position + lenTest) & p->pbMask;
1513 UInt32 curAndLenCharPrice = curAndLenPrice +
1514 GET_PRICE_0(p->isMatch[state2][posStateNext]) +
1515 LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
1516 data[lenTest], data2[lenTest], p->ProbPrices);
1517 state2 = kLiteralNextStates[state2];
1518 posStateNext = (posStateNext + 1) & p->pbMask;
1519 nextRepMatchPrice = curAndLenCharPrice +
1520 GET_PRICE_1(p->isMatch[state2][posStateNext]) +
1521 GET_PRICE_1(p->isRep[state2]);
1523 /* for (; lenTest2 >= 2; lenTest2--) */
1525 UInt32 offset = cur + lenTest + 1 + lenTest2;
1526 UInt32 curAndLenPrice;
1528 while (lenEnd < offset)
1529 p->opt[++lenEnd].price = kInfinityPrice;
1530 curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
1531 opt = &p->opt[offset];
1532 if (curAndLenPrice < opt->price)
1534 opt->price = curAndLenPrice;
1535 opt->posPrev = cur + lenTest + 1;
1537 opt->prev1IsChar = True;
1539 opt->posPrev2 = cur;
1540 opt->backPrev2 = curBack + LZMA_NUM_REPS;
1545 if (offs == numPairs)
1547 curBack = matches[offs + 1];
1548 if (curBack >= kNumFullDistances)
1549 GetPosSlot2(curBack, posSlot);
1556 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
1558 static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
1560 UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
1562 const UInt32 *matches;
1564 if (p->additionalOffset == 0)
1565 mainLen = ReadMatchDistances(p, &numPairs);
1568 mainLen = p->longestMatchLength;
1569 numPairs = p->numPairs;
1572 numAvail = p->numAvail;
1573 *backRes = (UInt32) - 1;
1576 if (numAvail > LZMA_MATCH_LEN_MAX)
1577 numAvail = LZMA_MATCH_LEN_MAX;
1578 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1580 repLen = repIndex = 0;
1581 for (i = 0; i < LZMA_NUM_REPS; i++)
1584 const Byte *data2 = data - (p->reps[i] + 1);
1585 if (data[0] != data2[0] || data[1] != data2[1])
1587 for (len = 2; len < numAvail && data[len] == data2[len]; len++)
1589 if (len >= p->numFastBytes)
1592 MovePos(p, len - 1);
1602 matches = p->matches;
1603 if (mainLen >= p->numFastBytes)
1605 *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
1606 MovePos(p, mainLen - 1);
1610 mainDist = 0; /* for GCC */
1613 mainDist = matches[numPairs - 1];
1614 while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
1616 if (!ChangePair(matches[numPairs - 3], mainDist))
1619 mainLen = matches[numPairs - 2];
1620 mainDist = matches[numPairs - 1];
1622 if (mainLen == 2 && mainDist >= 0x80)
1626 if (repLen >= 2 && ((repLen + 1 >= mainLen) ||
1627 (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
1628 (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
1630 *backRes = repIndex;
1631 MovePos(p, repLen - 1);
1635 if (mainLen < 2 || numAvail <= 2)
1638 p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
1639 if (p->longestMatchLength >= 2)
1641 UInt32 newDistance = matches[p->numPairs - 1];
1642 if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
1643 (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
1644 (p->longestMatchLength > mainLen + 1) ||
1645 (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
1649 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1650 for (i = 0; i < LZMA_NUM_REPS; i++)
1653 const Byte *data2 = data - (p->reps[i] + 1);
1654 if (data[0] != data2[0] || data[1] != data2[1])
1656 limit = mainLen - 1;
1657 for (len = 2; len < limit && data[len] == data2[len]; len++)
1662 *backRes = mainDist + LZMA_NUM_REPS;
1663 MovePos(p, mainLen - 2);
1667 static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
1670 RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
1671 RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
1672 p->state = kMatchNextStates[p->state];
1673 len = LZMA_MATCH_LEN_MIN;
1674 LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
1675 RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
1676 RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
1677 RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
1680 static SRes CheckErrors(CLzmaEnc *p)
1682 if (p->result != SZ_OK)
1684 if (p->rc.res != SZ_OK)
1685 p->result = SZ_ERROR_WRITE;
1686 if (p->matchFinderBase.result != SZ_OK)
1687 p->result = SZ_ERROR_READ;
1688 if (p->result != SZ_OK)
1693 static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
1695 /* ReleaseMFStream(); */
1697 if (p->writeEndMark)
1698 WriteEndMarker(p, nowPos & p->pbMask);
1699 RangeEnc_FlushData(&p->rc);
1700 RangeEnc_FlushStream(&p->rc);
1701 return CheckErrors(p);
1704 static void FillAlignPrices(CLzmaEnc *p)
1707 for (i = 0; i < kAlignTableSize; i++)
1708 p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
1709 p->alignPriceCount = 0;
1712 static void FillDistancesPrices(CLzmaEnc *p)
1714 UInt32 tempPrices[kNumFullDistances];
1715 UInt32 i, lenToPosState;
1716 for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
1718 UInt32 posSlot = GetPosSlot1(i);
1719 UInt32 footerBits = ((posSlot >> 1) - 1);
1720 UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1721 tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
1724 for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
1727 const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
1728 UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
1729 for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
1730 posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
1731 for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
1732 posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
1735 UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
1737 for (i = 0; i < kStartPosModelIndex; i++)
1738 distancesPrices[i] = posSlotPrices[i];
1739 for (; i < kNumFullDistances; i++)
1740 distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
1743 p->matchPriceCount = 0;
1746 void LzmaEnc_Construct(CLzmaEnc *p)
1748 RangeEnc_Construct(&p->rc);
1749 MatchFinder_Construct(&p->matchFinderBase);
1750 #ifdef COMPRESS_MF_MT
1751 MatchFinderMt_Construct(&p->matchFinderMt);
1752 p->matchFinderMt.MatchFinder = &p->matchFinderBase;
1756 CLzmaEncProps props;
1757 LzmaEncProps_Init(&props);
1758 LzmaEnc_SetProps(p, &props);
1761 #ifndef LZMA_LOG_BSR
1762 LzmaEnc_FastPosInit(p->g_FastPos);
1765 LzmaEnc_InitPriceTables(p->ProbPrices);
1767 p->saveState.litProbs = 0;
1770 CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
1773 p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
1775 LzmaEnc_Construct((CLzmaEnc *)p);
1779 void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
1781 alloc->Free(alloc, p->litProbs);
1782 alloc->Free(alloc, p->saveState.litProbs);
1784 p->saveState.litProbs = 0;
1787 void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
1789 #ifdef COMPRESS_MF_MT
1790 MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
1792 MatchFinder_Free(&p->matchFinderBase, allocBig);
1793 LzmaEnc_FreeLits(p, alloc);
1794 RangeEnc_Free(&p->rc, alloc);
1797 void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
1799 LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
1800 alloc->Free(alloc, p);
1803 static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
1805 UInt32 nowPos32, startPos32;
1806 if (p->inStream != 0)
1808 p->matchFinderBase.stream = p->inStream;
1809 p->matchFinder.Init(p->matchFinderObj);
1815 RINOK(CheckErrors(p));
1817 nowPos32 = (UInt32)p->nowPos64;
1818 startPos32 = nowPos32;
1820 if (p->nowPos64 == 0)
1824 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
1825 return Flush(p, nowPos32);
1826 ReadMatchDistances(p, &numPairs);
1827 RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
1828 p->state = kLiteralNextStates[p->state];
1829 curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
1830 LitEnc_Encode(&p->rc, p->litProbs, curByte);
1831 p->additionalOffset--;
1835 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
1838 UInt32 pos, len, posState;
1841 len = GetOptimumFast(p, &pos);
1843 len = GetOptimum(p, nowPos32, &pos);
1846 printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos);
1849 posState = nowPos32 & p->pbMask;
1850 if (len == 1 && pos == (UInt32) - 1)
1856 RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
1857 data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
1859 probs = LIT_PROBS(nowPos32, *(data - 1));
1860 if (IsCharState(p->state))
1861 LitEnc_Encode(&p->rc, probs, curByte);
1863 LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
1864 p->state = kLiteralNextStates[p->state];
1868 RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
1869 if (pos < LZMA_NUM_REPS)
1871 RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
1874 RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
1875 RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
1879 UInt32 distance = p->reps[pos];
1880 RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
1882 RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
1885 RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
1886 RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
1888 p->reps[3] = p->reps[2];
1889 p->reps[2] = p->reps[1];
1891 p->reps[1] = p->reps[0];
1892 p->reps[0] = distance;
1895 p->state = kShortRepNextStates[p->state];
1898 LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
1899 p->state = kRepNextStates[p->state];
1905 RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
1906 p->state = kMatchNextStates[p->state];
1907 LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
1908 pos -= LZMA_NUM_REPS;
1909 GetPosSlot(pos, posSlot);
1910 RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
1912 if (posSlot >= kStartPosModelIndex)
1914 UInt32 footerBits = ((posSlot >> 1) - 1);
1915 UInt32 base = ((2 | (posSlot & 1)) << footerBits);
1916 UInt32 posReduced = pos - base;
1918 if (posSlot < kEndPosModelIndex)
1919 RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
1922 RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
1923 RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
1924 p->alignPriceCount++;
1927 p->reps[3] = p->reps[2];
1928 p->reps[2] = p->reps[1];
1929 p->reps[1] = p->reps[0];
1931 p->matchPriceCount++;
1934 p->additionalOffset -= len;
1936 if (p->additionalOffset == 0)
1941 if (p->matchPriceCount >= (1 << 7))
1942 FillDistancesPrices(p);
1943 if (p->alignPriceCount >= kAlignTableSize)
1946 if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
1948 processed = nowPos32 - startPos32;
1951 if (processed + kNumOpts + 300 >= maxUnpackSize ||
1952 RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
1955 else if (processed >= (1 << 15))
1957 p->nowPos64 += nowPos32 - startPos32;
1958 return CheckErrors(p);
1962 p->nowPos64 += nowPos32 - startPos32;
1963 return Flush(p, nowPos32);
1966 #define kBigHashDicLimit ((UInt32)1 << 24)
1968 static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
1970 UInt32 beforeSize = kNumOpts;
1973 if (!RangeEnc_Alloc(&p->rc, alloc))
1974 return SZ_ERROR_MEM;
1975 btMode = (p->matchFinderBase.btMode != 0);
1976 #ifdef COMPRESS_MF_MT
1977 p->mtMode = (p->multiThread && !p->fastMode && btMode);
1981 unsigned lclp = p->lc + p->lp;
1982 if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
1984 LzmaEnc_FreeLits(p, alloc);
1985 p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
1986 p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
1987 if (p->litProbs == 0 || p->saveState.litProbs == 0)
1989 LzmaEnc_FreeLits(p, alloc);
1990 return SZ_ERROR_MEM;
1996 p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
1998 if (beforeSize + p->dictSize < keepWindowSize)
1999 beforeSize = keepWindowSize - p->dictSize;
2001 #ifdef COMPRESS_MF_MT
2004 RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
2005 p->matchFinderObj = &p->matchFinderMt;
2006 MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
2011 if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
2012 return SZ_ERROR_MEM;
2013 p->matchFinderObj = &p->matchFinderBase;
2014 MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
2019 void LzmaEnc_Init(CLzmaEnc *p)
2023 for (i = 0; i < LZMA_NUM_REPS; i++)
2026 RangeEnc_Init(&p->rc);
2028 for (i = 0; i < kNumStates; i++)
2031 for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
2033 p->isMatch[i][j] = kProbInitValue;
2034 p->isRep0Long[i][j] = kProbInitValue;
2036 p->isRep[i] = kProbInitValue;
2037 p->isRepG0[i] = kProbInitValue;
2038 p->isRepG1[i] = kProbInitValue;
2039 p->isRepG2[i] = kProbInitValue;
2043 UInt32 num = 0x300 << (p->lp + p->lc);
2044 for (i = 0; i < num; i++)
2045 p->litProbs[i] = kProbInitValue;
2049 for (i = 0; i < kNumLenToPosStates; i++)
2051 CLzmaProb *probs = p->posSlotEncoder[i];
2053 for (j = 0; j < (1 << kNumPosSlotBits); j++)
2054 probs[j] = kProbInitValue;
2058 for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
2059 p->posEncoders[i] = kProbInitValue;
2062 LenEnc_Init(&p->lenEnc.p);
2063 LenEnc_Init(&p->repLenEnc.p);
2065 for (i = 0; i < (1 << kNumAlignBits); i++)
2066 p->posAlignEncoder[i] = kProbInitValue;
2068 p->optimumEndIndex = 0;
2069 p->optimumCurrentIndex = 0;
2070 p->additionalOffset = 0;
2072 p->pbMask = (1 << p->pb) - 1;
2073 p->lpMask = (1 << p->lp) - 1;
2076 void LzmaEnc_InitPrices(CLzmaEnc *p)
2080 FillDistancesPrices(p);
2084 p->lenEnc.tableSize =
2085 p->repLenEnc.tableSize =
2086 p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
2087 LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
2088 LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
2091 static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
2094 for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
2095 if (p->dictSize <= ((UInt32)1 << i))
2097 p->distTableSize = i * 2;
2099 p->finished = False;
2101 RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
2103 LzmaEnc_InitPrices(p);
2108 static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
2109 ISzAlloc *alloc, ISzAlloc *allocBig)
2111 CLzmaEnc *p = (CLzmaEnc *)pp;
2112 p->inStream = inStream;
2113 p->rc.outStream = outStream;
2114 return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
2117 SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
2118 ISeqInStream *inStream, UInt32 keepWindowSize,
2119 ISzAlloc *alloc, ISzAlloc *allocBig)
2121 CLzmaEnc *p = (CLzmaEnc *)pp;
2122 p->inStream = inStream;
2123 return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2126 static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
2128 p->seqBufInStream.funcTable.Read = MyRead;
2129 p->seqBufInStream.data = src;
2130 p->seqBufInStream.rem = srcLen;
2133 SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
2134 UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
2136 CLzmaEnc *p = (CLzmaEnc *)pp;
2137 LzmaEnc_SetInputBuf(p, src, srcLen);
2138 p->inStream = &p->seqBufInStream.funcTable;
2139 return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2142 void LzmaEnc_Finish(CLzmaEncHandle pp)
2144 #ifdef COMPRESS_MF_MT
2145 CLzmaEnc *p = (CLzmaEnc *)pp;
2147 MatchFinderMt_ReleaseStream(&p->matchFinderMt);
2154 typedef struct _CSeqOutStreamBuf
2156 ISeqOutStream funcTable;
2162 static size_t MyWrite(void *pp, const void *data, size_t size)
2164 CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
2170 memcpy(p->data, data, size);
2176 UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
2178 const CLzmaEnc *p = (CLzmaEnc *)pp;
2179 return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
2182 const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
2184 const CLzmaEnc *p = (CLzmaEnc *)pp;
2185 return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2188 SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
2189 Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
2191 CLzmaEnc *p = (CLzmaEnc *)pp;
2194 CSeqOutStreamBuf outStream;
2196 outStream.funcTable.Write = MyWrite;
2197 outStream.data = dest;
2198 outStream.rem = *destLen;
2199 outStream.overflow = False;
2201 p->writeEndMark = False;
2202 p->finished = False;
2207 LzmaEnc_InitPrices(p);
2208 nowPos64 = p->nowPos64;
2209 RangeEnc_Init(&p->rc);
2210 p->rc.outStream = &outStream.funcTable;
2212 res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
2214 *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
2215 *destLen -= outStream.rem;
2216 if (outStream.overflow)
2217 return SZ_ERROR_OUTPUT_EOF;
2222 SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
2223 ISzAlloc *alloc, ISzAlloc *allocBig)
2225 CLzmaEnc *p = (CLzmaEnc *)pp;
2228 #ifdef COMPRESS_MF_MT
2229 Byte allocaDummy[0x300];
2232 for (i = 0; i < 16; i++)
2233 allocaDummy[i] = (Byte)i;
2236 RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
2240 res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
2241 if (res != SZ_OK || p->finished != 0)
2245 res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
2248 res = SZ_ERROR_PROGRESS;
2257 SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
2259 CLzmaEnc *p = (CLzmaEnc *)pp;
2261 UInt32 dictSize = p->dictSize;
2262 if (*size < LZMA_PROPS_SIZE)
2263 return SZ_ERROR_PARAM;
2264 *size = LZMA_PROPS_SIZE;
2265 props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
2267 for (i = 11; i <= 30; i++)
2269 if (dictSize <= ((UInt32)2 << i))
2271 dictSize = (2 << i);
2274 if (dictSize <= ((UInt32)3 << i))
2276 dictSize = (3 << i);
2281 for (i = 0; i < 4; i++)
2282 props[1 + i] = (Byte)(dictSize >> (8 * i));
2286 SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
2287 int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
2290 CLzmaEnc *p = (CLzmaEnc *)pp;
2292 CSeqOutStreamBuf outStream;
2294 LzmaEnc_SetInputBuf(p, src, srcLen);
2296 outStream.funcTable.Write = MyWrite;
2297 outStream.data = dest;
2298 outStream.rem = *destLen;
2299 outStream.overflow = False;
2301 p->writeEndMark = writeEndMark;
2302 res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
2303 progress, alloc, allocBig);
2305 *destLen -= outStream.rem;
2306 if (outStream.overflow)
2307 return SZ_ERROR_OUTPUT_EOF;
2311 SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
2312 const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
2313 ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
2315 CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
2318 return SZ_ERROR_MEM;
2320 res = LzmaEnc_SetProps(p, props);
2323 res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
2325 res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
2326 writeEndMark, progress, alloc, allocBig);
2329 LzmaEnc_Destroy(p, alloc, allocBig);