Coverage Report

Created: 2025-07-23 06:46

/src/perfetto/buildtools/lzma/C/LzmaEnc.c
Line
Count
Source (jump to first uncovered line)
1
/* LzmaEnc.c -- LZMA Encoder
2
2018-04-29 : Igor Pavlov : Public domain */
3
4
#include "Precomp.h"
5
6
#include <string.h>
7
8
/* #define SHOW_STAT */
9
/* #define SHOW_STAT2 */
10
11
#if defined(SHOW_STAT) || defined(SHOW_STAT2)
12
#include <stdio.h>
13
#endif
14
15
#include "LzmaEnc.h"
16
17
#include "LzFind.h"
18
#ifndef _7ZIP_ST
19
#include "LzFindMt.h"
20
#endif
21
22
#ifdef SHOW_STAT
23
static unsigned g_STAT_OFFSET = 0;
24
#endif
25
26
0
#define kLzmaMaxHistorySize ((UInt32)3 << 29)
27
/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */
28
29
0
#define kNumTopBits 24
30
0
#define kTopValue ((UInt32)1 << kNumTopBits)
31
32
0
#define kNumBitModelTotalBits 11
33
0
#define kBitModelTotal (1 << kNumBitModelTotalBits)
34
0
#define kNumMoveBits 5
35
0
#define kProbInitValue (kBitModelTotal >> 1)
36
37
0
#define kNumMoveReducingBits 4
38
0
#define kNumBitPriceShiftBits 4
39
#define kBitPrice (1 << kNumBitPriceShiftBits)
40
41
void LzmaEncProps_Init(CLzmaEncProps *p)
42
0
{
43
0
  p->level = 5;
44
0
  p->dictSize = p->mc = 0;
45
0
  p->reduceSize = (UInt64)(Int64)-1;
46
0
  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
47
0
  p->writeEndMark = 0;
48
0
}
49
50
void LzmaEncProps_Normalize(CLzmaEncProps *p)
51
0
{
52
0
  int level = p->level;
53
0
  if (level < 0) level = 5;
54
0
  p->level = level;
55
  
56
0
  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26)));
57
0
  if (p->dictSize > p->reduceSize)
58
0
  {
59
0
    unsigned i;
60
0
    UInt32 reduceSize = (UInt32)p->reduceSize;
61
0
    for (i = 11; i <= 30; i++)
62
0
    {
63
0
      if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; }
64
0
      if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; }
65
0
    }
66
0
  }
67
68
0
  if (p->lc < 0) p->lc = 3;
69
0
  if (p->lp < 0) p->lp = 0;
70
0
  if (p->pb < 0) p->pb = 2;
71
72
0
  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
73
0
  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
74
0
  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
75
0
  if (p->numHashBytes < 0) p->numHashBytes = 4;
76
0
  if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
77
  
78
0
  if (p->numThreads < 0)
79
0
    p->numThreads =
80
      #ifndef _7ZIP_ST
81
      ((p->btMode && p->algo) ? 2 : 1);
82
      #else
83
0
      1;
84
0
      #endif
85
0
}
86
87
UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
88
0
{
89
0
  CLzmaEncProps props = *props2;
90
0
  LzmaEncProps_Normalize(&props);
91
0
  return props.dictSize;
92
0
}
93
94
#if (_MSC_VER >= 1400)
95
/* BSR code is fast for some new CPUs */
96
/* #define LZMA_LOG_BSR */
97
#endif
98
99
#ifdef LZMA_LOG_BSR
100
101
#define kDicLogSizeMaxCompress 32
102
103
#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); }
104
105
static unsigned GetPosSlot1(UInt32 pos)
106
{
107
  unsigned res;
108
  BSR2_RET(pos, res);
109
  return res;
110
}
111
#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
112
#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
113
114
#else
115
116
0
#define kNumLogBits (9 + sizeof(size_t) / 2)
117
/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */
118
119
0
#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
120
121
static void LzmaEnc_FastPosInit(Byte *g_FastPos)
122
0
{
123
0
  unsigned slot;
124
0
  g_FastPos[0] = 0;
125
0
  g_FastPos[1] = 1;
126
0
  g_FastPos += 2;
127
  
128
0
  for (slot = 2; slot < kNumLogBits * 2; slot++)
129
0
  {
130
0
    size_t k = ((size_t)1 << ((slot >> 1) - 1));
131
0
    size_t j;
132
0
    for (j = 0; j < k; j++)
133
0
      g_FastPos[j] = (Byte)slot;
134
0
    g_FastPos += k;
135
0
  }
136
0
}
137
138
/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */
139
/*
140
#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
141
  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
142
  res = p->g_FastPos[pos >> zz] + (zz * 2); }
143
*/
144
145
/*
146
#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \
147
  (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \
148
  res = p->g_FastPos[pos >> zz] + (zz * 2); }
149
*/
150
151
0
#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \
152
0
  res = p->g_FastPos[pos >> zz] + (zz * 2); }
153
154
/*
155
#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
156
  p->g_FastPos[pos >> 6] + 12 : \
157
  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
158
*/
159
160
0
#define GetPosSlot1(pos) p->g_FastPos[pos]
161
0
#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
162
0
#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); }
163
164
#endif
165
166
167
0
#define LZMA_NUM_REPS 4
168
169
typedef UInt16 CState;
170
typedef UInt16 CExtra;
171
172
typedef struct
173
{
174
  UInt32 price;
175
  CState state;
176
  CExtra extra;
177
      // 0   : normal
178
      // 1   : LIT : MATCH
179
      // > 1 : MATCH (extra-1) : LIT : REP0 (len)
180
  UInt32 len;
181
  UInt32 dist;
182
  UInt32 reps[LZMA_NUM_REPS];
183
} COptimal;
184
185
186
0
#define kNumOpts (1 << 12)
187
0
#define kPackReserve (1 + kNumOpts * 2)
188
189
0
#define kNumLenToPosStates 4
190
0
#define kNumPosSlotBits 6
191
#define kDicLogSizeMin 0
192
0
#define kDicLogSizeMax 32
193
#define kDistTableSizeMax (kDicLogSizeMax * 2)
194
195
0
#define kNumAlignBits 4
196
0
#define kAlignTableSize (1 << kNumAlignBits)
197
0
#define kAlignMask (kAlignTableSize - 1)
198
199
0
#define kStartPosModelIndex 4
200
0
#define kEndPosModelIndex 14
201
0
#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
202
203
typedef
204
#ifdef _LZMA_PROB32
205
  UInt32
206
#else
207
  UInt16
208
#endif
209
  CLzmaProb;
210
211
0
#define LZMA_PB_MAX 4
212
0
#define LZMA_LC_MAX 8
213
0
#define LZMA_LP_MAX 4
214
215
0
#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
216
217
0
#define kLenNumLowBits 3
218
0
#define kLenNumLowSymbols (1 << kLenNumLowBits)
219
0
#define kLenNumHighBits 8
220
0
#define kLenNumHighSymbols (1 << kLenNumHighBits)
221
0
#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols)
222
223
0
#define LZMA_MATCH_LEN_MIN 2
224
0
#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
225
226
0
#define kNumStates 12
227
228
229
typedef struct
230
{
231
  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)];
232
  CLzmaProb high[kLenNumHighSymbols];
233
} CLenEnc;
234
235
236
typedef struct
237
{
238
  unsigned tableSize;
239
  unsigned counters[LZMA_NUM_PB_STATES_MAX];
240
  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
241
} CLenPriceEnc;
242
243
244
typedef struct
245
{
246
  UInt32 range;
247
  unsigned cache;
248
  UInt64 low;
249
  UInt64 cacheSize;
250
  Byte *buf;
251
  Byte *bufLim;
252
  Byte *bufBase;
253
  ISeqOutStream *outStream;
254
  UInt64 processed;
255
  SRes res;
256
} CRangeEnc;
257
258
259
typedef struct
260
{
261
  CLzmaProb *litProbs;
262
263
  unsigned state;
264
  UInt32 reps[LZMA_NUM_REPS];
265
266
  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
267
  CLzmaProb isRep[kNumStates];
268
  CLzmaProb isRepG0[kNumStates];
269
  CLzmaProb isRepG1[kNumStates];
270
  CLzmaProb isRepG2[kNumStates];
271
  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
272
  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
273
274
  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
275
  CLzmaProb posEncoders[kNumFullDistances];
276
  
277
  CLenEnc lenProbs;
278
  CLenEnc repLenProbs;
279
280
} CSaveState;
281
282
283
typedef UInt32 CProbPrice;
284
285
286
typedef struct
287
{
288
  void *matchFinderObj;
289
  IMatchFinder matchFinder;
290
291
  unsigned optCur;
292
  unsigned optEnd;
293
294
  unsigned longestMatchLen;
295
  unsigned numPairs;
296
  UInt32 numAvail;
297
298
  unsigned state;
299
  unsigned numFastBytes;
300
  unsigned additionalOffset;
301
  UInt32 reps[LZMA_NUM_REPS];
302
  unsigned lpMask, pbMask;
303
  CLzmaProb *litProbs;
304
  CRangeEnc rc;
305
306
  UInt32 backRes;
307
308
  unsigned lc, lp, pb;
309
  unsigned lclp;
310
311
  Bool fastMode;
312
  Bool writeEndMark;
313
  Bool finished;
314
  Bool multiThread;
315
  Bool needInit;
316
317
  UInt64 nowPos64;
318
  
319
  unsigned matchPriceCount;
320
  unsigned alignPriceCount;
321
322
  unsigned distTableSize;
323
324
  UInt32 dictSize;
325
  SRes result;
326
327
  #ifndef _7ZIP_ST
328
  Bool mtMode;
329
  // begin of CMatchFinderMt is used in LZ thread
330
  CMatchFinderMt matchFinderMt;
331
  // end of CMatchFinderMt is used in BT and HASH threads
332
  #endif
333
334
  CMatchFinder matchFinderBase;
335
336
  #ifndef _7ZIP_ST
337
  Byte pad[128];
338
  #endif
339
  
340
  // LZ thread
341
  CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
342
343
  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
344
345
  UInt32 alignPrices[kAlignTableSize];
346
  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
347
  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
348
349
  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
350
  CLzmaProb isRep[kNumStates];
351
  CLzmaProb isRepG0[kNumStates];
352
  CLzmaProb isRepG1[kNumStates];
353
  CLzmaProb isRepG2[kNumStates];
354
  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
355
  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
356
  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
357
  CLzmaProb posEncoders[kNumFullDistances];
358
  
359
  CLenEnc lenProbs;
360
  CLenEnc repLenProbs;
361
362
  #ifndef LZMA_LOG_BSR
363
  Byte g_FastPos[1 << kNumLogBits];
364
  #endif
365
366
  CLenPriceEnc lenEnc;
367
  CLenPriceEnc repLenEnc;
368
369
  COptimal opt[kNumOpts];
370
371
  CSaveState saveState;
372
373
  #ifndef _7ZIP_ST
374
  Byte pad2[128];
375
  #endif
376
} CLzmaEnc;
377
378
379
380
0
#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr));
381
382
void LzmaEnc_SaveState(CLzmaEncHandle pp)
383
0
{
384
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
385
0
  CSaveState *dest = &p->saveState;
386
  
387
0
  dest->state = p->state;
388
  
389
0
  dest->lenProbs = p->lenProbs;
390
0
  dest->repLenProbs = p->repLenProbs;
391
392
0
  COPY_ARR(dest, p, reps);
393
394
0
  COPY_ARR(dest, p, posAlignEncoder);
395
0
  COPY_ARR(dest, p, isRep);
396
0
  COPY_ARR(dest, p, isRepG0);
397
0
  COPY_ARR(dest, p, isRepG1);
398
0
  COPY_ARR(dest, p, isRepG2);
399
0
  COPY_ARR(dest, p, isMatch);
400
0
  COPY_ARR(dest, p, isRep0Long);
401
0
  COPY_ARR(dest, p, posSlotEncoder);
402
0
  COPY_ARR(dest, p, posEncoders);
403
404
0
  memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb));
