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