2 Based on LZMA SDK 4.65:
3 LzmaEnc.c -- LZMA Encoder
4 2009-02-02 : Igor Pavlov : Public domain
6 Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 /* #define SHOW_STAT */
20 /* #define SHOW_STAT2 */
22 #if defined(SHOW_STAT) || defined(SHOW_STAT2)
37 #define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
39 #define kBlockSize (9 << 10)
40 #define kUnpackBlockSize (1 << 18)
41 #define kMatchArraySize (1 << 21)
42 #define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
44 #define kNumMaxDirectBits (31)
46 #define kNumTopBits 24
47 #define kTopValue ((UInt32)1 << kNumTopBits)
49 #define kNumBitModelTotalBits 11
50 #define kBitModelTotal (1 << kNumBitModelTotalBits)
51 #define kNumMoveBits 5
52 #define kProbInitValue (kBitModelTotal >> 1)
54 #define kNumMoveReducingBits 4
55 #define kNumBitPriceShiftBits 4
56 #define kBitPrice (1 << kNumBitPriceShiftBits)
58 void LzmaEncProps_Init(CLzmaEncProps
*p
)
61 p
->dictSize
= p
->mc
= 0;
62 p
->lc
= p
->lp
= p
->pb
= p
->algo
= p
->fb
= p
->btMode
= p
->numHashBytes
= p
->numThreads
= -1;
66 void LzmaEncProps_Normalize(CLzmaEncProps
*p
)
69 if (level
< 0) level
= 5;
71 if (p
->dictSize
== 0) p
->dictSize
= (level
<= 5 ? (1 << (level
* 2 + 14)) : (level
== 6 ? (1 << 25) : (1 << 26)));
72 if (p
->lc
< 0) p
->lc
= 3;
73 if (p
->lp
< 0) p
->lp
= 0;
74 if (p
->pb
< 0) p
->pb
= 2;
75 if (p
->algo
< 0) p
->algo
= (level
< 5 ? 0 : 1);
76 if (p
->fb
< 0) p
->fb
= (level
< 7 ? 32 : 64);
77 if (p
->btMode
< 0) p
->btMode
= (p
->algo
== 0 ? 0 : 1);
78 if (p
->numHashBytes
< 0) p
->numHashBytes
= 4;
79 if (p
->mc
== 0) p
->mc
= (16 + (p
->fb
>> 1)) >> (p
->btMode
? 0 : 1);
80 if (p
->numThreads
< 0)
83 ((p
->btMode
&& p
->algo
) ? 2 : 1);
89 UInt32
LzmaEncProps_GetDictSize(const CLzmaEncProps
*props2
)
91 CLzmaEncProps props
= *props2
;
92 LzmaEncProps_Normalize(&props
);
93 return props
.dictSize
;
96 /* #define LZMA_LOG_BSR */
97 /* Define it for Intel's CPU */
102 #define kDicLogSizeMaxCompress 30
104 #define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
106 UInt32
GetPosSlot1(UInt32 pos
)
112 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
113 #define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
117 #define kNumLogBits (9 + (int)sizeof(size_t) / 2)
118 #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
120 void LzmaEnc_FastPosInit(Byte
*g_FastPos
)
126 for (slotFast
= 2; slotFast
< kNumLogBits
* 2; slotFast
++)
128 UInt32 k
= (1 << ((slotFast
>> 1) - 1));
130 for (j
= 0; j
< k
; j
++, c
++)
131 g_FastPos
[c
] = (Byte
)slotFast
;
135 #define BSR2_RET(pos, res) { UInt32 ij = 6 + ((kNumLogBits - 1) & \
136 (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
137 res = p->g_FastPos[pos >> ij] + (ij * 2); }
139 #define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
140 p->g_FastPos[pos >> 6] + 12 : \
141 p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
144 #define GetPosSlot1(pos) p->g_FastPos[pos]
145 #define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
146 #define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
151 #define LZMA_NUM_REPS 4
153 typedef unsigned CState
;
155 typedef struct _COptimal
168 UInt32 backs
[LZMA_NUM_REPS
];
171 #define kNumOpts (1 << 12)
173 #define kNumLenToPosStates 4
174 #define kNumPosSlotBits 6
175 #define kDicLogSizeMin 0
176 #define kDicLogSizeMax 32
177 #define kDistTableSizeMax (kDicLogSizeMax * 2)
180 #define kNumAlignBits 4
181 #define kAlignTableSize (1 << kNumAlignBits)
182 #define kAlignMask (kAlignTableSize - 1)
184 #define kStartPosModelIndex 4
185 #define kEndPosModelIndex 14
186 #define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
188 #define kNumFullDistances (1 << (kEndPosModelIndex / 2))
191 #define CLzmaProb UInt32
193 #define CLzmaProb UInt16
196 #define LZMA_PB_MAX 4
197 #define LZMA_LC_MAX 8
198 #define LZMA_LP_MAX 4
200 #define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
203 #define kLenNumLowBits 3
204 #define kLenNumLowSymbols (1 << kLenNumLowBits)
205 #define kLenNumMidBits 3
206 #define kLenNumMidSymbols (1 << kLenNumMidBits)
207 #define kLenNumHighBits 8
208 #define kLenNumHighSymbols (1 << kLenNumHighBits)
210 #define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
212 #define LZMA_MATCH_LEN_MIN 2
213 #define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
215 #define kNumStates 12
221 CLzmaProb low
[LZMA_NUM_PB_STATES_MAX
<< kLenNumLowBits
];
222 CLzmaProb mid
[LZMA_NUM_PB_STATES_MAX
<< kLenNumMidBits
];
223 CLzmaProb high
[kLenNumHighSymbols
];
229 UInt32 prices
[LZMA_NUM_PB_STATES_MAX
][kLenNumSymbolsTotal
];
231 UInt32 counters
[LZMA_NUM_PB_STATES_MAX
];
234 typedef struct _CRangeEnc
243 ISeqOutStream
*outStream
;
248 typedef struct _CSeqInStreamBuf
250 ISeqInStream funcTable
;
255 static SRes
MyRead(void *pp
, void *data
, size_t *size
)
257 size_t curSize
= *size
;
258 CSeqInStreamBuf
*p
= (CSeqInStreamBuf
*)pp
;
259 if (p
->rem
< curSize
)
261 memcpy(data
, p
->data
, curSize
);
272 CLzmaProb isMatch
[kNumStates
][LZMA_NUM_PB_STATES_MAX
];
273 CLzmaProb isRep
[kNumStates
];
274 CLzmaProb isRepG0
[kNumStates
];
275 CLzmaProb isRepG1
[kNumStates
];
276 CLzmaProb isRepG2
[kNumStates
];
277 CLzmaProb isRep0Long
[kNumStates
][LZMA_NUM_PB_STATES_MAX
];
279 CLzmaProb posSlotEncoder
[kNumLenToPosStates
][1 << kNumPosSlotBits
];
280 CLzmaProb posEncoders
[kNumFullDistances
- kEndPosModelIndex
];
281 CLzmaProb posAlignEncoder
[1 << kNumAlignBits
];
284 CLenPriceEnc repLenEnc
;
286 UInt32 reps
[LZMA_NUM_REPS
];
290 typedef struct _CLzmaEnc
292 IMatchFinder matchFinder
;
293 void *matchFinderObj
;
295 #ifdef COMPRESS_MF_MT
297 CMatchFinderMt matchFinderMt
;
300 CMatchFinder matchFinderBase
;
302 #ifdef COMPRESS_MF_MT
306 UInt32 optimumEndIndex
;
307 UInt32 optimumCurrentIndex
;
309 UInt32 longestMatchLength
;
312 COptimal opt
[kNumOpts
];
315 Byte g_FastPos
[1 << kNumLogBits
];
318 UInt32 ProbPrices
[kBitModelTotal
>> kNumMoveReducingBits
];
319 UInt32 matches
[LZMA_MATCH_LEN_MAX
* 2 + 2 + 1];
321 UInt32 additionalOffset
;
322 UInt32 reps
[LZMA_NUM_REPS
];
325 UInt32 posSlotPrices
[kNumLenToPosStates
][kDistTableSizeMax
];
326 UInt32 distancesPrices
[kNumLenToPosStates
][kNumFullDistances
];
327 UInt32 alignPrices
[kAlignTableSize
];
328 UInt32 alignPriceCount
;
330 UInt32 distTableSize
;
333 unsigned lpMask
, pbMask
;
337 CLzmaProb isMatch
[kNumStates
][LZMA_NUM_PB_STATES_MAX
];
338 CLzmaProb isRep
[kNumStates
];
339 CLzmaProb isRepG0
[kNumStates
];
340 CLzmaProb isRepG1
[kNumStates
];
341 CLzmaProb isRepG2
[kNumStates
];
342 CLzmaProb isRep0Long
[kNumStates
][LZMA_NUM_PB_STATES_MAX
];
344 CLzmaProb posSlotEncoder
[kNumLenToPosStates
][1 << kNumPosSlotBits
];
345 CLzmaProb posEncoders
[kNumFullDistances
- kEndPosModelIndex
];
346 CLzmaProb posAlignEncoder
[1 << kNumAlignBits
];
349 CLenPriceEnc repLenEnc
;
359 UInt32 matchPriceCount
;
365 UInt32 matchFinderCycles
;
367 ISeqInStream
*inStream
;
368 CSeqInStreamBuf seqBufInStream
;
370 CSaveState saveState
;
373 void LzmaEnc_SaveState(CLzmaEncHandle pp
)
375 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
376 CSaveState
*dest
= &p
->saveState
;
378 dest
->lenEnc
= p
->lenEnc
;
379 dest
->repLenEnc
= p
->repLenEnc
;
380 dest
->state
= p
->state
;
382 for (i
= 0; i
< kNumStates
; i
++)
384 memcpy(dest
->isMatch
[i
], p
->isMatch
[i
], sizeof(p
->isMatch
[i
]));
385 memcpy(dest
->isRep0Long
[i
], p
->isRep0Long
[i
], sizeof(p
->isRep0Long
[i
]));
387 for (i
= 0; i
< kNumLenToPosStates
; i
++)
388 memcpy(dest
->posSlotEncoder
[i
], p
->posSlotEncoder
[i
], sizeof(p
->posSlotEncoder
[i
]));
389 memcpy(dest
->isRep
, p
->isRep
, sizeof(p
->isRep
));
390 memcpy(dest
->isRepG0
, p
->isRepG0
, sizeof(p
->isRepG0
));
391 memcpy(dest
->isRepG1
, p
->isRepG1
, sizeof(p
->isRepG1
));
392 memcpy(dest
->isRepG2
, p
->isRepG2
, sizeof(p
->isRepG2
));
393 memcpy(dest
->posEncoders
, p
->posEncoders
, sizeof(p
->posEncoders
));
394 memcpy(dest
->posAlignEncoder
, p
->posAlignEncoder
, sizeof(p
->posAlignEncoder
));
395 memcpy(dest
->reps
, p
->reps
, sizeof(p
->reps
));
396 memcpy(dest
->litProbs
, p
->litProbs
, (0x300 << p
->lclp
) * sizeof(CLzmaProb
));
399 void LzmaEnc_RestoreState(CLzmaEncHandle pp
)
401 CLzmaEnc
*dest
= (CLzmaEnc
*)pp
;
402 const CSaveState
*p
= &dest
->saveState
;
404 dest
->lenEnc
= p
->lenEnc
;
405 dest
->repLenEnc
= p
->repLenEnc
;
406 dest
->state
= p
->state
;
408 for (i
= 0; i
< kNumStates
; i
++)
410 memcpy(dest
->isMatch
[i
], p
->isMatch
[i
], sizeof(p
->isMatch
[i
]));
411 memcpy(dest
->isRep0Long
[i
], p
->isRep0Long
[i
], sizeof(p
->isRep0Long
[i
]));
413 for (i
= 0; i
< kNumLenToPosStates
; i
++)
414 memcpy(dest
->posSlotEncoder
[i
], p
->posSlotEncoder
[i
], sizeof(p
->posSlotEncoder
[i
]));
415 memcpy(dest
->isRep
, p
->isRep
, sizeof(p
->isRep
));
416 memcpy(dest
->isRepG0
, p
->isRepG0
, sizeof(p
->isRepG0
));
417 memcpy(dest
->isRepG1
, p
->isRepG1
, sizeof(p
->isRepG1
));
418 memcpy(dest
->isRepG2
, p
->isRepG2
, sizeof(p
->isRepG2
));
419 memcpy(dest
->posEncoders
, p
->posEncoders
, sizeof(p
->posEncoders
));
420 memcpy(dest
->posAlignEncoder
, p
->posAlignEncoder
, sizeof(p
->posAlignEncoder
));
421 memcpy(dest
->reps
, p
->reps
, sizeof(p
->reps
));
422 memcpy(dest
->litProbs
, p
->litProbs
, (0x300 << dest
->lclp
) * sizeof(CLzmaProb
));
425 SRes
LzmaEnc_SetProps(CLzmaEncHandle pp
, const CLzmaEncProps
*props2
)
427 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
428 CLzmaEncProps props
= *props2
;
429 LzmaEncProps_Normalize(&props
);
431 if (props
.lc
> LZMA_LC_MAX
|| props
.lp
> LZMA_LP_MAX
|| props
.pb
> LZMA_PB_MAX
||
432 props
.dictSize
> (1 << kDicLogSizeMaxCompress
) || props
.dictSize
> (1 << 30))
433 return SZ_ERROR_PARAM
;
434 p
->dictSize
= props
.dictSize
;
435 p
->matchFinderCycles
= props
.mc
;
437 unsigned fb
= props
.fb
;
440 if (fb
> LZMA_MATCH_LEN_MAX
)
441 fb
= LZMA_MATCH_LEN_MAX
;
442 p
->numFastBytes
= fb
;
447 p
->fastMode
= (props
.algo
== 0);
448 p
->matchFinderBase
.btMode
= props
.btMode
;
450 UInt32 numHashBytes
= 4;
453 if (props
.numHashBytes
< 2)
455 else if (props
.numHashBytes
< 4)
456 numHashBytes
= props
.numHashBytes
;
458 p
->matchFinderBase
.numHashBytes
= numHashBytes
;
461 p
->matchFinderBase
.cutValue
= props
.mc
;
463 p
->writeEndMark
= props
.writeEndMark
;
465 #ifdef COMPRESS_MF_MT
467 if (newMultiThread != _multiThread)
469 ReleaseMatchFinder();
470 _multiThread = newMultiThread;
473 p
->multiThread
= (props
.numThreads
> 1);
479 static const int kLiteralNextStates
[kNumStates
] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
480 static const int kMatchNextStates
[kNumStates
] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
481 static const int kRepNextStates
[kNumStates
] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
482 static const int kShortRepNextStates
[kNumStates
]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
484 #define IsCharState(s) ((s) < 7)
486 #define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
488 #define kInfinityPrice (1 << 30)
490 static void RangeEnc_Construct(CRangeEnc
*p
)
496 #define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
498 #define RC_BUF_SIZE (1 << 16)
499 static int RangeEnc_Alloc(CRangeEnc
*p
, ISzAlloc
*alloc
)
503 p
->bufBase
= (Byte
*)alloc
->Alloc(alloc
, RC_BUF_SIZE
);
506 p
->bufLim
= p
->bufBase
+ RC_BUF_SIZE
;
511 static void RangeEnc_Free(CRangeEnc
*p
, ISzAlloc
*alloc
)
513 alloc
->Free(alloc
, p
->bufBase
);
517 static void RangeEnc_Init(CRangeEnc
*p
)
521 p
->range
= 0xFFFFFFFF;
531 static void RangeEnc_FlushStream(CRangeEnc
*p
)
536 num
= p
->buf
- p
->bufBase
;
537 if (num
!= p
->outStream
->Write(p
->outStream
, p
->bufBase
, num
))
538 p
->res
= SZ_ERROR_WRITE
;
543 static void MY_FAST_CALL
RangeEnc_ShiftLow(CRangeEnc
*p
)
545 if ((UInt32
)p
->low
< (UInt32
)0xFF000000 || (int)(p
->low
>> 32) != 0)
547 Byte temp
= p
->cache
;
551 *buf
++ = (Byte
)(temp
+ (Byte
)(p
->low
>> 32));
553 if (buf
== p
->bufLim
)
554 RangeEnc_FlushStream(p
);
557 while (--p
->cacheSize
!= 0);
558 p
->cache
= (Byte
)((UInt32
)p
->low
>> 24);
561 p
->low
= (UInt32
)p
->low
<< 8;
564 static void RangeEnc_FlushData(CRangeEnc
*p
)
567 for (i
= 0; i
< 5; i
++)
568 RangeEnc_ShiftLow(p
);
571 static void RangeEnc_EncodeDirectBits(CRangeEnc
*p
, UInt32 value
, int numBits
)
576 p
->low
+= p
->range
& (0 - ((value
>> --numBits
) & 1));
577 if (p
->range
< kTopValue
)
580 RangeEnc_ShiftLow(p
);
583 while (numBits
!= 0);
586 static void RangeEnc_EncodeBit(CRangeEnc
*p
, CLzmaProb
*prob
, UInt32 symbol
)
589 UInt32 newBound
= (p
->range
>> kNumBitModelTotalBits
) * ttt
;
593 ttt
+= (kBitModelTotal
- ttt
) >> kNumMoveBits
;
598 p
->range
-= newBound
;
599 ttt
-= ttt
>> kNumMoveBits
;
601 *prob
= (CLzmaProb
)ttt
;
602 if (p
->range
< kTopValue
)
605 RangeEnc_ShiftLow(p
);
609 static void LitEnc_Encode(CRangeEnc
*p
, CLzmaProb
*probs
, UInt32 symbol
)
614 RangeEnc_EncodeBit(p
, probs
+ (symbol
>> 8), (symbol
>> 7) & 1);
617 while (symbol
< 0x10000);
620 static void LitEnc_EncodeMatched(CRangeEnc
*p
, CLzmaProb
*probs
, UInt32 symbol
, UInt32 matchByte
)
627 RangeEnc_EncodeBit(p
, probs
+ (offs
+ (matchByte
& offs
) + (symbol
>> 8)), (symbol
>> 7) & 1);
629 offs
&= ~(matchByte
^ symbol
);
631 while (symbol
< 0x10000);
634 void LzmaEnc_InitPriceTables(UInt32
*ProbPrices
)
637 for (i
= (1 << kNumMoveReducingBits
) / 2; i
< kBitModelTotal
; i
+= (1 << kNumMoveReducingBits
))
639 const int kCyclesBits
= kNumBitPriceShiftBits
;
643 for (j
= 0; j
< kCyclesBits
; j
++)
647 while (w
>= ((UInt32
)1 << 16))
653 ProbPrices
[i
>> kNumMoveReducingBits
] = ((kNumBitModelTotalBits
<< kCyclesBits
) - 15 - bitCount
);
658 #define GET_PRICE(prob, symbol) \
659 p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
661 #define GET_PRICEa(prob, symbol) \
662 ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
664 #define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
665 #define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
667 #define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
668 #define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
670 static UInt32
LitEnc_GetPrice(const CLzmaProb
*probs
, UInt32 symbol
, UInt32
*ProbPrices
)
676 price
+= GET_PRICEa(probs
[symbol
>> 8], (symbol
>> 7) & 1);
679 while (symbol
< 0x10000);
683 static UInt32
LitEnc_GetPriceMatched(const CLzmaProb
*probs
, UInt32 symbol
, UInt32 matchByte
, UInt32
*ProbPrices
)
691 price
+= GET_PRICEa(probs
[offs
+ (matchByte
& offs
) + (symbol
>> 8)], (symbol
>> 7) & 1);
693 offs
&= ~(matchByte
^ symbol
);
695 while (symbol
< 0x10000);
700 static void RcTree_Encode(CRangeEnc
*rc
, CLzmaProb
*probs
, int numBitLevels
, UInt32 symbol
)
704 for (i
= numBitLevels
; i
!= 0;)
708 bit
= (symbol
>> i
) & 1;
709 RangeEnc_EncodeBit(rc
, probs
+ m
, bit
);
714 static void RcTree_ReverseEncode(CRangeEnc
*rc
, CLzmaProb
*probs
, int numBitLevels
, UInt32 symbol
)
718 for (i
= 0; i
< numBitLevels
; i
++)
720 UInt32 bit
= symbol
& 1;
721 RangeEnc_EncodeBit(rc
, probs
+ m
, bit
);
727 static UInt32
RcTree_GetPrice(const CLzmaProb
*probs
, int numBitLevels
, UInt32 symbol
, UInt32
*ProbPrices
)
730 symbol
|= (1 << numBitLevels
);
733 price
+= GET_PRICEa(probs
[symbol
>> 1], symbol
& 1);
739 static UInt32
RcTree_ReverseGetPrice(const CLzmaProb
*probs
, int numBitLevels
, UInt32 symbol
, UInt32
*ProbPrices
)
744 for (i
= numBitLevels
; i
!= 0; i
--)
746 UInt32 bit
= symbol
& 1;
748 price
+= GET_PRICEa(probs
[m
], bit
);
755 static void LenEnc_Init(CLenEnc
*p
)
758 p
->choice
= p
->choice2
= kProbInitValue
;
759 for (i
= 0; i
< (LZMA_NUM_PB_STATES_MAX
<< kLenNumLowBits
); i
++)
760 p
->low
[i
] = kProbInitValue
;
761 for (i
= 0; i
< (LZMA_NUM_PB_STATES_MAX
<< kLenNumMidBits
); i
++)
762 p
->mid
[i
] = kProbInitValue
;
763 for (i
= 0; i
< kLenNumHighSymbols
; i
++)
764 p
->high
[i
] = kProbInitValue
;
767 static void LenEnc_Encode(CLenEnc
*p
, CRangeEnc
*rc
, UInt32 symbol
, UInt32 posState
)
769 if (symbol
< kLenNumLowSymbols
)
771 RangeEnc_EncodeBit(rc
, &p
->choice
, 0);
772 RcTree_Encode(rc
, p
->low
+ (posState
<< kLenNumLowBits
), kLenNumLowBits
, symbol
);
776 RangeEnc_EncodeBit(rc
, &p
->choice
, 1);
777 if (symbol
< kLenNumLowSymbols
+ kLenNumMidSymbols
)
779 RangeEnc_EncodeBit(rc
, &p
->choice2
, 0);
780 RcTree_Encode(rc
, p
->mid
+ (posState
<< kLenNumMidBits
), kLenNumMidBits
, symbol
- kLenNumLowSymbols
);
784 RangeEnc_EncodeBit(rc
, &p
->choice2
, 1);
785 RcTree_Encode(rc
, p
->high
, kLenNumHighBits
, symbol
- kLenNumLowSymbols
- kLenNumMidSymbols
);
790 static void LenEnc_SetPrices(CLenEnc
*p
, UInt32 posState
, UInt32 numSymbols
, UInt32
*prices
, UInt32
*ProbPrices
)
792 UInt32 a0
= GET_PRICE_0a(p
->choice
);
793 UInt32 a1
= GET_PRICE_1a(p
->choice
);
794 UInt32 b0
= a1
+ GET_PRICE_0a(p
->choice2
);
795 UInt32 b1
= a1
+ GET_PRICE_1a(p
->choice2
);
797 for (i
= 0; i
< kLenNumLowSymbols
; i
++)
801 prices
[i
] = a0
+ RcTree_GetPrice(p
->low
+ (posState
<< kLenNumLowBits
), kLenNumLowBits
, i
, ProbPrices
);
803 for (; i
< kLenNumLowSymbols
+ kLenNumMidSymbols
; i
++)
807 prices
[i
] = b0
+ RcTree_GetPrice(p
->mid
+ (posState
<< kLenNumMidBits
), kLenNumMidBits
, i
- kLenNumLowSymbols
, ProbPrices
);
809 for (; i
< numSymbols
; i
++)
810 prices
[i
] = b1
+ RcTree_GetPrice(p
->high
, kLenNumHighBits
, i
- kLenNumLowSymbols
- kLenNumMidSymbols
, ProbPrices
);
813 static void MY_FAST_CALL
LenPriceEnc_UpdateTable(CLenPriceEnc
*p
, UInt32 posState
, UInt32
*ProbPrices
)
815 LenEnc_SetPrices(&p
->p
, posState
, p
->tableSize
, p
->prices
[posState
], ProbPrices
);
816 p
->counters
[posState
] = p
->tableSize
;
819 static void LenPriceEnc_UpdateTables(CLenPriceEnc
*p
, UInt32 numPosStates
, UInt32
*ProbPrices
)
822 for (posState
= 0; posState
< numPosStates
; posState
++)
823 LenPriceEnc_UpdateTable(p
, posState
, ProbPrices
);
826 static void LenEnc_Encode2(CLenPriceEnc
*p
, CRangeEnc
*rc
, UInt32 symbol
, UInt32 posState
, Bool updatePrice
, UInt32
*ProbPrices
)
828 LenEnc_Encode(&p
->p
, rc
, symbol
, posState
);
830 if (--p
->counters
[posState
] == 0)
831 LenPriceEnc_UpdateTable(p
, posState
, ProbPrices
);
837 static void MovePos(CLzmaEnc
*p
, UInt32 num
)
841 printf("\n MovePos %d", num
);
845 p
->additionalOffset
+= num
;
846 p
->matchFinder
.Skip(p
->matchFinderObj
, num
);
850 static UInt32
ReadMatchDistances(CLzmaEnc
*p
, UInt32
*numDistancePairsRes
)
852 UInt32 lenRes
= 0, numPairs
;
853 p
->numAvail
= p
->matchFinder
.GetNumAvailableBytes(p
->matchFinderObj
);
854 numPairs
= p
->matchFinder
.GetMatches(p
->matchFinderObj
, p
->matches
);
856 printf("\n i = %d numPairs = %d ", ttt
, numPairs
/ 2);
860 for (i
= 0; i
< numPairs
; i
+= 2)
861 printf("%2d %6d | ", p
->matches
[i
], p
->matches
[i
+ 1]);
866 lenRes
= p
->matches
[numPairs
- 2];
867 if (lenRes
== p
->numFastBytes
)
869 const Byte
*pby
= p
->matchFinder
.GetPointerToCurrentPos(p
->matchFinderObj
) - 1;
870 UInt32 distance
= p
->matches
[numPairs
- 1] + 1;
871 UInt32 numAvail
= p
->numAvail
;
872 if (numAvail
> LZMA_MATCH_LEN_MAX
)
873 numAvail
= LZMA_MATCH_LEN_MAX
;
875 const Byte
*pby2
= pby
- distance
;
876 for (; lenRes
< numAvail
&& pby
[lenRes
] == pby2
[lenRes
]; lenRes
++);
880 p
->additionalOffset
++;
881 *numDistancePairsRes
= numPairs
;
886 #define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
887 #define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
888 #define IsShortRep(p) ((p)->backPrev == 0)
890 static UInt32
GetRepLen1Price(CLzmaEnc
*p
, UInt32 state
, UInt32 posState
)
893 GET_PRICE_0(p
->isRepG0
[state
]) +
894 GET_PRICE_0(p
->isRep0Long
[state
][posState
]);
897 static UInt32
GetPureRepPrice(CLzmaEnc
*p
, UInt32 repIndex
, UInt32 state
, UInt32 posState
)
902 price
= GET_PRICE_0(p
->isRepG0
[state
]);
903 price
+= GET_PRICE_1(p
->isRep0Long
[state
][posState
]);
907 price
= GET_PRICE_1(p
->isRepG0
[state
]);
909 price
+= GET_PRICE_0(p
->isRepG1
[state
]);
912 price
+= GET_PRICE_1(p
->isRepG1
[state
]);
913 price
+= GET_PRICE(p
->isRepG2
[state
], repIndex
- 2);
919 static UInt32
GetRepPrice(CLzmaEnc
*p
, UInt32 repIndex
, UInt32 len
, UInt32 state
, UInt32 posState
)
921 return p
->repLenEnc
.prices
[posState
][len
- LZMA_MATCH_LEN_MIN
] +
922 GetPureRepPrice(p
, repIndex
, state
, posState
);
925 static UInt32
Backward(CLzmaEnc
*p
, UInt32
*backRes
, UInt32 cur
)
927 UInt32 posMem
= p
->opt
[cur
].posPrev
;
928 UInt32 backMem
= p
->opt
[cur
].backPrev
;
929 p
->optimumEndIndex
= cur
;
932 if (p
->opt
[cur
].prev1IsChar
)
934 MakeAsChar(&p
->opt
[posMem
])
935 p
->opt
[posMem
].posPrev
= posMem
- 1;
936 if (p
->opt
[cur
].prev2
)
938 p
->opt
[posMem
- 1].prev1IsChar
= False
;
939 p
->opt
[posMem
- 1].posPrev
= p
->opt
[cur
].posPrev2
;
940 p
->opt
[posMem
- 1].backPrev
= p
->opt
[cur
].backPrev2
;
944 UInt32 posPrev
= posMem
;
945 UInt32 backCur
= backMem
;
947 backMem
= p
->opt
[posPrev
].backPrev
;
948 posMem
= p
->opt
[posPrev
].posPrev
;
950 p
->opt
[posPrev
].backPrev
= backCur
;
951 p
->opt
[posPrev
].posPrev
= cur
;
956 *backRes
= p
->opt
[0].backPrev
;
957 p
->optimumCurrentIndex
= p
->opt
[0].posPrev
;
958 return p
->optimumCurrentIndex
;
961 #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
963 static UInt32
GetOptimum(CLzmaEnc
*p
, UInt32 position
, UInt32
*backRes
)
965 UInt32 numAvail
, mainLen
, numPairs
, repMaxIndex
, i
, posState
, lenEnd
, len
, cur
;
966 UInt32 matchPrice
, repMatchPrice
, normalMatchPrice
;
967 UInt32 reps
[LZMA_NUM_REPS
], repLens
[LZMA_NUM_REPS
];
970 Byte curByte
, matchByte
;
971 if (p
->optimumEndIndex
!= p
->optimumCurrentIndex
)
973 const COptimal
*opt
= &p
->opt
[p
->optimumCurrentIndex
];
974 UInt32 lenRes
= opt
->posPrev
- p
->optimumCurrentIndex
;
975 *backRes
= opt
->backPrev
;
976 p
->optimumCurrentIndex
= opt
->posPrev
;
979 p
->optimumCurrentIndex
= p
->optimumEndIndex
= 0;
981 if (p
->additionalOffset
== 0)
982 mainLen
= ReadMatchDistances(p
, &numPairs
);
985 mainLen
= p
->longestMatchLength
;
986 numPairs
= p
->numPairs
;
989 numAvail
= p
->numAvail
;
992 *backRes
= (UInt32
)(-1);
995 if (numAvail
> LZMA_MATCH_LEN_MAX
)
996 numAvail
= LZMA_MATCH_LEN_MAX
;
998 data
= p
->matchFinder
.GetPointerToCurrentPos(p
->matchFinderObj
) - 1;
1000 for (i
= 0; i
< LZMA_NUM_REPS
; i
++)
1004 reps
[i
] = p
->reps
[i
];
1005 data2
= data
- (reps
[i
] + 1);
1006 if (data
[0] != data2
[0] || data
[1] != data2
[1])
1011 for (lenTest
= 2; lenTest
< numAvail
&& data
[lenTest
] == data2
[lenTest
]; lenTest
++);
1012 repLens
[i
] = lenTest
;
1013 if (lenTest
> repLens
[repMaxIndex
])
1016 if (repLens
[repMaxIndex
] >= p
->numFastBytes
)
1019 *backRes
= repMaxIndex
;
1020 lenRes
= repLens
[repMaxIndex
];
1021 MovePos(p
, lenRes
- 1);
1025 matches
= p
->matches
;
1026 if (mainLen
>= p
->numFastBytes
)
1028 *backRes
= matches
[numPairs
- 1] + LZMA_NUM_REPS
;
1029 MovePos(p
, mainLen
- 1);
1033 matchByte
= *(data
- (reps
[0] + 1));
1035 if (mainLen
< 2 && curByte
!= matchByte
&& repLens
[repMaxIndex
] < 2)
1037 *backRes
= (UInt32
)-1;
1041 p
->opt
[0].state
= (CState
)p
->state
;
1043 posState
= (position
& p
->pbMask
);
1046 const CLzmaProb
*probs
= LIT_PROBS(position
, *(data
- 1));
1047 p
->opt
[1].price
= GET_PRICE_0(p
->isMatch
[p
->state
][posState
]) +
1048 (!IsCharState(p
->state
) ?
1049 LitEnc_GetPriceMatched(probs
, curByte
, matchByte
, p
->ProbPrices
) :
1050 LitEnc_GetPrice(probs
, curByte
, p
->ProbPrices
));
1053 MakeAsChar(&p
->opt
[1]);
1055 matchPrice
= GET_PRICE_1(p
->isMatch
[p
->state
][posState
]);
1056 repMatchPrice
= matchPrice
+ GET_PRICE_1(p
->isRep
[p
->state
]);
1058 if (matchByte
== curByte
)
1060 UInt32 shortRepPrice
= repMatchPrice
+ GetRepLen1Price(p
, p
->state
, posState
);
1061 if (shortRepPrice
< p
->opt
[1].price
)
1063 p
->opt
[1].price
= shortRepPrice
;
1064 MakeAsShortRep(&p
->opt
[1]);
1067 lenEnd
= ((mainLen
>= repLens
[repMaxIndex
]) ? mainLen
: repLens
[repMaxIndex
]);
1071 *backRes
= p
->opt
[1].backPrev
;
1075 p
->opt
[1].posPrev
= 0;
1076 for (i
= 0; i
< LZMA_NUM_REPS
; i
++)
1077 p
->opt
[0].backs
[i
] = reps
[i
];
1081 p
->opt
[len
--].price
= kInfinityPrice
;
1084 for (i
= 0; i
< LZMA_NUM_REPS
; i
++)
1086 UInt32 repLen
= repLens
[i
];
1090 price
= repMatchPrice
+ GetPureRepPrice(p
, i
, p
->state
, posState
);
1093 UInt32 curAndLenPrice
= price
+ p
->repLenEnc
.prices
[posState
][repLen
- 2];
1094 COptimal
*opt
= &p
->opt
[repLen
];
1095 if (curAndLenPrice
< opt
->price
)
1097 opt
->price
= curAndLenPrice
;
1100 opt
->prev1IsChar
= False
;
1103 while (--repLen
>= 2);
1106 normalMatchPrice
= matchPrice
+ GET_PRICE_0(p
->isRep
[p
->state
]);
1108 len
= ((repLens
[0] >= 2) ? repLens
[0] + 1 : 2);
1112 while (len
> matches
[offs
])
1117 UInt32 distance
= matches
[offs
+ 1];
1119 UInt32 curAndLenPrice
= normalMatchPrice
+ p
->lenEnc
.prices
[posState
][len
- LZMA_MATCH_LEN_MIN
];
1120 UInt32 lenToPosState
= GetLenToPosState(len
);
1121 if (distance
< kNumFullDistances
)
1122 curAndLenPrice
+= p
->distancesPrices
[lenToPosState
][distance
];
1126 GetPosSlot2(distance
, slot
);
1127 curAndLenPrice
+= p
->alignPrices
[distance
& kAlignMask
] + p
->posSlotPrices
[lenToPosState
][slot
];
1130 if (curAndLenPrice
< opt
->price
)
1132 opt
->price
= curAndLenPrice
;
1134 opt
->backPrev
= distance
+ LZMA_NUM_REPS
;
1135 opt
->prev1IsChar
= False
;
1137 if (len
== matches
[offs
])
1140 if (offs
== numPairs
)
1152 printf("\n pos = %4X", position
);
1153 for (ii
= cur
; ii
<= lenEnd
; ii
++)
1154 printf("\nprice[%4X] = %d", position
- cur
+ ii
, p
->opt
[ii
].price
);
1160 UInt32 numAvailFull
, newLen
, posPrev
, state
, startLen
;
1161 UInt32 curPrice
, curAnd1Price
;
1168 return Backward(p
, backRes
, cur
);
1170 newLen
= ReadMatchDistances(p
, &numPairs
);
1171 if (newLen
>= p
->numFastBytes
)
1173 p
->numPairs
= numPairs
;
1174 p
->longestMatchLength
= newLen
;
1175 return Backward(p
, backRes
, cur
);
1178 curOpt
= &p
->opt
[cur
];
1179 posPrev
= curOpt
->posPrev
;
1180 if (curOpt
->prev1IsChar
)
1185 state
= p
->opt
[curOpt
->posPrev2
].state
;
1186 if (curOpt
->backPrev2
< LZMA_NUM_REPS
)
1187 state
= kRepNextStates
[state
];
1189 state
= kMatchNextStates
[state
];
1192 state
= p
->opt
[posPrev
].state
;
1193 state
= kLiteralNextStates
[state
];
1196 state
= p
->opt
[posPrev
].state
;
1197 if (posPrev
== cur
- 1)
1199 if (IsShortRep(curOpt
))
1200 state
= kShortRepNextStates
[state
];
1202 state
= kLiteralNextStates
[state
];
1207 const COptimal
*prevOpt
;
1208 if (curOpt
->prev1IsChar
&& curOpt
->prev2
)
1210 posPrev
= curOpt
->posPrev2
;
1211 pos
= curOpt
->backPrev2
;
1212 state
= kRepNextStates
[state
];
1216 pos
= curOpt
->backPrev
;
1217 if (pos
< LZMA_NUM_REPS
)
1218 state
= kRepNextStates
[state
];
1220 state
= kMatchNextStates
[state
];
1222 prevOpt
= &p
->opt
[posPrev
];
1223 if (pos
< LZMA_NUM_REPS
)
1225 reps
[0] = prevOpt
->backs
[pos
];
1226 for (i
= 1; i
<= pos
; i
++)
1227 reps
[i
] = prevOpt
->backs
[i
- 1];
1228 for (; i
< LZMA_NUM_REPS
; i
++)
1229 reps
[i
] = prevOpt
->backs
[i
];
1233 reps
[0] = (pos
- LZMA_NUM_REPS
);
1234 for (i
= 1; i
< LZMA_NUM_REPS
; i
++)
1235 reps
[i
] = prevOpt
->backs
[i
- 1];
1238 curOpt
->state
= (CState
)state
;
1240 curOpt
->backs
[0] = reps
[0];
1241 curOpt
->backs
[1] = reps
[1];
1242 curOpt
->backs
[2] = reps
[2];
1243 curOpt
->backs
[3] = reps
[3];
1245 curPrice
= curOpt
->price
;
1247 data
= p
->matchFinder
.GetPointerToCurrentPos(p
->matchFinderObj
) - 1;
1249 matchByte
= *(data
- (reps
[0] + 1));
1251 posState
= (position
& p
->pbMask
);
1253 curAnd1Price
= curPrice
+ GET_PRICE_0(p
->isMatch
[state
][posState
]);
1255 const CLzmaProb
*probs
= LIT_PROBS(position
, *(data
- 1));
1257 (!IsCharState(state
) ?
1258 LitEnc_GetPriceMatched(probs
, curByte
, matchByte
, p
->ProbPrices
) :
1259 LitEnc_GetPrice(probs
, curByte
, p
->ProbPrices
));
1262 nextOpt
= &p
->opt
[cur
+ 1];
1264 if (curAnd1Price
< nextOpt
->price
)
1266 nextOpt
->price
= curAnd1Price
;
1267 nextOpt
->posPrev
= cur
;
1268 MakeAsChar(nextOpt
);
1272 matchPrice
= curPrice
+ GET_PRICE_1(p
->isMatch
[state
][posState
]);
1273 repMatchPrice
= matchPrice
+ GET_PRICE_1(p
->isRep
[state
]);
1275 if (matchByte
== curByte
&& !(nextOpt
->posPrev
< cur
&& nextOpt
->backPrev
== 0))
1277 UInt32 shortRepPrice
= repMatchPrice
+ GetRepLen1Price(p
, state
, posState
);
1278 if (shortRepPrice
<= nextOpt
->price
)
1280 nextOpt
->price
= shortRepPrice
;
1281 nextOpt
->posPrev
= cur
;
1282 MakeAsShortRep(nextOpt
);
1286 numAvailFull
= p
->numAvail
;
1288 UInt32 temp
= kNumOpts
- 1 - cur
;
1289 if (temp
< numAvailFull
)
1290 numAvailFull
= temp
;
1293 if (numAvailFull
< 2)
1295 numAvail
= (numAvailFull
<= p
->numFastBytes
? numAvailFull
: p
->numFastBytes
);
1297 if (!nextIsChar
&& matchByte
!= curByte
) /* speed optimization */
1299 /* try Literal + rep0 */
1302 const Byte
*data2
= data
- (reps
[0] + 1);
1303 UInt32 limit
= p
->numFastBytes
+ 1;
1304 if (limit
> numAvailFull
)
1305 limit
= numAvailFull
;
1307 for (temp
= 1; temp
< limit
&& data
[temp
] == data2
[temp
]; temp
++);
1308 lenTest2
= temp
- 1;
1311 UInt32 state2
= kLiteralNextStates
[state
];
1312 UInt32 posStateNext
= (position
+ 1) & p
->pbMask
;
1313 UInt32 nextRepMatchPrice
= curAnd1Price
+
1314 GET_PRICE_1(p
->isMatch
[state2
][posStateNext
]) +
1315 GET_PRICE_1(p
->isRep
[state2
]);
1316 /* for (; lenTest2 >= 2; lenTest2--) */
1319 UInt32 offset
= cur
+ 1 + lenTest2
;
1320 while (lenEnd
< offset
)
1321 p
->opt
[++lenEnd
].price
= kInfinityPrice
;
1322 UInt32 curAndLenPrice
= nextRepMatchPrice
+ GetRepPrice(p
, 0, lenTest2
, state2
, posStateNext
);
1323 opt
= &p
->opt
[offset
];
1324 if (curAndLenPrice
< opt
->price
)
1326 opt
->price
= curAndLenPrice
;
1327 opt
->posPrev
= cur
+ 1;
1329 opt
->prev1IsChar
= True
;
1336 startLen
= 2; /* speed optimization */
1339 for (repIndex
= 0; repIndex
< LZMA_NUM_REPS
; repIndex
++)
1344 const Byte
*data2
= data
- (reps
[repIndex
] + 1);
1345 if (data
[0] != data2
[0] || data
[1] != data2
[1])
1347 for (lenTest
= 2; lenTest
< numAvail
&& data
[lenTest
] == data2
[lenTest
]; lenTest
++);
1348 while (lenEnd
< cur
+ lenTest
)
1349 p
->opt
[++lenEnd
].price
= kInfinityPrice
;
1350 lenTestTemp
= lenTest
;
1351 price
= repMatchPrice
+ GetPureRepPrice(p
, repIndex
, state
, posState
);
1354 UInt32 curAndLenPrice
= price
+ p
->repLenEnc
.prices
[posState
][lenTest
- 2];
1355 COptimal
*opt
= &p
->opt
[cur
+ lenTest
];
1356 if (curAndLenPrice
< opt
->price
)
1358 opt
->price
= curAndLenPrice
;
1360 opt
->backPrev
= repIndex
;
1361 opt
->prev1IsChar
= False
;
1364 while (--lenTest
>= 2);
1365 lenTest
= lenTestTemp
;
1368 startLen
= lenTest
+ 1;
1372 UInt32 lenTest2
= lenTest
+ 1;
1373 UInt32 limit
= lenTest2
+ p
->numFastBytes
;
1374 UInt32 nextRepMatchPrice
;
1375 if (limit
> numAvailFull
)
1376 limit
= numAvailFull
;
1377 for (; lenTest2
< limit
&& data
[lenTest2
] == data2
[lenTest2
]; lenTest2
++);
1378 lenTest2
-= lenTest
+ 1;
1381 UInt32 state2
= kRepNextStates
[state
];
1382 UInt32 posStateNext
= (position
+ lenTest
) & p
->pbMask
;
1383 UInt32 curAndLenCharPrice
=
1384 price
+ p
->repLenEnc
.prices
[posState
][lenTest
- 2] +
1385 GET_PRICE_0(p
->isMatch
[state2
][posStateNext
]) +
1386 LitEnc_GetPriceMatched(LIT_PROBS(position
+ lenTest
, data
[lenTest
- 1]),
1387 data
[lenTest
], data2
[lenTest
], p
->ProbPrices
);
1388 state2
= kLiteralNextStates
[state2
];
1389 posStateNext
= (position
+ lenTest
+ 1) & p
->pbMask
;
1390 nextRepMatchPrice
= curAndLenCharPrice
+
1391 GET_PRICE_1(p
->isMatch
[state2
][posStateNext
]) +
1392 GET_PRICE_1(p
->isRep
[state2
]);
1394 /* for (; lenTest2 >= 2; lenTest2--) */
1396 UInt32 curAndLenPrice
;
1398 UInt32 offset
= cur
+ lenTest
+ 1 + lenTest2
;
1399 while (lenEnd
< offset
)
1400 p
->opt
[++lenEnd
].price
= kInfinityPrice
;
1401 curAndLenPrice
= nextRepMatchPrice
+ GetRepPrice(p
, 0, lenTest2
, state2
, posStateNext
);
1402 opt
= &p
->opt
[offset
];
1403 if (curAndLenPrice
< opt
->price
)
1405 opt
->price
= curAndLenPrice
;
1406 opt
->posPrev
= cur
+ lenTest
+ 1;
1408 opt
->prev1IsChar
= True
;
1410 opt
->posPrev2
= cur
;
1411 opt
->backPrev2
= repIndex
;
1418 /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
1419 if (newLen
> numAvail
)
1422 for (numPairs
= 0; newLen
> matches
[numPairs
]; numPairs
+= 2);
1423 matches
[numPairs
] = newLen
;
1426 if (newLen
>= startLen
)
1428 normalMatchPrice
= matchPrice
+ GET_PRICE_0(p
->isRep
[state
]);
1429 UInt32 offs
, curBack
, posSlot
;
1431 while (lenEnd
< cur
+ newLen
)
1432 p
->opt
[++lenEnd
].price
= kInfinityPrice
;
1435 while (startLen
> matches
[offs
])
1437 curBack
= matches
[offs
+ 1];
1438 GetPosSlot2(curBack
, posSlot
);
1439 for (lenTest
= /*2*/ startLen
; ; lenTest
++)
1441 UInt32 curAndLenPrice
;
1442 curAndLenPrice
= normalMatchPrice
+ p
->lenEnc
.prices
[posState
][lenTest
- LZMA_MATCH_LEN_MIN
];
1443 UInt32 lenToPosState
= GetLenToPosState(lenTest
);
1445 if (curBack
< kNumFullDistances
)
1446 curAndLenPrice
+= p
->distancesPrices
[lenToPosState
][curBack
];
1448 curAndLenPrice
+= p
->posSlotPrices
[lenToPosState
][posSlot
] + p
->alignPrices
[curBack
& kAlignMask
];
1450 opt
= &p
->opt
[cur
+ lenTest
];
1451 if (curAndLenPrice
< opt
->price
)
1453 opt
->price
= curAndLenPrice
;
1455 opt
->backPrev
= curBack
+ LZMA_NUM_REPS
;
1456 opt
->prev1IsChar
= False
;
1459 if (/*_maxMode && */lenTest
== matches
[offs
])
1461 /* Try Match + Literal + Rep0 */
1462 const Byte
*data2
= data
- (curBack
+ 1);
1463 UInt32 lenTest2
= lenTest
+ 1;
1464 UInt32 limit
= lenTest2
+ p
->numFastBytes
;
1465 UInt32 nextRepMatchPrice
;
1466 if (limit
> numAvailFull
)
1467 limit
= numAvailFull
;
1468 for (; lenTest2
< limit
&& data
[lenTest2
] == data2
[lenTest2
]; lenTest2
++);
1469 lenTest2
-= lenTest
+ 1;
1472 UInt32 state2
= kMatchNextStates
[state
];
1473 UInt32 posStateNext
= (position
+ lenTest
) & p
->pbMask
;
1474 UInt32 curAndLenCharPrice
= curAndLenPrice
+
1475 GET_PRICE_0(p
->isMatch
[state2
][posStateNext
]) +
1476 LitEnc_GetPriceMatched(LIT_PROBS(position
+ lenTest
, data
[lenTest
- 1]),
1477 data
[lenTest
], data2
[lenTest
], p
->ProbPrices
);
1478 state2
= kLiteralNextStates
[state2
];
1479 posStateNext
= (posStateNext
+ 1) & p
->pbMask
;
1480 nextRepMatchPrice
= curAndLenCharPrice
+
1481 GET_PRICE_1(p
->isMatch
[state2
][posStateNext
]) +
1482 GET_PRICE_1(p
->isRep
[state2
]);
1484 /* for (; lenTest2 >= 2; lenTest2--) */
1486 UInt32 offset
= cur
+ lenTest
+ 1 + lenTest2
;
1488 while (lenEnd
< offset
)
1489 p
->opt
[++lenEnd
].price
= kInfinityPrice
;
1490 curAndLenPrice
= nextRepMatchPrice
+ GetRepPrice(p
, 0, lenTest2
, state2
, posStateNext
);
1491 opt
= &p
->opt
[offset
];
1492 if (curAndLenPrice
< opt
->price
)
1494 opt
->price
= curAndLenPrice
;
1495 opt
->posPrev
= cur
+ lenTest
+ 1;
1497 opt
->prev1IsChar
= True
;
1499 opt
->posPrev2
= cur
;
1500 opt
->backPrev2
= curBack
+ LZMA_NUM_REPS
;
1505 if (offs
== numPairs
)
1507 curBack
= matches
[offs
+ 1];
1508 if (curBack
>= kNumFullDistances
)
1509 GetPosSlot2(curBack
, posSlot
);
1516 #define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
1518 static UInt32
GetOptimumFast(CLzmaEnc
*p
, UInt32
*backRes
)
1520 UInt32 numAvail
, mainLen
, mainDist
, numPairs
, repIndex
, repLen
, i
;
1522 const UInt32
*matches
;
1524 if (p
->additionalOffset
== 0)
1525 mainLen
= ReadMatchDistances(p
, &numPairs
);
1528 mainLen
= p
->longestMatchLength
;
1529 numPairs
= p
->numPairs
;
1532 numAvail
= p
->numAvail
;
1533 *backRes
= (UInt32
)-1;
1536 if (numAvail
> LZMA_MATCH_LEN_MAX
)
1537 numAvail
= LZMA_MATCH_LEN_MAX
;
1538 data
= p
->matchFinder
.GetPointerToCurrentPos(p
->matchFinderObj
) - 1;
1540 repLen
= repIndex
= 0;
1541 for (i
= 0; i
< LZMA_NUM_REPS
; i
++)
1544 const Byte
*data2
= data
- (p
->reps
[i
] + 1);
1545 if (data
[0] != data2
[0] || data
[1] != data2
[1])
1547 for (len
= 2; len
< numAvail
&& data
[len
] == data2
[len
]; len
++);
1548 if (len
>= p
->numFastBytes
)
1551 MovePos(p
, len
- 1);
1561 matches
= p
->matches
;
1562 if (mainLen
>= p
->numFastBytes
)
1564 *backRes
= matches
[numPairs
- 1] + LZMA_NUM_REPS
;
1565 MovePos(p
, mainLen
- 1);
1569 mainDist
= 0; /* for GCC */
1572 mainDist
= matches
[numPairs
- 1];
1573 while (numPairs
> 2 && mainLen
== matches
[numPairs
- 4] + 1)
1575 if (!ChangePair(matches
[numPairs
- 3], mainDist
))
1578 mainLen
= matches
[numPairs
- 2];
1579 mainDist
= matches
[numPairs
- 1];
1581 if (mainLen
== 2 && mainDist
>= 0x80)
1585 if (repLen
>= 2 && (
1586 (repLen
+ 1 >= mainLen
) ||
1587 (repLen
+ 2 >= mainLen
&& mainDist
>= (1 << 9)) ||
1588 (repLen
+ 3 >= mainLen
&& mainDist
>= (1 << 15))))
1590 *backRes
= repIndex
;
1591 MovePos(p
, repLen
- 1);
1595 if (mainLen
< 2 || numAvail
<= 2)
1598 p
->longestMatchLength
= ReadMatchDistances(p
, &p
->numPairs
);
1599 if (p
->longestMatchLength
>= 2)
1601 UInt32 newDistance
= matches
[p
->numPairs
- 1];
1602 if ((p
->longestMatchLength
>= mainLen
&& newDistance
< mainDist
) ||
1603 (p
->longestMatchLength
== mainLen
+ 1 && !ChangePair(mainDist
, newDistance
)) ||
1604 (p
->longestMatchLength
> mainLen
+ 1) ||
1605 (p
->longestMatchLength
+ 1 >= mainLen
&& mainLen
>= 3 && ChangePair(newDistance
, mainDist
)))
1609 data
= p
->matchFinder
.GetPointerToCurrentPos(p
->matchFinderObj
) - 1;
1610 for (i
= 0; i
< LZMA_NUM_REPS
; i
++)
1613 const Byte
*data2
= data
- (p
->reps
[i
] + 1);
1614 if (data
[0] != data2
[0] || data
[1] != data2
[1])
1616 limit
= mainLen
- 1;
1617 for (len
= 2; len
< limit
&& data
[len
] == data2
[len
]; len
++);
1621 *backRes
= mainDist
+ LZMA_NUM_REPS
;
1622 MovePos(p
, mainLen
- 2);
1626 static void WriteEndMarker(CLzmaEnc
*p
, UInt32 posState
)
1629 RangeEnc_EncodeBit(&p
->rc
, &p
->isMatch
[p
->state
][posState
], 1);
1630 RangeEnc_EncodeBit(&p
->rc
, &p
->isRep
[p
->state
], 0);
1631 p
->state
= kMatchNextStates
[p
->state
];
1632 len
= LZMA_MATCH_LEN_MIN
;
1633 LenEnc_Encode2(&p
->lenEnc
, &p
->rc
, len
- LZMA_MATCH_LEN_MIN
, posState
, !p
->fastMode
, p
->ProbPrices
);
1634 RcTree_Encode(&p
->rc
, p
->posSlotEncoder
[GetLenToPosState(len
)], kNumPosSlotBits
, (1 << kNumPosSlotBits
) - 1);
1635 RangeEnc_EncodeDirectBits(&p
->rc
, (((UInt32
)1 << 30) - 1) >> kNumAlignBits
, 30 - kNumAlignBits
);
1636 RcTree_ReverseEncode(&p
->rc
, p
->posAlignEncoder
, kNumAlignBits
, kAlignMask
);
1639 static SRes
CheckErrors(CLzmaEnc
*p
)
1641 if (p
->result
!= SZ_OK
)
1643 if (p
->rc
.res
!= SZ_OK
)
1644 p
->result
= SZ_ERROR_WRITE
;
1645 if (p
->matchFinderBase
.result
!= SZ_OK
)
1646 p
->result
= SZ_ERROR_READ
;
1647 if (p
->result
!= SZ_OK
)
1652 static SRes
Flush(CLzmaEnc
*p
, UInt32 nowPos
)
1654 /* ReleaseMFStream(); */
1656 if (p
->writeEndMark
)
1657 WriteEndMarker(p
, nowPos
& p
->pbMask
);
1658 RangeEnc_FlushData(&p
->rc
);
1659 RangeEnc_FlushStream(&p
->rc
);
1660 return CheckErrors(p
);
1663 static void FillAlignPrices(CLzmaEnc
*p
)
1666 for (i
= 0; i
< kAlignTableSize
; i
++)
1667 p
->alignPrices
[i
] = RcTree_ReverseGetPrice(p
->posAlignEncoder
, kNumAlignBits
, i
, p
->ProbPrices
);
1668 p
->alignPriceCount
= 0;
1671 static void FillDistancesPrices(CLzmaEnc
*p
)
1673 UInt32 tempPrices
[kNumFullDistances
];
1674 UInt32 i
, lenToPosState
;
1675 for (i
= kStartPosModelIndex
; i
< kNumFullDistances
; i
++)
1677 UInt32 posSlot
= GetPosSlot1(i
);
1678 UInt32 footerBits
= ((posSlot
>> 1) - 1);
1679 UInt32 base
= ((2 | (posSlot
& 1)) << footerBits
);
1680 tempPrices
[i
] = RcTree_ReverseGetPrice(p
->posEncoders
+ base
- posSlot
- 1, footerBits
, i
- base
, p
->ProbPrices
);
1683 for (lenToPosState
= 0; lenToPosState
< kNumLenToPosStates
; lenToPosState
++)
1686 const CLzmaProb
*encoder
= p
->posSlotEncoder
[lenToPosState
];
1687 UInt32
*posSlotPrices
= p
->posSlotPrices
[lenToPosState
];
1688 for (posSlot
= 0; posSlot
< p
->distTableSize
; posSlot
++)
1689 posSlotPrices
[posSlot
] = RcTree_GetPrice(encoder
, kNumPosSlotBits
, posSlot
, p
->ProbPrices
);
1690 for (posSlot
= kEndPosModelIndex
; posSlot
< p
->distTableSize
; posSlot
++)
1691 posSlotPrices
[posSlot
] += ((((posSlot
>> 1) - 1) - kNumAlignBits
) << kNumBitPriceShiftBits
);
1694 UInt32
*distancesPrices
= p
->distancesPrices
[lenToPosState
];
1696 for (i
= 0; i
< kStartPosModelIndex
; i
++)
1697 distancesPrices
[i
] = posSlotPrices
[i
];
1698 for (; i
< kNumFullDistances
; i
++)
1699 distancesPrices
[i
] = posSlotPrices
[GetPosSlot1(i
)] + tempPrices
[i
];
1702 p
->matchPriceCount
= 0;
1705 void LzmaEnc_Construct(CLzmaEnc
*p
)
1707 RangeEnc_Construct(&p
->rc
);
1708 MatchFinder_Construct(&p
->matchFinderBase
);
1709 #ifdef COMPRESS_MF_MT
1710 MatchFinderMt_Construct(&p
->matchFinderMt
);
1711 p
->matchFinderMt
.MatchFinder
= &p
->matchFinderBase
;
1715 CLzmaEncProps props
;
1716 LzmaEncProps_Init(&props
);
1717 LzmaEnc_SetProps(p
, &props
);
1720 #ifndef LZMA_LOG_BSR
1721 LzmaEnc_FastPosInit(p
->g_FastPos
);
1724 LzmaEnc_InitPriceTables(p
->ProbPrices
);
1726 p
->saveState
.litProbs
= 0;
1729 CLzmaEncHandle
LzmaEnc_Create(ISzAlloc
*alloc
)
1732 p
= alloc
->Alloc(alloc
, sizeof(CLzmaEnc
));
1734 LzmaEnc_Construct((CLzmaEnc
*)p
);
1738 void LzmaEnc_FreeLits(CLzmaEnc
*p
, ISzAlloc
*alloc
)
1740 alloc
->Free(alloc
, p
->litProbs
);
1741 alloc
->Free(alloc
, p
->saveState
.litProbs
);
1743 p
->saveState
.litProbs
= 0;
1746 void LzmaEnc_Destruct(CLzmaEnc
*p
, ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
1748 #ifdef COMPRESS_MF_MT
1749 MatchFinderMt_Destruct(&p
->matchFinderMt
, allocBig
);
1751 MatchFinder_Free(&p
->matchFinderBase
, allocBig
);
1752 LzmaEnc_FreeLits(p
, alloc
);
1753 RangeEnc_Free(&p
->rc
, alloc
);
1756 void LzmaEnc_Destroy(CLzmaEncHandle p
, ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
1758 LzmaEnc_Destruct((CLzmaEnc
*)p
, alloc
, allocBig
);
1759 alloc
->Free(alloc
, p
);
1762 static SRes
LzmaEnc_CodeOneBlock(CLzmaEnc
*p
, Bool useLimits
, UInt32 maxPackSize
, UInt32 maxUnpackSize
)
1764 UInt32 nowPos32
, startPos32
;
1765 if (p
->inStream
!= 0)
1767 p
->matchFinderBase
.stream
= p
->inStream
;
1768 p
->matchFinder
.Init(p
->matchFinderObj
);
1774 RINOK(CheckErrors(p
));
1776 nowPos32
= (UInt32
)p
->nowPos64
;
1777 startPos32
= nowPos32
;
1779 if (p
->nowPos64
== 0)
1783 if (p
->matchFinder
.GetNumAvailableBytes(p
->matchFinderObj
) == 0)
1784 return Flush(p
, nowPos32
);
1785 ReadMatchDistances(p
, &numPairs
);
1786 RangeEnc_EncodeBit(&p
->rc
, &p
->isMatch
[p
->state
][0], 0);
1787 p
->state
= kLiteralNextStates
[p
->state
];
1788 curByte
= p
->matchFinder
.GetIndexByte(p
->matchFinderObj
, 0 - p
->additionalOffset
);
1789 LitEnc_Encode(&p
->rc
, p
->litProbs
, curByte
);
1790 p
->additionalOffset
--;
1794 if (p
->matchFinder
.GetNumAvailableBytes(p
->matchFinderObj
) != 0)
1797 UInt32 pos
, len
, posState
;
1800 len
= GetOptimumFast(p
, &pos
);
1802 len
= GetOptimum(p
, nowPos32
, &pos
);
1805 printf("\n pos = %4X, len = %d pos = %d", nowPos32
, len
, pos
);
1808 posState
= nowPos32
& p
->pbMask
;
1809 if (len
== 1 && pos
== (UInt32
)-1)
1815 RangeEnc_EncodeBit(&p
->rc
, &p
->isMatch
[p
->state
][posState
], 0);
1816 data
= p
->matchFinder
.GetPointerToCurrentPos(p
->matchFinderObj
) - p
->additionalOffset
;
1818 probs
= LIT_PROBS(nowPos32
, *(data
- 1));
1819 if (IsCharState(p
->state
))
1820 LitEnc_Encode(&p
->rc
, probs
, curByte
);
1822 LitEnc_EncodeMatched(&p
->rc
, probs
, curByte
, *(data
- p
->reps
[0] - 1));
1823 p
->state
= kLiteralNextStates
[p
->state
];
1827 RangeEnc_EncodeBit(&p
->rc
, &p
->isMatch
[p
->state
][posState
], 1);
1828 if (pos
< LZMA_NUM_REPS
)
1830 RangeEnc_EncodeBit(&p
->rc
, &p
->isRep
[p
->state
], 1);
1833 RangeEnc_EncodeBit(&p
->rc
, &p
->isRepG0
[p
->state
], 0);
1834 RangeEnc_EncodeBit(&p
->rc
, &p
->isRep0Long
[p
->state
][posState
], ((len
== 1) ? 0 : 1));
1838 UInt32 distance
= p
->reps
[pos
];
1839 RangeEnc_EncodeBit(&p
->rc
, &p
->isRepG0
[p
->state
], 1);
1841 RangeEnc_EncodeBit(&p
->rc
, &p
->isRepG1
[p
->state
], 0);
1844 RangeEnc_EncodeBit(&p
->rc
, &p
->isRepG1
[p
->state
], 1);
1845 RangeEnc_EncodeBit(&p
->rc
, &p
->isRepG2
[p
->state
], pos
- 2);
1847 p
->reps
[3] = p
->reps
[2];
1848 p
->reps
[2] = p
->reps
[1];
1850 p
->reps
[1] = p
->reps
[0];
1851 p
->reps
[0] = distance
;
1854 p
->state
= kShortRepNextStates
[p
->state
];
1857 LenEnc_Encode2(&p
->repLenEnc
, &p
->rc
, len
- LZMA_MATCH_LEN_MIN
, posState
, !p
->fastMode
, p
->ProbPrices
);
1858 p
->state
= kRepNextStates
[p
->state
];
1864 RangeEnc_EncodeBit(&p
->rc
, &p
->isRep
[p
->state
], 0);
1865 p
->state
= kMatchNextStates
[p
->state
];
1866 LenEnc_Encode2(&p
->lenEnc
, &p
->rc
, len
- LZMA_MATCH_LEN_MIN
, posState
, !p
->fastMode
, p
->ProbPrices
);
1867 pos
-= LZMA_NUM_REPS
;
1868 GetPosSlot(pos
, posSlot
);
1869 RcTree_Encode(&p
->rc
, p
->posSlotEncoder
[GetLenToPosState(len
)], kNumPosSlotBits
, posSlot
);
1871 if (posSlot
>= kStartPosModelIndex
)
1873 UInt32 footerBits
= ((posSlot
>> 1) - 1);
1874 UInt32 base
= ((2 | (posSlot
& 1)) << footerBits
);
1875 UInt32 posReduced
= pos
- base
;
1877 if (posSlot
< kEndPosModelIndex
)
1878 RcTree_ReverseEncode(&p
->rc
, p
->posEncoders
+ base
- posSlot
- 1, footerBits
, posReduced
);
1881 RangeEnc_EncodeDirectBits(&p
->rc
, posReduced
>> kNumAlignBits
, footerBits
- kNumAlignBits
);
1882 RcTree_ReverseEncode(&p
->rc
, p
->posAlignEncoder
, kNumAlignBits
, posReduced
& kAlignMask
);
1883 p
->alignPriceCount
++;
1886 p
->reps
[3] = p
->reps
[2];
1887 p
->reps
[2] = p
->reps
[1];
1888 p
->reps
[1] = p
->reps
[0];
1890 p
->matchPriceCount
++;
1893 p
->additionalOffset
-= len
;
1895 if (p
->additionalOffset
== 0)
1900 if (p
->matchPriceCount
>= (1 << 7))
1901 FillDistancesPrices(p
);
1902 if (p
->alignPriceCount
>= kAlignTableSize
)
1905 if (p
->matchFinder
.GetNumAvailableBytes(p
->matchFinderObj
) == 0)
1907 processed
= nowPos32
- startPos32
;
1910 if (processed
+ kNumOpts
+ 300 >= maxUnpackSize
||
1911 RangeEnc_GetProcessed(&p
->rc
) + kNumOpts
* 2 >= maxPackSize
)
1914 else if (processed
>= (1 << 15))
1916 p
->nowPos64
+= nowPos32
- startPos32
;
1917 return CheckErrors(p
);
1921 p
->nowPos64
+= nowPos32
- startPos32
;
1922 return Flush(p
, nowPos32
);
1925 #define kBigHashDicLimit ((UInt32)1 << 24)
1927 static SRes
LzmaEnc_Alloc(CLzmaEnc
*p
, UInt32 keepWindowSize
, ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
1929 UInt32 beforeSize
= kNumOpts
;
1930 #ifdef COMPRESS_MF_MT
1933 if (!RangeEnc_Alloc(&p
->rc
, alloc
))
1934 return SZ_ERROR_MEM
;
1935 #ifdef COMPRESS_MF_MT
1936 btMode
= (p
->matchFinderBase
.btMode
!= 0);
1937 p
->mtMode
= (p
->multiThread
&& !p
->fastMode
&& btMode
);
1941 unsigned lclp
= p
->lc
+ p
->lp
;
1942 if (p
->litProbs
== 0 || p
->saveState
.litProbs
== 0 || p
->lclp
!= lclp
)
1944 LzmaEnc_FreeLits(p
, alloc
);
1945 p
->litProbs
= (CLzmaProb
*)alloc
->Alloc(alloc
, (0x300 << lclp
) * sizeof(CLzmaProb
));
1946 p
->saveState
.litProbs
= (CLzmaProb
*)alloc
->Alloc(alloc
, (0x300 << lclp
) * sizeof(CLzmaProb
));
1947 if (p
->litProbs
== 0 || p
->saveState
.litProbs
== 0)
1949 LzmaEnc_FreeLits(p
, alloc
);
1950 return SZ_ERROR_MEM
;
1956 p
->matchFinderBase
.bigHash
= (p
->dictSize
> kBigHashDicLimit
);
1958 if (beforeSize
+ p
->dictSize
< keepWindowSize
)
1959 beforeSize
= keepWindowSize
- p
->dictSize
;
1961 #ifdef COMPRESS_MF_MT
1964 RINOK(MatchFinderMt_Create(&p
->matchFinderMt
, p
->dictSize
, beforeSize
, p
->numFastBytes
, LZMA_MATCH_LEN_MAX
, allocBig
));
1965 p
->matchFinderObj
= &p
->matchFinderMt
;
1966 MatchFinderMt_CreateVTable(&p
->matchFinderMt
, &p
->matchFinder
);
1971 if (!MatchFinder_Create(&p
->matchFinderBase
, p
->dictSize
, beforeSize
, p
->numFastBytes
, LZMA_MATCH_LEN_MAX
, allocBig
))
1972 return SZ_ERROR_MEM
;
1973 p
->matchFinderObj
= &p
->matchFinderBase
;
1974 MatchFinder_CreateVTable(&p
->matchFinderBase
, &p
->matchFinder
);
1979 void LzmaEnc_Init(CLzmaEnc
*p
)
1983 for (i
= 0 ; i
< LZMA_NUM_REPS
; i
++)
1986 RangeEnc_Init(&p
->rc
);
1989 for (i
= 0; i
< kNumStates
; i
++)
1992 for (j
= 0; j
< LZMA_NUM_PB_STATES_MAX
; j
++)
1994 p
->isMatch
[i
][j
] = kProbInitValue
;
1995 p
->isRep0Long
[i
][j
] = kProbInitValue
;
1997 p
->isRep
[i
] = kProbInitValue
;
1998 p
->isRepG0
[i
] = kProbInitValue
;
1999 p
->isRepG1
[i
] = kProbInitValue
;
2000 p
->isRepG2
[i
] = kProbInitValue
;
2004 UInt32 num
= 0x300 << (p
->lp
+ p
->lc
);
2005 for (i
= 0; i
< num
; i
++)
2006 p
->litProbs
[i
] = kProbInitValue
;
2010 for (i
= 0; i
< kNumLenToPosStates
; i
++)
2012 CLzmaProb
*probs
= p
->posSlotEncoder
[i
];
2014 for (j
= 0; j
< (1 << kNumPosSlotBits
); j
++)
2015 probs
[j
] = kProbInitValue
;
2019 for (i
= 0; i
< kNumFullDistances
- kEndPosModelIndex
; i
++)
2020 p
->posEncoders
[i
] = kProbInitValue
;
2023 LenEnc_Init(&p
->lenEnc
.p
);
2024 LenEnc_Init(&p
->repLenEnc
.p
);
2026 for (i
= 0; i
< (1 << kNumAlignBits
); i
++)
2027 p
->posAlignEncoder
[i
] = kProbInitValue
;
2029 p
->optimumEndIndex
= 0;
2030 p
->optimumCurrentIndex
= 0;
2031 p
->additionalOffset
= 0;
2033 p
->pbMask
= (1 << p
->pb
) - 1;
2034 p
->lpMask
= (1 << p
->lp
) - 1;
2037 void LzmaEnc_InitPrices(CLzmaEnc
*p
)
2041 FillDistancesPrices(p
);
2045 p
->lenEnc
.tableSize
=
2046 p
->repLenEnc
.tableSize
=
2047 p
->numFastBytes
+ 1 - LZMA_MATCH_LEN_MIN
;
2048 LenPriceEnc_UpdateTables(&p
->lenEnc
, 1 << p
->pb
, p
->ProbPrices
);
2049 LenPriceEnc_UpdateTables(&p
->repLenEnc
, 1 << p
->pb
, p
->ProbPrices
);
2052 static SRes
LzmaEnc_AllocAndInit(CLzmaEnc
*p
, UInt32 keepWindowSize
, ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
2055 for (i
= 0; i
< (UInt32
)kDicLogSizeMaxCompress
; i
++)
2056 if (p
->dictSize
<= ((UInt32
)1 << i
))
2058 p
->distTableSize
= i
* 2;
2060 p
->finished
= False
;
2062 RINOK(LzmaEnc_Alloc(p
, keepWindowSize
, alloc
, allocBig
));
2064 LzmaEnc_InitPrices(p
);
2069 static SRes
LzmaEnc_Prepare(CLzmaEncHandle pp
, ISeqInStream
*inStream
, ISeqOutStream
*outStream
,
2070 ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
2072 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2073 p
->inStream
= inStream
;
2074 p
->rc
.outStream
= outStream
;
2075 return LzmaEnc_AllocAndInit(p
, 0, alloc
, allocBig
);
2078 SRes
LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp
,
2079 ISeqInStream
*inStream
, UInt32 keepWindowSize
,
2080 ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
2082 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2083 p
->inStream
= inStream
;
2084 return LzmaEnc_AllocAndInit(p
, keepWindowSize
, alloc
, allocBig
);
2087 static void LzmaEnc_SetInputBuf(CLzmaEnc
*p
, const Byte
*src
, SizeT srcLen
)
2089 p
->seqBufInStream
.funcTable
.Read
= MyRead
;
2090 p
->seqBufInStream
.data
= src
;
2091 p
->seqBufInStream
.rem
= srcLen
;
2094 SRes
LzmaEnc_MemPrepare(CLzmaEncHandle pp
, const Byte
*src
, SizeT srcLen
,
2095 UInt32 keepWindowSize
, ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
2097 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2098 LzmaEnc_SetInputBuf(p
, src
, srcLen
);
2099 p
->inStream
= &p
->seqBufInStream
.funcTable
;
2100 return LzmaEnc_AllocAndInit(p
, keepWindowSize
, alloc
, allocBig
);
2103 void LzmaEnc_Finish(CLzmaEncHandle pp
)
2105 #ifdef COMPRESS_MF_MT
2106 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2108 MatchFinderMt_ReleaseStream(&p
->matchFinderMt
);
2114 typedef struct _CSeqOutStreamBuf
2116 ISeqOutStream funcTable
;
2122 static size_t MyWrite(void *pp
, const void *data
, size_t size
)
2124 CSeqOutStreamBuf
*p
= (CSeqOutStreamBuf
*)pp
;
2130 memcpy(p
->data
, data
, size
);
2137 UInt32
LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp
)
2139 const CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2140 return p
->matchFinder
.GetNumAvailableBytes(p
->matchFinderObj
);
2143 const Byte
*LzmaEnc_GetCurBuf(CLzmaEncHandle pp
)
2145 const CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2146 return p
->matchFinder
.GetPointerToCurrentPos(p
->matchFinderObj
) - p
->additionalOffset
;
2149 SRes
LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp
, Bool reInit
,
2150 Byte
*dest
, size_t *destLen
, UInt32 desiredPackSize
, UInt32
*unpackSize
)
2152 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2155 CSeqOutStreamBuf outStream
;
2157 outStream
.funcTable
.Write
= MyWrite
;
2158 outStream
.data
= dest
;
2159 outStream
.rem
= *destLen
;
2160 outStream
.overflow
= False
;
2162 p
->writeEndMark
= False
;
2163 p
->finished
= False
;
2168 LzmaEnc_InitPrices(p
);
2169 nowPos64
= p
->nowPos64
;
2170 RangeEnc_Init(&p
->rc
);
2171 p
->rc
.outStream
= &outStream
.funcTable
;
2173 res
= LzmaEnc_CodeOneBlock(p
, True
, desiredPackSize
, *unpackSize
);
2175 *unpackSize
= (UInt32
)(p
->nowPos64
- nowPos64
);
2176 *destLen
-= outStream
.rem
;
2177 if (outStream
.overflow
)
2178 return SZ_ERROR_OUTPUT_EOF
;
2183 SRes
LzmaEnc_Encode(CLzmaEncHandle pp
, ISeqOutStream
*outStream
, ISeqInStream
*inStream
, ICompressProgress
*progress
,
2184 ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
2186 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2189 #ifdef COMPRESS_MF_MT
2190 Byte allocaDummy
[0x300];
2192 for (i
= 0; i
< 16; i
++)
2193 allocaDummy
[i
] = (Byte
)i
;
2196 RINOK(LzmaEnc_Prepare(pp
, inStream
, outStream
, alloc
, allocBig
));
2200 res
= LzmaEnc_CodeOneBlock(p
, False
, 0, 0);
2201 if (res
!= SZ_OK
|| p
->finished
!= 0)
2205 res
= progress
->Progress(progress
, p
->nowPos64
, RangeEnc_GetProcessed(&p
->rc
));
2208 res
= SZ_ERROR_PROGRESS
;
2217 SRes
LzmaEnc_WriteProperties(CLzmaEncHandle pp
, Byte
*props
, SizeT
*size
)
2219 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2221 UInt32 dictSize
= p
->dictSize
;
2222 if (*size
< LZMA_PROPS_SIZE
)
2223 return SZ_ERROR_PARAM
;
2224 *size
= LZMA_PROPS_SIZE
;
2225 props
[0] = (Byte
)((p
->pb
* 5 + p
->lp
) * 9 + p
->lc
);
2227 for (i
= 11; i
<= 30; i
++)
2229 if (dictSize
<= ((UInt32
)2 << i
))
2231 dictSize
= (2 << i
);
2234 if (dictSize
<= ((UInt32
)3 << i
))
2236 dictSize
= (3 << i
);
2241 for (i
= 0; i
< 4; i
++)
2242 props
[1 + i
] = (Byte
)(dictSize
>> (8 * i
));
2246 SRes
LzmaEnc_MemEncode(CLzmaEncHandle pp
, Byte
*dest
, SizeT
*destLen
, const Byte
*src
, SizeT srcLen
,
2247 int writeEndMark
, ICompressProgress
*progress
, ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
2250 CLzmaEnc
*p
= (CLzmaEnc
*)pp
;
2252 CSeqOutStreamBuf outStream
;
2254 LzmaEnc_SetInputBuf(p
, src
, srcLen
);
2256 outStream
.funcTable
.Write
= MyWrite
;
2257 outStream
.data
= dest
;
2258 outStream
.rem
= *destLen
;
2259 outStream
.overflow
= False
;
2261 p
->writeEndMark
= writeEndMark
;
2262 res
= LzmaEnc_Encode(pp
, &outStream
.funcTable
, &p
->seqBufInStream
.funcTable
,
2263 progress
, alloc
, allocBig
);
2265 *destLen
-= outStream
.rem
;
2266 if (outStream
.overflow
)
2267 return SZ_ERROR_OUTPUT_EOF
;
2271 SRes
LzmaEncode(Byte
*dest
, SizeT
*destLen
, const Byte
*src
, SizeT srcLen
,
2272 const CLzmaEncProps
*props
, Byte
*propsEncoded
, SizeT
*propsSize
, int writeEndMark
,
2273 ICompressProgress
*progress
, ISzAlloc
*alloc
, ISzAlloc
*allocBig
)
2275 CLzmaEnc
*p
= (CLzmaEnc
*)LzmaEnc_Create(alloc
);
2278 return SZ_ERROR_MEM
;
2280 res
= LzmaEnc_SetProps(p
, props
);
2283 res
= LzmaEnc_WriteProperties(p
, propsEncoded
, propsSize
);
2285 res
= LzmaEnc_MemEncode(p
, dest
, destLen
, src
, srcLen
,
2286 writeEndMark
, progress
, alloc
, allocBig
);
2289 LzmaEnc_Destroy(p
, alloc
, allocBig
);