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