10d2711a69397d2971079121df4326d84736c181elgao/** @file
20d2711a69397d2971079121df4326d84736c181elgao  Based on LZMA SDK 4.65:
30d2711a69397d2971079121df4326d84736c181elgao    LzmaEnc.c -- LZMA Encoder
40d2711a69397d2971079121df4326d84736c181elgao    2009-02-02 : Igor Pavlov : Public domain
50d2711a69397d2971079121df4326d84736c181elgao
60d2711a69397d2971079121df4326d84736c181elgao  Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
70d2711a69397d2971079121df4326d84736c181elgao  This program and the accompanying materials
80d2711a69397d2971079121df4326d84736c181elgao  are licensed and made available under the terms and conditions of the BSD License
90d2711a69397d2971079121df4326d84736c181elgao  which accompanies this distribution.  The full text of the license may be found at
100d2711a69397d2971079121df4326d84736c181elgao  http://opensource.org/licenses/bsd-license.php
110d2711a69397d2971079121df4326d84736c181elgao
120d2711a69397d2971079121df4326d84736c181elgao  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
130d2711a69397d2971079121df4326d84736c181elgao  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
140d2711a69397d2971079121df4326d84736c181elgao
150d2711a69397d2971079121df4326d84736c181elgao**/
1630fdf1140b8d1ce93f3821d986fa165552023440lgao
1730fdf1140b8d1ce93f3821d986fa165552023440lgao#include <string.h>
1830fdf1140b8d1ce93f3821d986fa165552023440lgao
1930fdf1140b8d1ce93f3821d986fa165552023440lgao/* #define SHOW_STAT */
2030fdf1140b8d1ce93f3821d986fa165552023440lgao/* #define SHOW_STAT2 */
2130fdf1140b8d1ce93f3821d986fa165552023440lgao
2230fdf1140b8d1ce93f3821d986fa165552023440lgao#if defined(SHOW_STAT) || defined(SHOW_STAT2)
2330fdf1140b8d1ce93f3821d986fa165552023440lgao#include <stdio.h>
2430fdf1140b8d1ce93f3821d986fa165552023440lgao#endif
2530fdf1140b8d1ce93f3821d986fa165552023440lgao
2630fdf1140b8d1ce93f3821d986fa165552023440lgao#include "LzmaEnc.h"
2730fdf1140b8d1ce93f3821d986fa165552023440lgao
2830fdf1140b8d1ce93f3821d986fa165552023440lgao#include "LzFind.h"
2930fdf1140b8d1ce93f3821d986fa165552023440lgao#ifdef COMPRESS_MF_MT
3030fdf1140b8d1ce93f3821d986fa165552023440lgao#include "LzFindMt.h"
3130fdf1140b8d1ce93f3821d986fa165552023440lgao#endif
3230fdf1140b8d1ce93f3821d986fa165552023440lgao
3330fdf1140b8d1ce93f3821d986fa165552023440lgao#ifdef SHOW_STAT
3430fdf1140b8d1ce93f3821d986fa165552023440lgaostatic int ttt = 0;
3530fdf1140b8d1ce93f3821d986fa165552023440lgao#endif
3630fdf1140b8d1ce93f3821d986fa165552023440lgao
3730fdf1140b8d1ce93f3821d986fa165552023440lgao#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
3830fdf1140b8d1ce93f3821d986fa165552023440lgao
3930fdf1140b8d1ce93f3821d986fa165552023440lgao#define kBlockSize (9 << 10)
4030fdf1140b8d1ce93f3821d986fa165552023440lgao#define kUnpackBlockSize (1 << 18)
4130fdf1140b8d1ce93f3821d986fa165552023440lgao#define kMatchArraySize (1 << 21)
4230fdf1140b8d1ce93f3821d986fa165552023440lgao#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
4330fdf1140b8d1ce93f3821d986fa165552023440lgao
4430fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumMaxDirectBits (31)
4530fdf1140b8d1ce93f3821d986fa165552023440lgao
4630fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumTopBits 24
4730fdf1140b8d1ce93f3821d986fa165552023440lgao#define kTopValue ((UInt32)1 << kNumTopBits)
4830fdf1140b8d1ce93f3821d986fa165552023440lgao
4930fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumBitModelTotalBits 11
5030fdf1140b8d1ce93f3821d986fa165552023440lgao#define kBitModelTotal (1 << kNumBitModelTotalBits)
5130fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumMoveBits 5
5230fdf1140b8d1ce93f3821d986fa165552023440lgao#define kProbInitValue (kBitModelTotal >> 1)
5330fdf1140b8d1ce93f3821d986fa165552023440lgao
5430fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumMoveReducingBits 4
5530fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumBitPriceShiftBits 4
5630fdf1140b8d1ce93f3821d986fa165552023440lgao#define kBitPrice (1 << kNumBitPriceShiftBits)
5730fdf1140b8d1ce93f3821d986fa165552023440lgao
5830fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEncProps_Init(CLzmaEncProps *p)
5930fdf1140b8d1ce93f3821d986fa165552023440lgao{
6030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->level = 5;
6130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->dictSize = p->mc = 0;
6230fdf1140b8d1ce93f3821d986fa165552023440lgao  p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
6330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->writeEndMark = 0;
6430fdf1140b8d1ce93f3821d986fa165552023440lgao}
6530fdf1140b8d1ce93f3821d986fa165552023440lgao
6630fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEncProps_Normalize(CLzmaEncProps *p)
6730fdf1140b8d1ce93f3821d986fa165552023440lgao{
6830fdf1140b8d1ce93f3821d986fa165552023440lgao  int level = p->level;
6930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (level < 0) level = 5;
7030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->level = level;
7130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
7230fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->lc < 0) p->lc = 3;
7330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->lp < 0) p->lp = 0;
7430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->pb < 0) p->pb = 2;
7530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
7630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
7730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
7830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->numHashBytes < 0) p->numHashBytes = 4;
7930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->mc == 0)  p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
8030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->numThreads < 0)
8130fdf1140b8d1ce93f3821d986fa165552023440lgao    p->numThreads =
8230fdf1140b8d1ce93f3821d986fa165552023440lgao      #ifdef COMPRESS_MF_MT
8330fdf1140b8d1ce93f3821d986fa165552023440lgao      ((p->btMode && p->algo) ? 2 : 1);
8430fdf1140b8d1ce93f3821d986fa165552023440lgao      #else
8530fdf1140b8d1ce93f3821d986fa165552023440lgao      1;
8630fdf1140b8d1ce93f3821d986fa165552023440lgao      #endif
8730fdf1140b8d1ce93f3821d986fa165552023440lgao}
8830fdf1140b8d1ce93f3821d986fa165552023440lgao
8930fdf1140b8d1ce93f3821d986fa165552023440lgaoUInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
9030fdf1140b8d1ce93f3821d986fa165552023440lgao{
9130fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEncProps props = *props2;
9230fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEncProps_Normalize(&props);
9330fdf1140b8d1ce93f3821d986fa165552023440lgao  return props.dictSize;
9430fdf1140b8d1ce93f3821d986fa165552023440lgao}
9530fdf1140b8d1ce93f3821d986fa165552023440lgao
9630fdf1140b8d1ce93f3821d986fa165552023440lgao/* #define LZMA_LOG_BSR */
9730fdf1140b8d1ce93f3821d986fa165552023440lgao/* Define it for Intel's CPU */
9830fdf1140b8d1ce93f3821d986fa165552023440lgao
9930fdf1140b8d1ce93f3821d986fa165552023440lgao
10030fdf1140b8d1ce93f3821d986fa165552023440lgao#ifdef LZMA_LOG_BSR
10130fdf1140b8d1ce93f3821d986fa165552023440lgao
10230fdf1140b8d1ce93f3821d986fa165552023440lgao#define kDicLogSizeMaxCompress 30
10330fdf1140b8d1ce93f3821d986fa165552023440lgao
10430fdf1140b8d1ce93f3821d986fa165552023440lgao#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
10530fdf1140b8d1ce93f3821d986fa165552023440lgao
10630fdf1140b8d1ce93f3821d986fa165552023440lgaoUInt32 GetPosSlot1(UInt32 pos)
10730fdf1140b8d1ce93f3821d986fa165552023440lgao{
10830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 res;
10930fdf1140b8d1ce93f3821d986fa165552023440lgao  BSR2_RET(pos, res);
11030fdf1140b8d1ce93f3821d986fa165552023440lgao  return res;
11130fdf1140b8d1ce93f3821d986fa165552023440lgao}
11230fdf1140b8d1ce93f3821d986fa165552023440lgao#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
11330fdf1140b8d1ce93f3821d986fa165552023440lgao#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
11430fdf1140b8d1ce93f3821d986fa165552023440lgao
11530fdf1140b8d1ce93f3821d986fa165552023440lgao#else
11630fdf1140b8d1ce93f3821d986fa165552023440lgao
11730fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
11830fdf1140b8d1ce93f3821d986fa165552023440lgao#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
11930fdf1140b8d1ce93f3821d986fa165552023440lgao
12030fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_FastPosInit(Byte *g_FastPos)
12130fdf1140b8d1ce93f3821d986fa165552023440lgao{
12230fdf1140b8d1ce93f3821d986fa165552023440lgao  int c = 2, slotFast;
12330fdf1140b8d1ce93f3821d986fa165552023440lgao  g_FastPos[0] = 0;
12430fdf1140b8d1ce93f3821d986fa165552023440lgao  g_FastPos[1] = 1;
12530fdf1140b8d1ce93f3821d986fa165552023440lgao
12630fdf1140b8d1ce93f3821d986fa165552023440lgao  for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
12730fdf1140b8d1ce93f3821d986fa165552023440lgao  {
12830fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 k = (1 << ((slotFast >> 1) - 1));
12930fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 j;
13030fdf1140b8d1ce93f3821d986fa165552023440lgao    for (j = 0; j < k; j++, c++)
13130fdf1140b8d1ce93f3821d986fa165552023440lgao      g_FastPos[c] = (Byte)slotFast;
13230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
13330fdf1140b8d1ce93f3821d986fa165552023440lgao}
13430fdf1140b8d1ce93f3821d986fa165552023440lgao
13530fdf1140b8d1ce93f3821d986fa165552023440lgao#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
13630fdf1140b8d1ce93f3821d986fa165552023440lgao  (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
13730fdf1140b8d1ce93f3821d986fa165552023440lgao  res = p->g_FastPos[pos >> i] + (i * 2); }
13830fdf1140b8d1ce93f3821d986fa165552023440lgao/*
13930fdf1140b8d1ce93f3821d986fa165552023440lgao#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
14030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->g_FastPos[pos >> 6] + 12 : \
14130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
14230fdf1140b8d1ce93f3821d986fa165552023440lgao*/
14330fdf1140b8d1ce93f3821d986fa165552023440lgao
14430fdf1140b8d1ce93f3821d986fa165552023440lgao#define GetPosSlot1(pos) p->g_FastPos[pos]
14530fdf1140b8d1ce93f3821d986fa165552023440lgao#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
14630fdf1140b8d1ce93f3821d986fa165552023440lgao#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
14730fdf1140b8d1ce93f3821d986fa165552023440lgao
14830fdf1140b8d1ce93f3821d986fa165552023440lgao#endif
14930fdf1140b8d1ce93f3821d986fa165552023440lgao
15030fdf1140b8d1ce93f3821d986fa165552023440lgao
15130fdf1140b8d1ce93f3821d986fa165552023440lgao#define LZMA_NUM_REPS 4
15230fdf1140b8d1ce93f3821d986fa165552023440lgao
15330fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef unsigned CState;
15430fdf1140b8d1ce93f3821d986fa165552023440lgao
15530fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct _COptimal
15630fdf1140b8d1ce93f3821d986fa165552023440lgao{
15730fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 price;
15830fdf1140b8d1ce93f3821d986fa165552023440lgao
15930fdf1140b8d1ce93f3821d986fa165552023440lgao  CState state;
16030fdf1140b8d1ce93f3821d986fa165552023440lgao  int prev1IsChar;
16130fdf1140b8d1ce93f3821d986fa165552023440lgao  int prev2;
16230fdf1140b8d1ce93f3821d986fa165552023440lgao
16330fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 posPrev2;
16430fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 backPrev2;
16530fdf1140b8d1ce93f3821d986fa165552023440lgao
16630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 posPrev;
16730fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 backPrev;
16830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 backs[LZMA_NUM_REPS];
16930fdf1140b8d1ce93f3821d986fa165552023440lgao} COptimal;
17030fdf1140b8d1ce93f3821d986fa165552023440lgao
17130fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumOpts (1 << 12)
17230fdf1140b8d1ce93f3821d986fa165552023440lgao
17330fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumLenToPosStates 4
17430fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumPosSlotBits 6
17530fdf1140b8d1ce93f3821d986fa165552023440lgao#define kDicLogSizeMin 0
17630fdf1140b8d1ce93f3821d986fa165552023440lgao#define kDicLogSizeMax 32
17730fdf1140b8d1ce93f3821d986fa165552023440lgao#define kDistTableSizeMax (kDicLogSizeMax * 2)
17830fdf1140b8d1ce93f3821d986fa165552023440lgao
17930fdf1140b8d1ce93f3821d986fa165552023440lgao
18030fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumAlignBits 4
18130fdf1140b8d1ce93f3821d986fa165552023440lgao#define kAlignTableSize (1 << kNumAlignBits)
18230fdf1140b8d1ce93f3821d986fa165552023440lgao#define kAlignMask (kAlignTableSize - 1)
18330fdf1140b8d1ce93f3821d986fa165552023440lgao
18430fdf1140b8d1ce93f3821d986fa165552023440lgao#define kStartPosModelIndex 4
18530fdf1140b8d1ce93f3821d986fa165552023440lgao#define kEndPosModelIndex 14
18630fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
18730fdf1140b8d1ce93f3821d986fa165552023440lgao
18830fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumFullDistances (1 << (kEndPosModelIndex / 2))
18930fdf1140b8d1ce93f3821d986fa165552023440lgao
19030fdf1140b8d1ce93f3821d986fa165552023440lgao#ifdef _LZMA_PROB32
19130fdf1140b8d1ce93f3821d986fa165552023440lgao#define CLzmaProb UInt32
19230fdf1140b8d1ce93f3821d986fa165552023440lgao#else
19330fdf1140b8d1ce93f3821d986fa165552023440lgao#define CLzmaProb UInt16
19430fdf1140b8d1ce93f3821d986fa165552023440lgao#endif
19530fdf1140b8d1ce93f3821d986fa165552023440lgao
19630fdf1140b8d1ce93f3821d986fa165552023440lgao#define LZMA_PB_MAX 4
19730fdf1140b8d1ce93f3821d986fa165552023440lgao#define LZMA_LC_MAX 8
19830fdf1140b8d1ce93f3821d986fa165552023440lgao#define LZMA_LP_MAX 4
19930fdf1140b8d1ce93f3821d986fa165552023440lgao
20030fdf1140b8d1ce93f3821d986fa165552023440lgao#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
20130fdf1140b8d1ce93f3821d986fa165552023440lgao
20230fdf1140b8d1ce93f3821d986fa165552023440lgao
20330fdf1140b8d1ce93f3821d986fa165552023440lgao#define kLenNumLowBits 3
20430fdf1140b8d1ce93f3821d986fa165552023440lgao#define kLenNumLowSymbols (1 << kLenNumLowBits)
20530fdf1140b8d1ce93f3821d986fa165552023440lgao#define kLenNumMidBits 3
20630fdf1140b8d1ce93f3821d986fa165552023440lgao#define kLenNumMidSymbols (1 << kLenNumMidBits)
20730fdf1140b8d1ce93f3821d986fa165552023440lgao#define kLenNumHighBits 8
20830fdf1140b8d1ce93f3821d986fa165552023440lgao#define kLenNumHighSymbols (1 << kLenNumHighBits)
20930fdf1140b8d1ce93f3821d986fa165552023440lgao
21030fdf1140b8d1ce93f3821d986fa165552023440lgao#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
21130fdf1140b8d1ce93f3821d986fa165552023440lgao
21230fdf1140b8d1ce93f3821d986fa165552023440lgao#define LZMA_MATCH_LEN_MIN 2
21330fdf1140b8d1ce93f3821d986fa165552023440lgao#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
21430fdf1140b8d1ce93f3821d986fa165552023440lgao
21530fdf1140b8d1ce93f3821d986fa165552023440lgao#define kNumStates 12
21630fdf1140b8d1ce93f3821d986fa165552023440lgao
21730fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct
21830fdf1140b8d1ce93f3821d986fa165552023440lgao{
21930fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb choice;
22030fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb choice2;
22130fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
22230fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
22330fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb high[kLenNumHighSymbols];
22430fdf1140b8d1ce93f3821d986fa165552023440lgao} CLenEnc;
22530fdf1140b8d1ce93f3821d986fa165552023440lgao
22630fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct
22730fdf1140b8d1ce93f3821d986fa165552023440lgao{
22830fdf1140b8d1ce93f3821d986fa165552023440lgao  CLenEnc p;
22930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
23030fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 tableSize;
23130fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 counters[LZMA_NUM_PB_STATES_MAX];
23230fdf1140b8d1ce93f3821d986fa165552023440lgao} CLenPriceEnc;
23330fdf1140b8d1ce93f3821d986fa165552023440lgao
23430fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct _CRangeEnc
23530fdf1140b8d1ce93f3821d986fa165552023440lgao{
23630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 range;
23730fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte cache;
23830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt64 low;
23930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt64 cacheSize;
24030fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte *buf;
24130fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte *bufLim;
24230fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte *bufBase;
24330fdf1140b8d1ce93f3821d986fa165552023440lgao  ISeqOutStream *outStream;
24430fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt64 processed;
24530fdf1140b8d1ce93f3821d986fa165552023440lgao  SRes res;
24630fdf1140b8d1ce93f3821d986fa165552023440lgao} CRangeEnc;
24730fdf1140b8d1ce93f3821d986fa165552023440lgao
24830fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct _CSeqInStreamBuf
24930fdf1140b8d1ce93f3821d986fa165552023440lgao{
25030fdf1140b8d1ce93f3821d986fa165552023440lgao  ISeqInStream funcTable;
25130fdf1140b8d1ce93f3821d986fa165552023440lgao  const Byte *data;
25230fdf1140b8d1ce93f3821d986fa165552023440lgao  SizeT rem;
25330fdf1140b8d1ce93f3821d986fa165552023440lgao} CSeqInStreamBuf;
25430fdf1140b8d1ce93f3821d986fa165552023440lgao
25530fdf1140b8d1ce93f3821d986fa165552023440lgaostatic SRes MyRead(void *pp, void *data, size_t *size)
25630fdf1140b8d1ce93f3821d986fa165552023440lgao{
25730fdf1140b8d1ce93f3821d986fa165552023440lgao  size_t curSize = *size;
25830fdf1140b8d1ce93f3821d986fa165552023440lgao  CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
25930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->rem < curSize)
26030fdf1140b8d1ce93f3821d986fa165552023440lgao    curSize = p->rem;
26130fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(data, p->data, curSize);
26230fdf1140b8d1ce93f3821d986fa165552023440lgao  p->rem -= curSize;
26330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->data += curSize;
26430fdf1140b8d1ce93f3821d986fa165552023440lgao  *size = curSize;
26530fdf1140b8d1ce93f3821d986fa165552023440lgao  return SZ_OK;
26630fdf1140b8d1ce93f3821d986fa165552023440lgao}
26730fdf1140b8d1ce93f3821d986fa165552023440lgao
26830fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct
26930fdf1140b8d1ce93f3821d986fa165552023440lgao{
27030fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb *litProbs;
27130fdf1140b8d1ce93f3821d986fa165552023440lgao
27230fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
27330fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRep[kNumStates];
27430fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRepG0[kNumStates];
27530fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRepG1[kNumStates];
27630fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRepG2[kNumStates];
27730fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
27830fdf1140b8d1ce93f3821d986fa165552023440lgao
27930fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
28030fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
28130fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
28230fdf1140b8d1ce93f3821d986fa165552023440lgao
28330fdf1140b8d1ce93f3821d986fa165552023440lgao  CLenPriceEnc lenEnc;
28430fdf1140b8d1ce93f3821d986fa165552023440lgao  CLenPriceEnc repLenEnc;
28530fdf1140b8d1ce93f3821d986fa165552023440lgao
28630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 reps[LZMA_NUM_REPS];
28730fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 state;
28830fdf1140b8d1ce93f3821d986fa165552023440lgao} CSaveState;
28930fdf1140b8d1ce93f3821d986fa165552023440lgao
29030fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct _CLzmaEnc
29130fdf1140b8d1ce93f3821d986fa165552023440lgao{
29230fdf1140b8d1ce93f3821d986fa165552023440lgao  IMatchFinder matchFinder;
29330fdf1140b8d1ce93f3821d986fa165552023440lgao  void *matchFinderObj;
29430fdf1140b8d1ce93f3821d986fa165552023440lgao
29530fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
29630fdf1140b8d1ce93f3821d986fa165552023440lgao  Bool mtMode;
29730fdf1140b8d1ce93f3821d986fa165552023440lgao  CMatchFinderMt matchFinderMt;
29830fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
29930fdf1140b8d1ce93f3821d986fa165552023440lgao
30030fdf1140b8d1ce93f3821d986fa165552023440lgao  CMatchFinder matchFinderBase;
30130fdf1140b8d1ce93f3821d986fa165552023440lgao
30230fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
30330fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte pad[128];
30430fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
30530fdf1140b8d1ce93f3821d986fa165552023440lgao
30630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 optimumEndIndex;
30730fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 optimumCurrentIndex;
30830fdf1140b8d1ce93f3821d986fa165552023440lgao
30930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 longestMatchLength;
31030fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 numPairs;
31130fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 numAvail;
31230fdf1140b8d1ce93f3821d986fa165552023440lgao  COptimal opt[kNumOpts];
31330fdf1140b8d1ce93f3821d986fa165552023440lgao
31430fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifndef LZMA_LOG_BSR
31530fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte g_FastPos[1 << kNumLogBits];
31630fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
31730fdf1140b8d1ce93f3821d986fa165552023440lgao
31830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
31930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
32030fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 numFastBytes;
32130fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 additionalOffset;
32230fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 reps[LZMA_NUM_REPS];
32330fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 state;
32430fdf1140b8d1ce93f3821d986fa165552023440lgao
32530fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
32630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
32730fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 alignPrices[kAlignTableSize];
32830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 alignPriceCount;
32930fdf1140b8d1ce93f3821d986fa165552023440lgao
33030fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 distTableSize;
33130fdf1140b8d1ce93f3821d986fa165552023440lgao
33230fdf1140b8d1ce93f3821d986fa165552023440lgao  unsigned lc, lp, pb;
33330fdf1140b8d1ce93f3821d986fa165552023440lgao  unsigned lpMask, pbMask;
33430fdf1140b8d1ce93f3821d986fa165552023440lgao
33530fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb *litProbs;
33630fdf1140b8d1ce93f3821d986fa165552023440lgao
33730fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
33830fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRep[kNumStates];
33930fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRepG0[kNumStates];
34030fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRepG1[kNumStates];
34130fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRepG2[kNumStates];
34230fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
34330fdf1140b8d1ce93f3821d986fa165552023440lgao
34430fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
34530fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
34630fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaProb posAlignEncoder[1 << kNumAlignBits];
34730fdf1140b8d1ce93f3821d986fa165552023440lgao
34830fdf1140b8d1ce93f3821d986fa165552023440lgao  CLenPriceEnc lenEnc;
34930fdf1140b8d1ce93f3821d986fa165552023440lgao  CLenPriceEnc repLenEnc;
35030fdf1140b8d1ce93f3821d986fa165552023440lgao
35130fdf1140b8d1ce93f3821d986fa165552023440lgao  unsigned lclp;
35230fdf1140b8d1ce93f3821d986fa165552023440lgao
35330fdf1140b8d1ce93f3821d986fa165552023440lgao  Bool fastMode;
35430fdf1140b8d1ce93f3821d986fa165552023440lgao
35530fdf1140b8d1ce93f3821d986fa165552023440lgao  CRangeEnc rc;
35630fdf1140b8d1ce93f3821d986fa165552023440lgao
35730fdf1140b8d1ce93f3821d986fa165552023440lgao  Bool writeEndMark;
35830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt64 nowPos64;
35930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 matchPriceCount;
36030fdf1140b8d1ce93f3821d986fa165552023440lgao  Bool finished;
36130fdf1140b8d1ce93f3821d986fa165552023440lgao  Bool multiThread;
36230fdf1140b8d1ce93f3821d986fa165552023440lgao
36330fdf1140b8d1ce93f3821d986fa165552023440lgao  SRes result;
36430fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 dictSize;
36530fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 matchFinderCycles;
36630fdf1140b8d1ce93f3821d986fa165552023440lgao
36730fdf1140b8d1ce93f3821d986fa165552023440lgao  ISeqInStream *inStream;
36830fdf1140b8d1ce93f3821d986fa165552023440lgao  CSeqInStreamBuf seqBufInStream;
36930fdf1140b8d1ce93f3821d986fa165552023440lgao
37030fdf1140b8d1ce93f3821d986fa165552023440lgao  CSaveState saveState;
37130fdf1140b8d1ce93f3821d986fa165552023440lgao} CLzmaEnc;
37230fdf1140b8d1ce93f3821d986fa165552023440lgao
37330fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_SaveState(CLzmaEncHandle pp)
37430fdf1140b8d1ce93f3821d986fa165552023440lgao{
37530fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
37630fdf1140b8d1ce93f3821d986fa165552023440lgao  CSaveState *dest = &p->saveState;
37730fdf1140b8d1ce93f3821d986fa165552023440lgao  int i;
37830fdf1140b8d1ce93f3821d986fa165552023440lgao  dest->lenEnc = p->lenEnc;
37930fdf1140b8d1ce93f3821d986fa165552023440lgao  dest->repLenEnc = p->repLenEnc;
38030fdf1140b8d1ce93f3821d986fa165552023440lgao  dest->state = p->state;
38130fdf1140b8d1ce93f3821d986fa165552023440lgao
38230fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kNumStates; i++)
38330fdf1140b8d1ce93f3821d986fa165552023440lgao  {
38430fdf1140b8d1ce93f3821d986fa165552023440lgao    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
38530fdf1140b8d1ce93f3821d986fa165552023440lgao    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
38630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
38730fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kNumLenToPosStates; i++)
38830fdf1140b8d1ce93f3821d986fa165552023440lgao    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
38930fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
39030fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
39130fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
39230fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
39330fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
39430fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
39530fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->reps, p->reps, sizeof(p->reps));
39630fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
39730fdf1140b8d1ce93f3821d986fa165552023440lgao}
39830fdf1140b8d1ce93f3821d986fa165552023440lgao
39930fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_RestoreState(CLzmaEncHandle pp)
40030fdf1140b8d1ce93f3821d986fa165552023440lgao{
40130fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *dest = (CLzmaEnc *)pp;
40230fdf1140b8d1ce93f3821d986fa165552023440lgao  const CSaveState *p = &dest->saveState;
40330fdf1140b8d1ce93f3821d986fa165552023440lgao  int i;
40430fdf1140b8d1ce93f3821d986fa165552023440lgao  dest->lenEnc = p->lenEnc;
40530fdf1140b8d1ce93f3821d986fa165552023440lgao  dest->repLenEnc = p->repLenEnc;
40630fdf1140b8d1ce93f3821d986fa165552023440lgao  dest->state = p->state;
40730fdf1140b8d1ce93f3821d986fa165552023440lgao
40830fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kNumStates; i++)
40930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
41030fdf1140b8d1ce93f3821d986fa165552023440lgao    memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
41130fdf1140b8d1ce93f3821d986fa165552023440lgao    memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
41230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
41330fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kNumLenToPosStates; i++)
41430fdf1140b8d1ce93f3821d986fa165552023440lgao    memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
41530fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
41630fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
41730fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
41830fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
41930fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
42030fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
42130fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->reps, p->reps, sizeof(p->reps));
42230fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
42330fdf1140b8d1ce93f3821d986fa165552023440lgao}
42430fdf1140b8d1ce93f3821d986fa165552023440lgao
42530fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
42630fdf1140b8d1ce93f3821d986fa165552023440lgao{
42730fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
42830fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEncProps props = *props2;
42930fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEncProps_Normalize(&props);
43030fdf1140b8d1ce93f3821d986fa165552023440lgao
43130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
43230fdf1140b8d1ce93f3821d986fa165552023440lgao      props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))
43330fdf1140b8d1ce93f3821d986fa165552023440lgao    return SZ_ERROR_PARAM;
43430fdf1140b8d1ce93f3821d986fa165552023440lgao  p->dictSize = props.dictSize;
43530fdf1140b8d1ce93f3821d986fa165552023440lgao  p->matchFinderCycles = props.mc;
43630fdf1140b8d1ce93f3821d986fa165552023440lgao  {
43730fdf1140b8d1ce93f3821d986fa165552023440lgao    unsigned fb = props.fb;
43830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (fb < 5)
43930fdf1140b8d1ce93f3821d986fa165552023440lgao      fb = 5;
44030fdf1140b8d1ce93f3821d986fa165552023440lgao    if (fb > LZMA_MATCH_LEN_MAX)
44130fdf1140b8d1ce93f3821d986fa165552023440lgao      fb = LZMA_MATCH_LEN_MAX;
44230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->numFastBytes = fb;
44330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
44430fdf1140b8d1ce93f3821d986fa165552023440lgao  p->lc = props.lc;
44530fdf1140b8d1ce93f3821d986fa165552023440lgao  p->lp = props.lp;
44630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->pb = props.pb;
44730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->fastMode = (props.algo == 0);
44830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->matchFinderBase.btMode = props.btMode;
44930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
45030fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 numHashBytes = 4;
45130fdf1140b8d1ce93f3821d986fa165552023440lgao    if (props.btMode)
45230fdf1140b8d1ce93f3821d986fa165552023440lgao    {
45330fdf1140b8d1ce93f3821d986fa165552023440lgao      if (props.numHashBytes < 2)
45430fdf1140b8d1ce93f3821d986fa165552023440lgao        numHashBytes = 2;
45530fdf1140b8d1ce93f3821d986fa165552023440lgao      else if (props.numHashBytes < 4)
45630fdf1140b8d1ce93f3821d986fa165552023440lgao        numHashBytes = props.numHashBytes;
45730fdf1140b8d1ce93f3821d986fa165552023440lgao    }
45830fdf1140b8d1ce93f3821d986fa165552023440lgao    p->matchFinderBase.numHashBytes = numHashBytes;
45930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
46030fdf1140b8d1ce93f3821d986fa165552023440lgao
46130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->matchFinderBase.cutValue = props.mc;
46230fdf1140b8d1ce93f3821d986fa165552023440lgao
46330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->writeEndMark = props.writeEndMark;
46430fdf1140b8d1ce93f3821d986fa165552023440lgao
46530fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
46630fdf1140b8d1ce93f3821d986fa165552023440lgao  /*
46730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (newMultiThread != _multiThread)
46830fdf1140b8d1ce93f3821d986fa165552023440lgao  {
46930fdf1140b8d1ce93f3821d986fa165552023440lgao    ReleaseMatchFinder();
47030fdf1140b8d1ce93f3821d986fa165552023440lgao    _multiThread = newMultiThread;
47130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
47230fdf1140b8d1ce93f3821d986fa165552023440lgao  */
47330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->multiThread = (props.numThreads > 1);
47430fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
47530fdf1140b8d1ce93f3821d986fa165552023440lgao
47630fdf1140b8d1ce93f3821d986fa165552023440lgao  return SZ_OK;
47730fdf1140b8d1ce93f3821d986fa165552023440lgao}
47830fdf1140b8d1ce93f3821d986fa165552023440lgao
47930fdf1140b8d1ce93f3821d986fa165552023440lgaostatic const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4,  5,  6,   4, 5};
48030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic const int kMatchNextStates[kNumStates]   = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
48130fdf1140b8d1ce93f3821d986fa165552023440lgaostatic const int kRepNextStates[kNumStates]     = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
48230fdf1140b8d1ce93f3821d986fa165552023440lgaostatic const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
48330fdf1140b8d1ce93f3821d986fa165552023440lgao
48430fdf1140b8d1ce93f3821d986fa165552023440lgao#define IsCharState(s) ((s) < 7)
48530fdf1140b8d1ce93f3821d986fa165552023440lgao
48630fdf1140b8d1ce93f3821d986fa165552023440lgao#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
48730fdf1140b8d1ce93f3821d986fa165552023440lgao
48830fdf1140b8d1ce93f3821d986fa165552023440lgao#define kInfinityPrice (1 << 30)
48930fdf1140b8d1ce93f3821d986fa165552023440lgao
49030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RangeEnc_Construct(CRangeEnc *p)
49130fdf1140b8d1ce93f3821d986fa165552023440lgao{
49230fdf1140b8d1ce93f3821d986fa165552023440lgao  p->outStream = 0;
49330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->bufBase = 0;
49430fdf1140b8d1ce93f3821d986fa165552023440lgao}
49530fdf1140b8d1ce93f3821d986fa165552023440lgao
49630fdf1140b8d1ce93f3821d986fa165552023440lgao#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
49730fdf1140b8d1ce93f3821d986fa165552023440lgao
49830fdf1140b8d1ce93f3821d986fa165552023440lgao#define RC_BUF_SIZE (1 << 16)
49930fdf1140b8d1ce93f3821d986fa165552023440lgaostatic int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
50030fdf1140b8d1ce93f3821d986fa165552023440lgao{
50130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->bufBase == 0)
50230fdf1140b8d1ce93f3821d986fa165552023440lgao  {
50330fdf1140b8d1ce93f3821d986fa165552023440lgao    p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
50430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->bufBase == 0)
50530fdf1140b8d1ce93f3821d986fa165552023440lgao      return 0;
50630fdf1140b8d1ce93f3821d986fa165552023440lgao    p->bufLim = p->bufBase + RC_BUF_SIZE;
50730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
50830fdf1140b8d1ce93f3821d986fa165552023440lgao  return 1;
50930fdf1140b8d1ce93f3821d986fa165552023440lgao}
51030fdf1140b8d1ce93f3821d986fa165552023440lgao
51130fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
51230fdf1140b8d1ce93f3821d986fa165552023440lgao{
51330fdf1140b8d1ce93f3821d986fa165552023440lgao  alloc->Free(alloc, p->bufBase);
51430fdf1140b8d1ce93f3821d986fa165552023440lgao  p->bufBase = 0;
51530fdf1140b8d1ce93f3821d986fa165552023440lgao}
51630fdf1140b8d1ce93f3821d986fa165552023440lgao
51730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RangeEnc_Init(CRangeEnc *p)
51830fdf1140b8d1ce93f3821d986fa165552023440lgao{
51930fdf1140b8d1ce93f3821d986fa165552023440lgao  /* Stream.Init(); */
52030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->low = 0;
52130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->range = 0xFFFFFFFF;
52230fdf1140b8d1ce93f3821d986fa165552023440lgao  p->cacheSize = 1;
52330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->cache = 0;
52430fdf1140b8d1ce93f3821d986fa165552023440lgao
52530fdf1140b8d1ce93f3821d986fa165552023440lgao  p->buf = p->bufBase;
52630fdf1140b8d1ce93f3821d986fa165552023440lgao
52730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->processed = 0;
52830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->res = SZ_OK;
52930fdf1140b8d1ce93f3821d986fa165552023440lgao}
53030fdf1140b8d1ce93f3821d986fa165552023440lgao
53130fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RangeEnc_FlushStream(CRangeEnc *p)
53230fdf1140b8d1ce93f3821d986fa165552023440lgao{
53330fdf1140b8d1ce93f3821d986fa165552023440lgao  size_t num;
53430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->res != SZ_OK)
53530fdf1140b8d1ce93f3821d986fa165552023440lgao    return;
53630fdf1140b8d1ce93f3821d986fa165552023440lgao  num = p->buf - p->bufBase;
53730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (num != p->outStream->Write(p->outStream, p->bufBase, num))
53830fdf1140b8d1ce93f3821d986fa165552023440lgao    p->res = SZ_ERROR_WRITE;
53930fdf1140b8d1ce93f3821d986fa165552023440lgao  p->processed += num;
54030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->buf = p->bufBase;
54130fdf1140b8d1ce93f3821d986fa165552023440lgao}
54230fdf1140b8d1ce93f3821d986fa165552023440lgao
54330fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
54430fdf1140b8d1ce93f3821d986fa165552023440lgao{
54530fdf1140b8d1ce93f3821d986fa165552023440lgao  if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
54630fdf1140b8d1ce93f3821d986fa165552023440lgao  {
54730fdf1140b8d1ce93f3821d986fa165552023440lgao    Byte temp = p->cache;
54830fdf1140b8d1ce93f3821d986fa165552023440lgao    do
54930fdf1140b8d1ce93f3821d986fa165552023440lgao    {
55030fdf1140b8d1ce93f3821d986fa165552023440lgao      Byte *buf = p->buf;
55130fdf1140b8d1ce93f3821d986fa165552023440lgao      *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
55230fdf1140b8d1ce93f3821d986fa165552023440lgao      p->buf = buf;
55330fdf1140b8d1ce93f3821d986fa165552023440lgao      if (buf == p->bufLim)
55430fdf1140b8d1ce93f3821d986fa165552023440lgao        RangeEnc_FlushStream(p);
55530fdf1140b8d1ce93f3821d986fa165552023440lgao      temp = 0xFF;
55630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
55730fdf1140b8d1ce93f3821d986fa165552023440lgao    while (--p->cacheSize != 0);
55830fdf1140b8d1ce93f3821d986fa165552023440lgao    p->cache = (Byte)((UInt32)p->low >> 24);
55930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
56030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->cacheSize++;
56130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->low = (UInt32)p->low << 8;
56230fdf1140b8d1ce93f3821d986fa165552023440lgao}
56330fdf1140b8d1ce93f3821d986fa165552023440lgao
56430fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RangeEnc_FlushData(CRangeEnc *p)
56530fdf1140b8d1ce93f3821d986fa165552023440lgao{
56630fdf1140b8d1ce93f3821d986fa165552023440lgao  int i;
56730fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < 5; i++)
56830fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_ShiftLow(p);
56930fdf1140b8d1ce93f3821d986fa165552023440lgao}
57030fdf1140b8d1ce93f3821d986fa165552023440lgao
57130fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
57230fdf1140b8d1ce93f3821d986fa165552023440lgao{
57330fdf1140b8d1ce93f3821d986fa165552023440lgao  do
57430fdf1140b8d1ce93f3821d986fa165552023440lgao  {
57530fdf1140b8d1ce93f3821d986fa165552023440lgao    p->range >>= 1;
57630fdf1140b8d1ce93f3821d986fa165552023440lgao    p->low += p->range & (0 - ((value >> --numBits) & 1));
57730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->range < kTopValue)
57830fdf1140b8d1ce93f3821d986fa165552023440lgao    {
57930fdf1140b8d1ce93f3821d986fa165552023440lgao      p->range <<= 8;
58030fdf1140b8d1ce93f3821d986fa165552023440lgao      RangeEnc_ShiftLow(p);
58130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
58230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
58330fdf1140b8d1ce93f3821d986fa165552023440lgao  while (numBits != 0);
58430fdf1140b8d1ce93f3821d986fa165552023440lgao}
58530fdf1140b8d1ce93f3821d986fa165552023440lgao
58630fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
58730fdf1140b8d1ce93f3821d986fa165552023440lgao{
58830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 ttt = *prob;
58930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
59030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (symbol == 0)
59130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
59230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->range = newBound;
59330fdf1140b8d1ce93f3821d986fa165552023440lgao    ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
59430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
59530fdf1140b8d1ce93f3821d986fa165552023440lgao  else
59630fdf1140b8d1ce93f3821d986fa165552023440lgao  {
59730fdf1140b8d1ce93f3821d986fa165552023440lgao    p->low += newBound;
59830fdf1140b8d1ce93f3821d986fa165552023440lgao    p->range -= newBound;
59930fdf1140b8d1ce93f3821d986fa165552023440lgao    ttt -= ttt >> kNumMoveBits;
60030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
60130fdf1140b8d1ce93f3821d986fa165552023440lgao  *prob = (CLzmaProb)ttt;
60230fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->range < kTopValue)
60330fdf1140b8d1ce93f3821d986fa165552023440lgao  {
60430fdf1140b8d1ce93f3821d986fa165552023440lgao    p->range <<= 8;
60530fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_ShiftLow(p);
60630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
60730fdf1140b8d1ce93f3821d986fa165552023440lgao}
60830fdf1140b8d1ce93f3821d986fa165552023440lgao
60930fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
61030fdf1140b8d1ce93f3821d986fa165552023440lgao{
61130fdf1140b8d1ce93f3821d986fa165552023440lgao  symbol |= 0x100;
61230fdf1140b8d1ce93f3821d986fa165552023440lgao  do
61330fdf1140b8d1ce93f3821d986fa165552023440lgao  {
61430fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
61530fdf1140b8d1ce93f3821d986fa165552023440lgao    symbol <<= 1;
61630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
61730fdf1140b8d1ce93f3821d986fa165552023440lgao  while (symbol < 0x10000);
61830fdf1140b8d1ce93f3821d986fa165552023440lgao}
61930fdf1140b8d1ce93f3821d986fa165552023440lgao
62030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
62130fdf1140b8d1ce93f3821d986fa165552023440lgao{
62230fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 offs = 0x100;
62330fdf1140b8d1ce93f3821d986fa165552023440lgao  symbol |= 0x100;
62430fdf1140b8d1ce93f3821d986fa165552023440lgao  do
62530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
62630fdf1140b8d1ce93f3821d986fa165552023440lgao    matchByte <<= 1;
62730fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
62830fdf1140b8d1ce93f3821d986fa165552023440lgao    symbol <<= 1;
62930fdf1140b8d1ce93f3821d986fa165552023440lgao    offs &= ~(matchByte ^ symbol);
63030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
63130fdf1140b8d1ce93f3821d986fa165552023440lgao  while (symbol < 0x10000);
63230fdf1140b8d1ce93f3821d986fa165552023440lgao}
63330fdf1140b8d1ce93f3821d986fa165552023440lgao
63430fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
63530fdf1140b8d1ce93f3821d986fa165552023440lgao{
63630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 i;
63730fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
63830fdf1140b8d1ce93f3821d986fa165552023440lgao  {
63930fdf1140b8d1ce93f3821d986fa165552023440lgao    const int kCyclesBits = kNumBitPriceShiftBits;
64030fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 w = i;
64130fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 bitCount = 0;
64230fdf1140b8d1ce93f3821d986fa165552023440lgao    int j;
64330fdf1140b8d1ce93f3821d986fa165552023440lgao    for (j = 0; j < kCyclesBits; j++)
64430fdf1140b8d1ce93f3821d986fa165552023440lgao    {
64530fdf1140b8d1ce93f3821d986fa165552023440lgao      w = w * w;
64630fdf1140b8d1ce93f3821d986fa165552023440lgao      bitCount <<= 1;
64730fdf1140b8d1ce93f3821d986fa165552023440lgao      while (w >= ((UInt32)1 << 16))
64830fdf1140b8d1ce93f3821d986fa165552023440lgao      {
64930fdf1140b8d1ce93f3821d986fa165552023440lgao        w >>= 1;
65030fdf1140b8d1ce93f3821d986fa165552023440lgao        bitCount++;
65130fdf1140b8d1ce93f3821d986fa165552023440lgao      }
65230fdf1140b8d1ce93f3821d986fa165552023440lgao    }
65330fdf1140b8d1ce93f3821d986fa165552023440lgao    ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
65430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
65530fdf1140b8d1ce93f3821d986fa165552023440lgao}
65630fdf1140b8d1ce93f3821d986fa165552023440lgao
65730fdf1140b8d1ce93f3821d986fa165552023440lgao
65830fdf1140b8d1ce93f3821d986fa165552023440lgao#define GET_PRICE(prob, symbol) \
65930fdf1140b8d1ce93f3821d986fa165552023440lgao  p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
66030fdf1140b8d1ce93f3821d986fa165552023440lgao
66130fdf1140b8d1ce93f3821d986fa165552023440lgao#define GET_PRICEa(prob, symbol) \
66230fdf1140b8d1ce93f3821d986fa165552023440lgao  ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
66330fdf1140b8d1ce93f3821d986fa165552023440lgao
66430fdf1140b8d1ce93f3821d986fa165552023440lgao#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
66530fdf1140b8d1ce93f3821d986fa165552023440lgao#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
66630fdf1140b8d1ce93f3821d986fa165552023440lgao
66730fdf1140b8d1ce93f3821d986fa165552023440lgao#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
66830fdf1140b8d1ce93f3821d986fa165552023440lgao#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
66930fdf1140b8d1ce93f3821d986fa165552023440lgao
67030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
67130fdf1140b8d1ce93f3821d986fa165552023440lgao{
67230fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 price = 0;
67330fdf1140b8d1ce93f3821d986fa165552023440lgao  symbol |= 0x100;
67430fdf1140b8d1ce93f3821d986fa165552023440lgao  do
67530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
67630fdf1140b8d1ce93f3821d986fa165552023440lgao    price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
67730fdf1140b8d1ce93f3821d986fa165552023440lgao    symbol <<= 1;
67830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
67930fdf1140b8d1ce93f3821d986fa165552023440lgao  while (symbol < 0x10000);
68030fdf1140b8d1ce93f3821d986fa165552023440lgao  return price;
68130fdf1140b8d1ce93f3821d986fa165552023440lgao}
68230fdf1140b8d1ce93f3821d986fa165552023440lgao
68330fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
68430fdf1140b8d1ce93f3821d986fa165552023440lgao{
68530fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 price = 0;
68630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 offs = 0x100;
68730fdf1140b8d1ce93f3821d986fa165552023440lgao  symbol |= 0x100;
68830fdf1140b8d1ce93f3821d986fa165552023440lgao  do
68930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
69030fdf1140b8d1ce93f3821d986fa165552023440lgao    matchByte <<= 1;
69130fdf1140b8d1ce93f3821d986fa165552023440lgao    price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
69230fdf1140b8d1ce93f3821d986fa165552023440lgao    symbol <<= 1;
69330fdf1140b8d1ce93f3821d986fa165552023440lgao    offs &= ~(matchByte ^ symbol);
69430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
69530fdf1140b8d1ce93f3821d986fa165552023440lgao  while (symbol < 0x10000);
69630fdf1140b8d1ce93f3821d986fa165552023440lgao  return price;
69730fdf1140b8d1ce93f3821d986fa165552023440lgao}
69830fdf1140b8d1ce93f3821d986fa165552023440lgao
69930fdf1140b8d1ce93f3821d986fa165552023440lgao
70030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
70130fdf1140b8d1ce93f3821d986fa165552023440lgao{
70230fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 m = 1;
70330fdf1140b8d1ce93f3821d986fa165552023440lgao  int i;
70430fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = numBitLevels; i != 0;)
70530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
70630fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 bit;
70730fdf1140b8d1ce93f3821d986fa165552023440lgao    i--;
70830fdf1140b8d1ce93f3821d986fa165552023440lgao    bit = (symbol >> i) & 1;
70930fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_EncodeBit(rc, probs + m, bit);
71030fdf1140b8d1ce93f3821d986fa165552023440lgao    m = (m << 1) | bit;
71130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
71230fdf1140b8d1ce93f3821d986fa165552023440lgao}
71330fdf1140b8d1ce93f3821d986fa165552023440lgao
71430fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
71530fdf1140b8d1ce93f3821d986fa165552023440lgao{
71630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 m = 1;
71730fdf1140b8d1ce93f3821d986fa165552023440lgao  int i;
71830fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < numBitLevels; i++)
71930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
72030fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 bit = symbol & 1;
72130fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_EncodeBit(rc, probs + m, bit);
72230fdf1140b8d1ce93f3821d986fa165552023440lgao    m = (m << 1) | bit;
72330fdf1140b8d1ce93f3821d986fa165552023440lgao    symbol >>= 1;
72430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
72530fdf1140b8d1ce93f3821d986fa165552023440lgao}
72630fdf1140b8d1ce93f3821d986fa165552023440lgao
72730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
72830fdf1140b8d1ce93f3821d986fa165552023440lgao{
72930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 price = 0;
73030fdf1140b8d1ce93f3821d986fa165552023440lgao  symbol |= (1 << numBitLevels);
73130fdf1140b8d1ce93f3821d986fa165552023440lgao  while (symbol != 1)
73230fdf1140b8d1ce93f3821d986fa165552023440lgao  {
73330fdf1140b8d1ce93f3821d986fa165552023440lgao    price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
73430fdf1140b8d1ce93f3821d986fa165552023440lgao    symbol >>= 1;
73530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
73630fdf1140b8d1ce93f3821d986fa165552023440lgao  return price;
73730fdf1140b8d1ce93f3821d986fa165552023440lgao}
73830fdf1140b8d1ce93f3821d986fa165552023440lgao
73930fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
74030fdf1140b8d1ce93f3821d986fa165552023440lgao{
74130fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 price = 0;
74230fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 m = 1;
74330fdf1140b8d1ce93f3821d986fa165552023440lgao  int i;
74430fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = numBitLevels; i != 0; i--)
74530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
74630fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 bit = symbol & 1;
74730fdf1140b8d1ce93f3821d986fa165552023440lgao    symbol >>= 1;
74830fdf1140b8d1ce93f3821d986fa165552023440lgao    price += GET_PRICEa(probs[m], bit);
74930fdf1140b8d1ce93f3821d986fa165552023440lgao    m = (m << 1) | bit;
75030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
75130fdf1140b8d1ce93f3821d986fa165552023440lgao  return price;
75230fdf1140b8d1ce93f3821d986fa165552023440lgao}
75330fdf1140b8d1ce93f3821d986fa165552023440lgao
75430fdf1140b8d1ce93f3821d986fa165552023440lgao
75530fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LenEnc_Init(CLenEnc *p)
75630fdf1140b8d1ce93f3821d986fa165552023440lgao{
75730fdf1140b8d1ce93f3821d986fa165552023440lgao  unsigned i;
75830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->choice = p->choice2 = kProbInitValue;
75930fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
76030fdf1140b8d1ce93f3821d986fa165552023440lgao    p->low[i] = kProbInitValue;
76130fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
76230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->mid[i] = kProbInitValue;
76330fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kLenNumHighSymbols; i++)
76430fdf1140b8d1ce93f3821d986fa165552023440lgao    p->high[i] = kProbInitValue;
76530fdf1140b8d1ce93f3821d986fa165552023440lgao}
76630fdf1140b8d1ce93f3821d986fa165552023440lgao
76730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
76830fdf1140b8d1ce93f3821d986fa165552023440lgao{
76930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (symbol < kLenNumLowSymbols)
77030fdf1140b8d1ce93f3821d986fa165552023440lgao  {
77130fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_EncodeBit(rc, &p->choice, 0);
77230fdf1140b8d1ce93f3821d986fa165552023440lgao    RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
77330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
77430fdf1140b8d1ce93f3821d986fa165552023440lgao  else
77530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
77630fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_EncodeBit(rc, &p->choice, 1);
77730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
77830fdf1140b8d1ce93f3821d986fa165552023440lgao    {
77930fdf1140b8d1ce93f3821d986fa165552023440lgao      RangeEnc_EncodeBit(rc, &p->choice2, 0);
78030fdf1140b8d1ce93f3821d986fa165552023440lgao      RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
78130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
78230fdf1140b8d1ce93f3821d986fa165552023440lgao    else
78330fdf1140b8d1ce93f3821d986fa165552023440lgao    {
78430fdf1140b8d1ce93f3821d986fa165552023440lgao      RangeEnc_EncodeBit(rc, &p->choice2, 1);
78530fdf1140b8d1ce93f3821d986fa165552023440lgao      RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
78630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
78730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
78830fdf1140b8d1ce93f3821d986fa165552023440lgao}
78930fdf1140b8d1ce93f3821d986fa165552023440lgao
79030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
79130fdf1140b8d1ce93f3821d986fa165552023440lgao{
79230fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 a0 = GET_PRICE_0a(p->choice);
79330fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 a1 = GET_PRICE_1a(p->choice);
79430fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
79530fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
79630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 i = 0;
79730fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kLenNumLowSymbols; i++)
79830fdf1140b8d1ce93f3821d986fa165552023440lgao  {
79930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (i >= numSymbols)
80030fdf1140b8d1ce93f3821d986fa165552023440lgao      return;
80130fdf1140b8d1ce93f3821d986fa165552023440lgao    prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
80230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
80330fdf1140b8d1ce93f3821d986fa165552023440lgao  for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
80430fdf1140b8d1ce93f3821d986fa165552023440lgao  {
80530fdf1140b8d1ce93f3821d986fa165552023440lgao    if (i >= numSymbols)
80630fdf1140b8d1ce93f3821d986fa165552023440lgao      return;
80730fdf1140b8d1ce93f3821d986fa165552023440lgao    prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
80830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
80930fdf1140b8d1ce93f3821d986fa165552023440lgao  for (; i < numSymbols; i++)
81030fdf1140b8d1ce93f3821d986fa165552023440lgao    prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
81130fdf1140b8d1ce93f3821d986fa165552023440lgao}
81230fdf1140b8d1ce93f3821d986fa165552023440lgao
81330fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
81430fdf1140b8d1ce93f3821d986fa165552023440lgao{
81530fdf1140b8d1ce93f3821d986fa165552023440lgao  LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
81630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->counters[posState] = p->tableSize;
81730fdf1140b8d1ce93f3821d986fa165552023440lgao}
81830fdf1140b8d1ce93f3821d986fa165552023440lgao
81930fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
82030fdf1140b8d1ce93f3821d986fa165552023440lgao{
82130fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 posState;
82230fdf1140b8d1ce93f3821d986fa165552023440lgao  for (posState = 0; posState < numPosStates; posState++)
82330fdf1140b8d1ce93f3821d986fa165552023440lgao    LenPriceEnc_UpdateTable(p, posState, ProbPrices);
82430fdf1140b8d1ce93f3821d986fa165552023440lgao}
82530fdf1140b8d1ce93f3821d986fa165552023440lgao
82630fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
82730fdf1140b8d1ce93f3821d986fa165552023440lgao{
82830fdf1140b8d1ce93f3821d986fa165552023440lgao  LenEnc_Encode(&p->p, rc, symbol, posState);
82930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (updatePrice)
83030fdf1140b8d1ce93f3821d986fa165552023440lgao    if (--p->counters[posState] == 0)
83130fdf1140b8d1ce93f3821d986fa165552023440lgao      LenPriceEnc_UpdateTable(p, posState, ProbPrices);
83230fdf1140b8d1ce93f3821d986fa165552023440lgao}
83330fdf1140b8d1ce93f3821d986fa165552023440lgao
83430fdf1140b8d1ce93f3821d986fa165552023440lgao
83530fdf1140b8d1ce93f3821d986fa165552023440lgao
83630fdf1140b8d1ce93f3821d986fa165552023440lgao
83730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void MovePos(CLzmaEnc *p, UInt32 num)
83830fdf1140b8d1ce93f3821d986fa165552023440lgao{
83930fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef SHOW_STAT
84030fdf1140b8d1ce93f3821d986fa165552023440lgao  ttt += num;
84130fdf1140b8d1ce93f3821d986fa165552023440lgao  printf("\n MovePos %d", num);
84230fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
84330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (num != 0)
84430fdf1140b8d1ce93f3821d986fa165552023440lgao  {
84530fdf1140b8d1ce93f3821d986fa165552023440lgao    p->additionalOffset += num;
84630fdf1140b8d1ce93f3821d986fa165552023440lgao    p->matchFinder.Skip(p->matchFinderObj, num);
84730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
84830fdf1140b8d1ce93f3821d986fa165552023440lgao}
84930fdf1140b8d1ce93f3821d986fa165552023440lgao
85030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
85130fdf1140b8d1ce93f3821d986fa165552023440lgao{
85230fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 lenRes = 0, numPairs;
85330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
85430fdf1140b8d1ce93f3821d986fa165552023440lgao  numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches);
85530fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef SHOW_STAT
85630fdf1140b8d1ce93f3821d986fa165552023440lgao  printf("\n i = %d numPairs = %d    ", ttt, numPairs / 2);
85730fdf1140b8d1ce93f3821d986fa165552023440lgao  ttt++;
85830fdf1140b8d1ce93f3821d986fa165552023440lgao  {
85930fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 i;
86030fdf1140b8d1ce93f3821d986fa165552023440lgao    for (i = 0; i < numPairs; i += 2)
86130fdf1140b8d1ce93f3821d986fa165552023440lgao      printf("%2d %6d   | ", p->matches[i], p->matches[i + 1]);
86230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
86330fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
86430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (numPairs > 0)
86530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
86630fdf1140b8d1ce93f3821d986fa165552023440lgao    lenRes = p->matches[numPairs - 2];
86730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (lenRes == p->numFastBytes)
86830fdf1140b8d1ce93f3821d986fa165552023440lgao    {
86930fdf1140b8d1ce93f3821d986fa165552023440lgao      const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
87030fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 distance = p->matches[numPairs - 1] + 1;
87130fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 numAvail = p->numAvail;
87230fdf1140b8d1ce93f3821d986fa165552023440lgao      if (numAvail > LZMA_MATCH_LEN_MAX)
87330fdf1140b8d1ce93f3821d986fa165552023440lgao        numAvail = LZMA_MATCH_LEN_MAX;
87430fdf1140b8d1ce93f3821d986fa165552023440lgao      {
87530fdf1140b8d1ce93f3821d986fa165552023440lgao        const Byte *pby2 = pby - distance;
87630fdf1140b8d1ce93f3821d986fa165552023440lgao        for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
87730fdf1140b8d1ce93f3821d986fa165552023440lgao      }
87830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
87930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
88030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->additionalOffset++;
88130fdf1140b8d1ce93f3821d986fa165552023440lgao  *numDistancePairsRes = numPairs;
88230fdf1140b8d1ce93f3821d986fa165552023440lgao  return lenRes;
88330fdf1140b8d1ce93f3821d986fa165552023440lgao}
88430fdf1140b8d1ce93f3821d986fa165552023440lgao
88530fdf1140b8d1ce93f3821d986fa165552023440lgao
88630fdf1140b8d1ce93f3821d986fa165552023440lgao#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
88730fdf1140b8d1ce93f3821d986fa165552023440lgao#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
88830fdf1140b8d1ce93f3821d986fa165552023440lgao#define IsShortRep(p) ((p)->backPrev == 0)
88930fdf1140b8d1ce93f3821d986fa165552023440lgao
89030fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
89130fdf1140b8d1ce93f3821d986fa165552023440lgao{
89230fdf1140b8d1ce93f3821d986fa165552023440lgao  return
89330fdf1140b8d1ce93f3821d986fa165552023440lgao    GET_PRICE_0(p->isRepG0[state]) +
89430fdf1140b8d1ce93f3821d986fa165552023440lgao    GET_PRICE_0(p->isRep0Long[state][posState]);
89530fdf1140b8d1ce93f3821d986fa165552023440lgao}
89630fdf1140b8d1ce93f3821d986fa165552023440lgao
89730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
89830fdf1140b8d1ce93f3821d986fa165552023440lgao{
89930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 price;
90030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (repIndex == 0)
90130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
90230fdf1140b8d1ce93f3821d986fa165552023440lgao    price = GET_PRICE_0(p->isRepG0[state]);
90330fdf1140b8d1ce93f3821d986fa165552023440lgao    price += GET_PRICE_1(p->isRep0Long[state][posState]);
90430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
90530fdf1140b8d1ce93f3821d986fa165552023440lgao  else
90630fdf1140b8d1ce93f3821d986fa165552023440lgao  {
90730fdf1140b8d1ce93f3821d986fa165552023440lgao    price = GET_PRICE_1(p->isRepG0[state]);
90830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (repIndex == 1)
90930fdf1140b8d1ce93f3821d986fa165552023440lgao      price += GET_PRICE_0(p->isRepG1[state]);
91030fdf1140b8d1ce93f3821d986fa165552023440lgao    else
91130fdf1140b8d1ce93f3821d986fa165552023440lgao    {
91230fdf1140b8d1ce93f3821d986fa165552023440lgao      price += GET_PRICE_1(p->isRepG1[state]);
91330fdf1140b8d1ce93f3821d986fa165552023440lgao      price += GET_PRICE(p->isRepG2[state], repIndex - 2);
91430fdf1140b8d1ce93f3821d986fa165552023440lgao    }
91530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
91630fdf1140b8d1ce93f3821d986fa165552023440lgao  return price;
91730fdf1140b8d1ce93f3821d986fa165552023440lgao}
91830fdf1140b8d1ce93f3821d986fa165552023440lgao
91930fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
92030fdf1140b8d1ce93f3821d986fa165552023440lgao{
92130fdf1140b8d1ce93f3821d986fa165552023440lgao  return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
92230fdf1140b8d1ce93f3821d986fa165552023440lgao    GetPureRepPrice(p, repIndex, state, posState);
92330fdf1140b8d1ce93f3821d986fa165552023440lgao}
92430fdf1140b8d1ce93f3821d986fa165552023440lgao
92530fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
92630fdf1140b8d1ce93f3821d986fa165552023440lgao{
92730fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 posMem = p->opt[cur].posPrev;
92830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 backMem = p->opt[cur].backPrev;
92930fdf1140b8d1ce93f3821d986fa165552023440lgao  p->optimumEndIndex = cur;
93030fdf1140b8d1ce93f3821d986fa165552023440lgao  do
93130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
93230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->opt[cur].prev1IsChar)
93330fdf1140b8d1ce93f3821d986fa165552023440lgao    {
93430fdf1140b8d1ce93f3821d986fa165552023440lgao      MakeAsChar(&p->opt[posMem])
93530fdf1140b8d1ce93f3821d986fa165552023440lgao      p->opt[posMem].posPrev = posMem - 1;
93630fdf1140b8d1ce93f3821d986fa165552023440lgao      if (p->opt[cur].prev2)
93730fdf1140b8d1ce93f3821d986fa165552023440lgao      {
93830fdf1140b8d1ce93f3821d986fa165552023440lgao        p->opt[posMem - 1].prev1IsChar = False;
93930fdf1140b8d1ce93f3821d986fa165552023440lgao        p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
94030fdf1140b8d1ce93f3821d986fa165552023440lgao        p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
94130fdf1140b8d1ce93f3821d986fa165552023440lgao      }
94230fdf1140b8d1ce93f3821d986fa165552023440lgao    }
94330fdf1140b8d1ce93f3821d986fa165552023440lgao    {
94430fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 posPrev = posMem;
94530fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 backCur = backMem;
94630fdf1140b8d1ce93f3821d986fa165552023440lgao
94730fdf1140b8d1ce93f3821d986fa165552023440lgao      backMem = p->opt[posPrev].backPrev;
94830fdf1140b8d1ce93f3821d986fa165552023440lgao      posMem = p->opt[posPrev].posPrev;
94930fdf1140b8d1ce93f3821d986fa165552023440lgao
95030fdf1140b8d1ce93f3821d986fa165552023440lgao      p->opt[posPrev].backPrev = backCur;
95130fdf1140b8d1ce93f3821d986fa165552023440lgao      p->opt[posPrev].posPrev = cur;
95230fdf1140b8d1ce93f3821d986fa165552023440lgao      cur = posPrev;
95330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
95430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
95530fdf1140b8d1ce93f3821d986fa165552023440lgao  while (cur != 0);
95630fdf1140b8d1ce93f3821d986fa165552023440lgao  *backRes = p->opt[0].backPrev;
95730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->optimumCurrentIndex  = p->opt[0].posPrev;
95830fdf1140b8d1ce93f3821d986fa165552023440lgao  return p->optimumCurrentIndex;
95930fdf1140b8d1ce93f3821d986fa165552023440lgao}
96030fdf1140b8d1ce93f3821d986fa165552023440lgao
96130fdf1140b8d1ce93f3821d986fa165552023440lgao#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
96230fdf1140b8d1ce93f3821d986fa165552023440lgao
96330fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
96430fdf1140b8d1ce93f3821d986fa165552023440lgao{
96530fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 numAvail, mainLen, numPairs, repMaxIndex, i, posState, lenEnd, len, cur;
96630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 matchPrice, repMatchPrice, normalMatchPrice;
96730fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 reps[LZMA_NUM_REPS], repLens[LZMA_NUM_REPS];
96830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 *matches;
96930fdf1140b8d1ce93f3821d986fa165552023440lgao  const Byte *data;
97030fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte curByte, matchByte;
97130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->optimumEndIndex != p->optimumCurrentIndex)
97230fdf1140b8d1ce93f3821d986fa165552023440lgao  {
97330fdf1140b8d1ce93f3821d986fa165552023440lgao    const COptimal *opt = &p->opt[p->optimumCurrentIndex];
97430fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
97530fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = opt->backPrev;
97630fdf1140b8d1ce93f3821d986fa165552023440lgao    p->optimumCurrentIndex = opt->posPrev;
97730fdf1140b8d1ce93f3821d986fa165552023440lgao    return lenRes;
97830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
97930fdf1140b8d1ce93f3821d986fa165552023440lgao  p->optimumCurrentIndex = p->optimumEndIndex = 0;
98030fdf1140b8d1ce93f3821d986fa165552023440lgao
98130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->additionalOffset == 0)
98230fdf1140b8d1ce93f3821d986fa165552023440lgao    mainLen = ReadMatchDistances(p, &numPairs);
98330fdf1140b8d1ce93f3821d986fa165552023440lgao  else
98430fdf1140b8d1ce93f3821d986fa165552023440lgao  {
98530fdf1140b8d1ce93f3821d986fa165552023440lgao    mainLen = p->longestMatchLength;
98630fdf1140b8d1ce93f3821d986fa165552023440lgao    numPairs = p->numPairs;
98730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
98830fdf1140b8d1ce93f3821d986fa165552023440lgao
98930fdf1140b8d1ce93f3821d986fa165552023440lgao  numAvail = p->numAvail;
99030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (numAvail < 2)
99130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
99230fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = (UInt32)(-1);
99330fdf1140b8d1ce93f3821d986fa165552023440lgao    return 1;
99430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
99530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (numAvail > LZMA_MATCH_LEN_MAX)
99630fdf1140b8d1ce93f3821d986fa165552023440lgao    numAvail = LZMA_MATCH_LEN_MAX;
99730fdf1140b8d1ce93f3821d986fa165552023440lgao
99830fdf1140b8d1ce93f3821d986fa165552023440lgao  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
99930fdf1140b8d1ce93f3821d986fa165552023440lgao  repMaxIndex = 0;
100030fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < LZMA_NUM_REPS; i++)
100130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
100230fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 lenTest;
100330fdf1140b8d1ce93f3821d986fa165552023440lgao    const Byte *data2;
100430fdf1140b8d1ce93f3821d986fa165552023440lgao    reps[i] = p->reps[i];
100530fdf1140b8d1ce93f3821d986fa165552023440lgao    data2 = data - (reps[i] + 1);
100630fdf1140b8d1ce93f3821d986fa165552023440lgao    if (data[0] != data2[0] || data[1] != data2[1])
100730fdf1140b8d1ce93f3821d986fa165552023440lgao    {
100830fdf1140b8d1ce93f3821d986fa165552023440lgao      repLens[i] = 0;
100930fdf1140b8d1ce93f3821d986fa165552023440lgao      continue;
101030fdf1140b8d1ce93f3821d986fa165552023440lgao    }
101130fdf1140b8d1ce93f3821d986fa165552023440lgao    for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
101230fdf1140b8d1ce93f3821d986fa165552023440lgao    repLens[i] = lenTest;
101330fdf1140b8d1ce93f3821d986fa165552023440lgao    if (lenTest > repLens[repMaxIndex])
101430fdf1140b8d1ce93f3821d986fa165552023440lgao      repMaxIndex = i;
101530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
101630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (repLens[repMaxIndex] >= p->numFastBytes)
101730fdf1140b8d1ce93f3821d986fa165552023440lgao  {
101830fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 lenRes;
101930fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = repMaxIndex;
102030fdf1140b8d1ce93f3821d986fa165552023440lgao    lenRes = repLens[repMaxIndex];
102130fdf1140b8d1ce93f3821d986fa165552023440lgao    MovePos(p, lenRes - 1);
102230fdf1140b8d1ce93f3821d986fa165552023440lgao    return lenRes;
102330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
102430fdf1140b8d1ce93f3821d986fa165552023440lgao
102530fdf1140b8d1ce93f3821d986fa165552023440lgao  matches = p->matches;
102630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mainLen >= p->numFastBytes)
102730fdf1140b8d1ce93f3821d986fa165552023440lgao  {
102830fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
102930fdf1140b8d1ce93f3821d986fa165552023440lgao    MovePos(p, mainLen - 1);
103030fdf1140b8d1ce93f3821d986fa165552023440lgao    return mainLen;
103130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
103230fdf1140b8d1ce93f3821d986fa165552023440lgao  curByte = *data;
103330fdf1140b8d1ce93f3821d986fa165552023440lgao  matchByte = *(data - (reps[0] + 1));
103430fdf1140b8d1ce93f3821d986fa165552023440lgao
103530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
103630fdf1140b8d1ce93f3821d986fa165552023440lgao  {
103730fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = (UInt32)-1;
103830fdf1140b8d1ce93f3821d986fa165552023440lgao    return 1;
103930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
104030fdf1140b8d1ce93f3821d986fa165552023440lgao
104130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->opt[0].state = (CState)p->state;
104230fdf1140b8d1ce93f3821d986fa165552023440lgao
104330fdf1140b8d1ce93f3821d986fa165552023440lgao  posState = (position & p->pbMask);
104430fdf1140b8d1ce93f3821d986fa165552023440lgao
104530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
104630fdf1140b8d1ce93f3821d986fa165552023440lgao    const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
104730fdf1140b8d1ce93f3821d986fa165552023440lgao    p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
104830fdf1140b8d1ce93f3821d986fa165552023440lgao        (!IsCharState(p->state) ?
104930fdf1140b8d1ce93f3821d986fa165552023440lgao          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
105030fdf1140b8d1ce93f3821d986fa165552023440lgao          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
105130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
105230fdf1140b8d1ce93f3821d986fa165552023440lgao
105330fdf1140b8d1ce93f3821d986fa165552023440lgao  MakeAsChar(&p->opt[1]);
105430fdf1140b8d1ce93f3821d986fa165552023440lgao
105530fdf1140b8d1ce93f3821d986fa165552023440lgao  matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
105630fdf1140b8d1ce93f3821d986fa165552023440lgao  repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
105730fdf1140b8d1ce93f3821d986fa165552023440lgao
105830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (matchByte == curByte)
105930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
106030fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
106130fdf1140b8d1ce93f3821d986fa165552023440lgao    if (shortRepPrice < p->opt[1].price)
106230fdf1140b8d1ce93f3821d986fa165552023440lgao    {
106330fdf1140b8d1ce93f3821d986fa165552023440lgao      p->opt[1].price = shortRepPrice;
106430fdf1140b8d1ce93f3821d986fa165552023440lgao      MakeAsShortRep(&p->opt[1]);
106530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
106630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
106730fdf1140b8d1ce93f3821d986fa165552023440lgao  lenEnd = ((mainLen >= repLens[repMaxIndex]) ? mainLen : repLens[repMaxIndex]);
106830fdf1140b8d1ce93f3821d986fa165552023440lgao
106930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (lenEnd < 2)
107030fdf1140b8d1ce93f3821d986fa165552023440lgao  {
107130fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = p->opt[1].backPrev;
107230fdf1140b8d1ce93f3821d986fa165552023440lgao    return 1;
107330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
107430fdf1140b8d1ce93f3821d986fa165552023440lgao
107530fdf1140b8d1ce93f3821d986fa165552023440lgao  p->opt[1].posPrev = 0;
107630fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < LZMA_NUM_REPS; i++)
107730fdf1140b8d1ce93f3821d986fa165552023440lgao    p->opt[0].backs[i] = reps[i];
107830fdf1140b8d1ce93f3821d986fa165552023440lgao
107930fdf1140b8d1ce93f3821d986fa165552023440lgao  len = lenEnd;
108030fdf1140b8d1ce93f3821d986fa165552023440lgao  do
108130fdf1140b8d1ce93f3821d986fa165552023440lgao    p->opt[len--].price = kInfinityPrice;
108230fdf1140b8d1ce93f3821d986fa165552023440lgao  while (len >= 2);
108330fdf1140b8d1ce93f3821d986fa165552023440lgao
108430fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < LZMA_NUM_REPS; i++)
108530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
108630fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 repLen = repLens[i];
108730fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 price;
108830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (repLen < 2)
108930fdf1140b8d1ce93f3821d986fa165552023440lgao      continue;
109030fdf1140b8d1ce93f3821d986fa165552023440lgao    price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
109130fdf1140b8d1ce93f3821d986fa165552023440lgao    do
109230fdf1140b8d1ce93f3821d986fa165552023440lgao    {
109330fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
109430fdf1140b8d1ce93f3821d986fa165552023440lgao      COptimal *opt = &p->opt[repLen];
109530fdf1140b8d1ce93f3821d986fa165552023440lgao      if (curAndLenPrice < opt->price)
109630fdf1140b8d1ce93f3821d986fa165552023440lgao      {
109730fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->price = curAndLenPrice;
109830fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->posPrev = 0;
109930fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->backPrev = i;
110030fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->prev1IsChar = False;
110130fdf1140b8d1ce93f3821d986fa165552023440lgao      }
110230fdf1140b8d1ce93f3821d986fa165552023440lgao    }
110330fdf1140b8d1ce93f3821d986fa165552023440lgao    while (--repLen >= 2);
110430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
110530fdf1140b8d1ce93f3821d986fa165552023440lgao
110630fdf1140b8d1ce93f3821d986fa165552023440lgao  normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
110730fdf1140b8d1ce93f3821d986fa165552023440lgao
110830fdf1140b8d1ce93f3821d986fa165552023440lgao  len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
110930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (len <= mainLen)
111030fdf1140b8d1ce93f3821d986fa165552023440lgao  {
111130fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 offs = 0;
111230fdf1140b8d1ce93f3821d986fa165552023440lgao    while (len > matches[offs])
111330fdf1140b8d1ce93f3821d986fa165552023440lgao      offs += 2;
111430fdf1140b8d1ce93f3821d986fa165552023440lgao    for (; ; len++)
111530fdf1140b8d1ce93f3821d986fa165552023440lgao    {
111630fdf1140b8d1ce93f3821d986fa165552023440lgao      COptimal *opt;
111730fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 distance = matches[offs + 1];
111830fdf1140b8d1ce93f3821d986fa165552023440lgao
111930fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
112030fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 lenToPosState = GetLenToPosState(len);
112130fdf1140b8d1ce93f3821d986fa165552023440lgao      if (distance < kNumFullDistances)
112230fdf1140b8d1ce93f3821d986fa165552023440lgao        curAndLenPrice += p->distancesPrices[lenToPosState][distance];
112330fdf1140b8d1ce93f3821d986fa165552023440lgao      else
112430fdf1140b8d1ce93f3821d986fa165552023440lgao      {
112530fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 slot;
112630fdf1140b8d1ce93f3821d986fa165552023440lgao        GetPosSlot2(distance, slot);
112730fdf1140b8d1ce93f3821d986fa165552023440lgao        curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
112830fdf1140b8d1ce93f3821d986fa165552023440lgao      }
112930fdf1140b8d1ce93f3821d986fa165552023440lgao      opt = &p->opt[len];
113030fdf1140b8d1ce93f3821d986fa165552023440lgao      if (curAndLenPrice < opt->price)
113130fdf1140b8d1ce93f3821d986fa165552023440lgao      {
113230fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->price = curAndLenPrice;
113330fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->posPrev = 0;
113430fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->backPrev = distance + LZMA_NUM_REPS;
113530fdf1140b8d1ce93f3821d986fa165552023440lgao        opt->prev1IsChar = False;
113630fdf1140b8d1ce93f3821d986fa165552023440lgao      }
113730fdf1140b8d1ce93f3821d986fa165552023440lgao      if (len == matches[offs])
113830fdf1140b8d1ce93f3821d986fa165552023440lgao      {
113930fdf1140b8d1ce93f3821d986fa165552023440lgao        offs += 2;
114030fdf1140b8d1ce93f3821d986fa165552023440lgao        if (offs == numPairs)
114130fdf1140b8d1ce93f3821d986fa165552023440lgao          break;
114230fdf1140b8d1ce93f3821d986fa165552023440lgao      }
114330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
114430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
114530fdf1140b8d1ce93f3821d986fa165552023440lgao
114630fdf1140b8d1ce93f3821d986fa165552023440lgao  cur = 0;
114730fdf1140b8d1ce93f3821d986fa165552023440lgao
114830fdf1140b8d1ce93f3821d986fa165552023440lgao    #ifdef SHOW_STAT2
114930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (position >= 0)
115030fdf1140b8d1ce93f3821d986fa165552023440lgao    {
115130fdf1140b8d1ce93f3821d986fa165552023440lgao      unsigned i;
115230fdf1140b8d1ce93f3821d986fa165552023440lgao      printf("\n pos = %4X", position);
115330fdf1140b8d1ce93f3821d986fa165552023440lgao      for (i = cur; i <= lenEnd; i++)
115430fdf1140b8d1ce93f3821d986fa165552023440lgao      printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
115530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
115630fdf1140b8d1ce93f3821d986fa165552023440lgao    #endif
115730fdf1140b8d1ce93f3821d986fa165552023440lgao
115830fdf1140b8d1ce93f3821d986fa165552023440lgao  for (;;)
115930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
116030fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 numAvailFull, newLen, numPairs, posPrev, state, posState, startLen;
116130fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 curPrice, curAnd1Price, matchPrice, repMatchPrice;
116230fdf1140b8d1ce93f3821d986fa165552023440lgao    Bool nextIsChar;
116330fdf1140b8d1ce93f3821d986fa165552023440lgao    Byte curByte, matchByte;
116430fdf1140b8d1ce93f3821d986fa165552023440lgao    const Byte *data;
116530fdf1140b8d1ce93f3821d986fa165552023440lgao    COptimal *curOpt;
116630fdf1140b8d1ce93f3821d986fa165552023440lgao    COptimal *nextOpt;
116730fdf1140b8d1ce93f3821d986fa165552023440lgao
116830fdf1140b8d1ce93f3821d986fa165552023440lgao    cur++;
116930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (cur == lenEnd)
117030fdf1140b8d1ce93f3821d986fa165552023440lgao      return Backward(p, backRes, cur);
117130fdf1140b8d1ce93f3821d986fa165552023440lgao
117230fdf1140b8d1ce93f3821d986fa165552023440lgao    newLen = ReadMatchDistances(p, &numPairs);
117330fdf1140b8d1ce93f3821d986fa165552023440lgao    if (newLen >= p->numFastBytes)
117430fdf1140b8d1ce93f3821d986fa165552023440lgao    {
117530fdf1140b8d1ce93f3821d986fa165552023440lgao      p->numPairs = numPairs;
117630fdf1140b8d1ce93f3821d986fa165552023440lgao      p->longestMatchLength = newLen;
117730fdf1140b8d1ce93f3821d986fa165552023440lgao      return Backward(p, backRes, cur);
117830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
117930fdf1140b8d1ce93f3821d986fa165552023440lgao    position++;
118030fdf1140b8d1ce93f3821d986fa165552023440lgao    curOpt = &p->opt[cur];
118130fdf1140b8d1ce93f3821d986fa165552023440lgao    posPrev = curOpt->posPrev;
118230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (curOpt->prev1IsChar)
118330fdf1140b8d1ce93f3821d986fa165552023440lgao    {
118430fdf1140b8d1ce93f3821d986fa165552023440lgao      posPrev--;
118530fdf1140b8d1ce93f3821d986fa165552023440lgao      if (curOpt->prev2)
118630fdf1140b8d1ce93f3821d986fa165552023440lgao      {
118730fdf1140b8d1ce93f3821d986fa165552023440lgao        state = p->opt[curOpt->posPrev2].state;
118830fdf1140b8d1ce93f3821d986fa165552023440lgao        if (curOpt->backPrev2 < LZMA_NUM_REPS)
118930fdf1140b8d1ce93f3821d986fa165552023440lgao          state = kRepNextStates[state];
119030fdf1140b8d1ce93f3821d986fa165552023440lgao        else
119130fdf1140b8d1ce93f3821d986fa165552023440lgao          state = kMatchNextStates[state];
119230fdf1140b8d1ce93f3821d986fa165552023440lgao      }
119330fdf1140b8d1ce93f3821d986fa165552023440lgao      else
119430fdf1140b8d1ce93f3821d986fa165552023440lgao        state = p->opt[posPrev].state;
119530fdf1140b8d1ce93f3821d986fa165552023440lgao      state = kLiteralNextStates[state];
119630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
119730fdf1140b8d1ce93f3821d986fa165552023440lgao    else
119830fdf1140b8d1ce93f3821d986fa165552023440lgao      state = p->opt[posPrev].state;
119930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (posPrev == cur - 1)
120030fdf1140b8d1ce93f3821d986fa165552023440lgao    {
120130fdf1140b8d1ce93f3821d986fa165552023440lgao      if (IsShortRep(curOpt))
120230fdf1140b8d1ce93f3821d986fa165552023440lgao        state = kShortRepNextStates[state];
120330fdf1140b8d1ce93f3821d986fa165552023440lgao      else
120430fdf1140b8d1ce93f3821d986fa165552023440lgao        state = kLiteralNextStates[state];
120530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
120630fdf1140b8d1ce93f3821d986fa165552023440lgao    else
120730fdf1140b8d1ce93f3821d986fa165552023440lgao    {
120830fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 pos;
120930fdf1140b8d1ce93f3821d986fa165552023440lgao      const COptimal *prevOpt;
121030fdf1140b8d1ce93f3821d986fa165552023440lgao      if (curOpt->prev1IsChar && curOpt->prev2)
121130fdf1140b8d1ce93f3821d986fa165552023440lgao      {
121230fdf1140b8d1ce93f3821d986fa165552023440lgao        posPrev = curOpt->posPrev2;
121330fdf1140b8d1ce93f3821d986fa165552023440lgao        pos = curOpt->backPrev2;
121430fdf1140b8d1ce93f3821d986fa165552023440lgao        state = kRepNextStates[state];
121530fdf1140b8d1ce93f3821d986fa165552023440lgao      }
121630fdf1140b8d1ce93f3821d986fa165552023440lgao      else
121730fdf1140b8d1ce93f3821d986fa165552023440lgao      {
121830fdf1140b8d1ce93f3821d986fa165552023440lgao        pos = curOpt->backPrev;
121930fdf1140b8d1ce93f3821d986fa165552023440lgao        if (pos < LZMA_NUM_REPS)
122030fdf1140b8d1ce93f3821d986fa165552023440lgao          state = kRepNextStates[state];
122130fdf1140b8d1ce93f3821d986fa165552023440lgao        else
122230fdf1140b8d1ce93f3821d986fa165552023440lgao          state = kMatchNextStates[state];
122330fdf1140b8d1ce93f3821d986fa165552023440lgao      }
122430fdf1140b8d1ce93f3821d986fa165552023440lgao      prevOpt = &p->opt[posPrev];
122530fdf1140b8d1ce93f3821d986fa165552023440lgao      if (pos < LZMA_NUM_REPS)
122630fdf1140b8d1ce93f3821d986fa165552023440lgao      {
122730fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 i;
122830fdf1140b8d1ce93f3821d986fa165552023440lgao        reps[0] = prevOpt->backs[pos];
122930fdf1140b8d1ce93f3821d986fa165552023440lgao        for (i = 1; i <= pos; i++)
123030fdf1140b8d1ce93f3821d986fa165552023440lgao          reps[i] = prevOpt->backs[i - 1];
123130fdf1140b8d1ce93f3821d986fa165552023440lgao        for (; i < LZMA_NUM_REPS; i++)
123230fdf1140b8d1ce93f3821d986fa165552023440lgao          reps[i] = prevOpt->backs[i];
123330fdf1140b8d1ce93f3821d986fa165552023440lgao      }
123430fdf1140b8d1ce93f3821d986fa165552023440lgao      else
123530fdf1140b8d1ce93f3821d986fa165552023440lgao      {
123630fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 i;
123730fdf1140b8d1ce93f3821d986fa165552023440lgao        reps[0] = (pos - LZMA_NUM_REPS);
123830fdf1140b8d1ce93f3821d986fa165552023440lgao        for (i = 1; i < LZMA_NUM_REPS; i++)
123930fdf1140b8d1ce93f3821d986fa165552023440lgao          reps[i] = prevOpt->backs[i - 1];
124030fdf1140b8d1ce93f3821d986fa165552023440lgao      }
124130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
124230fdf1140b8d1ce93f3821d986fa165552023440lgao    curOpt->state = (CState)state;
124330fdf1140b8d1ce93f3821d986fa165552023440lgao
124430fdf1140b8d1ce93f3821d986fa165552023440lgao    curOpt->backs[0] = reps[0];
124530fdf1140b8d1ce93f3821d986fa165552023440lgao    curOpt->backs[1] = reps[1];
124630fdf1140b8d1ce93f3821d986fa165552023440lgao    curOpt->backs[2] = reps[2];
124730fdf1140b8d1ce93f3821d986fa165552023440lgao    curOpt->backs[3] = reps[3];
124830fdf1140b8d1ce93f3821d986fa165552023440lgao
124930fdf1140b8d1ce93f3821d986fa165552023440lgao    curPrice = curOpt->price;
125030fdf1140b8d1ce93f3821d986fa165552023440lgao    nextIsChar = False;
125130fdf1140b8d1ce93f3821d986fa165552023440lgao    data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
125230fdf1140b8d1ce93f3821d986fa165552023440lgao    curByte = *data;
125330fdf1140b8d1ce93f3821d986fa165552023440lgao    matchByte = *(data - (reps[0] + 1));
125430fdf1140b8d1ce93f3821d986fa165552023440lgao
125530fdf1140b8d1ce93f3821d986fa165552023440lgao    posState = (position & p->pbMask);
125630fdf1140b8d1ce93f3821d986fa165552023440lgao
125730fdf1140b8d1ce93f3821d986fa165552023440lgao    curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
125830fdf1140b8d1ce93f3821d986fa165552023440lgao    {
125930fdf1140b8d1ce93f3821d986fa165552023440lgao      const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
126030fdf1140b8d1ce93f3821d986fa165552023440lgao      curAnd1Price +=
126130fdf1140b8d1ce93f3821d986fa165552023440lgao        (!IsCharState(state) ?
126230fdf1140b8d1ce93f3821d986fa165552023440lgao          LitEnc_GetPriceMatched(probs, curByte, matchByte, p->ProbPrices) :
126330fdf1140b8d1ce93f3821d986fa165552023440lgao          LitEnc_GetPrice(probs, curByte, p->ProbPrices));
126430fdf1140b8d1ce93f3821d986fa165552023440lgao    }
126530fdf1140b8d1ce93f3821d986fa165552023440lgao
126630fdf1140b8d1ce93f3821d986fa165552023440lgao    nextOpt = &p->opt[cur + 1];
126730fdf1140b8d1ce93f3821d986fa165552023440lgao
126830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (curAnd1Price < nextOpt->price)
126930fdf1140b8d1ce93f3821d986fa165552023440lgao    {
127030fdf1140b8d1ce93f3821d986fa165552023440lgao      nextOpt->price = curAnd1Price;
127130fdf1140b8d1ce93f3821d986fa165552023440lgao      nextOpt->posPrev = cur;
127230fdf1140b8d1ce93f3821d986fa165552023440lgao      MakeAsChar(nextOpt);
127330fdf1140b8d1ce93f3821d986fa165552023440lgao      nextIsChar = True;
127430fdf1140b8d1ce93f3821d986fa165552023440lgao    }
127530fdf1140b8d1ce93f3821d986fa165552023440lgao
127630fdf1140b8d1ce93f3821d986fa165552023440lgao    matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
127730fdf1140b8d1ce93f3821d986fa165552023440lgao    repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
127830fdf1140b8d1ce93f3821d986fa165552023440lgao
127930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (matchByte == curByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
128030fdf1140b8d1ce93f3821d986fa165552023440lgao    {
128130fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
128230fdf1140b8d1ce93f3821d986fa165552023440lgao      if (shortRepPrice <= nextOpt->price)
128330fdf1140b8d1ce93f3821d986fa165552023440lgao      {
128430fdf1140b8d1ce93f3821d986fa165552023440lgao        nextOpt->price = shortRepPrice;
128530fdf1140b8d1ce93f3821d986fa165552023440lgao        nextOpt->posPrev = cur;
128630fdf1140b8d1ce93f3821d986fa165552023440lgao        MakeAsShortRep(nextOpt);
128730fdf1140b8d1ce93f3821d986fa165552023440lgao        nextIsChar = True;
128830fdf1140b8d1ce93f3821d986fa165552023440lgao      }
128930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
129030fdf1140b8d1ce93f3821d986fa165552023440lgao    numAvailFull = p->numAvail;
129130fdf1140b8d1ce93f3821d986fa165552023440lgao    {
129230fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 temp = kNumOpts - 1 - cur;
129330fdf1140b8d1ce93f3821d986fa165552023440lgao      if (temp < numAvailFull)
129430fdf1140b8d1ce93f3821d986fa165552023440lgao        numAvailFull = temp;
129530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
129630fdf1140b8d1ce93f3821d986fa165552023440lgao
129730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (numAvailFull < 2)
129830fdf1140b8d1ce93f3821d986fa165552023440lgao      continue;
129930fdf1140b8d1ce93f3821d986fa165552023440lgao    numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
130030fdf1140b8d1ce93f3821d986fa165552023440lgao
130130fdf1140b8d1ce93f3821d986fa165552023440lgao    if (!nextIsChar && matchByte != curByte) /* speed optimization */
130230fdf1140b8d1ce93f3821d986fa165552023440lgao    {
130330fdf1140b8d1ce93f3821d986fa165552023440lgao      /* try Literal + rep0 */
130430fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 temp;
130530fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 lenTest2;
130630fdf1140b8d1ce93f3821d986fa165552023440lgao      const Byte *data2 = data - (reps[0] + 1);
130730fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 limit = p->numFastBytes + 1;
130830fdf1140b8d1ce93f3821d986fa165552023440lgao      if (limit > numAvailFull)
130930fdf1140b8d1ce93f3821d986fa165552023440lgao        limit = numAvailFull;
131030fdf1140b8d1ce93f3821d986fa165552023440lgao
131130fdf1140b8d1ce93f3821d986fa165552023440lgao      for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
131230fdf1140b8d1ce93f3821d986fa165552023440lgao      lenTest2 = temp - 1;
131330fdf1140b8d1ce93f3821d986fa165552023440lgao      if (lenTest2 >= 2)
131430fdf1140b8d1ce93f3821d986fa165552023440lgao      {
131530fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 state2 = kLiteralNextStates[state];
131630fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 posStateNext = (position + 1) & p->pbMask;
131730fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 nextRepMatchPrice = curAnd1Price +
131830fdf1140b8d1ce93f3821d986fa165552023440lgao            GET_PRICE_1(p->isMatch[state2][posStateNext]) +
131930fdf1140b8d1ce93f3821d986fa165552023440lgao            GET_PRICE_1(p->isRep[state2]);
132030fdf1140b8d1ce93f3821d986fa165552023440lgao        /* for (; lenTest2 >= 2; lenTest2--) */
132130fdf1140b8d1ce93f3821d986fa165552023440lgao        {
132230fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 curAndLenPrice;
132330fdf1140b8d1ce93f3821d986fa165552023440lgao          COptimal *opt;
132430fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 offset = cur + 1 + lenTest2;
132530fdf1140b8d1ce93f3821d986fa165552023440lgao          while (lenEnd < offset)
132630fdf1140b8d1ce93f3821d986fa165552023440lgao            p->opt[++lenEnd].price = kInfinityPrice;
132730fdf1140b8d1ce93f3821d986fa165552023440lgao          curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
132830fdf1140b8d1ce93f3821d986fa165552023440lgao          opt = &p->opt[offset];
132930fdf1140b8d1ce93f3821d986fa165552023440lgao          if (curAndLenPrice < opt->price)
133030fdf1140b8d1ce93f3821d986fa165552023440lgao          {
133130fdf1140b8d1ce93f3821d986fa165552023440lgao            opt->price = curAndLenPrice;
133230fdf1140b8d1ce93f3821d986fa165552023440lgao            opt->posPrev = cur + 1;
133330fdf1140b8d1ce93f3821d986fa165552023440lgao            opt->backPrev = 0;
133430fdf1140b8d1ce93f3821d986fa165552023440lgao            opt->prev1IsChar = True;
133530fdf1140b8d1ce93f3821d986fa165552023440lgao            opt->prev2 = False;
133630fdf1140b8d1ce93f3821d986fa165552023440lgao          }
133730fdf1140b8d1ce93f3821d986fa165552023440lgao        }
133830fdf1140b8d1ce93f3821d986fa165552023440lgao      }
133930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
134030fdf1140b8d1ce93f3821d986fa165552023440lgao
134130fdf1140b8d1ce93f3821d986fa165552023440lgao    startLen = 2; /* speed optimization */
134230fdf1140b8d1ce93f3821d986fa165552023440lgao    {
134330fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 repIndex;
134430fdf1140b8d1ce93f3821d986fa165552023440lgao    for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
134530fdf1140b8d1ce93f3821d986fa165552023440lgao    {
134630fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 lenTest;
134730fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 lenTestTemp;
134830fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 price;
134930fdf1140b8d1ce93f3821d986fa165552023440lgao      const Byte *data2 = data - (reps[repIndex] + 1);
135030fdf1140b8d1ce93f3821d986fa165552023440lgao      if (data[0] != data2[0] || data[1] != data2[1])
135130fdf1140b8d1ce93f3821d986fa165552023440lgao        continue;
135230fdf1140b8d1ce93f3821d986fa165552023440lgao      for (lenTest = 2; lenTest < numAvail && data[lenTest] == data2[lenTest]; lenTest++);
135330fdf1140b8d1ce93f3821d986fa165552023440lgao      while (lenEnd < cur + lenTest)
135430fdf1140b8d1ce93f3821d986fa165552023440lgao        p->opt[++lenEnd].price = kInfinityPrice;
135530fdf1140b8d1ce93f3821d986fa165552023440lgao      lenTestTemp = lenTest;
135630fdf1140b8d1ce93f3821d986fa165552023440lgao      price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
135730fdf1140b8d1ce93f3821d986fa165552023440lgao      do
135830fdf1140b8d1ce93f3821d986fa165552023440lgao      {
135930fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
136030fdf1140b8d1ce93f3821d986fa165552023440lgao        COptimal *opt = &p->opt[cur + lenTest];
136130fdf1140b8d1ce93f3821d986fa165552023440lgao        if (curAndLenPrice < opt->price)
136230fdf1140b8d1ce93f3821d986fa165552023440lgao        {
136330fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->price = curAndLenPrice;
136430fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->posPrev = cur;
136530fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->backPrev = repIndex;
136630fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->prev1IsChar = False;
136730fdf1140b8d1ce93f3821d986fa165552023440lgao        }
136830fdf1140b8d1ce93f3821d986fa165552023440lgao      }
136930fdf1140b8d1ce93f3821d986fa165552023440lgao      while (--lenTest >= 2);
137030fdf1140b8d1ce93f3821d986fa165552023440lgao      lenTest = lenTestTemp;
137130fdf1140b8d1ce93f3821d986fa165552023440lgao
137230fdf1140b8d1ce93f3821d986fa165552023440lgao      if (repIndex == 0)
137330fdf1140b8d1ce93f3821d986fa165552023440lgao        startLen = lenTest + 1;
137430fdf1140b8d1ce93f3821d986fa165552023440lgao
137530fdf1140b8d1ce93f3821d986fa165552023440lgao      /* if (_maxMode) */
137630fdf1140b8d1ce93f3821d986fa165552023440lgao        {
137730fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 lenTest2 = lenTest + 1;
137830fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 limit = lenTest2 + p->numFastBytes;
137930fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 nextRepMatchPrice;
138030fdf1140b8d1ce93f3821d986fa165552023440lgao          if (limit > numAvailFull)
138130fdf1140b8d1ce93f3821d986fa165552023440lgao            limit = numAvailFull;
138230fdf1140b8d1ce93f3821d986fa165552023440lgao          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
138330fdf1140b8d1ce93f3821d986fa165552023440lgao          lenTest2 -= lenTest + 1;
138430fdf1140b8d1ce93f3821d986fa165552023440lgao          if (lenTest2 >= 2)
138530fdf1140b8d1ce93f3821d986fa165552023440lgao          {
138630fdf1140b8d1ce93f3821d986fa165552023440lgao            UInt32 state2 = kRepNextStates[state];
138730fdf1140b8d1ce93f3821d986fa165552023440lgao            UInt32 posStateNext = (position + lenTest) & p->pbMask;
138830fdf1140b8d1ce93f3821d986fa165552023440lgao            UInt32 curAndLenCharPrice =
138930fdf1140b8d1ce93f3821d986fa165552023440lgao                price + p->repLenEnc.prices[posState][lenTest - 2] +
139030fdf1140b8d1ce93f3821d986fa165552023440lgao                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
139130fdf1140b8d1ce93f3821d986fa165552023440lgao                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
139230fdf1140b8d1ce93f3821d986fa165552023440lgao                    data[lenTest], data2[lenTest], p->ProbPrices);
139330fdf1140b8d1ce93f3821d986fa165552023440lgao            state2 = kLiteralNextStates[state2];
139430fdf1140b8d1ce93f3821d986fa165552023440lgao            posStateNext = (position + lenTest + 1) & p->pbMask;
139530fdf1140b8d1ce93f3821d986fa165552023440lgao            nextRepMatchPrice = curAndLenCharPrice +
139630fdf1140b8d1ce93f3821d986fa165552023440lgao                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
139730fdf1140b8d1ce93f3821d986fa165552023440lgao                GET_PRICE_1(p->isRep[state2]);
139830fdf1140b8d1ce93f3821d986fa165552023440lgao
139930fdf1140b8d1ce93f3821d986fa165552023440lgao            /* for (; lenTest2 >= 2; lenTest2--) */
140030fdf1140b8d1ce93f3821d986fa165552023440lgao            {
140130fdf1140b8d1ce93f3821d986fa165552023440lgao              UInt32 curAndLenPrice;
140230fdf1140b8d1ce93f3821d986fa165552023440lgao              COptimal *opt;
140330fdf1140b8d1ce93f3821d986fa165552023440lgao              UInt32 offset = cur + lenTest + 1 + lenTest2;
140430fdf1140b8d1ce93f3821d986fa165552023440lgao              while (lenEnd < offset)
140530fdf1140b8d1ce93f3821d986fa165552023440lgao                p->opt[++lenEnd].price = kInfinityPrice;
140630fdf1140b8d1ce93f3821d986fa165552023440lgao              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
140730fdf1140b8d1ce93f3821d986fa165552023440lgao              opt = &p->opt[offset];
140830fdf1140b8d1ce93f3821d986fa165552023440lgao              if (curAndLenPrice < opt->price)
140930fdf1140b8d1ce93f3821d986fa165552023440lgao              {
141030fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->price = curAndLenPrice;
141130fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->posPrev = cur + lenTest + 1;
141230fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->backPrev = 0;
141330fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->prev1IsChar = True;
141430fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->prev2 = True;
141530fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->posPrev2 = cur;
141630fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->backPrev2 = repIndex;
141730fdf1140b8d1ce93f3821d986fa165552023440lgao              }
141830fdf1140b8d1ce93f3821d986fa165552023440lgao            }
141930fdf1140b8d1ce93f3821d986fa165552023440lgao          }
142030fdf1140b8d1ce93f3821d986fa165552023440lgao        }
142130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
142230fdf1140b8d1ce93f3821d986fa165552023440lgao    }
142330fdf1140b8d1ce93f3821d986fa165552023440lgao    /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
142430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (newLen > numAvail)
142530fdf1140b8d1ce93f3821d986fa165552023440lgao    {
142630fdf1140b8d1ce93f3821d986fa165552023440lgao      newLen = numAvail;
142730fdf1140b8d1ce93f3821d986fa165552023440lgao      for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
142830fdf1140b8d1ce93f3821d986fa165552023440lgao      matches[numPairs] = newLen;
142930fdf1140b8d1ce93f3821d986fa165552023440lgao      numPairs += 2;
143030fdf1140b8d1ce93f3821d986fa165552023440lgao    }
143130fdf1140b8d1ce93f3821d986fa165552023440lgao    if (newLen >= startLen)
143230fdf1140b8d1ce93f3821d986fa165552023440lgao    {
143330fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
143430fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 offs, curBack, posSlot;
143530fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 lenTest;
143630fdf1140b8d1ce93f3821d986fa165552023440lgao      while (lenEnd < cur + newLen)
143730fdf1140b8d1ce93f3821d986fa165552023440lgao        p->opt[++lenEnd].price = kInfinityPrice;
143830fdf1140b8d1ce93f3821d986fa165552023440lgao
143930fdf1140b8d1ce93f3821d986fa165552023440lgao      offs = 0;
144030fdf1140b8d1ce93f3821d986fa165552023440lgao      while (startLen > matches[offs])
144130fdf1140b8d1ce93f3821d986fa165552023440lgao        offs += 2;
144230fdf1140b8d1ce93f3821d986fa165552023440lgao      curBack = matches[offs + 1];
144330fdf1140b8d1ce93f3821d986fa165552023440lgao      GetPosSlot2(curBack, posSlot);
144430fdf1140b8d1ce93f3821d986fa165552023440lgao      for (lenTest = /*2*/ startLen; ; lenTest++)
144530fdf1140b8d1ce93f3821d986fa165552023440lgao      {
144630fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
144730fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 lenToPosState = GetLenToPosState(lenTest);
144830fdf1140b8d1ce93f3821d986fa165552023440lgao        COptimal *opt;
144930fdf1140b8d1ce93f3821d986fa165552023440lgao        if (curBack < kNumFullDistances)
145030fdf1140b8d1ce93f3821d986fa165552023440lgao          curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
145130fdf1140b8d1ce93f3821d986fa165552023440lgao        else
145230fdf1140b8d1ce93f3821d986fa165552023440lgao          curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
145330fdf1140b8d1ce93f3821d986fa165552023440lgao
145430fdf1140b8d1ce93f3821d986fa165552023440lgao        opt = &p->opt[cur + lenTest];
145530fdf1140b8d1ce93f3821d986fa165552023440lgao        if (curAndLenPrice < opt->price)
145630fdf1140b8d1ce93f3821d986fa165552023440lgao        {
145730fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->price = curAndLenPrice;
145830fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->posPrev = cur;
145930fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->backPrev = curBack + LZMA_NUM_REPS;
146030fdf1140b8d1ce93f3821d986fa165552023440lgao          opt->prev1IsChar = False;
146130fdf1140b8d1ce93f3821d986fa165552023440lgao        }
146230fdf1140b8d1ce93f3821d986fa165552023440lgao
146330fdf1140b8d1ce93f3821d986fa165552023440lgao        if (/*_maxMode && */lenTest == matches[offs])
146430fdf1140b8d1ce93f3821d986fa165552023440lgao        {
146530fdf1140b8d1ce93f3821d986fa165552023440lgao          /* Try Match + Literal + Rep0 */
146630fdf1140b8d1ce93f3821d986fa165552023440lgao          const Byte *data2 = data - (curBack + 1);
146730fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 lenTest2 = lenTest + 1;
146830fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 limit = lenTest2 + p->numFastBytes;
146930fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 nextRepMatchPrice;
147030fdf1140b8d1ce93f3821d986fa165552023440lgao          if (limit > numAvailFull)
147130fdf1140b8d1ce93f3821d986fa165552023440lgao            limit = numAvailFull;
147230fdf1140b8d1ce93f3821d986fa165552023440lgao          for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
147330fdf1140b8d1ce93f3821d986fa165552023440lgao          lenTest2 -= lenTest + 1;
147430fdf1140b8d1ce93f3821d986fa165552023440lgao          if (lenTest2 >= 2)
147530fdf1140b8d1ce93f3821d986fa165552023440lgao          {
147630fdf1140b8d1ce93f3821d986fa165552023440lgao            UInt32 state2 = kMatchNextStates[state];
147730fdf1140b8d1ce93f3821d986fa165552023440lgao            UInt32 posStateNext = (position + lenTest) & p->pbMask;
147830fdf1140b8d1ce93f3821d986fa165552023440lgao            UInt32 curAndLenCharPrice = curAndLenPrice +
147930fdf1140b8d1ce93f3821d986fa165552023440lgao                GET_PRICE_0(p->isMatch[state2][posStateNext]) +
148030fdf1140b8d1ce93f3821d986fa165552023440lgao                LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
148130fdf1140b8d1ce93f3821d986fa165552023440lgao                    data[lenTest], data2[lenTest], p->ProbPrices);
148230fdf1140b8d1ce93f3821d986fa165552023440lgao            state2 = kLiteralNextStates[state2];
148330fdf1140b8d1ce93f3821d986fa165552023440lgao            posStateNext = (posStateNext + 1) & p->pbMask;
148430fdf1140b8d1ce93f3821d986fa165552023440lgao            nextRepMatchPrice = curAndLenCharPrice +
148530fdf1140b8d1ce93f3821d986fa165552023440lgao                GET_PRICE_1(p->isMatch[state2][posStateNext]) +
148630fdf1140b8d1ce93f3821d986fa165552023440lgao                GET_PRICE_1(p->isRep[state2]);
148730fdf1140b8d1ce93f3821d986fa165552023440lgao
148830fdf1140b8d1ce93f3821d986fa165552023440lgao            /* for (; lenTest2 >= 2; lenTest2--) */
148930fdf1140b8d1ce93f3821d986fa165552023440lgao            {
149030fdf1140b8d1ce93f3821d986fa165552023440lgao              UInt32 offset = cur + lenTest + 1 + lenTest2;
149130fdf1140b8d1ce93f3821d986fa165552023440lgao              UInt32 curAndLenPrice;
149230fdf1140b8d1ce93f3821d986fa165552023440lgao              COptimal *opt;
149330fdf1140b8d1ce93f3821d986fa165552023440lgao              while (lenEnd < offset)
149430fdf1140b8d1ce93f3821d986fa165552023440lgao                p->opt[++lenEnd].price = kInfinityPrice;
149530fdf1140b8d1ce93f3821d986fa165552023440lgao              curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
149630fdf1140b8d1ce93f3821d986fa165552023440lgao              opt = &p->opt[offset];
149730fdf1140b8d1ce93f3821d986fa165552023440lgao              if (curAndLenPrice < opt->price)
149830fdf1140b8d1ce93f3821d986fa165552023440lgao              {
149930fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->price = curAndLenPrice;
150030fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->posPrev = cur + lenTest + 1;
150130fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->backPrev = 0;
150230fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->prev1IsChar = True;
150330fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->prev2 = True;
150430fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->posPrev2 = cur;
150530fdf1140b8d1ce93f3821d986fa165552023440lgao                opt->backPrev2 = curBack + LZMA_NUM_REPS;
150630fdf1140b8d1ce93f3821d986fa165552023440lgao              }
150730fdf1140b8d1ce93f3821d986fa165552023440lgao            }
150830fdf1140b8d1ce93f3821d986fa165552023440lgao          }
150930fdf1140b8d1ce93f3821d986fa165552023440lgao          offs += 2;
151030fdf1140b8d1ce93f3821d986fa165552023440lgao          if (offs == numPairs)
151130fdf1140b8d1ce93f3821d986fa165552023440lgao            break;
151230fdf1140b8d1ce93f3821d986fa165552023440lgao          curBack = matches[offs + 1];
151330fdf1140b8d1ce93f3821d986fa165552023440lgao          if (curBack >= kNumFullDistances)
151430fdf1140b8d1ce93f3821d986fa165552023440lgao            GetPosSlot2(curBack, posSlot);
151530fdf1140b8d1ce93f3821d986fa165552023440lgao        }
151630fdf1140b8d1ce93f3821d986fa165552023440lgao      }
151730fdf1140b8d1ce93f3821d986fa165552023440lgao    }
151830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
151930fdf1140b8d1ce93f3821d986fa165552023440lgao}
152030fdf1140b8d1ce93f3821d986fa165552023440lgao
152130fdf1140b8d1ce93f3821d986fa165552023440lgao#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
152230fdf1140b8d1ce93f3821d986fa165552023440lgao
152330fdf1140b8d1ce93f3821d986fa165552023440lgaostatic UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
152430fdf1140b8d1ce93f3821d986fa165552023440lgao{
152530fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 numAvail, mainLen, mainDist, numPairs, repIndex, repLen, i;
152630fdf1140b8d1ce93f3821d986fa165552023440lgao  const Byte *data;
152730fdf1140b8d1ce93f3821d986fa165552023440lgao  const UInt32 *matches;
152830fdf1140b8d1ce93f3821d986fa165552023440lgao
152930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->additionalOffset == 0)
153030fdf1140b8d1ce93f3821d986fa165552023440lgao    mainLen = ReadMatchDistances(p, &numPairs);
153130fdf1140b8d1ce93f3821d986fa165552023440lgao  else
153230fdf1140b8d1ce93f3821d986fa165552023440lgao  {
153330fdf1140b8d1ce93f3821d986fa165552023440lgao    mainLen = p->longestMatchLength;
153430fdf1140b8d1ce93f3821d986fa165552023440lgao    numPairs = p->numPairs;
153530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
153630fdf1140b8d1ce93f3821d986fa165552023440lgao
153730fdf1140b8d1ce93f3821d986fa165552023440lgao  numAvail = p->numAvail;
153830fdf1140b8d1ce93f3821d986fa165552023440lgao  *backRes = (UInt32)-1;
153930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (numAvail < 2)
154030fdf1140b8d1ce93f3821d986fa165552023440lgao    return 1;
154130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (numAvail > LZMA_MATCH_LEN_MAX)
154230fdf1140b8d1ce93f3821d986fa165552023440lgao    numAvail = LZMA_MATCH_LEN_MAX;
154330fdf1140b8d1ce93f3821d986fa165552023440lgao  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
154430fdf1140b8d1ce93f3821d986fa165552023440lgao
154530fdf1140b8d1ce93f3821d986fa165552023440lgao  repLen = repIndex = 0;
154630fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < LZMA_NUM_REPS; i++)
154730fdf1140b8d1ce93f3821d986fa165552023440lgao  {
154830fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 len;
154930fdf1140b8d1ce93f3821d986fa165552023440lgao    const Byte *data2 = data - (p->reps[i] + 1);
155030fdf1140b8d1ce93f3821d986fa165552023440lgao    if (data[0] != data2[0] || data[1] != data2[1])
155130fdf1140b8d1ce93f3821d986fa165552023440lgao      continue;
155230fdf1140b8d1ce93f3821d986fa165552023440lgao    for (len = 2; len < numAvail && data[len] == data2[len]; len++);
155330fdf1140b8d1ce93f3821d986fa165552023440lgao    if (len >= p->numFastBytes)
155430fdf1140b8d1ce93f3821d986fa165552023440lgao    {
155530fdf1140b8d1ce93f3821d986fa165552023440lgao      *backRes = i;
155630fdf1140b8d1ce93f3821d986fa165552023440lgao      MovePos(p, len - 1);
155730fdf1140b8d1ce93f3821d986fa165552023440lgao      return len;
155830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
155930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (len > repLen)
156030fdf1140b8d1ce93f3821d986fa165552023440lgao    {
156130fdf1140b8d1ce93f3821d986fa165552023440lgao      repIndex = i;
156230fdf1140b8d1ce93f3821d986fa165552023440lgao      repLen = len;
156330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
156430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
156530fdf1140b8d1ce93f3821d986fa165552023440lgao
156630fdf1140b8d1ce93f3821d986fa165552023440lgao  matches = p->matches;
156730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mainLen >= p->numFastBytes)
156830fdf1140b8d1ce93f3821d986fa165552023440lgao  {
156930fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = matches[numPairs - 1] + LZMA_NUM_REPS;
157030fdf1140b8d1ce93f3821d986fa165552023440lgao    MovePos(p, mainLen - 1);
157130fdf1140b8d1ce93f3821d986fa165552023440lgao    return mainLen;
157230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
157330fdf1140b8d1ce93f3821d986fa165552023440lgao
157430fdf1140b8d1ce93f3821d986fa165552023440lgao  mainDist = 0; /* for GCC */
157530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mainLen >= 2)
157630fdf1140b8d1ce93f3821d986fa165552023440lgao  {
157730fdf1140b8d1ce93f3821d986fa165552023440lgao    mainDist = matches[numPairs - 1];
157830fdf1140b8d1ce93f3821d986fa165552023440lgao    while (numPairs > 2 && mainLen == matches[numPairs - 4] + 1)
157930fdf1140b8d1ce93f3821d986fa165552023440lgao    {
158030fdf1140b8d1ce93f3821d986fa165552023440lgao      if (!ChangePair(matches[numPairs - 3], mainDist))
158130fdf1140b8d1ce93f3821d986fa165552023440lgao        break;
158230fdf1140b8d1ce93f3821d986fa165552023440lgao      numPairs -= 2;
158330fdf1140b8d1ce93f3821d986fa165552023440lgao      mainLen = matches[numPairs - 2];
158430fdf1140b8d1ce93f3821d986fa165552023440lgao      mainDist = matches[numPairs - 1];
158530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
158630fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mainLen == 2 && mainDist >= 0x80)
158730fdf1140b8d1ce93f3821d986fa165552023440lgao      mainLen = 1;
158830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
158930fdf1140b8d1ce93f3821d986fa165552023440lgao
159030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (repLen >= 2 && (
159130fdf1140b8d1ce93f3821d986fa165552023440lgao        (repLen + 1 >= mainLen) ||
159230fdf1140b8d1ce93f3821d986fa165552023440lgao        (repLen + 2 >= mainLen && mainDist >= (1 << 9)) ||
159330fdf1140b8d1ce93f3821d986fa165552023440lgao        (repLen + 3 >= mainLen && mainDist >= (1 << 15))))
159430fdf1140b8d1ce93f3821d986fa165552023440lgao  {
159530fdf1140b8d1ce93f3821d986fa165552023440lgao    *backRes = repIndex;
159630fdf1140b8d1ce93f3821d986fa165552023440lgao    MovePos(p, repLen - 1);
159730fdf1140b8d1ce93f3821d986fa165552023440lgao    return repLen;
159830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
159930fdf1140b8d1ce93f3821d986fa165552023440lgao
160030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mainLen < 2 || numAvail <= 2)
160130fdf1140b8d1ce93f3821d986fa165552023440lgao    return 1;
160230fdf1140b8d1ce93f3821d986fa165552023440lgao
160330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->longestMatchLength = ReadMatchDistances(p, &p->numPairs);
160430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->longestMatchLength >= 2)
160530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
160630fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 newDistance = matches[p->numPairs - 1];
160730fdf1140b8d1ce93f3821d986fa165552023440lgao    if ((p->longestMatchLength >= mainLen && newDistance < mainDist) ||
160830fdf1140b8d1ce93f3821d986fa165552023440lgao        (p->longestMatchLength == mainLen + 1 && !ChangePair(mainDist, newDistance)) ||
160930fdf1140b8d1ce93f3821d986fa165552023440lgao        (p->longestMatchLength > mainLen + 1) ||
161030fdf1140b8d1ce93f3821d986fa165552023440lgao        (p->longestMatchLength + 1 >= mainLen && mainLen >= 3 && ChangePair(newDistance, mainDist)))
161130fdf1140b8d1ce93f3821d986fa165552023440lgao      return 1;
161230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
161330fdf1140b8d1ce93f3821d986fa165552023440lgao
161430fdf1140b8d1ce93f3821d986fa165552023440lgao  data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
161530fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < LZMA_NUM_REPS; i++)
161630fdf1140b8d1ce93f3821d986fa165552023440lgao  {
161730fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 len, limit;
161830fdf1140b8d1ce93f3821d986fa165552023440lgao    const Byte *data2 = data - (p->reps[i] + 1);
161930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (data[0] != data2[0] || data[1] != data2[1])
162030fdf1140b8d1ce93f3821d986fa165552023440lgao      continue;
162130fdf1140b8d1ce93f3821d986fa165552023440lgao    limit = mainLen - 1;
162230fdf1140b8d1ce93f3821d986fa165552023440lgao    for (len = 2; len < limit && data[len] == data2[len]; len++);
162330fdf1140b8d1ce93f3821d986fa165552023440lgao    if (len >= limit)
162430fdf1140b8d1ce93f3821d986fa165552023440lgao      return 1;
162530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
162630fdf1140b8d1ce93f3821d986fa165552023440lgao  *backRes = mainDist + LZMA_NUM_REPS;
162730fdf1140b8d1ce93f3821d986fa165552023440lgao  MovePos(p, mainLen - 2);
162830fdf1140b8d1ce93f3821d986fa165552023440lgao  return mainLen;
162930fdf1140b8d1ce93f3821d986fa165552023440lgao}
163030fdf1140b8d1ce93f3821d986fa165552023440lgao
163130fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
163230fdf1140b8d1ce93f3821d986fa165552023440lgao{
163330fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 len;
163430fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
163530fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
163630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->state = kMatchNextStates[p->state];
163730fdf1140b8d1ce93f3821d986fa165552023440lgao  len = LZMA_MATCH_LEN_MIN;
163830fdf1140b8d1ce93f3821d986fa165552023440lgao  LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
163930fdf1140b8d1ce93f3821d986fa165552023440lgao  RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
164030fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
164130fdf1140b8d1ce93f3821d986fa165552023440lgao  RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
164230fdf1140b8d1ce93f3821d986fa165552023440lgao}
164330fdf1140b8d1ce93f3821d986fa165552023440lgao
164430fdf1140b8d1ce93f3821d986fa165552023440lgaostatic SRes CheckErrors(CLzmaEnc *p)
164530fdf1140b8d1ce93f3821d986fa165552023440lgao{
164630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->result != SZ_OK)
164730fdf1140b8d1ce93f3821d986fa165552023440lgao    return p->result;
164830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->rc.res != SZ_OK)
164930fdf1140b8d1ce93f3821d986fa165552023440lgao    p->result = SZ_ERROR_WRITE;
165030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->matchFinderBase.result != SZ_OK)
165130fdf1140b8d1ce93f3821d986fa165552023440lgao    p->result = SZ_ERROR_READ;
165230fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->result != SZ_OK)
165330fdf1140b8d1ce93f3821d986fa165552023440lgao    p->finished = True;
165430fdf1140b8d1ce93f3821d986fa165552023440lgao  return p->result;
165530fdf1140b8d1ce93f3821d986fa165552023440lgao}
165630fdf1140b8d1ce93f3821d986fa165552023440lgao
165730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic SRes Flush(CLzmaEnc *p, UInt32 nowPos)
165830fdf1140b8d1ce93f3821d986fa165552023440lgao{
165930fdf1140b8d1ce93f3821d986fa165552023440lgao  /* ReleaseMFStream(); */
166030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->finished = True;
166130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->writeEndMark)
166230fdf1140b8d1ce93f3821d986fa165552023440lgao    WriteEndMarker(p, nowPos & p->pbMask);
166330fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_FlushData(&p->rc);
166430fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_FlushStream(&p->rc);
166530fdf1140b8d1ce93f3821d986fa165552023440lgao  return CheckErrors(p);
166630fdf1140b8d1ce93f3821d986fa165552023440lgao}
166730fdf1140b8d1ce93f3821d986fa165552023440lgao
166830fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void FillAlignPrices(CLzmaEnc *p)
166930fdf1140b8d1ce93f3821d986fa165552023440lgao{
167030fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 i;
167130fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kAlignTableSize; i++)
167230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
167330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->alignPriceCount = 0;
167430fdf1140b8d1ce93f3821d986fa165552023440lgao}
167530fdf1140b8d1ce93f3821d986fa165552023440lgao
167630fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void FillDistancesPrices(CLzmaEnc *p)
167730fdf1140b8d1ce93f3821d986fa165552023440lgao{
167830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 tempPrices[kNumFullDistances];
167930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 i, lenToPosState;
168030fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
168130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
168230fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 posSlot = GetPosSlot1(i);
168330fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 footerBits = ((posSlot >> 1) - 1);
168430fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 base = ((2 | (posSlot & 1)) << footerBits);
168530fdf1140b8d1ce93f3821d986fa165552023440lgao    tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
168630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
168730fdf1140b8d1ce93f3821d986fa165552023440lgao
168830fdf1140b8d1ce93f3821d986fa165552023440lgao  for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
168930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
169030fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 posSlot;
169130fdf1140b8d1ce93f3821d986fa165552023440lgao    const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
169230fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
169330fdf1140b8d1ce93f3821d986fa165552023440lgao    for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
169430fdf1140b8d1ce93f3821d986fa165552023440lgao      posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
169530fdf1140b8d1ce93f3821d986fa165552023440lgao    for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
169630fdf1140b8d1ce93f3821d986fa165552023440lgao      posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
169730fdf1140b8d1ce93f3821d986fa165552023440lgao
169830fdf1140b8d1ce93f3821d986fa165552023440lgao    {
169930fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
170030fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 i;
170130fdf1140b8d1ce93f3821d986fa165552023440lgao      for (i = 0; i < kStartPosModelIndex; i++)
170230fdf1140b8d1ce93f3821d986fa165552023440lgao        distancesPrices[i] = posSlotPrices[i];
170330fdf1140b8d1ce93f3821d986fa165552023440lgao      for (; i < kNumFullDistances; i++)
170430fdf1140b8d1ce93f3821d986fa165552023440lgao        distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
170530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
170630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
170730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->matchPriceCount = 0;
170830fdf1140b8d1ce93f3821d986fa165552023440lgao}
170930fdf1140b8d1ce93f3821d986fa165552023440lgao
171030fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_Construct(CLzmaEnc *p)
171130fdf1140b8d1ce93f3821d986fa165552023440lgao{
171230fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_Construct(&p->rc);
171330fdf1140b8d1ce93f3821d986fa165552023440lgao  MatchFinder_Construct(&p->matchFinderBase);
171430fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
171530fdf1140b8d1ce93f3821d986fa165552023440lgao  MatchFinderMt_Construct(&p->matchFinderMt);
171630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->matchFinderMt.MatchFinder = &p->matchFinderBase;
171730fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
171830fdf1140b8d1ce93f3821d986fa165552023440lgao
171930fdf1140b8d1ce93f3821d986fa165552023440lgao  {
172030fdf1140b8d1ce93f3821d986fa165552023440lgao    CLzmaEncProps props;
172130fdf1140b8d1ce93f3821d986fa165552023440lgao    LzmaEncProps_Init(&props);
172230fdf1140b8d1ce93f3821d986fa165552023440lgao    LzmaEnc_SetProps(p, &props);
172330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
172430fdf1140b8d1ce93f3821d986fa165552023440lgao
172530fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifndef LZMA_LOG_BSR
172630fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_FastPosInit(p->g_FastPos);
172730fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
172830fdf1140b8d1ce93f3821d986fa165552023440lgao
172930fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_InitPriceTables(p->ProbPrices);
173030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->litProbs = 0;
173130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->saveState.litProbs = 0;
173230fdf1140b8d1ce93f3821d986fa165552023440lgao}
173330fdf1140b8d1ce93f3821d986fa165552023440lgao
173430fdf1140b8d1ce93f3821d986fa165552023440lgaoCLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
173530fdf1140b8d1ce93f3821d986fa165552023440lgao{
173630fdf1140b8d1ce93f3821d986fa165552023440lgao  void *p;
173730fdf1140b8d1ce93f3821d986fa165552023440lgao  p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
173830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p != 0)
173930fdf1140b8d1ce93f3821d986fa165552023440lgao    LzmaEnc_Construct((CLzmaEnc *)p);
174030fdf1140b8d1ce93f3821d986fa165552023440lgao  return p;
174130fdf1140b8d1ce93f3821d986fa165552023440lgao}
174230fdf1140b8d1ce93f3821d986fa165552023440lgao
174330fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
174430fdf1140b8d1ce93f3821d986fa165552023440lgao{
174530fdf1140b8d1ce93f3821d986fa165552023440lgao  alloc->Free(alloc, p->litProbs);
174630fdf1140b8d1ce93f3821d986fa165552023440lgao  alloc->Free(alloc, p->saveState.litProbs);
174730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->litProbs = 0;
174830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->saveState.litProbs = 0;
174930fdf1140b8d1ce93f3821d986fa165552023440lgao}
175030fdf1140b8d1ce93f3821d986fa165552023440lgao
175130fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
175230fdf1140b8d1ce93f3821d986fa165552023440lgao{
175330fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
175430fdf1140b8d1ce93f3821d986fa165552023440lgao  MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
175530fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
175630fdf1140b8d1ce93f3821d986fa165552023440lgao  MatchFinder_Free(&p->matchFinderBase, allocBig);
175730fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_FreeLits(p, alloc);
175830fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_Free(&p->rc, alloc);
175930fdf1140b8d1ce93f3821d986fa165552023440lgao}
176030fdf1140b8d1ce93f3821d986fa165552023440lgao
176130fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
176230fdf1140b8d1ce93f3821d986fa165552023440lgao{
176330fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
176430fdf1140b8d1ce93f3821d986fa165552023440lgao  alloc->Free(alloc, p);
176530fdf1140b8d1ce93f3821d986fa165552023440lgao}
176630fdf1140b8d1ce93f3821d986fa165552023440lgao
176730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
176830fdf1140b8d1ce93f3821d986fa165552023440lgao{
176930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 nowPos32, startPos32;
177030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->inStream != 0)
177130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
177230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->matchFinderBase.stream = p->inStream;
177330fdf1140b8d1ce93f3821d986fa165552023440lgao    p->matchFinder.Init(p->matchFinderObj);
177430fdf1140b8d1ce93f3821d986fa165552023440lgao    p->inStream = 0;
177530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
177630fdf1140b8d1ce93f3821d986fa165552023440lgao
177730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->finished)
177830fdf1140b8d1ce93f3821d986fa165552023440lgao    return p->result;
177930fdf1140b8d1ce93f3821d986fa165552023440lgao  RINOK(CheckErrors(p));
178030fdf1140b8d1ce93f3821d986fa165552023440lgao
178130fdf1140b8d1ce93f3821d986fa165552023440lgao  nowPos32 = (UInt32)p->nowPos64;
178230fdf1140b8d1ce93f3821d986fa165552023440lgao  startPos32 = nowPos32;
178330fdf1140b8d1ce93f3821d986fa165552023440lgao
178430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->nowPos64 == 0)
178530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
178630fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 numPairs;
178730fdf1140b8d1ce93f3821d986fa165552023440lgao    Byte curByte;
178830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
178930fdf1140b8d1ce93f3821d986fa165552023440lgao      return Flush(p, nowPos32);
179030fdf1140b8d1ce93f3821d986fa165552023440lgao    ReadMatchDistances(p, &numPairs);
179130fdf1140b8d1ce93f3821d986fa165552023440lgao    RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
179230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->state = kLiteralNextStates[p->state];
179330fdf1140b8d1ce93f3821d986fa165552023440lgao    curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
179430fdf1140b8d1ce93f3821d986fa165552023440lgao    LitEnc_Encode(&p->rc, p->litProbs, curByte);
179530fdf1140b8d1ce93f3821d986fa165552023440lgao    p->additionalOffset--;
179630fdf1140b8d1ce93f3821d986fa165552023440lgao    nowPos32++;
179730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
179830fdf1140b8d1ce93f3821d986fa165552023440lgao
179930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
180030fdf1140b8d1ce93f3821d986fa165552023440lgao  for (;;)
180130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
180230fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 pos, len, posState;
180330fdf1140b8d1ce93f3821d986fa165552023440lgao
180430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->fastMode)
180530fdf1140b8d1ce93f3821d986fa165552023440lgao      len = GetOptimumFast(p, &pos);
180630fdf1140b8d1ce93f3821d986fa165552023440lgao    else
180730fdf1140b8d1ce93f3821d986fa165552023440lgao      len = GetOptimum(p, nowPos32, &pos);
180830fdf1140b8d1ce93f3821d986fa165552023440lgao
180930fdf1140b8d1ce93f3821d986fa165552023440lgao    #ifdef SHOW_STAT2
181030fdf1140b8d1ce93f3821d986fa165552023440lgao    printf("\n pos = %4X,   len = %d   pos = %d", nowPos32, len, pos);
181130fdf1140b8d1ce93f3821d986fa165552023440lgao    #endif
181230fdf1140b8d1ce93f3821d986fa165552023440lgao
181330fdf1140b8d1ce93f3821d986fa165552023440lgao    posState = nowPos32 & p->pbMask;
181430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (len == 1 && pos == (UInt32)-1)
181530fdf1140b8d1ce93f3821d986fa165552023440lgao    {
181630fdf1140b8d1ce93f3821d986fa165552023440lgao      Byte curByte;
181730fdf1140b8d1ce93f3821d986fa165552023440lgao      CLzmaProb *probs;
181830fdf1140b8d1ce93f3821d986fa165552023440lgao      const Byte *data;
181930fdf1140b8d1ce93f3821d986fa165552023440lgao
182030fdf1140b8d1ce93f3821d986fa165552023440lgao      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
182130fdf1140b8d1ce93f3821d986fa165552023440lgao      data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
182230fdf1140b8d1ce93f3821d986fa165552023440lgao      curByte = *data;
182330fdf1140b8d1ce93f3821d986fa165552023440lgao      probs = LIT_PROBS(nowPos32, *(data - 1));
182430fdf1140b8d1ce93f3821d986fa165552023440lgao      if (IsCharState(p->state))
182530fdf1140b8d1ce93f3821d986fa165552023440lgao        LitEnc_Encode(&p->rc, probs, curByte);
182630fdf1140b8d1ce93f3821d986fa165552023440lgao      else
182730fdf1140b8d1ce93f3821d986fa165552023440lgao        LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
182830fdf1140b8d1ce93f3821d986fa165552023440lgao      p->state = kLiteralNextStates[p->state];
182930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
183030fdf1140b8d1ce93f3821d986fa165552023440lgao    else
183130fdf1140b8d1ce93f3821d986fa165552023440lgao    {
183230fdf1140b8d1ce93f3821d986fa165552023440lgao      RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
183330fdf1140b8d1ce93f3821d986fa165552023440lgao      if (pos < LZMA_NUM_REPS)
183430fdf1140b8d1ce93f3821d986fa165552023440lgao      {
183530fdf1140b8d1ce93f3821d986fa165552023440lgao        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
183630fdf1140b8d1ce93f3821d986fa165552023440lgao        if (pos == 0)
183730fdf1140b8d1ce93f3821d986fa165552023440lgao        {
183830fdf1140b8d1ce93f3821d986fa165552023440lgao          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
183930fdf1140b8d1ce93f3821d986fa165552023440lgao          RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
184030fdf1140b8d1ce93f3821d986fa165552023440lgao        }
184130fdf1140b8d1ce93f3821d986fa165552023440lgao        else
184230fdf1140b8d1ce93f3821d986fa165552023440lgao        {
184330fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 distance = p->reps[pos];
184430fdf1140b8d1ce93f3821d986fa165552023440lgao          RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
184530fdf1140b8d1ce93f3821d986fa165552023440lgao          if (pos == 1)
184630fdf1140b8d1ce93f3821d986fa165552023440lgao            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
184730fdf1140b8d1ce93f3821d986fa165552023440lgao          else
184830fdf1140b8d1ce93f3821d986fa165552023440lgao          {
184930fdf1140b8d1ce93f3821d986fa165552023440lgao            RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
185030fdf1140b8d1ce93f3821d986fa165552023440lgao            RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
185130fdf1140b8d1ce93f3821d986fa165552023440lgao            if (pos == 3)
185230fdf1140b8d1ce93f3821d986fa165552023440lgao              p->reps[3] = p->reps[2];
185330fdf1140b8d1ce93f3821d986fa165552023440lgao            p->reps[2] = p->reps[1];
185430fdf1140b8d1ce93f3821d986fa165552023440lgao          }
185530fdf1140b8d1ce93f3821d986fa165552023440lgao          p->reps[1] = p->reps[0];
185630fdf1140b8d1ce93f3821d986fa165552023440lgao          p->reps[0] = distance;
185730fdf1140b8d1ce93f3821d986fa165552023440lgao        }
185830fdf1140b8d1ce93f3821d986fa165552023440lgao        if (len == 1)
185930fdf1140b8d1ce93f3821d986fa165552023440lgao          p->state = kShortRepNextStates[p->state];
186030fdf1140b8d1ce93f3821d986fa165552023440lgao        else
186130fdf1140b8d1ce93f3821d986fa165552023440lgao        {
186230fdf1140b8d1ce93f3821d986fa165552023440lgao          LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
186330fdf1140b8d1ce93f3821d986fa165552023440lgao          p->state = kRepNextStates[p->state];
186430fdf1140b8d1ce93f3821d986fa165552023440lgao        }
186530fdf1140b8d1ce93f3821d986fa165552023440lgao      }
186630fdf1140b8d1ce93f3821d986fa165552023440lgao      else
186730fdf1140b8d1ce93f3821d986fa165552023440lgao      {
186830fdf1140b8d1ce93f3821d986fa165552023440lgao        UInt32 posSlot;
186930fdf1140b8d1ce93f3821d986fa165552023440lgao        RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
187030fdf1140b8d1ce93f3821d986fa165552023440lgao        p->state = kMatchNextStates[p->state];
187130fdf1140b8d1ce93f3821d986fa165552023440lgao        LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
187230fdf1140b8d1ce93f3821d986fa165552023440lgao        pos -= LZMA_NUM_REPS;
187330fdf1140b8d1ce93f3821d986fa165552023440lgao        GetPosSlot(pos, posSlot);
187430fdf1140b8d1ce93f3821d986fa165552023440lgao        RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
187530fdf1140b8d1ce93f3821d986fa165552023440lgao
187630fdf1140b8d1ce93f3821d986fa165552023440lgao        if (posSlot >= kStartPosModelIndex)
187730fdf1140b8d1ce93f3821d986fa165552023440lgao        {
187830fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 footerBits = ((posSlot >> 1) - 1);
187930fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 base = ((2 | (posSlot & 1)) << footerBits);
188030fdf1140b8d1ce93f3821d986fa165552023440lgao          UInt32 posReduced = pos - base;
188130fdf1140b8d1ce93f3821d986fa165552023440lgao
188230fdf1140b8d1ce93f3821d986fa165552023440lgao          if (posSlot < kEndPosModelIndex)
188330fdf1140b8d1ce93f3821d986fa165552023440lgao            RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
188430fdf1140b8d1ce93f3821d986fa165552023440lgao          else
188530fdf1140b8d1ce93f3821d986fa165552023440lgao          {
188630fdf1140b8d1ce93f3821d986fa165552023440lgao            RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
188730fdf1140b8d1ce93f3821d986fa165552023440lgao            RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
188830fdf1140b8d1ce93f3821d986fa165552023440lgao            p->alignPriceCount++;
188930fdf1140b8d1ce93f3821d986fa165552023440lgao          }
189030fdf1140b8d1ce93f3821d986fa165552023440lgao        }
189130fdf1140b8d1ce93f3821d986fa165552023440lgao        p->reps[3] = p->reps[2];
189230fdf1140b8d1ce93f3821d986fa165552023440lgao        p->reps[2] = p->reps[1];
189330fdf1140b8d1ce93f3821d986fa165552023440lgao        p->reps[1] = p->reps[0];
189430fdf1140b8d1ce93f3821d986fa165552023440lgao        p->reps[0] = pos;
189530fdf1140b8d1ce93f3821d986fa165552023440lgao        p->matchPriceCount++;
189630fdf1140b8d1ce93f3821d986fa165552023440lgao      }
189730fdf1140b8d1ce93f3821d986fa165552023440lgao    }
189830fdf1140b8d1ce93f3821d986fa165552023440lgao    p->additionalOffset -= len;
189930fdf1140b8d1ce93f3821d986fa165552023440lgao    nowPos32 += len;
190030fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->additionalOffset == 0)
190130fdf1140b8d1ce93f3821d986fa165552023440lgao    {
190230fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 processed;
190330fdf1140b8d1ce93f3821d986fa165552023440lgao      if (!p->fastMode)
190430fdf1140b8d1ce93f3821d986fa165552023440lgao      {
190530fdf1140b8d1ce93f3821d986fa165552023440lgao        if (p->matchPriceCount >= (1 << 7))
190630fdf1140b8d1ce93f3821d986fa165552023440lgao          FillDistancesPrices(p);
190730fdf1140b8d1ce93f3821d986fa165552023440lgao        if (p->alignPriceCount >= kAlignTableSize)
190830fdf1140b8d1ce93f3821d986fa165552023440lgao          FillAlignPrices(p);
190930fdf1140b8d1ce93f3821d986fa165552023440lgao      }
191030fdf1140b8d1ce93f3821d986fa165552023440lgao      if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
191130fdf1140b8d1ce93f3821d986fa165552023440lgao        break;
191230fdf1140b8d1ce93f3821d986fa165552023440lgao      processed = nowPos32 - startPos32;
191330fdf1140b8d1ce93f3821d986fa165552023440lgao      if (useLimits)
191430fdf1140b8d1ce93f3821d986fa165552023440lgao      {
191530fdf1140b8d1ce93f3821d986fa165552023440lgao        if (processed + kNumOpts + 300 >= maxUnpackSize ||
191630fdf1140b8d1ce93f3821d986fa165552023440lgao            RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
191730fdf1140b8d1ce93f3821d986fa165552023440lgao          break;
191830fdf1140b8d1ce93f3821d986fa165552023440lgao      }
191930fdf1140b8d1ce93f3821d986fa165552023440lgao      else if (processed >= (1 << 15))
192030fdf1140b8d1ce93f3821d986fa165552023440lgao      {
192130fdf1140b8d1ce93f3821d986fa165552023440lgao        p->nowPos64 += nowPos32 - startPos32;
192230fdf1140b8d1ce93f3821d986fa165552023440lgao        return CheckErrors(p);
192330fdf1140b8d1ce93f3821d986fa165552023440lgao      }
192430fdf1140b8d1ce93f3821d986fa165552023440lgao    }
192530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
192630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->nowPos64 += nowPos32 - startPos32;
192730fdf1140b8d1ce93f3821d986fa165552023440lgao  return Flush(p, nowPos32);
192830fdf1140b8d1ce93f3821d986fa165552023440lgao}
192930fdf1140b8d1ce93f3821d986fa165552023440lgao
193030fdf1140b8d1ce93f3821d986fa165552023440lgao#define kBigHashDicLimit ((UInt32)1 << 24)
193130fdf1140b8d1ce93f3821d986fa165552023440lgao
193230fdf1140b8d1ce93f3821d986fa165552023440lgaostatic SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
193330fdf1140b8d1ce93f3821d986fa165552023440lgao{
193430fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 beforeSize = kNumOpts;
19350d2711a69397d2971079121df4326d84736c181elgao  #ifdef COMPRESS_MF_MT
193630fdf1140b8d1ce93f3821d986fa165552023440lgao  Bool btMode;
19370d2711a69397d2971079121df4326d84736c181elgao  #endif
193830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (!RangeEnc_Alloc(&p->rc, alloc))
193930fdf1140b8d1ce93f3821d986fa165552023440lgao    return SZ_ERROR_MEM;
194030fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
19410d2711a69397d2971079121df4326d84736c181elgao  btMode = (p->matchFinderBase.btMode != 0);
194230fdf1140b8d1ce93f3821d986fa165552023440lgao  p->mtMode = (p->multiThread && !p->fastMode && btMode);
194330fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
194430fdf1140b8d1ce93f3821d986fa165552023440lgao
194530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
194630fdf1140b8d1ce93f3821d986fa165552023440lgao    unsigned lclp = p->lc + p->lp;
194730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
194830fdf1140b8d1ce93f3821d986fa165552023440lgao    {
194930fdf1140b8d1ce93f3821d986fa165552023440lgao      LzmaEnc_FreeLits(p, alloc);
195030fdf1140b8d1ce93f3821d986fa165552023440lgao      p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
195130fdf1140b8d1ce93f3821d986fa165552023440lgao      p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
195230fdf1140b8d1ce93f3821d986fa165552023440lgao      if (p->litProbs == 0 || p->saveState.litProbs == 0)
195330fdf1140b8d1ce93f3821d986fa165552023440lgao      {
195430fdf1140b8d1ce93f3821d986fa165552023440lgao        LzmaEnc_FreeLits(p, alloc);
195530fdf1140b8d1ce93f3821d986fa165552023440lgao        return SZ_ERROR_MEM;
195630fdf1140b8d1ce93f3821d986fa165552023440lgao      }
195730fdf1140b8d1ce93f3821d986fa165552023440lgao      p->lclp = lclp;
195830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
195930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
196030fdf1140b8d1ce93f3821d986fa165552023440lgao
196130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
196230fdf1140b8d1ce93f3821d986fa165552023440lgao
196330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (beforeSize + p->dictSize < keepWindowSize)
196430fdf1140b8d1ce93f3821d986fa165552023440lgao    beforeSize = keepWindowSize - p->dictSize;
196530fdf1140b8d1ce93f3821d986fa165552023440lgao
196630fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
196730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->mtMode)
196830fdf1140b8d1ce93f3821d986fa165552023440lgao  {
196930fdf1140b8d1ce93f3821d986fa165552023440lgao    RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
197030fdf1140b8d1ce93f3821d986fa165552023440lgao    p->matchFinderObj = &p->matchFinderMt;
197130fdf1140b8d1ce93f3821d986fa165552023440lgao    MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
197230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
197330fdf1140b8d1ce93f3821d986fa165552023440lgao  else
197430fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
197530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
197630fdf1140b8d1ce93f3821d986fa165552023440lgao    if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
197730fdf1140b8d1ce93f3821d986fa165552023440lgao      return SZ_ERROR_MEM;
197830fdf1140b8d1ce93f3821d986fa165552023440lgao    p->matchFinderObj = &p->matchFinderBase;
197930fdf1140b8d1ce93f3821d986fa165552023440lgao    MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
198030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
198130fdf1140b8d1ce93f3821d986fa165552023440lgao  return SZ_OK;
198230fdf1140b8d1ce93f3821d986fa165552023440lgao}
198330fdf1140b8d1ce93f3821d986fa165552023440lgao
198430fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_Init(CLzmaEnc *p)
198530fdf1140b8d1ce93f3821d986fa165552023440lgao{
198630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 i;
198730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->state = 0;
198830fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0 ; i < LZMA_NUM_REPS; i++)
198930fdf1140b8d1ce93f3821d986fa165552023440lgao    p->reps[i] = 0;
199030fdf1140b8d1ce93f3821d986fa165552023440lgao
199130fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_Init(&p->rc);
199230fdf1140b8d1ce93f3821d986fa165552023440lgao
199330fdf1140b8d1ce93f3821d986fa165552023440lgao
199430fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < kNumStates; i++)
199530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
199630fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 j;
199730fdf1140b8d1ce93f3821d986fa165552023440lgao    for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
199830fdf1140b8d1ce93f3821d986fa165552023440lgao    {
199930fdf1140b8d1ce93f3821d986fa165552023440lgao      p->isMatch[i][j] = kProbInitValue;
200030fdf1140b8d1ce93f3821d986fa165552023440lgao      p->isRep0Long[i][j] = kProbInitValue;
200130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
200230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->isRep[i] = kProbInitValue;
200330fdf1140b8d1ce93f3821d986fa165552023440lgao    p->isRepG0[i] = kProbInitValue;
200430fdf1140b8d1ce93f3821d986fa165552023440lgao    p->isRepG1[i] = kProbInitValue;
200530fdf1140b8d1ce93f3821d986fa165552023440lgao    p->isRepG2[i] = kProbInitValue;
200630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
200730fdf1140b8d1ce93f3821d986fa165552023440lgao
200830fdf1140b8d1ce93f3821d986fa165552023440lgao  {
200930fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 num = 0x300 << (p->lp + p->lc);
201030fdf1140b8d1ce93f3821d986fa165552023440lgao    for (i = 0; i < num; i++)
201130fdf1140b8d1ce93f3821d986fa165552023440lgao      p->litProbs[i] = kProbInitValue;
201230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
201330fdf1140b8d1ce93f3821d986fa165552023440lgao
201430fdf1140b8d1ce93f3821d986fa165552023440lgao  {
201530fdf1140b8d1ce93f3821d986fa165552023440lgao    for (i = 0; i < kNumLenToPosStates; i++)
201630fdf1140b8d1ce93f3821d986fa165552023440lgao    {
201730fdf1140b8d1ce93f3821d986fa165552023440lgao      CLzmaProb *probs = p->posSlotEncoder[i];
201830fdf1140b8d1ce93f3821d986fa165552023440lgao      UInt32 j;
201930fdf1140b8d1ce93f3821d986fa165552023440lgao      for (j = 0; j < (1 << kNumPosSlotBits); j++)
202030fdf1140b8d1ce93f3821d986fa165552023440lgao        probs[j] = kProbInitValue;
202130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
202230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
202330fdf1140b8d1ce93f3821d986fa165552023440lgao  {
202430fdf1140b8d1ce93f3821d986fa165552023440lgao    for (i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
202530fdf1140b8d1ce93f3821d986fa165552023440lgao      p->posEncoders[i] = kProbInitValue;
202630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
202730fdf1140b8d1ce93f3821d986fa165552023440lgao
202830fdf1140b8d1ce93f3821d986fa165552023440lgao  LenEnc_Init(&p->lenEnc.p);
202930fdf1140b8d1ce93f3821d986fa165552023440lgao  LenEnc_Init(&p->repLenEnc.p);
203030fdf1140b8d1ce93f3821d986fa165552023440lgao
203130fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < (1 << kNumAlignBits); i++)
203230fdf1140b8d1ce93f3821d986fa165552023440lgao    p->posAlignEncoder[i] = kProbInitValue;
203330fdf1140b8d1ce93f3821d986fa165552023440lgao
203430fdf1140b8d1ce93f3821d986fa165552023440lgao  p->optimumEndIndex = 0;
203530fdf1140b8d1ce93f3821d986fa165552023440lgao  p->optimumCurrentIndex = 0;
203630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->additionalOffset = 0;
203730fdf1140b8d1ce93f3821d986fa165552023440lgao
203830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->pbMask = (1 << p->pb) - 1;
203930fdf1140b8d1ce93f3821d986fa165552023440lgao  p->lpMask = (1 << p->lp) - 1;
204030fdf1140b8d1ce93f3821d986fa165552023440lgao}
204130fdf1140b8d1ce93f3821d986fa165552023440lgao
204230fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_InitPrices(CLzmaEnc *p)
204330fdf1140b8d1ce93f3821d986fa165552023440lgao{
204430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (!p->fastMode)
204530fdf1140b8d1ce93f3821d986fa165552023440lgao  {
204630fdf1140b8d1ce93f3821d986fa165552023440lgao    FillDistancesPrices(p);
204730fdf1140b8d1ce93f3821d986fa165552023440lgao    FillAlignPrices(p);
204830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
204930fdf1140b8d1ce93f3821d986fa165552023440lgao
205030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->lenEnc.tableSize =
205130fdf1140b8d1ce93f3821d986fa165552023440lgao  p->repLenEnc.tableSize =
205230fdf1140b8d1ce93f3821d986fa165552023440lgao      p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
205330fdf1140b8d1ce93f3821d986fa165552023440lgao  LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
205430fdf1140b8d1ce93f3821d986fa165552023440lgao  LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
205530fdf1140b8d1ce93f3821d986fa165552023440lgao}
205630fdf1140b8d1ce93f3821d986fa165552023440lgao
205730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
205830fdf1140b8d1ce93f3821d986fa165552023440lgao{
205930fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 i;
206030fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
206130fdf1140b8d1ce93f3821d986fa165552023440lgao    if (p->dictSize <= ((UInt32)1 << i))
206230fdf1140b8d1ce93f3821d986fa165552023440lgao      break;
206330fdf1140b8d1ce93f3821d986fa165552023440lgao  p->distTableSize = i * 2;
206430fdf1140b8d1ce93f3821d986fa165552023440lgao
206530fdf1140b8d1ce93f3821d986fa165552023440lgao  p->finished = False;
206630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->result = SZ_OK;
206730fdf1140b8d1ce93f3821d986fa165552023440lgao  RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
206830fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_Init(p);
206930fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_InitPrices(p);
207030fdf1140b8d1ce93f3821d986fa165552023440lgao  p->nowPos64 = 0;
207130fdf1140b8d1ce93f3821d986fa165552023440lgao  return SZ_OK;
207230fdf1140b8d1ce93f3821d986fa165552023440lgao}
207330fdf1140b8d1ce93f3821d986fa165552023440lgao
207430fdf1140b8d1ce93f3821d986fa165552023440lgaostatic SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
207530fdf1140b8d1ce93f3821d986fa165552023440lgao    ISzAlloc *alloc, ISzAlloc *allocBig)
207630fdf1140b8d1ce93f3821d986fa165552023440lgao{
207730fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
207830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->inStream = inStream;
207930fdf1140b8d1ce93f3821d986fa165552023440lgao  p->rc.outStream = outStream;
208030fdf1140b8d1ce93f3821d986fa165552023440lgao  return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
208130fdf1140b8d1ce93f3821d986fa165552023440lgao}
208230fdf1140b8d1ce93f3821d986fa165552023440lgao
208330fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
208430fdf1140b8d1ce93f3821d986fa165552023440lgao    ISeqInStream *inStream, UInt32 keepWindowSize,
208530fdf1140b8d1ce93f3821d986fa165552023440lgao    ISzAlloc *alloc, ISzAlloc *allocBig)
208630fdf1140b8d1ce93f3821d986fa165552023440lgao{
208730fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
208830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->inStream = inStream;
208930fdf1140b8d1ce93f3821d986fa165552023440lgao  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
209030fdf1140b8d1ce93f3821d986fa165552023440lgao}
209130fdf1140b8d1ce93f3821d986fa165552023440lgao
209230fdf1140b8d1ce93f3821d986fa165552023440lgaostatic void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
209330fdf1140b8d1ce93f3821d986fa165552023440lgao{
209430fdf1140b8d1ce93f3821d986fa165552023440lgao  p->seqBufInStream.funcTable.Read = MyRead;
209530fdf1140b8d1ce93f3821d986fa165552023440lgao  p->seqBufInStream.data = src;
209630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->seqBufInStream.rem = srcLen;
209730fdf1140b8d1ce93f3821d986fa165552023440lgao}
209830fdf1140b8d1ce93f3821d986fa165552023440lgao
209930fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
210030fdf1140b8d1ce93f3821d986fa165552023440lgao    UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
210130fdf1140b8d1ce93f3821d986fa165552023440lgao{
210230fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
210330fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_SetInputBuf(p, src, srcLen);
210430fdf1140b8d1ce93f3821d986fa165552023440lgao  p->inStream = &p->seqBufInStream.funcTable;
210530fdf1140b8d1ce93f3821d986fa165552023440lgao  return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
210630fdf1140b8d1ce93f3821d986fa165552023440lgao}
210730fdf1140b8d1ce93f3821d986fa165552023440lgao
210830fdf1140b8d1ce93f3821d986fa165552023440lgaovoid LzmaEnc_Finish(CLzmaEncHandle pp)
210930fdf1140b8d1ce93f3821d986fa165552023440lgao{
211030fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
211130fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
211230fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->mtMode)
211330fdf1140b8d1ce93f3821d986fa165552023440lgao    MatchFinderMt_ReleaseStream(&p->matchFinderMt);
211430fdf1140b8d1ce93f3821d986fa165552023440lgao  #else
21155ddccf34c4f57e6e7fca767c1628a0d98ce8bdafBruce Cran  (void)pp;
211630fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
211730fdf1140b8d1ce93f3821d986fa165552023440lgao}
211830fdf1140b8d1ce93f3821d986fa165552023440lgao
211930fdf1140b8d1ce93f3821d986fa165552023440lgaotypedef struct _CSeqOutStreamBuf
212030fdf1140b8d1ce93f3821d986fa165552023440lgao{
212130fdf1140b8d1ce93f3821d986fa165552023440lgao  ISeqOutStream funcTable;
212230fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte *data;
212330fdf1140b8d1ce93f3821d986fa165552023440lgao  SizeT rem;
212430fdf1140b8d1ce93f3821d986fa165552023440lgao  Bool overflow;
212530fdf1140b8d1ce93f3821d986fa165552023440lgao} CSeqOutStreamBuf;
212630fdf1140b8d1ce93f3821d986fa165552023440lgao
212730fdf1140b8d1ce93f3821d986fa165552023440lgaostatic size_t MyWrite(void *pp, const void *data, size_t size)
212830fdf1140b8d1ce93f3821d986fa165552023440lgao{
212930fdf1140b8d1ce93f3821d986fa165552023440lgao  CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
213030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p->rem < size)
213130fdf1140b8d1ce93f3821d986fa165552023440lgao  {
213230fdf1140b8d1ce93f3821d986fa165552023440lgao    size = p->rem;
213330fdf1140b8d1ce93f3821d986fa165552023440lgao    p->overflow = True;
213430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
213530fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy(p->data, data, size);
213630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->rem -= size;
213730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->data += size;
213830fdf1140b8d1ce93f3821d986fa165552023440lgao  return size;
213930fdf1140b8d1ce93f3821d986fa165552023440lgao}
214030fdf1140b8d1ce93f3821d986fa165552023440lgao
214130fdf1140b8d1ce93f3821d986fa165552023440lgao
214230fdf1140b8d1ce93f3821d986fa165552023440lgaoUInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
214330fdf1140b8d1ce93f3821d986fa165552023440lgao{
214430fdf1140b8d1ce93f3821d986fa165552023440lgao  const CLzmaEnc *p = (CLzmaEnc *)pp;
214530fdf1140b8d1ce93f3821d986fa165552023440lgao  return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
214630fdf1140b8d1ce93f3821d986fa165552023440lgao}
214730fdf1140b8d1ce93f3821d986fa165552023440lgao
214830fdf1140b8d1ce93f3821d986fa165552023440lgaoconst Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
214930fdf1140b8d1ce93f3821d986fa165552023440lgao{
215030fdf1140b8d1ce93f3821d986fa165552023440lgao  const CLzmaEnc *p = (CLzmaEnc *)pp;
215130fdf1140b8d1ce93f3821d986fa165552023440lgao  return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
215230fdf1140b8d1ce93f3821d986fa165552023440lgao}
215330fdf1140b8d1ce93f3821d986fa165552023440lgao
215430fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
215530fdf1140b8d1ce93f3821d986fa165552023440lgao    Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
215630fdf1140b8d1ce93f3821d986fa165552023440lgao{
215730fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
215830fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt64 nowPos64;
215930fdf1140b8d1ce93f3821d986fa165552023440lgao  SRes res;
216030fdf1140b8d1ce93f3821d986fa165552023440lgao  CSeqOutStreamBuf outStream;
216130fdf1140b8d1ce93f3821d986fa165552023440lgao
216230fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.funcTable.Write = MyWrite;
216330fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.data = dest;
216430fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.rem = *destLen;
216530fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.overflow = False;
216630fdf1140b8d1ce93f3821d986fa165552023440lgao
216730fdf1140b8d1ce93f3821d986fa165552023440lgao  p->writeEndMark = False;
216830fdf1140b8d1ce93f3821d986fa165552023440lgao  p->finished = False;
216930fdf1140b8d1ce93f3821d986fa165552023440lgao  p->result = SZ_OK;
217030fdf1140b8d1ce93f3821d986fa165552023440lgao
217130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (reInit)
217230fdf1140b8d1ce93f3821d986fa165552023440lgao    LzmaEnc_Init(p);
217330fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_InitPrices(p);
217430fdf1140b8d1ce93f3821d986fa165552023440lgao  nowPos64 = p->nowPos64;
217530fdf1140b8d1ce93f3821d986fa165552023440lgao  RangeEnc_Init(&p->rc);
217630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->rc.outStream = &outStream.funcTable;
217730fdf1140b8d1ce93f3821d986fa165552023440lgao
217830fdf1140b8d1ce93f3821d986fa165552023440lgao  res = LzmaEnc_CodeOneBlock(p, True, desiredPackSize, *unpackSize);
217930fdf1140b8d1ce93f3821d986fa165552023440lgao
218030fdf1140b8d1ce93f3821d986fa165552023440lgao  *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
218130fdf1140b8d1ce93f3821d986fa165552023440lgao  *destLen -= outStream.rem;
218230fdf1140b8d1ce93f3821d986fa165552023440lgao  if (outStream.overflow)
218330fdf1140b8d1ce93f3821d986fa165552023440lgao    return SZ_ERROR_OUTPUT_EOF;
218430fdf1140b8d1ce93f3821d986fa165552023440lgao
218530fdf1140b8d1ce93f3821d986fa165552023440lgao  return res;
218630fdf1140b8d1ce93f3821d986fa165552023440lgao}
218730fdf1140b8d1ce93f3821d986fa165552023440lgao
218830fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
218930fdf1140b8d1ce93f3821d986fa165552023440lgao    ISzAlloc *alloc, ISzAlloc *allocBig)
219030fdf1140b8d1ce93f3821d986fa165552023440lgao{
219130fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
219230fdf1140b8d1ce93f3821d986fa165552023440lgao  SRes res = SZ_OK;
219330fdf1140b8d1ce93f3821d986fa165552023440lgao
219430fdf1140b8d1ce93f3821d986fa165552023440lgao  #ifdef COMPRESS_MF_MT
219530fdf1140b8d1ce93f3821d986fa165552023440lgao  Byte allocaDummy[0x300];
219630fdf1140b8d1ce93f3821d986fa165552023440lgao  int i = 0;
219730fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < 16; i++)
219830fdf1140b8d1ce93f3821d986fa165552023440lgao    allocaDummy[i] = (Byte)i;
219930fdf1140b8d1ce93f3821d986fa165552023440lgao  #endif
220030fdf1140b8d1ce93f3821d986fa165552023440lgao
220130fdf1140b8d1ce93f3821d986fa165552023440lgao  RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
220230fdf1140b8d1ce93f3821d986fa165552023440lgao
220330fdf1140b8d1ce93f3821d986fa165552023440lgao  for (;;)
220430fdf1140b8d1ce93f3821d986fa165552023440lgao  {
220530fdf1140b8d1ce93f3821d986fa165552023440lgao    res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
220630fdf1140b8d1ce93f3821d986fa165552023440lgao    if (res != SZ_OK || p->finished != 0)
220730fdf1140b8d1ce93f3821d986fa165552023440lgao      break;
220830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (progress != 0)
220930fdf1140b8d1ce93f3821d986fa165552023440lgao    {
221030fdf1140b8d1ce93f3821d986fa165552023440lgao      res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
221130fdf1140b8d1ce93f3821d986fa165552023440lgao      if (res != SZ_OK)
221230fdf1140b8d1ce93f3821d986fa165552023440lgao      {
221330fdf1140b8d1ce93f3821d986fa165552023440lgao        res = SZ_ERROR_PROGRESS;
221430fdf1140b8d1ce93f3821d986fa165552023440lgao        break;
221530fdf1140b8d1ce93f3821d986fa165552023440lgao      }
221630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
221730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
221830fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_Finish(pp);
221930fdf1140b8d1ce93f3821d986fa165552023440lgao  return res;
222030fdf1140b8d1ce93f3821d986fa165552023440lgao}
222130fdf1140b8d1ce93f3821d986fa165552023440lgao
222230fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
222330fdf1140b8d1ce93f3821d986fa165552023440lgao{
222430fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
222530fdf1140b8d1ce93f3821d986fa165552023440lgao  int i;
222630fdf1140b8d1ce93f3821d986fa165552023440lgao  UInt32 dictSize = p->dictSize;
222730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (*size < LZMA_PROPS_SIZE)
222830fdf1140b8d1ce93f3821d986fa165552023440lgao    return SZ_ERROR_PARAM;
222930fdf1140b8d1ce93f3821d986fa165552023440lgao  *size = LZMA_PROPS_SIZE;
223030fdf1140b8d1ce93f3821d986fa165552023440lgao  props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
223130fdf1140b8d1ce93f3821d986fa165552023440lgao
223230fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 11; i <= 30; i++)
223330fdf1140b8d1ce93f3821d986fa165552023440lgao  {
223430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (dictSize <= ((UInt32)2 << i))
223530fdf1140b8d1ce93f3821d986fa165552023440lgao    {
223630fdf1140b8d1ce93f3821d986fa165552023440lgao      dictSize = (2 << i);
223730fdf1140b8d1ce93f3821d986fa165552023440lgao      break;
223830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
223930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (dictSize <= ((UInt32)3 << i))
224030fdf1140b8d1ce93f3821d986fa165552023440lgao    {
224130fdf1140b8d1ce93f3821d986fa165552023440lgao      dictSize = (3 << i);
224230fdf1140b8d1ce93f3821d986fa165552023440lgao      break;
224330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
224430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
224530fdf1140b8d1ce93f3821d986fa165552023440lgao
224630fdf1140b8d1ce93f3821d986fa165552023440lgao  for (i = 0; i < 4; i++)
224730fdf1140b8d1ce93f3821d986fa165552023440lgao    props[1 + i] = (Byte)(dictSize >> (8 * i));
224830fdf1140b8d1ce93f3821d986fa165552023440lgao  return SZ_OK;
224930fdf1140b8d1ce93f3821d986fa165552023440lgao}
225030fdf1140b8d1ce93f3821d986fa165552023440lgao
225130fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
225230fdf1140b8d1ce93f3821d986fa165552023440lgao    int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
225330fdf1140b8d1ce93f3821d986fa165552023440lgao{
225430fdf1140b8d1ce93f3821d986fa165552023440lgao  SRes res;
225530fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)pp;
225630fdf1140b8d1ce93f3821d986fa165552023440lgao
225730fdf1140b8d1ce93f3821d986fa165552023440lgao  CSeqOutStreamBuf outStream;
225830fdf1140b8d1ce93f3821d986fa165552023440lgao
225930fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_SetInputBuf(p, src, srcLen);
226030fdf1140b8d1ce93f3821d986fa165552023440lgao
226130fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.funcTable.Write = MyWrite;
226230fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.data = dest;
226330fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.rem = *destLen;
226430fdf1140b8d1ce93f3821d986fa165552023440lgao  outStream.overflow = False;
226530fdf1140b8d1ce93f3821d986fa165552023440lgao
226630fdf1140b8d1ce93f3821d986fa165552023440lgao  p->writeEndMark = writeEndMark;
226730fdf1140b8d1ce93f3821d986fa165552023440lgao  res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
226830fdf1140b8d1ce93f3821d986fa165552023440lgao      progress, alloc, allocBig);
226930fdf1140b8d1ce93f3821d986fa165552023440lgao
227030fdf1140b8d1ce93f3821d986fa165552023440lgao  *destLen -= outStream.rem;
227130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (outStream.overflow)
227230fdf1140b8d1ce93f3821d986fa165552023440lgao    return SZ_ERROR_OUTPUT_EOF;
227330fdf1140b8d1ce93f3821d986fa165552023440lgao  return res;
227430fdf1140b8d1ce93f3821d986fa165552023440lgao}
227530fdf1140b8d1ce93f3821d986fa165552023440lgao
227630fdf1140b8d1ce93f3821d986fa165552023440lgaoSRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
227730fdf1140b8d1ce93f3821d986fa165552023440lgao    const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
227830fdf1140b8d1ce93f3821d986fa165552023440lgao    ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
227930fdf1140b8d1ce93f3821d986fa165552023440lgao{
228030fdf1140b8d1ce93f3821d986fa165552023440lgao  CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
228130fdf1140b8d1ce93f3821d986fa165552023440lgao  SRes res;
228230fdf1140b8d1ce93f3821d986fa165552023440lgao  if (p == 0)
228330fdf1140b8d1ce93f3821d986fa165552023440lgao    return SZ_ERROR_MEM;
228430fdf1140b8d1ce93f3821d986fa165552023440lgao
228530fdf1140b8d1ce93f3821d986fa165552023440lgao  res = LzmaEnc_SetProps(p, props);
228630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (res == SZ_OK)
228730fdf1140b8d1ce93f3821d986fa165552023440lgao  {
228830fdf1140b8d1ce93f3821d986fa165552023440lgao    res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
228930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (res == SZ_OK)
229030fdf1140b8d1ce93f3821d986fa165552023440lgao      res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
229130fdf1140b8d1ce93f3821d986fa165552023440lgao          writeEndMark, progress, alloc, allocBig);
229230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
229330fdf1140b8d1ce93f3821d986fa165552023440lgao
229430fdf1140b8d1ce93f3821d986fa165552023440lgao  LzmaEnc_Destroy(p, alloc, allocBig);
229530fdf1140b8d1ce93f3821d986fa165552023440lgao  return res;
229630fdf1140b8d1ce93f3821d986fa165552023440lgao}
2297