405
0
}
406
407
408
void LzmaEnc_RestoreState(CLzmaEncHandle pp)
409
0
{
410
0
  CLzmaEnc *dest = (CLzmaEnc *)pp;
411
0
  const CSaveState *p = &dest->saveState;
412
413
0
  dest->state = p->state;
414
415
0
  dest->lenProbs = p->lenProbs;
416
0
  dest->repLenProbs = p->repLenProbs;
417
  
418
0
  COPY_ARR(dest, p, reps);
419
  
420
0
  COPY_ARR(dest, p, posAlignEncoder);
421
0
  COPY_ARR(dest, p, isRep);
422
0
  COPY_ARR(dest, p, isRepG0);
423
0
  COPY_ARR(dest, p, isRepG1);
424
0
  COPY_ARR(dest, p, isRepG2);
425
0
  COPY_ARR(dest, p, isMatch);
426
0
  COPY_ARR(dest, p, isRep0Long);
427
0
  COPY_ARR(dest, p, posSlotEncoder);
428
0
  COPY_ARR(dest, p, posEncoders);
429
430
0
  memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb));
431
0
}
432
433
434
435
SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
436
0
{
437
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
438
0
  CLzmaEncProps props = *props2;
439
0
  LzmaEncProps_Normalize(&props);
440
441
0
  if (props.lc > LZMA_LC_MAX
442
0
      || props.lp > LZMA_LP_MAX
443
0
      || props.pb > LZMA_PB_MAX
444
0
      || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress)
445
0
      || props.dictSize > kLzmaMaxHistorySize)
446
0
    return SZ_ERROR_PARAM;
447
448
0
  p->dictSize = props.dictSize;
449
0
  {
450
0
    unsigned fb = props.fb;
451
0
    if (fb < 5)
452
0
      fb = 5;
453
0
    if (fb > LZMA_MATCH_LEN_MAX)
454
0
      fb = LZMA_MATCH_LEN_MAX;
455
0
    p->numFastBytes = fb;
456
0
  }
457
0
  p->lc = props.lc;
458
0
  p->lp = props.lp;
459
0
  p->pb = props.pb;
460
0
  p->fastMode = (props.algo == 0);
461
0
  p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
462
0
  {
463
0
    unsigned numHashBytes = 4;
464
0
    if (props.btMode)
465
0
    {
466
0
      if (props.numHashBytes < 2)
467
0
        numHashBytes = 2;
468
0
      else if (props.numHashBytes < 4)
469
0
        numHashBytes = props.numHashBytes;
470
0
    }
471
0
    p->matchFinderBase.numHashBytes = numHashBytes;
472
0
  }
473
474
0
  p->matchFinderBase.cutValue = props.mc;
475
476
0
  p->writeEndMark = props.writeEndMark;
477
478
  #ifndef _7ZIP_ST
479
  /*
480
  if (newMultiThread != _multiThread)
481
  {
482
    ReleaseMatchFinder();
483
    _multiThread = newMultiThread;
484
  }
485
  */
486
  p->multiThread = (props.numThreads > 1);
487
  #endif
488
489
0
  return SZ_OK;
490
0
}
491
492
493
void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize)
494
0
{
495
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
496
0
  p->matchFinderBase.expectedDataSize = expectedDataSiize;
497
0
}
498
499
500
0
#define kState_Start 0
501
0
#define kState_LitAfterMatch 4
502
0
#define kState_LitAfterRep   5
503
0
#define kState_MatchAfterLit 7
504
0
#define kState_RepAfterLit   8
505
506
static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
507
static const Byte kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
508
static const Byte kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
509
static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
510
511
0
#define IsLitState(s) ((s) < 7)
512
0
#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1)
513
0
#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
514
515
0
#define kInfinityPrice (1 << 30)
516
517
static void RangeEnc_Construct(CRangeEnc *p)
518
0
{
519
0
  p->outStream = NULL;
520
0
  p->bufBase = NULL;
521
0
}
522
523
#define RangeEnc_GetProcessed(p)       ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
524
0
#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize)
525
526
0
#define RC_BUF_SIZE (1 << 16)
527
528
static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc)
529
0
{
530
0
  if (!p->bufBase)
531
0
  {
532
0
    p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE);
533
0
    if (!p->bufBase)
534
0
      return 0;
535
0
    p->bufLim = p->bufBase + RC_BUF_SIZE;
536
0
  }
537
0
  return 1;
538
0
}
539
540
static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc)
541
0
{
542
0
  ISzAlloc_Free(alloc, p->bufBase);
543
0
  p->bufBase = 0;
544
0
}
545
546
static void RangeEnc_Init(CRangeEnc *p)
547
0
{
548
  /* Stream.Init(); */
549
0
  p->range = 0xFFFFFFFF;
550
0
  p->cache = 0;
551
0
  p->low = 0;
552
0
  p->cacheSize = 0;
553
554
0
  p->buf = p->bufBase;
555
556
0
  p->processed = 0;
557
0
  p->res = SZ_OK;
558
0
}
559
560
MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p)
561
0
{
562
0
  size_t num;
563
0
  if (p->res != SZ_OK)
564
0
    return;
565
0
  num = p->buf - p->bufBase;
566
0
  if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num))
567
0
    p->res = SZ_ERROR_WRITE;
568
0
  p->processed += num;
569
0
  p->buf = p->bufBase;
570
0
}
571
572
MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
573
0
{
574
0
  UInt32 low = (UInt32)p->low;
575
0
  unsigned high = (unsigned)(p->low >> 32);
576
0
  p->low = (UInt32)(low << 8);
577
0
  if (low < (UInt32)0xFF000000 || high != 0)
578
0
  {
579
0
    {
580
0
      Byte *buf = p->buf;
581
0
      *buf++ = (Byte)(p->cache + high);
582
0
      p->cache = (unsigned)(low >> 24);
583
0
      p->buf = buf;
584
0
      if (buf == p->bufLim)
585
0
        RangeEnc_FlushStream(p);
586
0
      if (p->cacheSize == 0)
587
0
        return;
588
0
    }
589
0
    high += 0xFF;
590
0
    for (;;)
591
0
    {
592
0
      Byte *buf = p->buf;
593
0
      *buf++ = (Byte)(high);
594
0
      p->buf = buf;
595
0
      if (buf == p->bufLim)
596
0
        RangeEnc_FlushStream(p);
597
0
      if (--p->cacheSize == 0)
598
0
        return;
599
0
    }
600
0
  }
601
0
  p->cacheSize++;
602
0
}
603
604
static void RangeEnc_FlushData(CRangeEnc *p)
605
0
{
606
0
  int i;
607
0
  for (i = 0; i < 5; i++)
608
0
    RangeEnc_ShiftLow(p);
609
0
}
610
611
0
#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); }
612
613
#define RC_BIT_PRE(p, prob) \
614
0
  ttt = *(prob); \
615
0
  newBound = (range >> kNumBitModelTotalBits) * ttt;
616
617
// #define _LZMA_ENC_USE_BRANCH
618
619
#ifdef _LZMA_ENC_USE_BRANCH
620
621
#define RC_BIT(p, prob, symbol) { \
622
  RC_BIT_PRE(p, prob) \
623
  if (symbol == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
624
  else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
625
  *(prob) = (CLzmaProb)ttt; \
626
  RC_NORM(p) \
627
  }
628
629
#else
630
631
0
#define RC_BIT(p, prob, symbol) { \
632
0
  UInt32 mask; \
633
0
  RC_BIT_PRE(p, prob) \
634
0
  mask = 0 - (UInt32)symbol; \
635
0
  range &= mask; \
636
0
  mask &= newBound; \
637
0
  range -= mask; \
638
0
  (p)->low += mask; \
639
0
  mask = (UInt32)symbol - 1; \
640
0
  range += newBound & mask; \
641
0
  mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
642
0
  mask += ((1 << kNumMoveBits) - 1); \
643
0
  ttt += (Int32)(mask - ttt) >> kNumMoveBits; \
644
0
  *(prob) = (CLzmaProb)ttt; \
645
0
  RC_NORM(p) \
646
0
  }
647
648
#endif
649
650
651
652
653
#define RC_BIT_0_BASE(p, prob) \
654
0
  range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
655
656
#define RC_BIT_1_BASE(p, prob) \
657
0
  range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \
658
659
#define RC_BIT_0(p, prob) \
660
0
  RC_BIT_0_BASE(p, prob) \
661
0
  RC_NORM(p)
662
663
#define RC_BIT_1(p, prob) \
664
0
  RC_BIT_1_BASE(p, prob) \
665
0
  RC_NORM(p)
666
667
static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
668
0
{
669
0
  UInt32 range, ttt, newBound;
670
0
  range = p->range;
671
0
  RC_BIT_PRE(p, prob)
672
0
  RC_BIT_0(p, prob)
673
0
  p->range = range;
674
0
}
675
676
static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
677
0
{
678
0
  UInt32 range = p->range;
679
0
  symbol |= 0x100;
680
0
  do
681
0
  {
682
0
    UInt32 ttt, newBound;
683
    // RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
684
0
    CLzmaProb *prob = probs + (symbol >> 8);
685
0
    UInt32 bit = (symbol >> 7) & 1;
686
0
    symbol <<= 1;
687
0
    RC_BIT(p, prob, bit);
688
0
  }
689
0
  while (symbol < 0x10000);
690
0
  p->range = range;
691
0
}
692
693
static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
694
0
{
695
0
  UInt32 range = p->range;
696
0
  UInt32 offs = 0x100;
697
0
  symbol |= 0x100;
698
0
  do
699
0
  {
700
0
    UInt32 ttt, newBound;
701
0
    CLzmaProb *prob;
702
0
    UInt32 bit;
703
0
    matchByte <<= 1;
704
    // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
705
0
    prob = probs + (offs + (matchByte & offs) + (symbol >> 8));
706
0
    bit = (symbol >> 7) & 1;
707
0
    symbol <<= 1;
708
0
    offs &= ~(matchByte ^ symbol);
709
0
    RC_BIT(p, prob, bit);
710
0
  }
711
0
  while (symbol < 0x10000);
712
0
  p->range = range;
713
0
}
714
715
716
717
static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
718
0
{
719
0
  UInt32 i;
720
0
  for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++)
721
0
  {
722
0
    const unsigned kCyclesBits = kNumBitPriceShiftBits;
723
0
    UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1));
724
0
    unsigned bitCount = 0;
725
0
    unsigned j;
726
0
    for (j = 0; j < kCyclesBits; j++)
727
0
    {
728
0
      w = w * w;
729
0
      bitCount <<= 1;
730
0
      while (w >= ((UInt32)1 << 16))
731
0
      {
732
0
        w >>= 1;
733
0
        bitCount++;
734
0
      }
735
0
    }
736
0
    ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
737
    // printf("\n%3d: %5d", i, ProbPrices[i]);
738
0
  }
