Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

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