1 package SevenZip.Compression.LZMA; 2 3 import SevenZip.Compression.RangeCoder.BitTreeEncoder; 4 import SevenZip.Compression.LZMA.Base; 5 import SevenZip.Compression.LZ.BinTree; 6 import SevenZip.ICodeProgress; 7 import java.io.IOException; 8 9 public class Encoder 10 { 11 public static final int EMatchFinderTypeBT2 = 0; 12 public static final int EMatchFinderTypeBT4 = 1; 13 14 15 16 17 static final int kIfinityPrice = 0xFFFFFFF; 18 19 static byte[] g_FastPos = new byte[1 << 11]; 20 21 static 22 { 23 int kFastSlots = 22; 24 int c = 2; 25 g_FastPos[0] = 0; 26 g_FastPos[1] = 1; 27 for (int slotFast = 2; slotFast < kFastSlots; slotFast++) 28 { 29 int k = (1 << ((slotFast >> 1) - 1)); 30 for (int j = 0; j < k; j++, c++) 31 g_FastPos[c] = (byte)slotFast; 32 } 33 } 34 GetPosSlot(int pos)35 static int GetPosSlot(int pos) 36 { 37 if (pos < (1 << 11)) 38 return g_FastPos[pos]; 39 if (pos < (1 << 21)) 40 return (g_FastPos[pos >> 10] + 20); 41 return (g_FastPos[pos >> 20] + 40); 42 } 43 GetPosSlot2(int pos)44 static int GetPosSlot2(int pos) 45 { 46 if (pos < (1 << 17)) 47 return (g_FastPos[pos >> 6] + 12); 48 if (pos < (1 << 27)) 49 return (g_FastPos[pos >> 16] + 32); 50 return (g_FastPos[pos >> 26] + 52); 51 } 52 53 int _state = Base.StateInit(); 54 byte _previousByte; 55 int[] _repDistances = new int[Base.kNumRepDistances]; 56 BaseInit()57 void BaseInit() 58 { 59 _state = Base.StateInit(); 60 _previousByte = 0; 61 for (int i = 0; i < Base.kNumRepDistances; i++) 62 _repDistances[i] = 0; 63 } 64 65 static final int kDefaultDictionaryLogSize = 22; 66 static final int kNumFastBytesDefault = 0x20; 67 68 class LiteralEncoder 69 { 70 class Encoder2 71 { 72 short[] m_Encoders = new short[0x300]; 73 Init()74 public void Init() { SevenZip.Compression.RangeCoder.Encoder.InitBitModels(m_Encoders); } 75 76 77 Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol)78 public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte symbol) throws IOException 79 { 80 int context = 1; 81 for (int i = 7; i >= 0; i--) 82 { 83 int bit = ((symbol >> i) & 1); 84 rangeEncoder.Encode(m_Encoders, context, bit); 85 context = (context << 1) | bit; 86 } 87 } 88 EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)89 public void EncodeMatched(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) throws IOException 90 { 91 int context = 1; 92 boolean same = true; 93 for (int i = 7; i >= 0; i--) 94 { 95 int bit = ((symbol >> i) & 1); 96 int state = context; 97 if (same) 98 { 99 int matchBit = ((matchByte >> i) & 1); 100 state += ((1 + matchBit) << 8); 101 same = (matchBit == bit); 102 } 103 rangeEncoder.Encode(m_Encoders, state, bit); 104 context = (context << 1) | bit; 105 } 106 } 107 GetPrice(boolean matchMode, byte matchByte, byte symbol)108 public int GetPrice(boolean matchMode, byte matchByte, byte symbol) 109 { 110 int price = 0; 111 int context = 1; 112 int i = 7; 113 if (matchMode) 114 { 115 for (; i >= 0; i--) 116 { 117 int matchBit = (matchByte >> i) & 1; 118 int bit = (symbol >> i) & 1; 119 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[((1 + matchBit) << 8) + context], bit); 120 context = (context << 1) | bit; 121 if (matchBit != bit) 122 { 123 i--; 124 break; 125 } 126 } 127 } 128 for (; i >= 0; i--) 129 { 130 int bit = (symbol >> i) & 1; 131 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(m_Encoders[context], bit); 132 context = (context << 1) | bit; 133 } 134 return price; 135 } 136 } 137 138 Encoder2[] m_Coders; 139 int m_NumPrevBits; 140 int m_NumPosBits; 141 int m_PosMask; 142 Create(int numPosBits, int numPrevBits)143 public void Create(int numPosBits, int numPrevBits) 144 { 145 if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) 146 return; 147 m_NumPosBits = numPosBits; 148 m_PosMask = (1 << numPosBits) - 1; 149 m_NumPrevBits = numPrevBits; 150 int numStates = 1 << (m_NumPrevBits + m_NumPosBits); 151 m_Coders = new Encoder2[numStates]; 152 for (int i = 0; i < numStates; i++) 153 m_Coders[i] = new Encoder2(); 154 } 155 Init()156 public void Init() 157 { 158 int numStates = 1 << (m_NumPrevBits + m_NumPosBits); 159 for (int i = 0; i < numStates; i++) 160 m_Coders[i].Init(); 161 } 162 GetSubCoder(int pos, byte prevByte)163 public Encoder2 GetSubCoder(int pos, byte prevByte) 164 { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + ((prevByte & 0xFF) >>> (8 - m_NumPrevBits))]; } 165 } 166 167 class LenEncoder 168 { 169 short[] _choice = new short[2]; 170 BitTreeEncoder[] _lowCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; 171 BitTreeEncoder[] _midCoder = new BitTreeEncoder[Base.kNumPosStatesEncodingMax]; 172 BitTreeEncoder _highCoder = new BitTreeEncoder(Base.kNumHighLenBits); 173 174 LenEncoder()175 public LenEncoder() 176 { 177 for (int posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) 178 { 179 _lowCoder[posState] = new BitTreeEncoder(Base.kNumLowLenBits); 180 _midCoder[posState] = new BitTreeEncoder(Base.kNumMidLenBits); 181 } 182 } 183 Init(int numPosStates)184 public void Init(int numPosStates) 185 { 186 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_choice); 187 188 for (int posState = 0; posState < numPosStates; posState++) 189 { 190 _lowCoder[posState].Init(); 191 _midCoder[posState].Init(); 192 } 193 _highCoder.Init(); 194 } 195 Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState)196 public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException 197 { 198 if (symbol < Base.kNumLowLenSymbols) 199 { 200 rangeEncoder.Encode(_choice, 0, 0); 201 _lowCoder[posState].Encode(rangeEncoder, symbol); 202 } 203 else 204 { 205 symbol -= Base.kNumLowLenSymbols; 206 rangeEncoder.Encode(_choice, 0, 1); 207 if (symbol < Base.kNumMidLenSymbols) 208 { 209 rangeEncoder.Encode(_choice, 1, 0); 210 _midCoder[posState].Encode(rangeEncoder, symbol); 211 } 212 else 213 { 214 rangeEncoder.Encode(_choice, 1, 1); 215 _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); 216 } 217 } 218 } 219 SetPrices(int posState, int numSymbols, int[] prices, int st)220 public void SetPrices(int posState, int numSymbols, int[] prices, int st) 221 { 222 int a0 = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[0]); 223 int a1 = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[0]); 224 int b0 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_choice[1]); 225 int b1 = a1 + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_choice[1]); 226 int i = 0; 227 for (i = 0; i < Base.kNumLowLenSymbols; i++) 228 { 229 if (i >= numSymbols) 230 return; 231 prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); 232 } 233 for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) 234 { 235 if (i >= numSymbols) 236 return; 237 prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); 238 } 239 for (; i < numSymbols; i++) 240 prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); 241 } 242 }; 243 244 public static final int kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; 245 246 class LenPriceTableEncoder extends LenEncoder 247 { 248 int[] _prices = new int[Base.kNumLenSymbols<<Base.kNumPosStatesBitsEncodingMax]; 249 int _tableSize; 250 int[] _counters = new int[Base.kNumPosStatesEncodingMax]; 251 SetTableSize(int tableSize)252 public void SetTableSize(int tableSize) { _tableSize = tableSize; } 253 GetPrice(int symbol, int posState)254 public int GetPrice(int symbol, int posState) 255 { 256 return _prices[posState * Base.kNumLenSymbols + symbol]; 257 } 258 UpdateTable(int posState)259 void UpdateTable(int posState) 260 { 261 SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); 262 _counters[posState] = _tableSize; 263 } 264 UpdateTables(int numPosStates)265 public void UpdateTables(int numPosStates) 266 { 267 for (int posState = 0; posState < numPosStates; posState++) 268 UpdateTable(posState); 269 } 270 Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState)271 public void Encode(SevenZip.Compression.RangeCoder.Encoder rangeEncoder, int symbol, int posState) throws IOException 272 { 273 super.Encode(rangeEncoder, symbol, posState); 274 if (--_counters[posState] == 0) 275 UpdateTable(posState); 276 } 277 } 278 279 static final int kNumOpts = 1 << 12; 280 class Optimal 281 { 282 public int State; 283 284 public boolean Prev1IsChar; 285 public boolean Prev2; 286 287 public int PosPrev2; 288 public int BackPrev2; 289 290 public int Price; 291 public int PosPrev; 292 public int BackPrev; 293 294 public int Backs0; 295 public int Backs1; 296 public int Backs2; 297 public int Backs3; 298 MakeAsChar()299 public void MakeAsChar() { BackPrev = -1; Prev1IsChar = false; } MakeAsShortRep()300 public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } IsShortRep()301 public boolean IsShortRep() { return (BackPrev == 0); } 302 }; 303 Optimal[] _optimum = new Optimal[kNumOpts]; 304 SevenZip.Compression.LZ.BinTree _matchFinder = null; 305 SevenZip.Compression.RangeCoder.Encoder _rangeEncoder = new SevenZip.Compression.RangeCoder.Encoder(); 306 307 short[] _isMatch = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; 308 short[] _isRep = new short[Base.kNumStates]; 309 short[] _isRepG0 = new short[Base.kNumStates]; 310 short[] _isRepG1 = new short[Base.kNumStates]; 311 short[] _isRepG2 = new short[Base.kNumStates]; 312 short[] _isRep0Long = new short[Base.kNumStates<<Base.kNumPosStatesBitsMax]; 313 314 BitTreeEncoder[] _posSlotEncoder = new BitTreeEncoder[Base.kNumLenToPosStates]; // kNumPosSlotBits 315 316 short[] _posEncoders = new short[Base.kNumFullDistances-Base.kEndPosModelIndex]; 317 BitTreeEncoder _posAlignEncoder = new BitTreeEncoder(Base.kNumAlignBits); 318 319 LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); 320 LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); 321 322 LiteralEncoder _literalEncoder = new LiteralEncoder(); 323 324 int[] _matchDistances = new int[Base.kMatchMaxLen*2+2]; 325 326 int _numFastBytes = kNumFastBytesDefault; 327 int _longestMatchLength; 328 int _numDistancePairs; 329 330 int _additionalOffset; 331 332 int _optimumEndIndex; 333 int _optimumCurrentIndex; 334 335 boolean _longestMatchWasFound; 336 337 int[] _posSlotPrices = new int[1<<(Base.kNumPosSlotBits+Base.kNumLenToPosStatesBits)]; 338 int[] _distancesPrices = new int[Base.kNumFullDistances<<Base.kNumLenToPosStatesBits]; 339 int[] _alignPrices = new int[Base.kAlignTableSize]; 340 int _alignPriceCount; 341 342 int _distTableSize = (kDefaultDictionaryLogSize * 2); 343 344 int _posStateBits = 2; 345 int _posStateMask = (4 - 1); 346 int _numLiteralPosStateBits = 0; 347 int _numLiteralContextBits = 3; 348 349 int _dictionarySize = (1 << kDefaultDictionaryLogSize); 350 int _dictionarySizePrev = -1; 351 int _numFastBytesPrev = -1; 352 353 long nowPos64; 354 boolean _finished; 355 java.io.InputStream _inStream; 356 357 int _matchFinderType = EMatchFinderTypeBT4; 358 boolean _writeEndMark = false; 359 360 boolean _needReleaseMFStream = false; 361 Create()362 void Create() 363 { 364 if (_matchFinder == null) 365 { 366 SevenZip.Compression.LZ.BinTree bt = new SevenZip.Compression.LZ.BinTree(); 367 int numHashBytes = 4; 368 if (_matchFinderType == EMatchFinderTypeBT2) 369 numHashBytes = 2; 370 bt.SetType(numHashBytes); 371 _matchFinder = bt; 372 } 373 _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); 374 375 if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) 376 return; 377 _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); 378 _dictionarySizePrev = _dictionarySize; 379 _numFastBytesPrev = _numFastBytes; 380 } 381 Encoder()382 public Encoder() 383 { 384 for (int i = 0; i < kNumOpts; i++) 385 _optimum[i] = new Optimal(); 386 for (int i = 0; i < Base.kNumLenToPosStates; i++) 387 _posSlotEncoder[i] = new BitTreeEncoder(Base.kNumPosSlotBits); 388 } 389 SetWriteEndMarkerMode(boolean writeEndMarker)390 void SetWriteEndMarkerMode(boolean writeEndMarker) 391 { 392 _writeEndMark = writeEndMarker; 393 } 394 Init()395 void Init() 396 { 397 BaseInit(); 398 _rangeEncoder.Init(); 399 400 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isMatch); 401 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep0Long); 402 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRep); 403 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG0); 404 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG1); 405 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_isRepG2); 406 SevenZip.Compression.RangeCoder.Encoder.InitBitModels(_posEncoders); 407 408 409 410 411 412 413 414 _literalEncoder.Init(); 415 for (int i = 0; i < Base.kNumLenToPosStates; i++) 416 _posSlotEncoder[i].Init(); 417 418 419 420 _lenEncoder.Init(1 << _posStateBits); 421 _repMatchLenEncoder.Init(1 << _posStateBits); 422 423 _posAlignEncoder.Init(); 424 425 _longestMatchWasFound = false; 426 _optimumEndIndex = 0; 427 _optimumCurrentIndex = 0; 428 _additionalOffset = 0; 429 } 430 ReadMatchDistances()431 int ReadMatchDistances() throws java.io.IOException 432 { 433 int lenRes = 0; 434 _numDistancePairs = _matchFinder.GetMatches(_matchDistances); 435 if (_numDistancePairs > 0) 436 { 437 lenRes = _matchDistances[_numDistancePairs - 2]; 438 if (lenRes == _numFastBytes) 439 lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[_numDistancePairs - 1], 440 Base.kMatchMaxLen - lenRes); 441 } 442 _additionalOffset++; 443 return lenRes; 444 } 445 MovePos(int num)446 void MovePos(int num) throws java.io.IOException 447 { 448 if (num > 0) 449 { 450 _matchFinder.Skip(num); 451 _additionalOffset += num; 452 } 453 } 454 GetRepLen1Price(int state, int posState)455 int GetRepLen1Price(int state, int posState) 456 { 457 return SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]) + 458 SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); 459 } 460 GetPureRepPrice(int repIndex, int state, int posState)461 int GetPureRepPrice(int repIndex, int state, int posState) 462 { 463 int price; 464 if (repIndex == 0) 465 { 466 price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG0[state]); 467 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep0Long[(state << Base.kNumPosStatesBitsMax) + posState]); 468 } 469 else 470 { 471 price = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG0[state]); 472 if (repIndex == 1) 473 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRepG1[state]); 474 else 475 { 476 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRepG1[state]); 477 price += SevenZip.Compression.RangeCoder.Encoder.GetPrice(_isRepG2[state], repIndex - 2); 478 } 479 } 480 return price; 481 } 482 GetRepPrice(int repIndex, int len, int state, int posState)483 int GetRepPrice(int repIndex, int len, int state, int posState) 484 { 485 int price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); 486 return price + GetPureRepPrice(repIndex, state, posState); 487 } 488 GetPosLenPrice(int pos, int len, int posState)489 int GetPosLenPrice(int pos, int len, int posState) 490 { 491 int price; 492 int lenToPosState = Base.GetLenToPosState(len); 493 if (pos < Base.kNumFullDistances) 494 price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; 495 else 496 price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + 497 _alignPrices[pos & Base.kAlignMask]; 498 return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); 499 } 500 Backward(int cur)501 int Backward(int cur) 502 { 503 _optimumEndIndex = cur; 504 int posMem = _optimum[cur].PosPrev; 505 int backMem = _optimum[cur].BackPrev; 506 do 507 { 508 if (_optimum[cur].Prev1IsChar) 509 { 510 _optimum[posMem].MakeAsChar(); 511 _optimum[posMem].PosPrev = posMem - 1; 512 if (_optimum[cur].Prev2) 513 { 514 _optimum[posMem - 1].Prev1IsChar = false; 515 _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; 516 _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; 517 } 518 } 519 int posPrev = posMem; 520 int backCur = backMem; 521 522 backMem = _optimum[posPrev].BackPrev; 523 posMem = _optimum[posPrev].PosPrev; 524 525 _optimum[posPrev].BackPrev = backCur; 526 _optimum[posPrev].PosPrev = cur; 527 cur = posPrev; 528 } 529 while (cur > 0); 530 backRes = _optimum[0].BackPrev; 531 _optimumCurrentIndex = _optimum[0].PosPrev; 532 return _optimumCurrentIndex; 533 } 534 535 int[] reps = new int[Base.kNumRepDistances]; 536 int[] repLens = new int[Base.kNumRepDistances]; 537 int backRes; 538 GetOptimum(int position)539 int GetOptimum(int position) throws IOException 540 { 541 if (_optimumEndIndex != _optimumCurrentIndex) 542 { 543 int lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; 544 backRes = _optimum[_optimumCurrentIndex].BackPrev; 545 _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; 546 return lenRes; 547 } 548 _optimumCurrentIndex = _optimumEndIndex = 0; 549 550 int lenMain, numDistancePairs; 551 if (!_longestMatchWasFound) 552 { 553 lenMain = ReadMatchDistances(); 554 } 555 else 556 { 557 lenMain = _longestMatchLength; 558 _longestMatchWasFound = false; 559 } 560 numDistancePairs = _numDistancePairs; 561 562 int numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; 563 if (numAvailableBytes < 2) 564 { 565 backRes = -1; 566 return 1; 567 } 568 if (numAvailableBytes > Base.kMatchMaxLen) 569 numAvailableBytes = Base.kMatchMaxLen; 570 571 int repMaxIndex = 0; 572 int i; 573 for (i = 0; i < Base.kNumRepDistances; i++) 574 { 575 reps[i] = _repDistances[i]; 576 repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); 577 if (repLens[i] > repLens[repMaxIndex]) 578 repMaxIndex = i; 579 } 580 if (repLens[repMaxIndex] >= _numFastBytes) 581 { 582 backRes = repMaxIndex; 583 int lenRes = repLens[repMaxIndex]; 584 MovePos(lenRes - 1); 585 return lenRes; 586 } 587 588 if (lenMain >= _numFastBytes) 589 { 590 backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; 591 MovePos(lenMain - 1); 592 return lenMain; 593 } 594 595 byte currentByte = _matchFinder.GetIndexByte(0 - 1); 596 byte matchByte = _matchFinder.GetIndexByte(0 - _repDistances[0] - 1 - 1); 597 598 if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) 599 { 600 backRes = -1; 601 return 1; 602 } 603 604 _optimum[0].State = _state; 605 606 int posState = (position & _posStateMask); 607 608 _optimum[1].Price = SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]) + 609 _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!Base.StateIsCharState(_state), matchByte, currentByte); 610 _optimum[1].MakeAsChar(); 611 612 int matchPrice = SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(_state << Base.kNumPosStatesBitsMax) + posState]); 613 int repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[_state]); 614 615 if (matchByte == currentByte) 616 { 617 int shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); 618 if (shortRepPrice < _optimum[1].Price) 619 { 620 _optimum[1].Price = shortRepPrice; 621 _optimum[1].MakeAsShortRep(); 622 } 623 } 624 625 int lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); 626 627 if (lenEnd < 2) 628 { 629 backRes = _optimum[1].BackPrev; 630 return 1; 631 } 632 633 _optimum[1].PosPrev = 0; 634 635 _optimum[0].Backs0 = reps[0]; 636 _optimum[0].Backs1 = reps[1]; 637 _optimum[0].Backs2 = reps[2]; 638 _optimum[0].Backs3 = reps[3]; 639 640 int len = lenEnd; 641 do 642 _optimum[len--].Price = kIfinityPrice; 643 while (len >= 2); 644 645 for (i = 0; i < Base.kNumRepDistances; i++) 646 { 647 int repLen = repLens[i]; 648 if (repLen < 2) 649 continue; 650 int price = repMatchPrice + GetPureRepPrice(i, _state, posState); 651 do 652 { 653 int curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); 654 Optimal optimum = _optimum[repLen]; 655 if (curAndLenPrice < optimum.Price) 656 { 657 optimum.Price = curAndLenPrice; 658 optimum.PosPrev = 0; 659 optimum.BackPrev = i; 660 optimum.Prev1IsChar = false; 661 } 662 } 663 while (--repLen >= 2); 664 } 665 666 int normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[_state]); 667 668 len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); 669 if (len <= lenMain) 670 { 671 int offs = 0; 672 while (len > _matchDistances[offs]) 673 offs += 2; 674 for (; ; len++) 675 { 676 int distance = _matchDistances[offs + 1]; 677 int curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); 678 Optimal optimum = _optimum[len]; 679 if (curAndLenPrice < optimum.Price) 680 { 681 optimum.Price = curAndLenPrice; 682 optimum.PosPrev = 0; 683 optimum.BackPrev = distance + Base.kNumRepDistances; 684 optimum.Prev1IsChar = false; 685 } 686 if (len == _matchDistances[offs]) 687 { 688 offs += 2; 689 if (offs == numDistancePairs) 690 break; 691 } 692 } 693 } 694 695 int cur = 0; 696 697 while (true) 698 { 699 cur++; 700 if (cur == lenEnd) 701 return Backward(cur); 702 int newLen = ReadMatchDistances(); 703 numDistancePairs = _numDistancePairs; 704 if (newLen >= _numFastBytes) 705 { 706 707 _longestMatchLength = newLen; 708 _longestMatchWasFound = true; 709 return Backward(cur); 710 } 711 position++; 712 int posPrev = _optimum[cur].PosPrev; 713 int state; 714 if (_optimum[cur].Prev1IsChar) 715 { 716 posPrev--; 717 if (_optimum[cur].Prev2) 718 { 719 state = _optimum[_optimum[cur].PosPrev2].State; 720 if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) 721 state = Base.StateUpdateRep(state); 722 else 723 state = Base.StateUpdateMatch(state); 724 } 725 else 726 state = _optimum[posPrev].State; 727 state = Base.StateUpdateChar(state); 728 } 729 else 730 state = _optimum[posPrev].State; 731 if (posPrev == cur - 1) 732 { 733 if (_optimum[cur].IsShortRep()) 734 state = Base.StateUpdateShortRep(state); 735 else 736 state = Base.StateUpdateChar(state); 737 } 738 else 739 { 740 int pos; 741 if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) 742 { 743 posPrev = _optimum[cur].PosPrev2; 744 pos = _optimum[cur].BackPrev2; 745 state = Base.StateUpdateRep(state); 746 } 747 else 748 { 749 pos = _optimum[cur].BackPrev; 750 if (pos < Base.kNumRepDistances) 751 state = Base.StateUpdateRep(state); 752 else 753 state = Base.StateUpdateMatch(state); 754 } 755 Optimal opt = _optimum[posPrev]; 756 if (pos < Base.kNumRepDistances) 757 { 758 if (pos == 0) 759 { 760 reps[0] = opt.Backs0; 761 reps[1] = opt.Backs1; 762 reps[2] = opt.Backs2; 763 reps[3] = opt.Backs3; 764 } 765 else if (pos == 1) 766 { 767 reps[0] = opt.Backs1; 768 reps[1] = opt.Backs0; 769 reps[2] = opt.Backs2; 770 reps[3] = opt.Backs3; 771 } 772 else if (pos == 2) 773 { 774 reps[0] = opt.Backs2; 775 reps[1] = opt.Backs0; 776 reps[2] = opt.Backs1; 777 reps[3] = opt.Backs3; 778 } 779 else 780 { 781 reps[0] = opt.Backs3; 782 reps[1] = opt.Backs0; 783 reps[2] = opt.Backs1; 784 reps[3] = opt.Backs2; 785 } 786 } 787 else 788 { 789 reps[0] = (pos - Base.kNumRepDistances); 790 reps[1] = opt.Backs0; 791 reps[2] = opt.Backs1; 792 reps[3] = opt.Backs2; 793 } 794 } 795 _optimum[cur].State = state; 796 _optimum[cur].Backs0 = reps[0]; 797 _optimum[cur].Backs1 = reps[1]; 798 _optimum[cur].Backs2 = reps[2]; 799 _optimum[cur].Backs3 = reps[3]; 800 int curPrice = _optimum[cur].Price; 801 802 currentByte = _matchFinder.GetIndexByte(0 - 1); 803 matchByte = _matchFinder.GetIndexByte(0 - reps[0] - 1 - 1); 804 805 posState = (position & _posStateMask); 806 807 int curAnd1Price = curPrice + 808 SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]) + 809 _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). 810 GetPrice(!Base.StateIsCharState(state), matchByte, currentByte); 811 812 Optimal nextOptimum = _optimum[cur + 1]; 813 814 boolean nextIsChar = false; 815 if (curAnd1Price < nextOptimum.Price) 816 { 817 nextOptimum.Price = curAnd1Price; 818 nextOptimum.PosPrev = cur; 819 nextOptimum.MakeAsChar(); 820 nextIsChar = true; 821 } 822 823 matchPrice = curPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state << Base.kNumPosStatesBitsMax) + posState]); 824 repMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state]); 825 826 if (matchByte == currentByte && 827 !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) 828 { 829 int shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); 830 if (shortRepPrice <= nextOptimum.Price) 831 { 832 nextOptimum.Price = shortRepPrice; 833 nextOptimum.PosPrev = cur; 834 nextOptimum.MakeAsShortRep(); 835 nextIsChar = true; 836 } 837 } 838 839 int numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; 840 numAvailableBytesFull = Math.min(kNumOpts - 1 - cur, numAvailableBytesFull); 841 numAvailableBytes = numAvailableBytesFull; 842 843 if (numAvailableBytes < 2) 844 continue; 845 if (numAvailableBytes > _numFastBytes) 846 numAvailableBytes = _numFastBytes; 847 if (!nextIsChar && matchByte != currentByte) 848 { 849 // try Literal + rep0 850 int t = Math.min(numAvailableBytesFull - 1, _numFastBytes); 851 int lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); 852 if (lenTest2 >= 2) 853 { 854 int state2 = Base.StateUpdateChar(state); 855 856 int posStateNext = (position + 1) & _posStateMask; 857 int nextRepMatchPrice = curAnd1Price + 858 SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + 859 SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); 860 { 861 int offset = cur + 1 + lenTest2; 862 while (lenEnd < offset) 863 _optimum[++lenEnd].Price = kIfinityPrice; 864 int curAndLenPrice = nextRepMatchPrice + GetRepPrice( 865 0, lenTest2, state2, posStateNext); 866 Optimal optimum = _optimum[offset]; 867 if (curAndLenPrice < optimum.Price) 868 { 869 optimum.Price = curAndLenPrice; 870 optimum.PosPrev = cur + 1; 871 optimum.BackPrev = 0; 872 optimum.Prev1IsChar = true; 873 optimum.Prev2 = false; 874 } 875 } 876 } 877 } 878 879 int startLen = 2; // speed optimization 880 881 for (int repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) 882 { 883 int lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); 884 if (lenTest < 2) 885 continue; 886 int lenTestTemp = lenTest; 887 do 888 { 889 while (lenEnd < cur + lenTest) 890 _optimum[++lenEnd].Price = kIfinityPrice; 891 int curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); 892 Optimal optimum = _optimum[cur + lenTest]; 893 if (curAndLenPrice < optimum.Price) 894 { 895 optimum.Price = curAndLenPrice; 896 optimum.PosPrev = cur; 897 optimum.BackPrev = repIndex; 898 optimum.Prev1IsChar = false; 899 } 900 } 901 while (--lenTest >= 2); 902 lenTest = lenTestTemp; 903 904 if (repIndex == 0) 905 startLen = lenTest + 1; 906 907 // if (_maxMode) 908 if (lenTest < numAvailableBytesFull) 909 { 910 int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); 911 int lenTest2 = _matchFinder.GetMatchLen(lenTest, reps[repIndex], t); 912 if (lenTest2 >= 2) 913 { 914 int state2 = Base.StateUpdateRep(state); 915 916 int posStateNext = (position + lenTest) & _posStateMask; 917 int curAndLenCharPrice = 918 repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + 919 SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + 920 _literalEncoder.GetSubCoder(position + lenTest, 921 _matchFinder.GetIndexByte(lenTest - 1 - 1)).GetPrice(true, 922 _matchFinder.GetIndexByte(lenTest - 1 - (reps[repIndex] + 1)), 923 _matchFinder.GetIndexByte(lenTest - 1)); 924 state2 = Base.StateUpdateChar(state2); 925 posStateNext = (position + lenTest + 1) & _posStateMask; 926 int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); 927 int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); 928 929 // for(; lenTest2 >= 2; lenTest2--) 930 { 931 int offset = lenTest + 1 + lenTest2; 932 while (lenEnd < cur + offset) 933 _optimum[++lenEnd].Price = kIfinityPrice; 934 int curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); 935 Optimal optimum = _optimum[cur + offset]; 936 if (curAndLenPrice < optimum.Price) 937 { 938 optimum.Price = curAndLenPrice; 939 optimum.PosPrev = cur + lenTest + 1; 940 optimum.BackPrev = 0; 941 optimum.Prev1IsChar = true; 942 optimum.Prev2 = true; 943 optimum.PosPrev2 = cur; 944 optimum.BackPrev2 = repIndex; 945 } 946 } 947 } 948 } 949 } 950 951 if (newLen > numAvailableBytes) 952 { 953 newLen = numAvailableBytes; 954 for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; 955 _matchDistances[numDistancePairs] = newLen; 956 numDistancePairs += 2; 957 } 958 if (newLen >= startLen) 959 { 960 normalMatchPrice = matchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isRep[state]); 961 while (lenEnd < cur + newLen) 962 _optimum[++lenEnd].Price = kIfinityPrice; 963 964 int offs = 0; 965 while (startLen > _matchDistances[offs]) 966 offs += 2; 967 968 for (int lenTest = startLen; ; lenTest++) 969 { 970 int curBack = _matchDistances[offs + 1]; 971 int curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); 972 Optimal optimum = _optimum[cur + lenTest]; 973 if (curAndLenPrice < optimum.Price) 974 { 975 optimum.Price = curAndLenPrice; 976 optimum.PosPrev = cur; 977 optimum.BackPrev = curBack + Base.kNumRepDistances; 978 optimum.Prev1IsChar = false; 979 } 980 981 if (lenTest == _matchDistances[offs]) 982 { 983 if (lenTest < numAvailableBytesFull) 984 { 985 int t = Math.min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); 986 int lenTest2 = _matchFinder.GetMatchLen(lenTest, curBack, t); 987 if (lenTest2 >= 2) 988 { 989 int state2 = Base.StateUpdateMatch(state); 990 991 int posStateNext = (position + lenTest) & _posStateMask; 992 int curAndLenCharPrice = curAndLenPrice + 993 SevenZip.Compression.RangeCoder.Encoder.GetPrice0(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]) + 994 _literalEncoder.GetSubCoder(position + lenTest, 995 _matchFinder.GetIndexByte(lenTest - 1 - 1)). 996 GetPrice(true, 997 _matchFinder.GetIndexByte(lenTest - (curBack + 1) - 1), 998 _matchFinder.GetIndexByte(lenTest - 1)); 999 state2 = Base.StateUpdateChar(state2); 1000 posStateNext = (position + lenTest + 1) & _posStateMask; 1001 int nextMatchPrice = curAndLenCharPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isMatch[(state2 << Base.kNumPosStatesBitsMax) + posStateNext]); 1002 int nextRepMatchPrice = nextMatchPrice + SevenZip.Compression.RangeCoder.Encoder.GetPrice1(_isRep[state2]); 1003 1004 int offset = lenTest + 1 + lenTest2; 1005 while (lenEnd < cur + offset) 1006 _optimum[++lenEnd].Price = kIfinityPrice; 1007 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); 1008 optimum = _optimum[cur + offset]; 1009 if (curAndLenPrice < optimum.Price) 1010 { 1011 optimum.Price = curAndLenPrice; 1012 optimum.PosPrev = cur + lenTest + 1; 1013 optimum.BackPrev = 0; 1014 optimum.Prev1IsChar = true; 1015 optimum.Prev2 = true; 1016 optimum.PosPrev2 = cur; 1017 optimum.BackPrev2 = curBack + Base.kNumRepDistances; 1018 } 1019 } 1020 } 1021 offs += 2; 1022 if (offs == numDistancePairs) 1023 break; 1024 } 1025 } 1026 } 1027 } 1028 } 1029 ChangePair(int smallDist, int bigDist)1030 boolean ChangePair(int smallDist, int bigDist) 1031 { 1032 int kDif = 7; 1033 return (smallDist < (1 << (32 - kDif)) && bigDist >= (smallDist << kDif)); 1034 } 1035 WriteEndMarker(int posState)1036 void WriteEndMarker(int posState) throws IOException 1037 { 1038 if (!_writeEndMark) 1039 return; 1040 1041 _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 1); 1042 _rangeEncoder.Encode(_isRep, _state, 0); 1043 _state = Base.StateUpdateMatch(_state); 1044 int len = Base.kMatchMinLen; 1045 _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); 1046 int posSlot = (1 << Base.kNumPosSlotBits) - 1; 1047 int lenToPosState = Base.GetLenToPosState(len); 1048 _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); 1049 int footerBits = 30; 1050 int posReduced = (1 << footerBits) - 1; 1051 _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); 1052 _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); 1053 } 1054 Flush(int nowPos)1055 void Flush(int nowPos) throws IOException 1056 { 1057 ReleaseMFStream(); 1058 WriteEndMarker(nowPos & _posStateMask); 1059 _rangeEncoder.FlushData(); 1060 _rangeEncoder.FlushStream(); 1061 } 1062 CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished)1063 public void CodeOneBlock(long[] inSize, long[] outSize, boolean[] finished) throws IOException 1064 { 1065 inSize[0] = 0; 1066 outSize[0] = 0; 1067 finished[0] = true; 1068 1069 if (_inStream != null) 1070 { 1071 _matchFinder.SetStream(_inStream); 1072 _matchFinder.Init(); 1073 _needReleaseMFStream = true; 1074 _inStream = null; 1075 } 1076 1077 if (_finished) 1078 return; 1079 _finished = true; 1080 1081 1082 long progressPosValuePrev = nowPos64; 1083 if (nowPos64 == 0) 1084 { 1085 if (_matchFinder.GetNumAvailableBytes() == 0) 1086 { 1087 Flush((int)nowPos64); 1088 return; 1089 } 1090 1091 ReadMatchDistances(); 1092 int posState = (int)(nowPos64) & _posStateMask; 1093 _rangeEncoder.Encode(_isMatch, (_state << Base.kNumPosStatesBitsMax) + posState, 0); 1094 _state = Base.StateUpdateChar(_state); 1095 byte curByte = _matchFinder.GetIndexByte(0 - _additionalOffset); 1096 _literalEncoder.GetSubCoder((int)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); 1097 _previousByte = curByte; 1098 _additionalOffset--; 1099 nowPos64++; 1100 } 1101 if (_matchFinder.GetNumAvailableBytes() == 0) 1102 { 1103 Flush((int)nowPos64); 1104 return; 1105 } 1106 while (true) 1107 { 1108 1109 int len = GetOptimum((int)nowPos64); 1110 int pos = backRes; 1111 int posState = ((int)nowPos64) & _posStateMask; 1112 int complexState = (_state << Base.kNumPosStatesBitsMax) + posState; 1113 if (len == 1 && pos == -1) 1114 { 1115 _rangeEncoder.Encode(_isMatch, complexState, 0); 1116 byte curByte = _matchFinder.GetIndexByte((int)(0 - _additionalOffset)); 1117 LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((int)nowPos64, _previousByte); 1118 if (!Base.StateIsCharState(_state)) 1119 { 1120 byte matchByte = _matchFinder.GetIndexByte((int)(0 - _repDistances[0] - 1 - _additionalOffset)); 1121 subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); 1122 } 1123 else 1124 subCoder.Encode(_rangeEncoder, curByte); 1125 _previousByte = curByte; 1126 _state = Base.StateUpdateChar(_state); 1127 } 1128 else 1129 { 1130 _rangeEncoder.Encode(_isMatch, complexState, 1); 1131 if (pos < Base.kNumRepDistances) 1132 { 1133 _rangeEncoder.Encode(_isRep, _state, 1); 1134 if (pos == 0) 1135 { 1136 _rangeEncoder.Encode(_isRepG0, _state, 0); 1137 if (len == 1) 1138 _rangeEncoder.Encode(_isRep0Long, complexState, 0); 1139 else 1140 _rangeEncoder.Encode(_isRep0Long, complexState, 1); 1141 } 1142 else 1143 { 1144 _rangeEncoder.Encode(_isRepG0, _state, 1); 1145 if (pos == 1) 1146 _rangeEncoder.Encode(_isRepG1, _state, 0); 1147 else 1148 { 1149 _rangeEncoder.Encode(_isRepG1, _state, 1); 1150 _rangeEncoder.Encode(_isRepG2, _state, pos - 2); 1151 } 1152 } 1153 if (len == 1) 1154 _state = Base.StateUpdateShortRep(_state); 1155 else 1156 { 1157 _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); 1158 _state = Base.StateUpdateRep(_state); 1159 } 1160 int distance = _repDistances[pos]; 1161 if (pos != 0) 1162 { 1163 for (int i = pos; i >= 1; i--) 1164 _repDistances[i] = _repDistances[i - 1]; 1165 _repDistances[0] = distance; 1166 } 1167 } 1168 else 1169 { 1170 _rangeEncoder.Encode(_isRep, _state, 0); 1171 _state = Base.StateUpdateMatch(_state); 1172 _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); 1173 pos -= Base.kNumRepDistances; 1174 int posSlot = GetPosSlot(pos); 1175 int lenToPosState = Base.GetLenToPosState(len); 1176 _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); 1177 1178 if (posSlot >= Base.kStartPosModelIndex) 1179 { 1180 int footerBits = (int)((posSlot >> 1) - 1); 1181 int baseVal = ((2 | (posSlot & 1)) << footerBits); 1182 int posReduced = pos - baseVal; 1183 1184 if (posSlot < Base.kEndPosModelIndex) 1185 BitTreeEncoder.ReverseEncode(_posEncoders, 1186 baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); 1187 else 1188 { 1189 _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); 1190 _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); 1191 _alignPriceCount++; 1192 } 1193 } 1194 int distance = pos; 1195 for (int i = Base.kNumRepDistances - 1; i >= 1; i--) 1196 _repDistances[i] = _repDistances[i - 1]; 1197 _repDistances[0] = distance; 1198 _matchPriceCount++; 1199 } 1200 _previousByte = _matchFinder.GetIndexByte(len - 1 - _additionalOffset); 1201 } 1202 _additionalOffset -= len; 1203 nowPos64 += len; 1204 if (_additionalOffset == 0) 1205 { 1206 // if (!_fastMode) 1207 if (_matchPriceCount >= (1 << 7)) 1208 FillDistancesPrices(); 1209 if (_alignPriceCount >= Base.kAlignTableSize) 1210 FillAlignPrices(); 1211 inSize[0] = nowPos64; 1212 outSize[0] = _rangeEncoder.GetProcessedSizeAdd(); 1213 if (_matchFinder.GetNumAvailableBytes() == 0) 1214 { 1215 Flush((int)nowPos64); 1216 return; 1217 } 1218 1219 if (nowPos64 - progressPosValuePrev >= (1 << 12)) 1220 { 1221 _finished = false; 1222 finished[0] = false; 1223 return; 1224 } 1225 } 1226 } 1227 } 1228 ReleaseMFStream()1229 void ReleaseMFStream() 1230 { 1231 if (_matchFinder != null && _needReleaseMFStream) 1232 { 1233 _matchFinder.ReleaseStream(); 1234 _needReleaseMFStream = false; 1235 } 1236 } 1237 SetOutStream(java.io.OutputStream outStream)1238 void SetOutStream(java.io.OutputStream outStream) 1239 { _rangeEncoder.SetStream(outStream); } ReleaseOutStream()1240 void ReleaseOutStream() 1241 { _rangeEncoder.ReleaseStream(); } 1242 ReleaseStreams()1243 void ReleaseStreams() 1244 { 1245 ReleaseMFStream(); 1246 ReleaseOutStream(); 1247 } 1248 SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize)1249 void SetStreams(java.io.InputStream inStream, java.io.OutputStream outStream, 1250 long inSize, long outSize) 1251 { 1252 _inStream = inStream; 1253 _finished = false; 1254 Create(); 1255 SetOutStream(outStream); 1256 Init(); 1257 1258 // if (!_fastMode) 1259 { 1260 FillDistancesPrices(); 1261 FillAlignPrices(); 1262 } 1263 1264 _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); 1265 _lenEncoder.UpdateTables(1 << _posStateBits); 1266 _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); 1267 _repMatchLenEncoder.UpdateTables(1 << _posStateBits); 1268 1269 nowPos64 = 0; 1270 } 1271 1272 long[] processedInSize = new long[1]; long[] processedOutSize = new long[1]; boolean[] finished = new boolean[1]; Code(java.io.InputStream inStream, java.io.OutputStream outStream, long inSize, long outSize, ICodeProgress progress)1273 public void Code(java.io.InputStream inStream, java.io.OutputStream outStream, 1274 long inSize, long outSize, ICodeProgress progress) throws IOException 1275 { 1276 _needReleaseMFStream = false; 1277 try 1278 { 1279 SetStreams(inStream, outStream, inSize, outSize); 1280 while (true) 1281 { 1282 1283 1284 1285 CodeOneBlock(processedInSize, processedOutSize, finished); 1286 if (finished[0]) 1287 return; 1288 if (progress != null) 1289 { 1290 progress.SetProgress(processedInSize[0], processedOutSize[0]); 1291 } 1292 } 1293 } 1294 finally 1295 { 1296 ReleaseStreams(); 1297 } 1298 } 1299 1300 public static final int kPropSize = 5; 1301 byte[] properties = new byte[kPropSize]; 1302 WriteCoderProperties(java.io.OutputStream outStream)1303 public void WriteCoderProperties(java.io.OutputStream outStream) throws IOException 1304 { 1305 properties[0] = (byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); 1306 for (int i = 0; i < 4; i++) 1307 properties[1 + i] = (byte)(_dictionarySize >> (8 * i)); 1308 outStream.write(properties, 0, kPropSize); 1309 } 1310 1311 int[] tempPrices = new int[Base.kNumFullDistances]; 1312 int _matchPriceCount; 1313 FillDistancesPrices()1314 void FillDistancesPrices() 1315 { 1316 for (int i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) 1317 { 1318 int posSlot = GetPosSlot(i); 1319 int footerBits = (int)((posSlot >> 1) - 1); 1320 int baseVal = ((2 | (posSlot & 1)) << footerBits); 1321 tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, 1322 baseVal - posSlot - 1, footerBits, i - baseVal); 1323 } 1324 1325 for (int lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) 1326 { 1327 int posSlot; 1328 BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; 1329 1330 int st = (lenToPosState << Base.kNumPosSlotBits); 1331 for (posSlot = 0; posSlot < _distTableSize; posSlot++) 1332 _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); 1333 for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) 1334 _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << SevenZip.Compression.RangeCoder.Encoder.kNumBitPriceShiftBits); 1335 1336 int st2 = lenToPosState * Base.kNumFullDistances; 1337 int i; 1338 for (i = 0; i < Base.kStartPosModelIndex; i++) 1339 _distancesPrices[st2 + i] = _posSlotPrices[st + i]; 1340 for (; i < Base.kNumFullDistances; i++) 1341 _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; 1342 } 1343 _matchPriceCount = 0; 1344 } 1345 FillAlignPrices()1346 void FillAlignPrices() 1347 { 1348 for (int i = 0; i < Base.kAlignTableSize; i++) 1349 _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); 1350 _alignPriceCount = 0; 1351 } 1352 1353 SetAlgorithm(int algorithm)1354 public boolean SetAlgorithm(int algorithm) 1355 { 1356 /* 1357 _fastMode = (algorithm == 0); 1358 _maxMode = (algorithm >= 2); 1359 */ 1360 return true; 1361 } 1362 SetDictionarySize(int dictionarySize)1363 public boolean SetDictionarySize(int dictionarySize) 1364 { 1365 int kDicLogSizeMaxCompress = 29; 1366 if (dictionarySize < (1 << Base.kDicLogSizeMin) || dictionarySize > (1 << kDicLogSizeMaxCompress)) 1367 return false; 1368 _dictionarySize = dictionarySize; 1369 int dicLogSize; 1370 for (dicLogSize = 0; dictionarySize > (1 << dicLogSize); dicLogSize++) ; 1371 _distTableSize = dicLogSize * 2; 1372 return true; 1373 } 1374 SetNumFastBytes(int numFastBytes)1375 public boolean SetNumFastBytes(int numFastBytes) 1376 { 1377 if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) 1378 return false; 1379 _numFastBytes = numFastBytes; 1380 return true; 1381 } 1382 SetMatchFinder(int matchFinderIndex)1383 public boolean SetMatchFinder(int matchFinderIndex) 1384 { 1385 if (matchFinderIndex < 0 || matchFinderIndex > 2) 1386 return false; 1387 int matchFinderIndexPrev = _matchFinderType; 1388 _matchFinderType = matchFinderIndex; 1389 if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) 1390 { 1391 _dictionarySizePrev = -1; 1392 _matchFinder = null; 1393 } 1394 return true; 1395 } 1396 SetLcLpPb(int lc, int lp, int pb)1397 public boolean SetLcLpPb(int lc, int lp, int pb) 1398 { 1399 if ( 1400 lp < 0 || lp > Base.kNumLitPosStatesBitsEncodingMax || 1401 lc < 0 || lc > Base.kNumLitContextBitsMax || 1402 pb < 0 || pb > Base.kNumPosStatesBitsEncodingMax) 1403 return false; 1404 _numLiteralPosStateBits = lp; 1405 _numLiteralContextBits = lc; 1406 _posStateBits = pb; 1407 _posStateMask = ((1) << _posStateBits) - 1; 1408 return true; 1409 } 1410 SetEndMarkerMode(boolean endMarkerMode)1411 public void SetEndMarkerMode(boolean endMarkerMode) 1412 { 1413 _writeEndMark = endMarkerMode; 1414 } 1415 } 1416 1417