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