attempt to fix build
[pcsx_rearmed.git] / deps / libchdr / deps / lzma-19.00 / src / LzmaEnc.c
CommitLineData
b24e7fce 1/* LzmaEnc.c -- LZMA Encoder
22019-01-10: Igor Pavlov : Public domain */
3
4#include "Precomp.h"
5
6#include <string.h>
7
8/* #define SHOW_STAT */
9/* #define SHOW_STAT2 */
10
11#if defined(SHOW_STAT) || defined(SHOW_STAT2)
12#include <stdio.h>
13#endif
14
15#include "LzmaEnc.h"
16
17#include "LzFind.h"
18#ifndef _7ZIP_ST
19#include "LzFindMt.h"
20#endif
21
22#ifdef SHOW_STAT
23static unsigned g_STAT_OFFSET = 0;
24#endif
25
26#define kLzmaMaxHistorySize ((UInt32)3 << 29)
27/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */
28
29#define kNumTopBits 24
30#define kTopValue ((UInt32)1 << kNumTopBits)
31
32#define kNumBitModelTotalBits 11
33#define kBitModelTotal (1 << kNumBitModelTotalBits)
34#define kNumMoveBits 5
35#define kProbInitValue (kBitModelTotal >> 1)
36
37#define kNumMoveReducingBits 4
38#define kNumBitPriceShiftBits 4
39#define kBitPrice (1 << kNumBitPriceShiftBits)
40
41#define REP_LEN_COUNT 64
42
43void LzmaEncProps_Init(CLzmaEncProps *p)
44{
45 p->level = 5;
46 p->dictSize = p->mc = 0;
47 p->reduceSize = (UInt64)(Int64)-1;
48 p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
49 p->writeEndMark = 0;
50}
51
52void LzmaEncProps_Normalize(CLzmaEncProps *p)
53{
54 int level = p->level;
55 if (level < 0) level = 5;
56 p->level = level;
57
58 if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26)));
59 if (p->dictSize > p->reduceSize)
60 {
61 unsigned i;
62 UInt32 reduceSize = (UInt32)p->reduceSize;
63 for (i = 11; i <= 30; i++)
64 {
65 if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
66 if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
67 }
68 }
69
70 if (p->lc < 0) p->lc = 3;
71 if (p->lp < 0) p->lp = 0;
72 if (p->pb < 0) p->pb = 2;
73
74 if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
75 if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
76 if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
77 if (p->numHashBytes < 0) p->numHashBytes = 4;
78 if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
79
80 if (p->numThreads < 0)
81 p->numThreads =
82 #ifndef _7ZIP_ST
83 ((p->btMode && p->algo) ? 2 : 1);
84 #else
85 1;
86 #endif
87}
88
89UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
90{
91 CLzmaEncProps props = *props2;
92 LzmaEncProps_Normalize(&props);
93 return props.dictSize;
94}
95
96#if (_MSC_VER >= 1400)
97/* BSR code is fast for some new CPUs */
98/* #define LZMA_LOG_BSR */
99#endif
100
101#ifdef LZMA_LOG_BSR
102
103#define kDicLogSizeMaxCompress 32
104
105#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }
106
107static unsigned GetPosSlot1(UInt32 pos)
108{
109 unsigned res;
110 BSR2_RET(pos, res);
111 return res;
112}
113#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
114#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
115
116#else
117
118#define kNumLogBits (9 + sizeof(size_t) / 2)
119/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
120
121#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
122
123static void LzmaEnc_FastPosInit(Byte *g_FastPos)
124{
125 unsigned slot;
126 g_FastPos[0] = 0;
127 g_FastPos[1] = 1;
128 g_FastPos += 2;
129
130 for (slot = 2; slot < kNumLogBits * 2; slot++)
131 {
132 size_t k = ((size_t)1 << ((slot >> 1) - 1));
133 size_t j;
134 for (j = 0; j < k; j++)
135 g_FastPos[j] = (Byte)slot;
136 g_FastPos += k;
137 }
138}
139
140/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
141/*
142#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
143 (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
144 res = p->g_FastPos[pos >> zz] + (zz * 2); }
145*/
146
147/*
148#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
149 (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
150 res = p->g_FastPos[pos >> zz] + (zz * 2); }
151*/
152
153#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
154 res = p->g_FastPos[pos >> zz] + (zz * 2); }
155
156/*
157#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
158 p->g_FastPos[pos >> 6] + 12 : \
159 p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
160*/
161
162#define GetPosSlot1(pos) p->g_FastPos[pos]
163#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
164#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
165
166#endif
167
168
169#define LZMA_NUM_REPS 4
170
171typedef UInt16 CState;
172typedef UInt16 CExtra;
173
174typedef struct
175{
176 UInt32 price;
177 CState state;
178 CExtra extra;
179 // 0 : normal
180 // 1 : LIT : MATCH
181 // > 1 : MATCH (extra-1) : LIT : REP0 (len)
182 UInt32 len;
183 UInt32 dist;
184 UInt32 reps[LZMA_NUM_REPS];
185} COptimal;
186
187
188// 18.06
189#define kNumOpts (1 << 11)
190#define kPackReserve (kNumOpts * 8)
191// #define kNumOpts (1 << 12)
192// #define kPackReserve (1 + kNumOpts * 2)
193
194#define kNumLenToPosStates 4
195#define kNumPosSlotBits 6
196#define kDicLogSizeMin 0
197#define kDicLogSizeMax 32
198#define kDistTableSizeMax (kDicLogSizeMax * 2)
199
200#define kNumAlignBits 4
201#define kAlignTableSize (1 << kNumAlignBits)
202#define kAlignMask (kAlignTableSize - 1)
203
204#define kStartPosModelIndex 4
205#define kEndPosModelIndex 14
206#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
207
208typedef
209#ifdef _LZMA_PROB32
210 UInt32
211#else
212 UInt16
213#endif
214 CLzmaProb;
215
216#define LZMA_PB_MAX 4
217#define LZMA_LC_MAX 8
218#define LZMA_LP_MAX 4
219
220#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
221
222#define kLenNumLowBits 3
223#define kLenNumLowSymbols (1 << kLenNumLowBits)
224#define kLenNumHighBits 8
225#define kLenNumHighSymbols (1 << kLenNumHighBits)
226#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
227
228#define LZMA_MATCH_LEN_MIN 2
229#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
230
231#define kNumStates 12
232
233
234typedef struct
235{
236 CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
237 CLzmaProb high[kLenNumHighSymbols];
238} CLenEnc;
239
240
241typedef struct
242{
243 unsigned tableSize;
244 UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
245 // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2];
246 // UInt32 prices2[kLenNumSymbolsTotal];
247} CLenPriceEnc;
248
249#define GET_PRICE_LEN(p, posState, len) \
250 ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN])
251
252/*
253#define GET_PRICE_LEN(p, posState, len) \
254 ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9)))
255*/
256
257typedef struct
258{
259 UInt32 range;
260 unsigned cache;
261 UInt64 low;
262 UInt64 cacheSize;
263 Byte *buf;
264 Byte *bufLim;
265 Byte *bufBase;
266 ISeqOutStream *outStream;
267 UInt64 processed;
268 SRes res;
269} CRangeEnc;
270
271
272typedef struct
273{
274 CLzmaProb *litProbs;
275
276 unsigned state;
277 UInt32 reps[LZMA_NUM_REPS];
278
279 CLzmaProb posAlignEncoder[1 << kNumAlignBits];
280 CLzmaProb isRep[kNumStates];
281 CLzmaProb isRepG0[kNumStates];
282 CLzmaProb isRepG1[kNumStates];
283 CLzmaProb isRepG2[kNumStates];
284 CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
285 CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
286
287 CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
288 CLzmaProb posEncoders[kNumFullDistances];
289
290 CLenEnc lenProbs;
291 CLenEnc repLenProbs;
292
293} CSaveState;
294
295
296typedef UInt32 CProbPrice;
297
298
299typedef struct
300{
301 void *matchFinderObj;
302 IMatchFinder matchFinder;
303
304 unsigned optCur;
305 unsigned optEnd;
306
307 unsigned longestMatchLen;
308 unsigned numPairs;
309 UInt32 numAvail;
310
311 unsigned state;
312 unsigned numFastBytes;
313 unsigned additionalOffset;
314 UInt32 reps[LZMA_NUM_REPS];
315 unsigned lpMask, pbMask;
316 CLzmaProb *litProbs;
317 CRangeEnc rc;
318
319 UInt32 backRes;
320
321 unsigned lc, lp, pb;
322 unsigned lclp;
323
324 BoolInt fastMode;
325 BoolInt writeEndMark;
326 BoolInt finished;
327 BoolInt multiThread;
328 BoolInt needInit;
329 // BoolInt _maxMode;
330
331 UInt64 nowPos64;
332
333 unsigned matchPriceCount;
334 // unsigned alignPriceCount;
335 int repLenEncCounter;
336
337 unsigned distTableSize;
338
339 UInt32 dictSize;
340 SRes result;
341
342 #ifndef _7ZIP_ST
343 BoolInt mtMode;
344 // begin of CMatchFinderMt is used in LZ thread
345 CMatchFinderMt matchFinderMt;
346 // end of CMatchFinderMt is used in BT and HASH threads
347 #endif
348
349 CMatchFinder matchFinderBase;
350
351 #ifndef _7ZIP_ST
352 Byte pad[128];
353 #endif
354
355 // LZ thread
356 CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
357
358 UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
359
360 UInt32 alignPrices[kAlignTableSize];
361 UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
362 UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
363
364 CLzmaProb posAlignEncoder[1 << kNumAlignBits];
365 CLzmaProb isRep[kNumStates];
366 CLzmaProb isRepG0[kNumStates];
367 CLzmaProb isRepG1[kNumStates];
368 CLzmaProb isRepG2[kNumStates];
369 CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
370 CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
371 CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
372 CLzmaProb posEncoders[kNumFullDistances];
373
374 CLenEnc lenProbs;
375 CLenEnc repLenProbs;
376
377 #ifndef LZMA_LOG_BSR
378 Byte g_FastPos[1 << kNumLogBits];
379 #endif
380
381 CLenPriceEnc lenEnc;
382 CLenPriceEnc repLenEnc;
383
384 COptimal opt[kNumOpts];
385
386 CSaveState saveState;
387
388 #ifndef _7ZIP_ST
389 Byte pad2[128];
390 #endif
391} CLzmaEnc;
392
393
394SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
395{
396 CLzmaEnc *p = (CLzmaEnc *)pp;
397 CLzmaEncProps props = *props2;
398 LzmaEncProps_Normalize(&props);
399
400 if (props.lc > LZMA_LC_MAX
401 || props.lp > LZMA_LP_MAX
402 || props.pb > LZMA_PB_MAX
403 || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
404 || props.dictSize > kLzmaMaxHistorySize)
405 return SZ_ERROR_PARAM;
406
407 p->dictSize = props.dictSize;
408 {
409 unsigned fb = props.fb;
410 if (fb < 5)
411 fb = 5;
412 if (fb > LZMA_MATCH_LEN_MAX)
413 fb = LZMA_MATCH_LEN_MAX;
414 p->numFastBytes = fb;
415 }
416 p->lc = props.lc;
417 p->lp = props.lp;
418 p->pb = props.pb;
419 p->fastMode = (props.algo == 0);
420 // p->_maxMode = True;
421 p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
422 {
423 unsigned numHashBytes = 4;
424 if (props.btMode)
425 {
426 if (props.numHashBytes < 2)
427 numHashBytes = 2;
428 else if (props.numHashBytes < 4)
429 numHashBytes = props.numHashBytes;
430 }
431 p->matchFinderBase.numHashBytes = numHashBytes;
432 }
433
434 p->matchFinderBase.cutValue = props.mc;
435
436 p->writeEndMark = props.writeEndMark;
437
438 #ifndef _7ZIP_ST
439 /*
440 if (newMultiThread != _multiThread)
441 {
442 ReleaseMatchFinder();
443 _multiThread = newMultiThread;
444 }
445 */
446 p->multiThread = (props.numThreads > 1);
447 #endif
448
449 return SZ_OK;
450}
451
452
453void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
454{
455 CLzmaEnc *p = (CLzmaEnc *)pp;
456 p->matchFinderBase.expectedDataSize = expectedDataSiize;
457}
458
459
460#define kState_Start 0
461#define kState_LitAfterMatch 4
462#define kState_LitAfterRep 5
463#define kState_MatchAfterLit 7
464#define kState_RepAfterLit 8
465
466static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
467static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
468static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
469static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
470
471#define IsLitState(s) ((s) < 7)
472#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
473#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
474
475#define kInfinityPrice (1 << 30)
476
477static void RangeEnc_Construct(CRangeEnc *p)
478{
479 p->outStream = NULL;
480 p->bufBase = NULL;
481}
482
483#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
484#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
485
486#define RC_BUF_SIZE (1 << 16)
487
488static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
489{
490 if (!p->bufBase)
491 {
492 p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
493 if (!p->bufBase)
494 return 0;
495 p->bufLim = p->bufBase + RC_BUF_SIZE;
496 }
497 return 1;
498}
499
500static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
501{
502 ISzAlloc_Free(alloc, p->bufBase);
503 p->bufBase = 0;
504}
505
506static void RangeEnc_Init(CRangeEnc *p)
507{
508 /* Stream.Init(); */
509 p->range = 0xFFFFFFFF;
510 p->cache = 0;
511 p->low = 0;
512 p->cacheSize = 0;
513
514 p->buf = p->bufBase;
515
516 p->processed = 0;
517 p->res = SZ_OK;
518}
519
520MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
521{
522 size_t num;
523 if (p->res != SZ_OK)
524 return;
525 num = p->buf - p->bufBase;
526 if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
527 p->res = SZ_ERROR_WRITE;
528 p->processed += num;
529 p->buf = p->bufBase;
530}
531
532MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
533{
534 UInt32 low = (UInt32)p->low;
535 unsigned high = (unsigned)(p->low >> 32);
536 p->low = (UInt32)(low << 8);
537 if (low < (UInt32)0xFF000000 || high != 0)
538 {
539 {
540 Byte *buf = p->buf;
541 *buf++ = (Byte)(p->cache + high);
542 p->cache = (unsigned)(low >> 24);
543 p->buf = buf;
544 if (buf == p->bufLim)
545 RangeEnc_FlushStream(p);
546 if (p->cacheSize == 0)
547 return;
548 }
549 high += 0xFF;
550 for (;;)
551 {
552 Byte *buf = p->buf;
553 *buf++ = (Byte)(high);
554 p->buf = buf;
555 if (buf == p->bufLim)
556 RangeEnc_FlushStream(p);
557 if (--p->cacheSize == 0)
558 return;
559 }
560 }
561 p->cacheSize++;
562}
563
564static void RangeEnc_FlushData(CRangeEnc *p)
565{
566 int i;
567 for (i = 0; i < 5; i++)
568 RangeEnc_ShiftLow(p);
569}
570
571#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
572
573#define RC_BIT_PRE(p, prob) \
574 ttt = *(prob); \
575 newBound = (range >> kNumBitModelTotalBits) * ttt;
576
577// #define _LZMA_ENC_USE_BRANCH
578
579#ifdef _LZMA_ENC_USE_BRANCH
580
581#define RC_BIT(p, prob, bit) { \
582 RC_BIT_PRE(p, prob) \
583 if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
584 else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
585 *(prob) = (CLzmaProb)ttt; \
586 RC_NORM(p) \
587 }
588
589#else
590
591#define RC_BIT(p, prob, bit) { \
592 UInt32 mask; \
593 RC_BIT_PRE(p, prob) \
594 mask = 0 - (UInt32)bit; \
595 range &= mask; \
596 mask &= newBound; \
597 range -= mask; \
598 (p)->low += mask; \
599 mask = (UInt32)bit - 1; \
600 range += newBound & mask; \
601 mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
602 mask += ((1 << kNumMoveBits) - 1); \
603 ttt += (Int32)(mask - ttt) >> kNumMoveBits; \
604 *(prob) = (CLzmaProb)ttt; \
605 RC_NORM(p) \
606 }
607
608#endif
609
610
611
612
613#define RC_BIT_0_BASE(p, prob) \
614 range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
615
616#define RC_BIT_1_BASE(p, prob) \
617 range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
618
619#define RC_BIT_0(p, prob) \
620 RC_BIT_0_BASE(p, prob) \
621 RC_NORM(p)
622
623#define RC_BIT_1(p, prob) \
624 RC_BIT_1_BASE(p, prob) \
625 RC_NORM(p)
626
627static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
628{
629 UInt32 range, ttt, newBound;
630 range = p->range;
631 RC_BIT_PRE(p, prob)
632 RC_BIT_0(p, prob)
633 p->range = range;
634}
635
636static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym)
637{
638 UInt32 range = p->range;
639 sym |= 0x100;
640 do
641 {
642 UInt32 ttt, newBound;
643 // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1);
644 CLzmaProb *prob = probs + (sym >> 8);
645 UInt32 bit = (sym >> 7) & 1;
646 sym <<= 1;
647 RC_BIT(p, prob, bit);
648 }
649 while (sym < 0x10000);
650 p->range = range;
651}
652
653static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
654{
655 UInt32 i;
656 for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
657 {
658 const unsigned kCyclesBits = kNumBitPriceShiftBits;
659 UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
660 unsigned bitCount = 0;
661 unsigned j;
662 for (j = 0; j < kCyclesBits; j++)
663 {
664 w = w * w;
665 bitCount <<= 1;
666 while (w >= ((UInt32)1 << 16))
667 {
668 w >>= 1;
669 bitCount++;
670 }
671 }
672 ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
673 // printf("\n%3d: %5d", i, ProbPrices[i]);
674 }
675}
676
677
678#define GET_PRICE(prob, bit) \
679 p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
680
681#define GET_PRICEa(prob, bit) \
682 ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
683
684#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
685#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
686
687#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
688#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
689
690
691static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices)
692{
693 UInt32 price = 0;
694 sym |= 0x100;
695 do
696 {
697 unsigned bit = sym & 1;
698 sym >>= 1;
699 price += GET_PRICEa(probs[sym], bit);
700 }
701 while (sym >= 2);
702 return price;
703}
704
705
706static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices)
707{
708 UInt32 price = 0;
709 UInt32 offs = 0x100;
710 sym |= 0x100;
711 do
712 {
713 matchByte <<= 1;
714 price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1);
715 sym <<= 1;
716 offs &= ~(matchByte ^ sym);
717 }
718 while (sym < 0x10000);
719 return price;
720}
721
722
723
724static void LenEnc_Init(CLenEnc *p)
725{
726 unsigned i;
727 for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
728 p->low[i] = kProbInitValue;
729 for (i = 0; i < kLenNumHighSymbols; i++)
730 p->high[i] = kProbInitValue;
731}
732
733static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState)
734{
735 UInt32 range, ttt, newBound;
736 CLzmaProb *probs = p->low;
737 range = rc->range;
738 RC_BIT_PRE(rc, probs);
739 if (sym >= kLenNumLowSymbols)
740 {
741 RC_BIT_1(rc, probs);
742 probs += kLenNumLowSymbols;
743 RC_BIT_PRE(rc, probs);
744 if (sym >= kLenNumLowSymbols * 2)
745 {
746 RC_BIT_1(rc, probs);
747 rc->range = range;
748 // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2);
749 LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2);
750 return;
751 }
752 sym -= kLenNumLowSymbols;
753 }
754
755 // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym);
756 {
757 unsigned m;
758 unsigned bit;
759 RC_BIT_0(rc, probs);
760 probs += (posState << (1 + kLenNumLowBits));
761 bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
762 bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
763 bit = sym & 1; RC_BIT(rc, probs + m, bit);
764 rc->range = range;
765 }
766}
767
768static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
769{
770 unsigned i;
771 for (i = 0; i < 8; i += 2)
772 {
773 UInt32 price = startPrice;
774 UInt32 prob;
775 price += GET_PRICEa(probs[1 ], (i >> 2));
776 price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
777 prob = probs[4 + (i >> 1)];
778 prices[i ] = price + GET_PRICEa_0(prob);
779 prices[i + 1] = price + GET_PRICEa_1(prob);
780 }
781}
782
783
784MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables(
785 CLenPriceEnc *p,
786 unsigned numPosStates,
787 const CLenEnc *enc,
788 const CProbPrice *ProbPrices)
789{
790 UInt32 b;
791
792 {
793 unsigned prob = enc->low[0];
794 UInt32 a, c;
795 unsigned posState;
796 b = GET_PRICEa_1(prob);
797 a = GET_PRICEa_0(prob);
798 c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
799 for (posState = 0; posState < numPosStates; posState++)
800 {
801 UInt32 *prices = p->prices[posState];
802 const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
803 SetPrices_3(probs, a, prices, ProbPrices);
804 SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices);
805 }
806 }
807
808 /*
809 {
810 unsigned i;
811 UInt32 b;
812 a = GET_PRICEa_0(enc->low[0]);
813 for (i = 0; i < kLenNumLowSymbols; i++)
814 p->prices2[i] = a;
815 a = GET_PRICEa_1(enc->low[0]);
816 b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
817 for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++)
818 p->prices2[i] = b;
819 a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
820 }
821 */
822
823 // p->counter = numSymbols;
824 // p->counter = 64;
825
826 {
827 unsigned i = p->tableSize;
828
829 if (i > kLenNumLowSymbols * 2)
830 {
831 const CLzmaProb *probs = enc->high;
832 UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2;
833 i -= kLenNumLowSymbols * 2 - 1;
834 i >>= 1;
835 b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
836 do
837 {
838 /*
839 p->prices2[i] = a +
840 // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
841 LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices);
842 */
843 // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices);
844 unsigned sym = --i + (1 << (kLenNumHighBits - 1));
845 UInt32 price = b;
846 do
847 {
848 unsigned bit = sym & 1;
849 sym >>= 1;
850 price += GET_PRICEa(probs[sym], bit);
851 }
852 while (sym >= 2);
853
854 {
855 unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];
856 prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob);
857 prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);
858 }
859 }
860 while (i);
861
862 {
863 unsigned posState;
864 size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);
865 for (posState = 1; posState < numPosStates; posState++)
866 memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
867 }
868 }
869 }
870}
871
872/*
873 #ifdef SHOW_STAT
874 g_STAT_OFFSET += num;
875 printf("\n MovePos %u", num);
876 #endif
877*/
878
879#define MOVE_POS(p, num) { \
880 p->additionalOffset += (num); \
881 p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }
882
883
884#define MARK_LIT ((UInt32)(Int32)-1)
885
886#define MakeAs_Lit(p) { (p)->dist = MARK_LIT; (p)->extra = 0; }
887#define MakeAs_ShortRep(p) { (p)->dist = 0; (p)->extra = 0; }
888#define IsShortRep(p) ((p)->dist == 0)
889
890
891#define GetPrice_ShortRep(p, state, posState) \
892 ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
893
894#define GetPrice_Rep_0(p, state, posState) ( \
895 GET_PRICE_1(p->isMatch[state][posState]) \
896 + GET_PRICE_1(p->isRep0Long[state][posState])) \
897 + GET_PRICE_1(p->isRep[state]) \
898 + GET_PRICE_0(p->isRepG0[state])
899
900MY_FORCE_INLINE
901static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
902{
903 UInt32 price;
904 UInt32 prob = p->isRepG0[state];
905 if (repIndex == 0)
906 {
907 price = GET_PRICE_0(prob);
908 price += GET_PRICE_1(p->isRep0Long[state][posState]);
909 }
910 else
911 {
912 price = GET_PRICE_1(prob);
913 prob = p->isRepG1[state];
914 if (repIndex == 1)
915 price += GET_PRICE_0(prob);
916 else
917 {
918 price += GET_PRICE_1(prob);
919 price += GET_PRICE(p->isRepG2[state], repIndex - 2);
920 }
921 }
922 return price;
923}
924
925
926static SRes CheckErrors(CLzmaEnc *p)
927{
928 if (p->result != SZ_OK)
929 return p->result;
930 if (p->rc.res != SZ_OK)
931 p->result = SZ_ERROR_WRITE;
932 if (p->matchFinderBase.result != SZ_OK)
933 p->result = SZ_ERROR_READ;
934 if (p->result != SZ_OK)
935 p->finished = True;
936 return p->result;
937}
938
939
940MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p)
941{
942 unsigned i;
943 const CProbPrice *ProbPrices = p->ProbPrices;
944 const CLzmaProb *probs = p->posAlignEncoder;
945 // p->alignPriceCount = 0;
946 for (i = 0; i < kAlignTableSize / 2; i++)
947 {
948 UInt32 price = 0;
949 unsigned sym = i;
950 unsigned m = 1;
951 unsigned bit;
952 UInt32 prob;
953 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
954 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
955 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
956 prob = probs[m];
957 p->alignPrices[i ] = price + GET_PRICEa_0(prob);
958 p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
959 // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
960 }
961}
962
963
964MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)
965{
966 // int y; for (y = 0; y < 100; y++) {
967
968 UInt32 tempPrices[kNumFullDistances];
969 unsigned i, lps;
970
971 const CProbPrice *ProbPrices = p->ProbPrices;
972 p->matchPriceCount = 0;
973
974 for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++)
975 {
976 unsigned posSlot = GetPosSlot1(i);
977 unsigned footerBits = (posSlot >> 1) - 1;
978 unsigned base = ((2 | (posSlot & 1)) << footerBits);
979 const CLzmaProb *probs = p->posEncoders + (size_t)base * 2;
980 // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
981 UInt32 price = 0;
982 unsigned m = 1;
983 unsigned sym = i;
984 unsigned offset = (unsigned)1 << footerBits;
985 base += i;
986
987 if (footerBits)
988 do
989 {
990 unsigned bit = sym & 1;
991 sym >>= 1;
992 price += GET_PRICEa(probs[m], bit);
993 m = (m << 1) + bit;
994 }
995 while (--footerBits);
996
997 {
998 unsigned prob = probs[m];
999 tempPrices[base ] = price + GET_PRICEa_0(prob);
1000 tempPrices[base + offset] = price + GET_PRICEa_1(prob);
1001 }
1002 }
1003
1004 for (lps = 0; lps < kNumLenToPosStates; lps++)
1005 {
1006 unsigned slot;
1007 unsigned distTableSize2 = (p->distTableSize + 1) >> 1;
1008 UInt32 *posSlotPrices = p->posSlotPrices[lps];
1009 const CLzmaProb *probs = p->posSlotEncoder[lps];
1010
1011 for (slot = 0; slot < distTableSize2; slot++)
1012 {
1013 // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices);
1014 UInt32 price;
1015 unsigned bit;
1016 unsigned sym = slot + (1 << (kNumPosSlotBits - 1));
1017 unsigned prob;
1018 bit = sym & 1; sym >>= 1; price = GET_PRICEa(probs[sym], bit);
1019 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
1020 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
1021 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
1022 bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
1023 prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))];
1024 posSlotPrices[(size_t)slot * 2 ] = price + GET_PRICEa_0(prob);
1025 posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob);
1026 }
1027
1028 {
1029 UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
1030 for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++)
1031 {
1032 posSlotPrices[(size_t)slot * 2 ] += delta;
1033 posSlotPrices[(size_t)slot * 2 + 1] += delta;
1034 delta += ((UInt32)1 << kNumBitPriceShiftBits);
1035 }
1036 }
1037
1038 {
1039 UInt32 *dp = p->distancesPrices[lps];
1040
1041 dp[0] = posSlotPrices[0];
1042 dp[1] = posSlotPrices[1];
1043 dp[2] = posSlotPrices[2];
1044 dp[3] = posSlotPrices[3];
1045
1046 for (i = 4; i < kNumFullDistances; i += 2)
1047 {
1048 UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
1049 dp[i ] = slotPrice + tempPrices[i];
1050 dp[i + 1] = slotPrice + tempPrices[i + 1];
1051 }
1052 }
1053 }
1054 // }
1055}
1056
1057
1058
1059void LzmaEnc_Construct(CLzmaEnc *p)
1060{
1061 RangeEnc_Construct(&p->rc);
1062 MatchFinder_Construct(&p->matchFinderBase);
1063
1064 #ifndef _7ZIP_ST
1065 MatchFinderMt_Construct(&p->matchFinderMt);
1066 p->matchFinderMt.MatchFinder = &p->matchFinderBase;
1067 #endif
1068
1069 {
1070 CLzmaEncProps props;
1071 LzmaEncProps_Init(&props);
1072 LzmaEnc_SetProps(p, &props);
1073 }
1074
1075 #ifndef LZMA_LOG_BSR
1076 LzmaEnc_FastPosInit(p->g_FastPos);
1077 #endif
1078
1079 LzmaEnc_InitPriceTables(p->ProbPrices);
1080 p->litProbs = NULL;
1081 p->saveState.litProbs = NULL;
1082
1083}
1084
1085CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
1086{
1087 void *p;
1088 p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
1089 if (p)
1090 LzmaEnc_Construct((CLzmaEnc *)p);
1091 return p;
1092}
1093
1094void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
1095{
1096 ISzAlloc_Free(alloc, p->litProbs);
1097 ISzAlloc_Free(alloc, p->saveState.litProbs);
1098 p->litProbs = NULL;
1099 p->saveState.litProbs = NULL;
1100}
1101
1102void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
1103{
1104 #ifndef _7ZIP_ST
1105 MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
1106 #endif
1107
1108 MatchFinder_Free(&p->matchFinderBase, allocBig);
1109 LzmaEnc_FreeLits(p, alloc);
1110 RangeEnc_Free(&p->rc, alloc);
1111}
1112
1113void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
1114{
1115 LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
1116 ISzAlloc_Free(alloc, p);
1117}
1118
1119
1120#define kBigHashDicLimit ((UInt32)1 << 24)
1121
1122static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
1123{
1124 UInt32 beforeSize = kNumOpts;
1125 if (!RangeEnc_Alloc(&p->rc, alloc))
1126 return SZ_ERROR_MEM;
1127
1128 #ifndef _7ZIP_ST
1129 p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
1130 #endif
1131
1132 {
1133 unsigned lclp = p->lc + p->lp;
1134 if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
1135 {
1136 LzmaEnc_FreeLits(p, alloc);
1137 p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
1138 p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
1139 if (!p->litProbs || !p->saveState.litProbs)
1140 {
1141 LzmaEnc_FreeLits(p, alloc);
1142 return SZ_ERROR_MEM;
1143 }
1144 p->lclp = lclp;
1145 }
1146 }
1147
1148 p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
1149
1150 if (beforeSize + p->dictSize < keepWindowSize)
1151 beforeSize = keepWindowSize - p->dictSize;
1152
1153 #ifndef _7ZIP_ST
1154 if (p->mtMode)
1155 {
1156 RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,
1157 LZMA_MATCH_LEN_MAX
1158 + 1 /* 18.04 */
1159 , allocBig));
1160 p->matchFinderObj = &p->matchFinderMt;
1161 p->matchFinderBase.bigHash = (Byte)(
1162 (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);
1163 MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
1164 }
1165 else
1166 #endif
1167 {
1168 if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
1169 return SZ_ERROR_MEM;
1170 p->matchFinderObj = &p->matchFinderBase;
1171 MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
1172 }
1173
1174 return SZ_OK;
1175}
1176
1177void LzmaEnc_Init(CLzmaEnc *p)
1178{
1179 unsigned i;
1180 p->state = 0;
1181 p->reps[0] =
1182 p->reps[1] =
1183 p->reps[2] =
1184 p->reps[3] = 1;
1185
1186 RangeEnc_Init(&p->rc);
1187
1188 for (i = 0; i < (1 << kNumAlignBits); i++)
1189 p->posAlignEncoder[i] = kProbInitValue;
1190
1191 for (i = 0; i < kNumStates; i++)
1192 {
1193 unsigned j;
1194 for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
1195 {
1196 p->isMatch[i][j] = kProbInitValue;
1197 p->isRep0Long[i][j] = kProbInitValue;
1198 }
1199 p->isRep[i] = kProbInitValue;
1200 p->isRepG0[i] = kProbInitValue;
1201 p->isRepG1[i] = kProbInitValue;
1202 p->isRepG2[i] = kProbInitValue;
1203 }
1204
1205 {
1206 for (i = 0; i < kNumLenToPosStates; i++)
1207 {
1208 CLzmaProb *probs = p->posSlotEncoder[i];
1209 unsigned j;
1210 for (j = 0; j < (1 << kNumPosSlotBits); j++)
1211 probs[j] = kProbInitValue;
1212 }
1213 }
1214 {
1215 for (i = 0; i < kNumFullDistances; i++)
1216 p->posEncoders[i] = kProbInitValue;
1217 }
1218
1219 {
1220 UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
1221 UInt32 k;
1222 CLzmaProb *probs = p->litProbs;
1223 for (k = 0; k < num; k++)
1224 probs[k] = kProbInitValue;
1225 }
1226
1227
1228 LenEnc_Init(&p->lenProbs);
1229 LenEnc_Init(&p->repLenProbs);
1230
1231 p->optEnd = 0;
1232 p->optCur = 0;
1233
1234 {
1235 for (i = 0; i < kNumOpts; i++)
1236 p->opt[i].price = kInfinityPrice;
1237 }
1238
1239 p->additionalOffset = 0;
1240
1241 p->pbMask = (1 << p->pb) - 1;
1242 p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
1243}
1244
1245
1246void LzmaEnc_InitPrices(CLzmaEnc *p)
1247{
1248 if (!p->fastMode)
1249 {
1250 FillDistancesPrices(p);
1251 FillAlignPrices(p);
1252 }
1253
1254 p->lenEnc.tableSize =
1255 p->repLenEnc.tableSize =
1256 p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
1257
1258 p->repLenEncCounter = REP_LEN_COUNT;
1259
1260 LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
1261 LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
1262}
1263
1264typedef struct
1265{
1266 ISeqOutStream vt;
1267 Byte *data;
1268 SizeT rem;
1269 BoolInt overflow;
1270} CLzmaEnc_SeqOutStreamBuf;
1271
1272static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
1273{
1274 CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);
1275 if (p->rem < size)
1276 {
1277 size = p->rem;
1278 p->overflow = True;
1279 }
1280 memcpy(p->data, data, size);
1281 p->rem -= size;
1282 p->data += size;
1283 return size;
1284}
1285
1286
1287UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
1288{
1289 const CLzmaEnc *p = (CLzmaEnc *)pp;
1290 return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
1291}
1292
1293
1294const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
1295{
1296 const CLzmaEnc *p = (CLzmaEnc *)pp;
1297 return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
1298}
1299
1300
1301SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
1302{
1303 CLzmaEnc *p = (CLzmaEnc *)pp;
1304 unsigned i;
1305 UInt32 dictSize = p->dictSize;
1306 if (*size < LZMA_PROPS_SIZE)
1307 return SZ_ERROR_PARAM;
1308 *size = LZMA_PROPS_SIZE;
1309 props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
1310
1311 if (dictSize >= ((UInt32)1 << 22))
1312 {
1313 UInt32 kDictMask = ((UInt32)1 << 20) - 1;
1314 if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)
1315 dictSize = (dictSize + kDictMask) & ~kDictMask;
1316 }
1317 else for (i = 11; i <= 30; i++)
1318 {
1319 if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }
1320 if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }
1321 }
1322
1323 for (i = 0; i < 4; i++)
1324 props[1 + i] = (Byte)(dictSize >> (8 * i));
1325 return SZ_OK;
1326}
1327
1328
1329
1330