739
0
}
740
741
742
#define GET_PRICE(prob, symbol) \
743
0
  p->ProbPrices[((prob) ^ (unsigned)(((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
744
745
#define GET_PRICEa(prob, symbol) \
746
0
     ProbPrices[((prob) ^ (unsigned)((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
747
748
0
#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
749
0
#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
750
751
0
#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
752
0
#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
753
754
755
static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const CProbPrice *ProbPrices)
756
0
{
757
0
  UInt32 price = 0;
758
0
  symbol |= 0x100;
759
0
  do
760
0
  {
761
0
    unsigned bit = symbol & 1;
762
0
    symbol >>= 1;
763
0
    price += GET_PRICEa(probs[symbol], bit);
764
0
  }
765
0
  while (symbol >= 2);
766
0
  return price;
767
0
}
768
769
770
static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const CProbPrice *ProbPrices)
771
0
{
772
0
  UInt32 price = 0;
773
0
  UInt32 offs = 0x100;
774
0
  symbol |= 0x100;
775
0
  do
776
0
  {
777
0
    matchByte <<= 1;
778
0
    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
779
0
    symbol <<= 1;
780
0
    offs &= ~(matchByte ^ symbol);
781
0
  }
782
0
  while (symbol < 0x10000);
783
0
  return price;
784
0
}
785
786
787
static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, UInt32 symbol)
788
0
{
789
0
  UInt32 range = rc->range;
790
0
  unsigned m = 1;
791
0
  do
792
0
  {
793
0
    UInt32 ttt, newBound;
794
0
    unsigned bit = symbol & 1;
795
    // RangeEnc_EncodeBit(rc, probs + m, bit);
796
0
    symbol >>= 1;
797
0
    RC_BIT(rc, probs + m, bit);
798
0
    m = (m << 1) | bit;
799
0
  }
800
0
  while (--numBits);
801
0
  rc->range = range;
802
0
}
803
804
805
806
static void LenEnc_Init(CLenEnc *p)
807
0
{
808
0
  unsigned i;
809
0
  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++)
810
0
    p->low[i] = kProbInitValue;
811
0
  for (i = 0; i < kLenNumHighSymbols; i++)
812
0
    p->high[i] = kProbInitValue;
813
0
}
814
815
static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned symbol, unsigned posState)
816
0
{
817
0
  UInt32 range, ttt, newBound;
818
0
  CLzmaProb *probs = p->low;
819
0
  range = rc->range;
820
0
  RC_BIT_PRE(rc, probs);
821
0
  if (symbol >= kLenNumLowSymbols)
822
0
  {
823
0
    RC_BIT_1(rc, probs);
824
0
    probs += kLenNumLowSymbols;
825
0
    RC_BIT_PRE(rc, probs);
826
0
    if (symbol >= kLenNumLowSymbols * 2)
827
0
    {
828
0
      RC_BIT_1(rc, probs);
829
0
      rc->range = range;
830
      // RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols * 2);
831
0
      LitEnc_Encode(rc, p->high, symbol - kLenNumLowSymbols * 2);
832
0
      return;
833
0
    }
834
0
    symbol -= kLenNumLowSymbols;
835
0
  }
836
837
  // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
838
0
  {
839
0
    unsigned m;
840
0
    unsigned bit;
841
0
    RC_BIT_0(rc, probs);
842
0
    probs += (posState << (1 + kLenNumLowBits));
843
0
    bit = (symbol >> 2)    ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
844
0
    bit = (symbol >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
845
0
    bit =  symbol       & 1; RC_BIT(rc, probs + m, bit);
846
0
    rc->range = range;
847
0
  }
848
0
}
849
850
static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices)
851
0
{
852
0
  unsigned i;
853
0
  for (i = 0; i < 8; i += 2)
854
0
  {
855
0
    UInt32 price = startPrice;
856
0
    UInt32 prob;
857
0
    price += GET_PRICEa(probs[1           ], (i >> 2));
858
0
    price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1);
859
0
    prob = probs[4 + (i >> 1)];
860
0
    prices[i    ] = price + GET_PRICEa_0(prob);
861
0
    prices[i + 1] = price + GET_PRICEa_1(prob);
862
0
  }
863
0
}
864
865
866
MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTable(
867
    CLenPriceEnc *p, unsigned posState,
868
    const CLenEnc *enc,
869
    const CProbPrice *ProbPrices)
870
0
{
871
  // int y; for (y = 0; y < 100; y++) {
872
0
  UInt32 a;
873
0
  unsigned i, numSymbols;
874
875
0
  UInt32 *prices = p->prices[posState];
876
0
  {
877
0
    const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
878
0
    SetPrices_3(probs, GET_PRICEa_0(enc->low[0]), prices, ProbPrices);
879
0
    a = GET_PRICEa_1(enc->low[0]);
880
0
    SetPrices_3(probs + kLenNumLowSymbols, a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]), prices + kLenNumLowSymbols, ProbPrices);
881
0
    a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
882
0
  }
883
0
  numSymbols = p->tableSize;
884
0
  p->counters[posState] = numSymbols;
885
0
  for (i = kLenNumLowSymbols * 2; i < numSymbols; i += 1)
886
0
  {
887
0
    prices[i] = a +
888
       // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
889
0
       LitEnc_GetPrice(enc->high, i - kLenNumLowSymbols * 2, ProbPrices);
890
    /*
891
    unsigned sym = (i - kLenNumLowSymbols * 2) >> 1;
892
    UInt32 price = a + RcTree_GetPrice(enc->high, kLenNumHighBits - 1, sym, ProbPrices);
893
    UInt32 prob = enc->high[(1 << 7) + sym];
894
    prices[i    ] = price + GET_PRICEa_0(prob);
895
    prices[i + 1] = price + GET_PRICEa_1(prob);
896
    */
897
0
  }
898
  // }
899
0
}
900
901
static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, unsigned numPosStates,
902
    const CLenEnc *enc,
903
    const CProbPrice *ProbPrices)
904
0
{
905
0
  unsigned posState;
906
0
  for (posState = 0; posState < numPosStates; posState++)
907
0
    LenPriceEnc_UpdateTable(p, posState, enc, ProbPrices);
908
0
}
909
910
911
/*
912
  #ifdef SHOW_STAT
913
  g_STAT_OFFSET += num;
914
  printf("\n MovePos %u", num);
915
  #endif
916
*/
917
  
918
0
#define MOVE_POS(p, num) { \
919
0
    p->additionalOffset += (num); \
920
0
    p->matchFinder.Skip(p->matchFinderObj, (num)); }
921
922
923
static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
924
0
{
925
0
  unsigned numPairs;
926
  
927
0
  p->additionalOffset++;
928
0
  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
929
0
  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
930
0
  *numPairsRes = numPairs;
931
  
932
  #ifdef SHOW_STAT
933
  printf("\n i = %u numPairs = %u    ", g_STAT_OFFSET, numPairs / 2);
934
  g_STAT_OFFSET++;
935
  {
936
    unsigned i;
937
    for (i = 0; i < numPairs; i += 2)
938
      printf("%2u %6u   | ", p->matches[i], p->matches[i + 1]);
939
  }
940
  #endif
941
  
942
0
  if (numPairs == 0)
943
0
    return 0;
944
0
  {
945
0
    unsigned len = p->matches[(size_t)numPairs - 2];
946
0
    if (len != p->numFastBytes)
947
0
      return len;
948
0
    {
949
0
      UInt32 numAvail = p->numAvail;
950
0
      if (numAvail > LZMA_MATCH_LEN_MAX)
951
0
        numAvail = LZMA_MATCH_LEN_MAX;
952
0
      {
953
0
        const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
954
0
        const Byte *p2 = p1 + len;
955
0
        ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1];
956
0
        const Byte *lim = p1 + numAvail;
957
0
        for (; p2 != lim && *p2 == p2[dif]; p2++);
958
0
        return (unsigned)(p2 - p1);
959
0
      }
960
0
    }
961
0
  }
962
0
}
963
964
0
#define MARK_LIT ((UInt32)(Int32)-1)
965
966
0
#define MakeAs_Lit(p)       { (p)->dist = MARK_LIT; (p)->extra = 0; }
967
0
#define MakeAs_ShortRep(p)  { (p)->dist = 0; (p)->extra = 0; }
968
0
#define IsShortRep(p)       ((p)->dist == 0)
969
970
971
#define GetPrice_ShortRep(p, state, posState) \
972
0
  ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState]))
973
974
0
#define GetPrice_Rep_0(p, state, posState) ( \
975
0
    GET_PRICE_1(p->isMatch[state][posState]) \
976
0
  + GET_PRICE_1(p->isRep0Long[state][posState])) \
977
0
  + GET_PRICE_1(p->isRep[state]) \
978
0
  + GET_PRICE_0(p->isRepG0[state])
979
  
980
981
static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
982
0
{
983
0
  UInt32 price;
984
0
  UInt32 prob = p->isRepG0[state];
985
0
  if (repIndex == 0)
986
0
  {
987
0
    price = GET_PRICE_0(prob);
988
0
    price += GET_PRICE_1(p->isRep0Long[state][posState]);
989
0
  }
990
0
  else
991
0
  {
992
0
    price = GET_PRICE_1(prob);
993
0
    prob = p->isRepG1[state];
994
0
    if (repIndex == 1)
995
0
      price += GET_PRICE_0(prob);
996
0
    else
997
0
    {
998
0
      price += GET_PRICE_1(prob);
999
0
      price += GET_PRICE(p->isRepG2[state], repIndex - 2);
1000
0
    }
1001
0
  }
1002
0
  return price;
1003
0
}
1004
1005
1006
static unsigned Backward(CLzmaEnc *p, unsigned cur)
1007
0
{
1008
0
  unsigned wr = cur + 1;
1009
0
  p->optEnd = wr;
1010
1011
0
  for (;;)
1012
0
  {
1013
0
    UInt32 dist = p->opt[cur].dist;
1014
0
    UInt32 len = p->opt[cur].len;
1015
0
    UInt32 extra = p->opt[cur].extra;
1016
0
    cur -= len;
1017
1018
0
    if (extra)
1019
0
    {
1020
0
      wr--;
1021
0
      p->opt[wr].len = len;
1022
0
      cur -= extra;
1023
0
      len = extra;
1024
0
      if (extra == 1)
1025
0
      {
1026
0
        p->opt[wr].dist = dist;
1027
0
        dist = MARK_LIT;
1028
0
      }
1029
0
      else
1030
0
      {
1031
0
        p->opt[wr].dist = 0;
1032
0
        len--;
1033
0
        wr--;
1034
0
        p->opt[wr].dist = MARK_LIT;
1035
0
        p->opt[wr].len = 1;
1036
0
      }
1037
0
    }
1038
1039
0
    if (cur == 0)
1040
0
    {
1041
0
      p->backRes = dist;
1042
0
      p->optCur = wr;
1043
0
      return len;
1044
0
    }
1045
    
1046
0
    wr--;
1047
0
    p->opt[wr].dist = dist;
1048
0
    p->opt[wr].len = len;
1049
0
  }
1050
0
}
1051
1052
1053
1054
#define LIT_PROBS(pos, prevByte) \
1055
0
  (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc))
