Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: third_party/lzma_sdk/LzmaEnc.cc

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

Powered by Google App Engine
This is Rietveld 408576698