1056
1057
1058
static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
1059
0
{
1060
0
  unsigned last, cur;
1061
0
  UInt32 reps[LZMA_NUM_REPS];
1062
0
  unsigned repLens[LZMA_NUM_REPS];
1063
0
  UInt32 *matches;
1064
1065
0
  {
1066
0
    UInt32 numAvail;
1067
0
    unsigned numPairs, mainLen, repMaxIndex, i, posState;
1068
0
    UInt32 matchPrice, repMatchPrice;
1069
0
    const Byte *data;
1070
0
    Byte curByte, matchByte;
1071
    
1072
0
    p->optCur = p->optEnd = 0;
1073
    
1074
0
    if (p->additionalOffset == 0)
1075
0
      mainLen = ReadMatchDistances(p, &numPairs);
1076
0
    else
1077
0
    {
1078
0
      mainLen = p->longestMatchLen;
1079
0
      numPairs = p->numPairs;
1080
0
    }
1081
    
1082
0
    numAvail = p->numAvail;
1083
0
    if (numAvail < 2)
1084
0
    {
1085
0
      p->backRes = MARK_LIT;
1086
0
      return 1;
1087
0
    }
1088
0
    if (numAvail > LZMA_MATCH_LEN_MAX)
1089
0
      numAvail = LZMA_MATCH_LEN_MAX;
1090
    
1091
0
    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1092
0
    repMaxIndex = 0;
1093
    
1094
0
    for (i = 0; i < LZMA_NUM_REPS; i++)
1095
0
    {
1096
0
      unsigned len;
1097
0
      const Byte *data2;
1098
0
      reps[i] = p->reps[i];
1099
0
      data2 = data - reps[i];
1100
0
      if (data[0] != data2[0] || data[1] != data2[1])
1101
0
      {
1102
0
        repLens[i] = 0;
1103
0
        continue;
1104
0
      }
1105
0
      for (len = 2; len < numAvail && data[len] == data2[len]; len++);
1106
0
      repLens[i] = len;
1107
0
      if (len > repLens[repMaxIndex])
1108
0
        repMaxIndex = i;
1109
0
    }
1110
    
1111
0
    if (repLens[repMaxIndex] >= p->numFastBytes)
1112
0
    {
1113
0
      unsigned len;
1114
0
      p->backRes = repMaxIndex;
1115
0
      len = repLens[repMaxIndex];
1116
0
      MOVE_POS(p, len - 1)
1117
0
      return len;
1118
0
    }
1119
    
1120
0
    matches = p->matches;
1121
    
1122
0
    if (mainLen >= p->numFastBytes)
1123
0
    {
1124
0
      p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
1125
0
      MOVE_POS(p, mainLen - 1)
1126
0
      return mainLen;
1127
0
    }
1128
    
1129
0
    curByte = *data;
1130
0
    matchByte = *(data - reps[0]);
1131
    
1132
0
    if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
1133
0
    {
1134
0
      p->backRes = MARK_LIT;
1135
0
      return 1;
1136
0
    }
1137
    
1138
0
    p->opt[0].state = (CState)p->state;
1139
    
1140
0
    posState = (position & p->pbMask);
1141
    
1142
0
    {
1143
0
      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1144
0
      p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
1145
0
        (!IsLitState(p->state) ?
1146
0
          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
1147
0
          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1148
0
    }
1149
    
1150
0
    MakeAs_Lit(&p->opt[1]);
1151
    
1152
0
    matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
1153
0
    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
1154
    
1155
0
    if (matchByte == curByte)
1156
0
    {
1157
0
      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
1158
0
      if (shortRepPrice < p->opt[1].price)
1159
0
      {
1160
0
        p->opt[1].price = shortRepPrice;
1161
0
        MakeAs_ShortRep(&p->opt[1]);
1162
0
      }
1163
0
    }
1164
    
1165
0
    last = (mainLen >= repLens[repMaxIndex] ? mainLen : repLens[repMaxIndex]);
1166
    
1167
0
    if (last < 2)
1168
0
    {
1169
0
      p->backRes = p->opt[1].dist;
1170
0
      return 1;
1171
0
    }
1172
    
1173
0
    p->opt[1].len = 1;
1174
    
1175
0
    p->opt[0].reps[0] = reps[0];
1176
0
    p->opt[0].reps[1] = reps[1];
1177
0
    p->opt[0].reps[2] = reps[2];
1178
0
    p->opt[0].reps[3] = reps[3];
1179
    
1180
0
    {
1181
0
      unsigned len = last;
1182
0
      do
1183
0
        p->opt[len--].price = kInfinityPrice;
1184
0
      while (len >= 2);
1185
0
    }
1186
1187
    // ---------- REP ----------
1188
    
1189
0
    for (i = 0; i < LZMA_NUM_REPS; i++)
1190
0
    {
1191
0
      unsigned repLen = repLens[i];
1192
0
      UInt32 price;
1193
0
      if (repLen < 2)
1194
0
        continue;
1195
0
      price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
1196
0
      do
1197
0
      {
1198
0
        UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)repLen - 2];
1199
0
        COptimal *opt = &p->opt[repLen];
1200
0
        if (price2 < opt->price)
1201
0
        {
1202
0
          opt->price = price2;
1203
0
          opt->len = repLen;
1204
0
          opt->dist = i;
1205
0
          opt->extra = 0;
1206
0
        }
1207
0
      }
1208
0
      while (--repLen >= 2);
1209
0
    }
1210
    
1211
    
1212
    // ---------- MATCH ----------
1213
0
    {
1214
0
      unsigned len  = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
1215
0
      if (len <= mainLen)
1216
0
      {
1217
0
        unsigned offs = 0;
1218
0
        UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
1219
1220
0
        while (len > matches[offs])
1221
0
          offs += 2;
1222
    
1223
0
        for (; ; len++)
1224
0
        {
1225
0
          COptimal *opt;
1226
0
          UInt32 dist = matches[(size_t)offs + 1];
1227
0
          UInt32 price2 = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
1228
0
          unsigned lenToPosState = GetLenToPosState(len);
1229
       
1230
0
          if (dist < kNumFullDistances)
1231
0
            price2 += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
1232
0
          else
1233
0
          {
1234
0
            unsigned slot;
1235
0
            GetPosSlot2(dist, slot);
1236
0
            price2 += p->alignPrices[dist & kAlignMask];
1237
0
            price2 += p->posSlotPrices[lenToPosState][slot];
1238
0
          }
1239
          
1240
0
          opt = &p->opt[len];
1241
          
1242
0
          if (price2 < opt->price)
1243
0
          {
1244
0
            opt->price = price2;
1245
0
            opt->len = len;
1246
0
            opt->dist = dist + LZMA_NUM_REPS;
1247
0
            opt->extra = 0;
1248
0
          }
1249
          
1250
0
          if (len == matches[offs])
1251
0
          {
1252
0
            offs += 2;
1253
0
            if (offs == numPairs)
1254
0
              break;
1255
0
          }
1256
0
        }
1257
0
      }
1258
0
    }
1259
    
1260
1261
0
    cur = 0;
1262
1263
    #ifdef SHOW_STAT2
1264
    /* if (position >= 0) */
1265
    {
1266
      unsigned i;
1267
      printf("\n pos = %4X", position);
1268
      for (i = cur; i <= last; i++)
1269
      printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price);
1270
    }
1271
    #endif
1272
0
  }
1273
1274
1275
  
1276
  // ---------- Optimal Parsing ----------
1277
1278
0
  for (;;)
1279
0
  {
1280
0
    UInt32 numAvail, numAvailFull;
1281
0
    unsigned newLen, numPairs, prev, state, posState, startLen;
1282
0
    UInt32 curPrice, litPrice, matchPrice, repMatchPrice;
1283
0
    Bool nextIsLit;
1284
0
    Byte curByte, matchByte;
1285
0
    const Byte *data;
1286
0
    COptimal *curOpt, *nextOpt;
1287
1288
0
    if (++cur == last)
1289
0
      return Backward(p, cur);
1290
1291
0
    newLen = ReadMatchDistances(p, &numPairs);
1292
    
1293
0
    if (newLen >= p->numFastBytes)
1294
0
    {
1295
0
      p->numPairs = numPairs;
1296
0
      p->longestMatchLen = newLen;
1297
0
      return Backward(p, cur);
1298
0
    }
1299
    
1300
0
    curOpt = &p->opt[cur];
1301
0
    prev = cur - curOpt->len;
1302
    
1303
0
    if (curOpt->len == 1)
1304
0
    {
1305
0
      state = p->opt[prev].state;
1306
0
      if (IsShortRep(curOpt))
1307
0
        state = kShortRepNextStates[state];
1308
0
      else
1309
0
        state = kLiteralNextStates[state];
1310
0
    }
1311
0
    else
1312
0
    {
1313
0
      const COptimal *prevOpt;
1314
0
      UInt32 b0;
1315
0
      UInt32 dist = curOpt->dist;
1316
1317
0
      if (curOpt->extra)
1318
0
      {
1319
0
        prev -= curOpt->extra;
1320
0
        state = kState_RepAfterLit;
1321
0
        if (curOpt->extra == 1)
1322
0
          state = (dist < LZMA_NUM_REPS) ? kState_RepAfterLit : kState_MatchAfterLit;
1323
0
      }
1324
0
      else
1325
0
      {
1326
0
        state = p->opt[prev].state;
1327
0
        if (dist < LZMA_NUM_REPS)
1328
0
          state = kRepNextStates[state];
1329
0
        else
1330
0
          state = kMatchNextStates[state];
1331
0
      }
1332
1333
0
      prevOpt = &p->opt[prev];
1334
0
      b0 = prevOpt->reps[0];
1335
1336
0
      if (dist < LZMA_NUM_REPS)
1337
0
      {
1338
0
        if (dist == 0)
1339
0
        {
1340
0
          reps[0] = b0;
1341
0
          reps[1] = prevOpt->reps[1];
1342
0
          reps[2] = prevOpt->reps[2];
1343
0
          reps[3] = prevOpt->reps[3];
1344
0
        }
1345
0
        else
1346
0
        {
1347
0
          reps[1] = b0;
1348
0
          b0 = prevOpt->reps[1];
1349
0
          if (dist == 1)
1350
0
          {
1351
0
            reps[0] = b0;
1352
0
            reps[2] = prevOpt->reps[2];
1353
0
            reps[3] = prevOpt->reps[3];
1354
0
          }
1355
0
          else
1356
0
          {
1357
0
            reps[2] = b0;
1358
0
            reps[0] = prevOpt->reps[dist];
1359
0
            reps[3] = prevOpt->reps[dist ^ 1];
1360
0
          }
1361
0
        }
1362
0
      }
1363
0
      else
1364
0
      {
1365
0
        reps[0] = (dist - LZMA_NUM_REPS + 1);
1366
0
        reps[1] = b0;
1367
0
        reps[2] = prevOpt->reps[1];
1368
0
        reps[3] = prevOpt->reps[2];
1369
0
      }
1370
0
    }
1371
    
1372
0
    curOpt->state = (CState)state;
1373
0
    curOpt->reps[0] = reps[0];
1374
0
    curOpt->reps[1] = reps[1];
1375
0
    curOpt->reps[2] = reps[2];
1376
0
    curOpt->reps[3] = reps[3];
1377
1378
0
    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1379
0
    curByte = *data;
1380
0
    matchByte = *(data - reps[0]);
1381
1382
0
    position++;
1383
0
    posState = (position & p->pbMask);
1384
1385
    /*
1386
    The order of Price checks:
1387
       <  LIT
1388
       <= SHORT_REP
1389
       <  LIT : REP_0
1390
       <  REP    [ : LIT : REP_0 ]
1391
       <  MATCH  [ : LIT : REP_0 ]
1392
    */
1393
1394
0
    curPrice = curOpt->price;
1395
0
    litPrice = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
1396
1397
0
    nextOpt = &p->opt[(size_t)cur + 1];
1398
0
    nextIsLit = False;
1399
1400
    // if (litPrice >= nextOpt->price) litPrice = 0; else // 18.new
1401
0
    {
1402
0
      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
1403
0
      litPrice += (!IsLitState(state) ?
1404
0
          LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) :
1405
0
          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
1406
      
1407
0
      if (litPrice < nextOpt->price)
1408
0
      {
1409
0
        nextOpt->price = litPrice;
1410
0
        nextOpt->len = 1;
1411
0
        MakeAs_Lit(nextOpt);
1412
0
        nextIsLit = True;
1413
0
      }
1414
0
    }
1415
1416
0
    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
1417
0
    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
1418
    
1419
    // ---------- SHORT_REP ----------
1420
    // if (IsLitState(state)) // 18.new
1421
0
    if (matchByte == curByte)
1422
    // if (repMatchPrice < nextOpt->price) // 18.new
1423
0
    if (nextOpt->len < 2
1424
0
        || (nextOpt->dist != 0
1425
0
            && nextOpt->extra <= 1 // 17.old
1426
0
        ))
1427
0
    {
1428
0
      UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
1429
0
      if (shortRepPrice <= nextOpt->price) // 17.old
1430
      // if (shortRepPrice < nextOpt->price)  // 18.new
1431
0
      {
1432
0
        nextOpt->price = shortRepPrice;
1433
0
        nextOpt->len = 1;
1434
0
        MakeAs_ShortRep(nextOpt);
1435
0
        nextIsLit = False;
1436
0
      }
1437
0
    }
1438
    
1439
0
    numAvailFull = p->numAvail;
1440
0
    {
1441
0
      UInt32 temp = kNumOpts - 1 - cur;
1442
0
      if (numAvailFull > temp)
1443
0
        numAvailFull = temp;
1444
0
    }
1445
1446
0
    if (numAvailFull < 2)
1447
0
      continue;
1448
0
    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
1449
1450
    // numAvail <= p->numFastBytes
1451
1452
    // ---------- LIT : REP_0 ----------
1453
1454
0
    if (
1455
        // litPrice != 0 && // 18.new
1456
0
        !nextIsLit
1457
0
        && matchByte != curByte
1458
0
        && numAvailFull > 2)
1459
0
    {
1460
0
      const Byte *data2 = data - reps[0];
1461
0
      if (data[1] == data2[1] && data[2] == data2[2])
1462
0
      {
1463
0
        unsigned len;
1464
0
        unsigned limit = p->numFastBytes + 1;
1465
0
        if (limit > numAvailFull)
1466
0
          limit = numAvailFull;
1467
0
        for (len = 3; len < limit && data[len] == data2[len]; len++);
1468
        
1469
0
        {
1470
0
          unsigned state2 = kLiteralNextStates[state];
1471
0
          unsigned posState2 = (position + 1) & p->pbMask;
1472
0
          UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
1473
0
          {
1474
0
            unsigned offset = cur + len;
1475
0
            while (last < offset)
1476
0
              p->opt[++last].price = kInfinityPrice;
1477
          
1478
            // do
1479
0
            {
1480
0
              UInt32 price2;
1481
0
              COptimal *opt;
1482
0
              len--;
1483
              // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
1484
0
              price2 = price + p->repLenEnc.prices[posState2][len - LZMA_MATCH_LEN_MIN];
1485
1486
0
              opt = &p->opt[offset];
1487
              // offset--;
1488
0
              if (price2 < opt->price)
1489
0
              {
1490
0
                opt->price = price2;
1491
0
                opt->len = len;
1492
0
                opt->dist = 0;
1493
0
                opt->extra = 1;
1494
0
              }
1495
0
            }
1496
            // while (len >= 3);
1497
0
          }
1498
0
        }
1499
0
      }
1500
0
    }
1501
    
1502
0
    startLen = 2; /* speed optimization */
1503
0
    {
1504
      // ---------- REP ----------
1505
0
      unsigned repIndex = 0; // 17.old
1506
      // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused
1507
0
      for (; repIndex < LZMA_NUM_REPS; repIndex++)
1508
0
      {
1509
0
        unsigned len;
1510
0
        UInt32 price;
1511
0
        const Byte *data2 = data - reps[repIndex];
1512
0
        if (data[0] != data2[0] || data[1] != data2[1])
1513
0
          continue;
1514
        
1515
0
        for (len = 2; len < numAvail && data[len] == data2[len]; len++);
1516
        
1517
        // if (len < startLen) continue; // 18.new: speed optimization
1518
1519
0
        while (last < cur + len)
1520
0
          p->opt[++last].price = kInfinityPrice;
1521
0
        {
1522
0
          unsigned len2 = len;
1523
0
          price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
1524
0
          do
1525
0
          {
1526
0
            UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)len2 - 2];
1527
0
            COptimal *opt = &p->opt[cur + len2];
1528
0
            if (price2 < opt->price)
1529
0
            {
1530
0
              opt->price = price2;
1531
0
              opt->len = len2;
1532
0
              opt->dist = repIndex;
1533
0
              opt->extra = 0;
1534
0
            }
1535
0
          }
1536
0
          while (--len2 >= 2);
1537
0
        }
1538
        
1539
0
        if (repIndex == 0) startLen = len + 1;  // 17.old
1540
        // startLen = len + 1; // 18.new
1541
1542
        /* if (_maxMode) */
1543
0
        {
1544
          // ---------- REP : LIT : REP_0 ----------
1545
          // numFastBytes + 1 + numFastBytes
1546
1547
0
          unsigned len2 = len + 1;
1548
0
          unsigned limit = len2 + p->numFastBytes;
1549
0
          if (limit > numAvailFull)
1550
0
            limit = numAvailFull;
1551
          
1552
0
          for (; len2 < limit && data[len2] == data2[len2]; len2++);
1553
          
1554
0
          len2 -= len;
1555
0
          if (len2 >= 3)
1556
0
          {
1557
0
            unsigned state2 = kRepNextStates[state];
1558
0
            unsigned posState2 = (position + len) & p->pbMask;
1559
0
            price +=
1560
0
                  p->repLenEnc.prices[posState][(size_t)len - 2]
1561
0
                + GET_PRICE_0(p->isMatch[state2][posState2])
1562
0
                + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
1563
0
                    data[len], data2[len], p->ProbPrices);
1564
            
1565
            // state2 = kLiteralNextStates[state2];
1566
0
            state2 = kState_LitAfterRep;
1567
0
            posState2 = (posState2 + 1) & p->pbMask;
1568
1569
1570
0
            price += GetPrice_Rep_0(p, state2, posState2);
1571
0
            {
1572
0
              unsigned offset = cur + len + len2;
1573
0
              while (last < offset)
1574
0
                p->opt[++last].price = kInfinityPrice;
1575
              // do
1576
0
              {
1577
0
                unsigned price2;
1578
0
                COptimal *opt;
1579
0
                len2--;
1580
                // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
1581
0
                price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
1582
1583
0
                opt = &p->opt[offset];
1584
                // offset--;
1585
0
                if (price2 < opt->price)
1586
0
                {
1587
0
                  opt->price = price2;
1588
0
                  opt->len = len2;
1589
0
                  opt->extra = (CExtra)(len + 1);
1590
0
                  opt->dist = repIndex;
1591
0
                }
1592
0
              }
1593
              // while (len2 >= 3);
1594
0
            }
1595
0
          }
1596
0
        }
1597
0
      }
1598
0
    }
1599
1600
1601
    // ---------- MATCH ----------
1602
    /* for (unsigned len = 2; len <= newLen; len++) */
1603
0
    if (newLen > numAvail)
1604
0
    {
1605
0
      newLen = numAvail;
1606
0
      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
1607
0
      matches[numPairs] = newLen;
1608
0
      numPairs += 2;
1609
0
    }
1610
    
1611
0
    if (newLen >= startLen)
1612
0
    {
1613
0
      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
1614
0
      UInt32 dist;
1615
0
      unsigned offs, posSlot, len;
1616
0
      while (last < cur + newLen)
1617
0
        p->opt[++last].price = kInfinityPrice;
1618
1619
0
      offs = 0;
1620
0
      while (startLen > matches[offs])
1621
0
        offs += 2;
1622
0
      dist = matches[(size_t)offs + 1];
1623
      
1624
      // if (dist >= kNumFullDistances)
1625
0
      GetPosSlot2(dist, posSlot);
1626
      
1627
0
      for (len = /*2*/ startLen; ; len++)
1628
0
      {
1629
0
        UInt32 price = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
1630
0
        {
1631
0
          COptimal *opt;
1632
0
          unsigned lenToPosState = len - 2; lenToPosState = GetLenToPosState2(lenToPosState);
1633
0
          if (dist < kNumFullDistances)
1634
0
            price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
1635
0
          else
1636
0
            price += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[dist & kAlignMask];
1637
          
1638
0
          opt = &p->opt[cur + len];
1639
0
          if (price < opt->price)
1640
0
          {
1641
0
            opt->price = price;
1642
0
            opt->len = len;
1643
0
            opt->dist = dist + LZMA_NUM_REPS;
1644
0
            opt->extra = 0;
1645
0
          }
1646
0
        }
1647
1648
0
        if (/*_maxMode && */ len == matches[offs])
1649
0
        {
1650
          // MATCH : LIT : REP_0
1651
1652
0
          const Byte *data2 = data - dist - 1;
1653
0
          unsigned len2 = len + 1;
1654
0
          unsigned limit = len2 + p->numFastBytes;
1655
0
          if (limit > numAvailFull)
1656
0
            limit = numAvailFull;
1657
          
1658
0
          for (; len2 < limit && data[len2] == data2[len2]; len2++);
1659
          
1660
0
          len2 -= len;
1661
          
1662
0
          if (len2 >= 3)
1663
0
          {
1664
0
            unsigned state2 = kMatchNextStates[state];
1665
0
            unsigned posState2 = (position + len) & p->pbMask;
1666
0
            unsigned offset;
1667
0
            price += GET_PRICE_0(p->isMatch[state2][posState2]);
1668
0
            price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
1669
0
                    data[len], data2[len], p->ProbPrices);
1670
1671
            // state2 = kLiteralNextStates[state2];
1672
0
            state2 = kState_LitAfterMatch;
1673
1674
0
            posState2 = (posState2 + 1) & p->pbMask;
1675
0
            price += GetPrice_Rep_0(p, state2, posState2);
1676
1677
0
            offset = cur + len + len2;
1678
0
            while (last < offset)
1679
0
              p->opt[++last].price = kInfinityPrice;
1680
            // do
1681
0
            {
1682
0
              UInt32 price2;
1683
0
              COptimal *opt;
1684
0
              len2--;
1685
              // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
1686
0
              price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
1687
0
              opt = &p->opt[offset];
1688
              // offset--;
1689
0
              if (price2 < opt->price)
1690
0
              {
1691
0
                opt->price = price2;
1692
0
                opt->len = len2;
1693
0
                opt->extra = (CExtra)(len + 1);
1694
0
                opt->dist = dist + LZMA_NUM_REPS;
1695
0
              }
1696
0
            }
1697
            // while (len2 >= 3);
1698
0
          }
1699
        
1700
0
          offs += 2;
1701
0
          if (offs == numPairs)
1702
0
            break;
1703
0
          dist = matches[(size_t)offs + 1];
1704
          // if (dist >= kNumFullDistances)
1705
0
            GetPosSlot2(dist, posSlot);
1706
0
        }
1707
0
      }
1708
0
    }
1709
0
  }
1710
0
}
1711
1712
1713
1714
0
#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
1715
1716
1717
1718
static unsigned GetOptimumFast(CLzmaEnc *p)
1719
0
{
1720
0
  UInt32 numAvail, mainDist;
1721
0
  unsigned mainLen, numPairs, repIndex, repLen, i;
1722
0
  const Byte *data;
1723
1724
0
  if (p->additionalOffset == 0)
1725
0
    mainLen = ReadMatchDistances(p, &numPairs);
1726
0
  else
1727
0
  {
1728
0
    mainLen = p->longestMatchLen;
1729
0
    numPairs = p->numPairs;
1730
0
  }
1731
1732
0
  numAvail = p->numAvail;
1733
0
  p->backRes = MARK_LIT;
1734
0
  if (numAvail < 2)
1735
0
    return 1;
1736
0
  if (numAvail > LZMA_MATCH_LEN_MAX)
1737
0
    numAvail = LZMA_MATCH_LEN_MAX;
1738
0
  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1739
0
  repLen = repIndex = 0;
1740
  
1741
0
  for (i = 0; i < LZMA_NUM_REPS; i++)
1742
0
  {
1743
0
    unsigned len;
1744
0
    const Byte *data2 = data - p->reps[i];
1745
0
    if (data[0] != data2[0] || data[1] != data2[1])
1746
0
      continue;
1747
0
    for (len = 2; len < numAvail && data[len] == data2[len]; len++);
1748
0
    if (len >= p->numFastBytes)
1749
0
    {
1750
0
      p->backRes = i;
1751
0
      MOVE_POS(p, len - 1)
1752
0
      return len;
1753
0
    }
1754
0
    if (len > repLen)
1755
0
    {
1756
0
      repIndex = i;
1757
0
      repLen = len;
1758
0
    }
1759
0
  }
1760
1761
0
  if (mainLen >= p->numFastBytes)
1762
0
  {
1763
0
    p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS;
1764
0
    MOVE_POS(p, mainLen - 1)
1765
0
    return mainLen;
1766
0
  }
1767
1768
0
  mainDist = 0; /* for GCC */
1769
  
1770
0
  if (mainLen >= 2)
1771
0
  {
1772
0
    mainDist = p->matches[(size_t)numPairs - 1];
1773
0
    while (numPairs > 2)
1774
0
    {
1775
0
      UInt32 dist2;
1776
0
      if (mainLen != p->matches[(size_t)numPairs - 4] + 1)
1777
0
        break;
1778
0
      dist2 = p->matches[(size_t)numPairs - 3];
1779
0
      if (!ChangePair(dist2, mainDist))
1780
0
        break;
1781
0
      numPairs -= 2;
1782
0
      mainLen--;
1783
0
      mainDist = dist2;
1784
0
    }
1785
0
    if (mainLen == 2 && mainDist >= 0x80)
1786
0
      mainLen = 1;
1787
0
  }
1788
1789
0
  if (repLen >= 2)
1790
0
    if (    repLen + 1 >= mainLen
1791
0
        || (repLen + 2 >= mainLen && mainDist >= (1 << 9))
1792
0
        || (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
1793
0
  {
1794
0
    p->backRes = repIndex;
1795
0
    MOVE_POS(p, repLen - 1)
1796
0
    return repLen;
1797
0
  }
1798
  
1799
0
  if (mainLen < 2 || numAvail <= 2)
1800
0
    return 1;
1801
1802
0
  {
1803
0
    unsigned len1 = ReadMatchDistances(p, &p->numPairs);
1804
0
    p->longestMatchLen = len1;
1805
  
1806
0
    if (len1 >= 2)
1807
0
    {
1808
0
      UInt32 newDist = p->matches[(size_t)p->numPairs - 1];
1809
0
      if (   (len1 >= mainLen && newDist < mainDist)
1810
0
          || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist))
1811
0
          || (len1 >  mainLen + 1)
1812
0
          || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist)))
1813
0
        return 1;
1814
0
    }
1815
0
  }
1816
  
1817
0
  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
1818
  
1819
0
  for (i = 0; i < LZMA_NUM_REPS; i++)
1820
0
  {
1821
0
    unsigned len, limit;
1822
0
    const Byte *data2 = data - p->reps[i];
1823
0
    if (data[0] != data2[0] || data[1] != data2[1])
1824
0
      continue;
1825
0
    limit = mainLen - 1;
1826
0
    for (len = 2;; len++)
1827
0
    {
1828
0
      if (len >= limit)
1829
0
        return 1;
1830
0
      if (data[len] != data2[len])
1831
0
        break;
1832
0
    }
1833
0
  }
1834
  
1835
0
  p->backRes = mainDist + LZMA_NUM_REPS;
1836
0
  if (mainLen != 2)
1837
0
  {
1838
0
    MOVE_POS(p, mainLen - 2)
1839
0
  }
1840
0
  return mainLen;
1841
0
}
1842
1843
1844
1845
1846
static void WriteEndMarker(CLzmaEnc *p, unsigned posState)
1847
0
{
1848
0
  UInt32 range;
1849
0
  range = p->rc.range;
1850
0
  {
1851
0
    UInt32 ttt, newBound;
1852
0
    CLzmaProb *prob = &p->isMatch[p->state][posState];
1853
0
    RC_BIT_PRE(&p->rc, prob)
1854
0
    RC_BIT_1(&p->rc, prob)
1855
0
    prob = &p->isRep[p->state];
1856
0
    RC_BIT_PRE(&p->rc, prob)
1857
0
    RC_BIT_0(&p->rc, prob)
1858
0
  }
1859
0
  p->state = kMatchNextStates[p->state];
1860
  
1861
0
  p->rc.range = range;
1862
0
  LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState);
1863
0
  range = p->rc.range;
1864
1865
0
  {
1866
    // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1);
1867
0
    CLzmaProb *probs = p->posSlotEncoder[0];
1868
0
    unsigned m = 1;
1869
0
    do
1870
0
    {
1871
0
      UInt32 ttt, newBound;
1872
0
      RC_BIT_PRE(p, probs + m)
1873
0
      RC_BIT_1(&p->rc, probs + m);
1874
0
      m = (m << 1) + 1;
1875
0
    }
1876
0
    while (m < (1 << kNumPosSlotBits));
1877
0
  }
1878
0
  {
1879
    // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits);    UInt32 range = p->range;
1880
0
    unsigned numBits = 30 - kNumAlignBits;
1881
0
    do
1882
0
    {
1883
0
      range >>= 1;
1884
0
      p->rc.low += range;
1885
0
      RC_NORM(&p->rc)
1886
0
    }
1887
0
    while (--numBits);
1888
0
  }
1889
   
1890
0
  {
1891
    // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
1892
0
    CLzmaProb *probs = p->posAlignEncoder;
1893
0
    unsigned m = 1;
1894
0
    do
1895
0
    {
1896
0
      UInt32 ttt, newBound;
1897
0
      RC_BIT_PRE(p, probs + m)
1898
0
      RC_BIT_1(&p->rc, probs + m);
1899
0
      m = (m << 1) + 1;
1900
0
    }
1901
0
    while (m < kAlignTableSize);
1902
0
  }
1903
0
  p->rc.range = range;
1904
0
}
1905
1906
1907
static SRes CheckErrors(CLzmaEnc *p)
1908
0
{
1909
0
  if (p->result != SZ_OK)
1910
0
    return p->result;
1911
0
  if (p->rc.res != SZ_OK)
1912
0
    p->result = SZ_ERROR_WRITE;
1913
0
  if (p->matchFinderBase.result != SZ_OK)
1914
0
    p->result = SZ_ERROR_READ;
1915
0
  if (p->result != SZ_OK)
1916
0
    p->finished = True;
1917
0
  return p->result;
1918
0
}
1919
1920
1921
MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
1922
0
{
1923
  /* ReleaseMFStream(); */
1924
0
  p->finished = True;
1925
0
  if (p->writeEndMark)
1926
0
    WriteEndMarker(p, nowPos & p->pbMask);
1927
0
  RangeEnc_FlushData(&p->rc);
1928
0
  RangeEnc_FlushStream(&p->rc);
1929
0
  return CheckErrors(p);
1930
0
}
1931
1932
1933
1934
static void FillAlignPrices(CLzmaEnc *p)
1935
0
{
1936
0
  unsigned i;
1937
0
  const CProbPrice *ProbPrices = p->ProbPrices;
1938
0
  const CLzmaProb *probs = p->posAlignEncoder;
1939
0
  p->alignPriceCount = 0;
1940
0
  for (i = 0; i < kAlignTableSize / 2; i++)
1941
0
  {
1942
0
    UInt32 price = 0;
1943
0
    unsigned symbol = i;
1944
0
    unsigned m = 1;
1945
0
    unsigned bit;
1946
0
    UInt32 prob;
1947
0
    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
1948
0
    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
1949
0
    bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
1950
0
    prob = probs[m];
1951
0
    p->alignPrices[i    ] = price + GET_PRICEa_0(prob);
1952
0
    p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
1953
    // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
1954
0
  }
1955
0
}
1956
1957
1958
static void FillDistancesPrices(CLzmaEnc *p)
1959
0
{
1960
0
  UInt32 tempPrices[kNumFullDistances];
1961
0
  unsigned i, lenToPosState;
1962
1963
0
  const CProbPrice *ProbPrices = p->ProbPrices;
1964
0
  p->matchPriceCount = 0;
1965
1966
0
  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
1967
0
  {
1968
0
    unsigned posSlot = GetPosSlot1(i);
1969
0
    unsigned footerBits = ((posSlot >> 1) - 1);
1970
0
    unsigned base = ((2 | (posSlot & 1)) << footerBits);
1971
    // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
1972
1973
0
    const CLzmaProb *probs = p->posEncoders + base;
1974
0
    UInt32 price = 0;
1975
0
    unsigned m = 1;
1976
0
    unsigned symbol = i - base;
1977
0
    do
1978
0
    {
1979
0
      unsigned bit = symbol & 1;
1980
0
      symbol >>= 1;
1981
0
      price += GET_PRICEa(probs[m], bit);
1982
0
      m = (m << 1) + bit;
1983
0
    }
1984
0
    while (--footerBits);
1985
0
    tempPrices[i] = price;
1986
0
  }
1987
1988
0
  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
1989
0
  {
1990
0
    unsigned posSlot;
1991
0
    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
1992
0
    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
1993
0
    unsigned distTableSize = p->distTableSize;
1994
0
    const CLzmaProb *probs = encoder;
1995
0
    for (posSlot = 0; posSlot < distTableSize; posSlot += 2)
1996
0
    {
1997
      // posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
1998
0
      UInt32 price = 0;
1999
0
      unsigned bit;
2000
0
      unsigned symbol = (posSlot >> 1) + (1 << (kNumPosSlotBits - 1));
2001
0
      UInt32 prob;
2002
0
      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
2003
0
      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
2004
0
      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
2005
0
      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
2006
0
      bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
2007
0
      prob = probs[(posSlot >> 1) + (1 << (kNumPosSlotBits - 1))];
2008
0
      posSlotPrices[posSlot    ] = price + GET_PRICEa_0(prob);
2009
0
      posSlotPrices[posSlot + 1] = price + GET_PRICEa_1(prob);
2010
0
    }
2011
0
    for (posSlot = kEndPosModelIndex; posSlot < distTableSize; posSlot++)
2012
0
      posSlotPrices[posSlot] += ((UInt32)(((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
2013
2014
0
    {
2015
0
      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
2016
0
      {
2017
0
        distancesPrices[0] = posSlotPrices[0];
2018
0
        distancesPrices[1] = posSlotPrices[1];
2019
0
        distancesPrices[2] = posSlotPrices[2];
2020
0
        distancesPrices[3] = posSlotPrices[3];
2021
0
      }
2022
0
      for (i = 4; i < kNumFullDistances; i += 2)
2023
0
      {
2024
0
        UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
2025
0
        distancesPrices[i    ] = slotPrice + tempPrices[i];
2026
0
        distancesPrices[i + 1] = slotPrice + tempPrices[i + 1];
2027
0
      }
2028
0
    }
2029
0
  }
2030
0
}
2031
2032
2033
2034
void LzmaEnc_Construct(CLzmaEnc *p)
2035
0
{
2036
0
  RangeEnc_Construct(&p->rc);
2037
0
  MatchFinder_Construct(&p->matchFinderBase);
2038
  
2039
  #ifndef _7ZIP_ST
2040
  MatchFinderMt_Construct(&p->matchFinderMt);
2041
  p->matchFinderMt.MatchFinder = &p->matchFinderBase;
2042
  #endif
2043
2044
0
  {
2045
0
    CLzmaEncProps props;
2046
0
    LzmaEncProps_Init(&props);
2047
0
    LzmaEnc_SetProps(p, &props);
2048
0
  }
2049
2050
0
  #ifndef LZMA_LOG_BSR
2051
0
  LzmaEnc_FastPosInit(p->g_FastPos);
2052
0
  #endif
2053
2054
0
  LzmaEnc_InitPriceTables(p->ProbPrices);
2055
0
  p->litProbs = NULL;
2056
0
  p->saveState.litProbs = NULL;
2057
2058
0
}
2059
2060
CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
2061
0
{
2062
0
  void *p;
2063
0
  p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
2064
0
  if (p)
2065
0
    LzmaEnc_Construct((CLzmaEnc *)p);
2066
0
  return p;
2067
0
}
2068
2069
void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc)
2070
0
{
2071
0
  ISzAlloc_Free(alloc, p->litProbs);
2072
0
  ISzAlloc_Free(alloc, p->saveState.litProbs);
2073
0
  p->litProbs = NULL;
2074
0
  p->saveState.litProbs = NULL;
2075
0
}
2076
2077
void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2078
0
{
2079
  #ifndef _7ZIP_ST
2080
  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
2081
  #endif
2082
  
2083
0
  MatchFinder_Free(&p->matchFinderBase, allocBig);
2084
0
  LzmaEnc_FreeLits(p, alloc);
2085
0
  RangeEnc_Free(&p->rc, alloc);
2086
0
}
2087
2088
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2089
0
{
2090
0
  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
2091
0
  ISzAlloc_Free(alloc, p);
2092
0
}
2093
2094
2095
static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize)
2096
0
{
2097
0
  UInt32 nowPos32, startPos32;
2098
0
  if (p->needInit)
2099
0
  {
2100
0
    p->matchFinder.Init(p->matchFinderObj);
2101
0
    p->needInit = 0;
2102
0
  }
2103
2104
0
  if (p->finished)
2105
0
    return p->result;
2106
0
  RINOK(CheckErrors(p));
2107
2108
0
  nowPos32 = (UInt32)p->nowPos64;
2109
0
  startPos32 = nowPos32;
2110
2111
0
  if (p->nowPos64 == 0)
2112
0
  {
2113
0
    unsigned numPairs;
2114
0
    Byte curByte;
2115
0
    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
2116
0
      return Flush(p, nowPos32);
2117
0
    ReadMatchDistances(p, &numPairs);
2118
0
    RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]);
2119
    // p->state = kLiteralNextStates[p->state];
2120
0
    curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset);
2121
0
    LitEnc_Encode(&p->rc, p->litProbs, curByte);
2122
0
    p->additionalOffset--;
2123
0
    nowPos32++;
2124
0
  }
2125
2126
0
  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
2127
  
2128
0
  for (;;)
2129
0
  {
2130
0
    UInt32 dist;
2131
0
    unsigned len, posState;
2132
0
    UInt32 range, ttt, newBound;
2133
0
    CLzmaProb *probs;
2134
  
2135
0
    if (p->fastMode)
2136
0
      len = GetOptimumFast(p);
2137
0
    else
2138
0
    {
2139
0
      unsigned oci = p->optCur;
2140
0
      if (p->optEnd == oci)
2141
0
        len = GetOptimum(p, nowPos32);
2142
0
      else
2143
0
      {
2144
0
        const COptimal *opt = &p->opt[oci];
2145
0
        len = opt->len;
2146
0
        p->backRes = opt->dist;
2147
0
        p->optCur = oci + 1;
2148
0
      }
2149
0
    }
2150
2151
0
    posState = (unsigned)nowPos32 & p->pbMask;
2152
0
    range = p->rc.range;
2153
0
    probs = &p->isMatch[p->state][posState];
2154
    
2155
0
    RC_BIT_PRE(&p->rc, probs)
2156
    
2157
0
    dist = p->backRes;
2158
2159
    #ifdef SHOW_STAT2
2160
    printf("\n pos = %6X, len = %3u  pos = %6u", nowPos32, len, dist);
2161
    #endif
2162
2163
0
    if (dist == MARK_LIT)
2164
0
    {
2165
0
      Byte curByte;
2166
0
      const Byte *data;
2167
0
      unsigned state;
2168
2169
0
      RC_BIT_0(&p->rc, probs);
2170
0
      p->rc.range = range;
2171
0
      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2172
0
      probs = LIT_PROBS(nowPos32, *(data - 1));
2173
0
      curByte = *data;
2174
0
      state = p->state;
2175
0
      p->state = kLiteralNextStates[state];
2176
0
      if (IsLitState(state))
2177
0
        LitEnc_Encode(&p->rc, probs, curByte);
2178
0
      else
2179
0
        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0]));
2180
0
    }
2181
0
    else
2182
0
    {
2183
0
      RC_BIT_1(&p->rc, probs);
2184
0
      probs = &p->isRep[p->state];
2185
0
      RC_BIT_PRE(&p->rc, probs)
2186
      
2187
0
      if (dist < LZMA_NUM_REPS)
2188
0
      {
2189
0
        RC_BIT_1(&p->rc, probs);
2190
0
        probs = &p->isRepG0[p->state];
2191
0
        RC_BIT_PRE(&p->rc, probs)
2192
0
        if (dist == 0)
2193
0
        {
2194
0
          RC_BIT_0(&p->rc, probs);
2195
0
          probs = &p->isRep0Long[p->state][posState];
2196
0
          RC_BIT_PRE(&p->rc, probs)
2197
0
          if (len != 1)
2198
0
          {
2199
0
            RC_BIT_1_BASE(&p->rc, probs);
2200
0
          }
2201
0
          else
2202
0
          {
2203
0
            RC_BIT_0_BASE(&p->rc, probs);
2204
0
            p->state = kShortRepNextStates[p->state];
2205
0
          }
2206
0
        }
2207
0
        else
2208
0
        {
2209
0
          RC_BIT_1(&p->rc, probs);
2210
0
          probs = &p->isRepG1[p->state];
2211
0
          RC_BIT_PRE(&p->rc, probs)
2212
0
          if (dist == 1)
2213
0
          {
2214
0
            RC_BIT_0_BASE(&p->rc, probs);
2215
0
            dist = p->reps[1];
2216
0
          }
2217
0
          else
2218
0
          {
2219
0
            RC_BIT_1(&p->rc, probs);
2220
0
            probs = &p->isRepG2[p->state];
2221
0
            RC_BIT_PRE(&p->rc, probs)
2222
0
            if (dist == 2)
2223
0
            {
2224
0
              RC_BIT_0_BASE(&p->rc, probs);
2225
0
              dist = p->reps[2];
2226
0
            }
2227
0
            else
2228
0
            {
2229
0
              RC_BIT_1_BASE(&p->rc, probs);
2230
0
              dist = p->reps[3];
2231
0
              p->reps[3] = p->reps[2];
2232
0
            }
2233
0
            p->reps[2] = p->reps[1];
2234
0
          }
2235
0
          p->reps[1] = p->reps[0];
2236
0
          p->reps[0] = dist;
2237
0
        }
2238
2239
0
        RC_NORM(&p->rc)
2240
2241
0
        p->rc.range = range;
2242
2243
0
        if (len != 1)
2244
0
        {
2245
0
          LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
2246
0
          if (!p->fastMode)
2247
0
            if (--p->repLenEnc.counters[posState] == 0)
2248
0
              LenPriceEnc_UpdateTable(&p->repLenEnc, posState, &p->repLenProbs, p->ProbPrices);
2249
2250
0
          p->state = kRepNextStates[p->state];
2251
0
        }
2252
0
      }
2253
0
      else
2254
0
      {
2255
0
        unsigned posSlot;
2256
0
        RC_BIT_0(&p->rc, probs);
2257
0
        p->rc.range = range;
2258
0
        p->state = kMatchNextStates[p->state];
2259
2260
0
        LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
2261
0
        if (!p->fastMode)
2262
0
          if (--p->lenEnc.counters[posState] == 0)
2263
0
            LenPriceEnc_UpdateTable(&p->lenEnc, posState, &p->lenProbs, p->ProbPrices);
2264
2265
0
        dist -= LZMA_NUM_REPS;
2266
0
        p->reps[3] = p->reps[2];
2267
0
        p->reps[2] = p->reps[1];
2268
0
        p->reps[1] = p->reps[0];
2269
0
        p->reps[0] = dist + 1;
2270
        
2271
0
        p->matchPriceCount++;
2272
0
        GetPosSlot(dist, posSlot);
2273
        // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
2274
0
        {
2275
0
          UInt32 symbol = posSlot + (1 << kNumPosSlotBits);
2276
0
          range = p->rc.range;
2277
0
          probs = p->posSlotEncoder[GetLenToPosState(len)];
2278
0
          do
2279
0
          {
2280
0
            CLzmaProb *prob = probs + (symbol >> kNumPosSlotBits);
2281
0
            UInt32 bit = (symbol >> (kNumPosSlotBits - 1)) & 1;
2282
0
            symbol <<= 1;
2283
0
            RC_BIT(&p->rc, prob, bit);
2284
0
          }
2285
0
          while (symbol < (1 << kNumPosSlotBits * 2));
2286
0
          p->rc.range = range;
2287
0
        }
2288
        
2289
0
        if (dist >= kStartPosModelIndex)
2290
0
        {
2291
0
          unsigned footerBits = ((posSlot >> 1) - 1);
2292
2293
0
          if (dist < kNumFullDistances)
2294
0
          {
2295
0
            unsigned base = ((2 | (posSlot & 1)) << footerBits);
2296
0
            RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, dist - base);
2297
0
          }
2298
0
          else
2299
0
          {
2300
0
            UInt32 pos2 = (dist | 0xF) << (32 - footerBits);
2301
0
            range = p->rc.range;
2302
            // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
2303
            /*
2304
            do
2305
            {
2306
              range >>= 1;
2307
              p->rc.low += range & (0 - ((dist >> --footerBits) & 1));
2308
              RC_NORM(&p->rc)
2309
            }
2310
            while (footerBits > kNumAlignBits);
2311
            */
2312
0
            do
2313
0
            {
2314
0
              range >>= 1;
2315
0
              p->rc.low += range & (0 - (pos2 >> 31));
2316
0
              pos2 += pos2;
2317
0
              RC_NORM(&p->rc)
2318
0
            }
2319
0
            while (pos2 != 0xF0000000);
2320
2321
2322
            // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
2323
2324
0
            {
2325
0
              unsigned m = 1;
2326
0
              unsigned bit;
2327
0
              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
2328
0
              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
2329
0
              bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
2330
0
              bit = dist & 1;             RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
2331
0
              p->rc.range = range;
2332
0
              p->alignPriceCount++;
2333
0
            }
2334
0
          }
2335
0
        }
2336
0
      }
2337
0
    }
2338
2339
0
    nowPos32 += len;
2340
0
    p->additionalOffset -= len;
2341
    
2342
0
    if (p->additionalOffset == 0)
2343
0
    {
2344
0
      UInt32 processed;
2345
2346
0
      if (!p->fastMode)
2347
0
      {
2348
0
        if (p->matchPriceCount >= (1 << 7))
2349
0
          FillDistancesPrices(p);
2350
0
        if (p->alignPriceCount >= kAlignTableSize)
2351
0
          FillAlignPrices(p);
2352
0
      }
2353
    
2354
0
      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
2355
0
        break;
2356
0
      processed = nowPos32 - startPos32;
2357
      
2358
0
      if (maxPackSize)
2359
0
      {
2360
0
        if (processed + kNumOpts + 300 >= maxUnpackSize
2361
0
            || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize)
2362
0
          break;
2363
0
      }
2364
0
      else if (processed >= (1 << 17))
2365
0
      {
2366
0
        p->nowPos64 += nowPos32 - startPos32;
2367
0
        return CheckErrors(p);
2368
0
      }
2369
0
    }
2370
0
  }
2371
2372
0
  p->nowPos64 += nowPos32 - startPos32;
2373
0
  return Flush(p, nowPos32);
2374
0
}
2375
2376
2377
2378
0
#define kBigHashDicLimit ((UInt32)1 << 24)
2379
2380
static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2381
0
{
2382
0
  UInt32 beforeSize = kNumOpts;
2383
0
  if (!RangeEnc_Alloc(&p->rc, alloc))
2384
0
    return SZ_ERROR_MEM;
2385
2386
  #ifndef _7ZIP_ST
2387
  p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0));
2388
  #endif
2389
2390
0
  {
2391
0
    unsigned lclp = p->lc + p->lp;
2392
0
    if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp)
2393
0
    {
2394
0
      LzmaEnc_FreeLits(p, alloc);
2395
0
      p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
2396
0
      p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb));
2397
0
      if (!p->litProbs || !p->saveState.litProbs)
2398
0
      {
2399
0
        LzmaEnc_FreeLits(p, alloc);
2400
0
        return SZ_ERROR_MEM;
2401
0
      }
2402
0
      p->lclp = lclp;
2403
0
    }
2404
0
  }
2405
2406
0
  p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0);
2407
2408
0
  if (beforeSize + p->dictSize < keepWindowSize)
2409
0
    beforeSize = keepWindowSize - p->dictSize;
2410
2411
  #ifndef _7ZIP_ST
2412
  if (p->mtMode)
2413
  {
2414
    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes,
2415
        LZMA_MATCH_LEN_MAX
2416
        + 1  /* 18.04 */
2417
        , allocBig));
2418
    p->matchFinderObj = &p->matchFinderMt;
2419
    p->matchFinderBase.bigHash = (Byte)(
2420
        (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0);
2421
    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
2422
  }
2423
  else
2424
  #endif
2425
0
  {
2426
0
    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
2427
0
      return SZ_ERROR_MEM;
2428
0
    p->matchFinderObj = &p->matchFinderBase;
2429
0
    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
2430
0
  }
2431
  
2432
0
  return SZ_OK;
2433
0
}
2434
2435
void LzmaEnc_Init(CLzmaEnc *p)
2436
0
{
2437
0
  unsigned i;
2438
0
  p->state = 0;
2439
0
  p->reps[0] =
2440
0
  p->reps[1] =
2441
0
  p->reps[2] =
2442
0
  p->reps[3] = 1;
2443
2444
0
  RangeEnc_Init(&p->rc);
2445
2446
0
  for (i = 0; i < (1 << kNumAlignBits); i++)
2447
0
    p->posAlignEncoder[i] = kProbInitValue;
2448
2449
0
  for (i = 0; i < kNumStates; i++)
2450
0
  {
2451
0
    unsigned j;
2452
0
    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
2453
0
    {
2454
0
      p->isMatch[i][j] = kProbInitValue;
2455
0
      p->isRep0Long[i][j] = kProbInitValue;
2456
0
    }
2457
0
    p->isRep[i] = kProbInitValue;
2458
0
    p->isRepG0[i] = kProbInitValue;
2459
0
    p->isRepG1[i] = kProbInitValue;
2460
0
    p->isRepG2[i] = kProbInitValue;
2461
0
  }
2462
2463
0
  {
2464
0
    for (i = 0; i < kNumLenToPosStates; i++)
2465
0
    {
2466
0
      CLzmaProb *probs = p->posSlotEncoder[i];
2467
0
      unsigned j;
2468
0
      for (j = 0; j < (1 << kNumPosSlotBits); j++)
2469
0
        probs[j] = kProbInitValue;
2470
0
    }
2471
0
  }
2472
0
  {
2473
0
    for (i = 0; i < kNumFullDistances; i++)
2474
0
      p->posEncoders[i] = kProbInitValue;
2475
0
  }
2476
2477
0
  {
2478
0
    UInt32 num = (UInt32)0x300 << (p->lp + p->lc);
2479
0
    UInt32 k;
2480
0
    CLzmaProb *probs = p->litProbs;
2481
0
    for (k = 0; k < num; k++)
2482
0
      probs[k] = kProbInitValue;
2483
0
  }
2484
2485
2486
0
  LenEnc_Init(&p->lenProbs);
2487
0
  LenEnc_Init(&p->repLenProbs);
2488
2489
0
  p->optEnd = 0;
2490
0
  p->optCur = 0;
2491
0
  p->additionalOffset = 0;
2492
2493
0
  p->pbMask = (1 << p->pb) - 1;
2494
0
  p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
2495
0
}
2496
2497
void LzmaEnc_InitPrices(CLzmaEnc *p)
2498
0
{
2499
0
  if (!p->fastMode)
2500
0
  {
2501
0
    FillDistancesPrices(p);
2502
0
    FillAlignPrices(p);
2503
0
  }
2504
2505
0
  p->lenEnc.tableSize =
2506
0
  p->repLenEnc.tableSize =
2507
0
      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
2508
0
  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
2509
0
  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
2510
0
}
2511
2512
static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2513
0
{
2514
0
  unsigned i;
2515
0
  for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++)
2516
0
    if (p->dictSize <= ((UInt32)1 << i))
2517
0
      break;
2518
0
  p->distTableSize = i * 2;
2519
2520
0
  p->finished = False;
2521
0
  p->result = SZ_OK;
2522
0
  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
2523
0
  LzmaEnc_Init(p);
2524
0
  LzmaEnc_InitPrices(p);
2525
0
  p->nowPos64 = 0;
2526
0
  return SZ_OK;
2527
0
}
2528
2529
static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
2530
    ISzAllocPtr alloc, ISzAllocPtr allocBig)
2531
0
{
2532
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
2533
0
  p->matchFinderBase.stream = inStream;
2534
0
  p->needInit = 1;
2535
0
  p->rc.outStream = outStream;
2536
0
  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
2537
0
}
2538
2539
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
2540
    ISeqInStream *inStream, UInt32 keepWindowSize,
2541
    ISzAllocPtr alloc, ISzAllocPtr allocBig)
2542
0
{
2543
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
2544
0
  p->matchFinderBase.stream = inStream;
2545
0
  p->needInit = 1;
2546
0
  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2547
0
}
2548
2549
static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
2550
0
{
2551
0
  p->matchFinderBase.directInput = 1;
2552
0
  p->matchFinderBase.bufferBase = (Byte *)src;
2553
0
  p->matchFinderBase.directInputRem = srcLen;
2554
0
}
2555
2556
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
2557
    UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2558
0
{
2559
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
2560
0
  LzmaEnc_SetInputBuf(p, src, srcLen);
2561
0
  p->needInit = 1;
2562
2563
0
  LzmaEnc_SetDataSize(pp, srcLen);
2564
0
  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
2565
0
}
2566
2567
void LzmaEnc_Finish(CLzmaEncHandle pp)
2568
0
{
2569
  #ifndef _7ZIP_ST
2570
  CLzmaEnc *p = (CLzmaEnc *)pp;
2571
  if (p->mtMode)
2572
    MatchFinderMt_ReleaseStream(&p->matchFinderMt);
2573
  #else
2574
0
  UNUSED_VAR(pp);
2575
0
  #endif
2576
0
}
2577
2578
2579
typedef struct
2580
{
2581
  ISeqOutStream vt;
2582
  Byte *data;
2583
  SizeT rem;
2584
  Bool overflow;
2585
} CLzmaEnc_SeqOutStreamBuf;
2586
2587
static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
2588
0
{
2589
0
  CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt);
2590
0
  if (p->rem < size)
2591
0
  {
2592
0
    size = p->rem;
2593
0
    p->overflow = True;
2594
0
  }
2595
0
  memcpy(p->data, data, size);
2596
0
  p->rem -= size;
2597
0
  p->data += size;
2598
0
  return size;
2599
0
}
2600
2601
2602
UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
2603
0
{
2604
0
  const CLzmaEnc *p = (CLzmaEnc *)pp;
2605
0
  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
2606
0
}
2607
2608
2609
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
2610
0
{
2611
0
  const CLzmaEnc *p = (CLzmaEnc *)pp;
2612
0
  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
2613
0
}
2614
2615
2616
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
2617
    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
2618
0
{
2619
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
2620
0
  UInt64 nowPos64;
2621
0
  SRes res;
2622
0
  CLzmaEnc_SeqOutStreamBuf outStream;
2623
2624
0
  outStream.vt.Write = SeqOutStreamBuf_Write;
2625
0
  outStream.data = dest;
2626
0
  outStream.rem = *destLen;
2627
0
  outStream.overflow = False;
2628
2629
0
  p->writeEndMark = False;
2630
0
  p->finished = False;
2631
0
  p->result = SZ_OK;
2632
2633
0
  if (reInit)
2634
0
    LzmaEnc_Init(p);
2635
0
  LzmaEnc_InitPrices(p);
2636
2637
0
  nowPos64 = p->nowPos64;
2638
0
  RangeEnc_Init(&p->rc);
2639
0
  p->rc.outStream = &outStream.vt;
2640
2641
0
  if (desiredPackSize == 0)
2642
0
    return SZ_ERROR_OUTPUT_EOF;
2643
2644
0
  res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize);
2645
  
2646
0
  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
2647
0
  *destLen -= outStream.rem;
2648
0
  if (outStream.overflow)
2649
0
    return SZ_ERROR_OUTPUT_EOF;
2650
2651
0
  return res;
2652
0
}
2653
2654
2655
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
2656
0
{
2657
0
  SRes res = SZ_OK;
2658
2659
  #ifndef _7ZIP_ST
2660
  Byte allocaDummy[0x300];
2661
  allocaDummy[0] = 0;
2662
  allocaDummy[1] = allocaDummy[0];
2663
  #endif
2664
2665
0
  for (;;)
2666
0
  {
2667
0
    res = LzmaEnc_CodeOneBlock(p, 0, 0);
2668
0
    if (res != SZ_OK || p->finished)
2669
0
      break;
2670
0
    if (progress)
2671
0
    {
2672
0
      res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
2673
0
      if (res != SZ_OK)
2674
0
      {
2675
0
        res = SZ_ERROR_PROGRESS;
2676
0
        break;
2677
0
      }
2678
0
    }
2679
0
  }
2680
  
2681
0
  LzmaEnc_Finish(p);
2682
2683
  /*
2684
  if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase))
2685
    res = SZ_ERROR_FAIL;
2686
  }
2687
  */
2688
2689
0
  return res;
2690
0
}
2691
2692
2693
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
2694
    ISzAllocPtr alloc, ISzAllocPtr allocBig)
2695
0
{
2696
0
  RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
2697
0
  return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
2698
0
}
2699
2700
2701
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
2702
0
{
2703
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
2704
0
  unsigned i;
2705
0
  UInt32 dictSize = p->dictSize;
2706
0
  if (*size < LZMA_PROPS_SIZE)
2707
0
    return SZ_ERROR_PARAM;
2708
0
  *size = LZMA_PROPS_SIZE;
2709
0
  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
2710
2711
0
  if (dictSize >= ((UInt32)1 << 22))
2712
0
  {
2713
0
    UInt32 kDictMask = ((UInt32)1 << 20) - 1;
2714
0
    if (dictSize < (UInt32)0xFFFFFFFF - kDictMask)
2715
0
      dictSize = (dictSize + kDictMask) & ~kDictMask;
2716
0
  }
2717
0
  else for (i = 11; i <= 30; i++)
2718
0
  {
2719
0
    if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; }
2720
0
    if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; }
2721
0
  }
2722
2723
0
  for (i = 0; i < 4; i++)
2724
0
    props[1 + i] = (Byte)(dictSize >> (8 * i));
2725
0
  return SZ_OK;
2726
0
}
2727
2728
2729
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp)
2730
0
{
2731
0
  return ((CLzmaEnc *)pp)->writeEndMark;
2732
0
}
2733
2734
2735
SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
2736
    int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2737
0
{
2738
0
  SRes res;
2739
0
  CLzmaEnc *p = (CLzmaEnc *)pp;
2740
2741
0
  CLzmaEnc_SeqOutStreamBuf outStream;
2742
2743
0
  outStream.vt.Write = SeqOutStreamBuf_Write;
2744
0
  outStream.data = dest;
2745
0
  outStream.rem = *destLen;
2746
0
  outStream.overflow = False;
2747
2748
0
  p->writeEndMark = writeEndMark;
2749
0
  p->rc.outStream = &outStream.vt;
2750
2751
0
  res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
2752
  
2753
0
  if (res == SZ_OK)
2754
0
  {
2755
0
    res = LzmaEnc_Encode2(p, progress);
2756
0
    if (res == SZ_OK && p->nowPos64 != srcLen)
2757
0
      res = SZ_ERROR_FAIL;
2758
0
  }
2759
2760
0
  *destLen -= outStream.rem;
2761
0
  if (outStream.overflow)
2762
0
    return SZ_ERROR_OUTPUT_EOF;
2763
0
  return res;
2764
0
}
2765
2766
2767
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
2768
    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
2769
    ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig)
2770
0
{
2771
0
  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
2772
0
  SRes res;
2773
0
  if (!p)
2774
0
    return SZ_ERROR_MEM;
2775
2776
0
  res = LzmaEnc_SetProps(p, props);
2777
0
  if (res == SZ_OK)
2778
0
  {
2779
0
    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
2780
0
    if (res == SZ_OK)
2781
0
      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
2782
0
          writeEndMark, progress, alloc, allocBig);
2783
0
  }
2784
2785
0
  LzmaEnc_Destroy(p, alloc, allocBig);
2786
0
  return res;
2787
0
}