Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZMA/LZMAEncoder.cpp, revision 1.1
1.1 ! misho 1: // LZMA/Encoder.cpp
! 2:
! 3: #include "StdAfx.h"
! 4:
! 5: #include "../../../Common/Defs.h"
! 6:
! 7: #include "LZMAEncoder.h"
! 8:
! 9: // for minimal compressing code size define these:
! 10: // #define COMPRESS_MF_BT
! 11: // #define COMPRESS_MF_BT4
! 12:
! 13: #if !defined(COMPRESS_MF_BT) && !defined(COMPRESS_MF_PAT) && !defined(COMPRESS_MF_HC)
! 14: #define COMPRESS_MF_BT
! 15: #define COMPRESS_MF_PAT
! 16: #define COMPRESS_MF_HC
! 17: #endif
! 18:
! 19: #ifdef COMPRESS_MF_BT
! 20: #if !defined(COMPRESS_MF_BT2) && !defined(COMPRESS_MF_BT3) && !defined(COMPRESS_MF_BT4) && !defined(COMPRESS_MF_BT4B)
! 21: #define COMPRESS_MF_BT2
! 22: #define COMPRESS_MF_BT3
! 23: #define COMPRESS_MF_BT4
! 24: #define COMPRESS_MF_BT4B
! 25: #endif
! 26: #ifdef COMPRESS_MF_BT2
! 27: #include "../LZ/BinTree/BinTree2.h"
! 28: #endif
! 29: #ifdef COMPRESS_MF_BT3
! 30: #include "../LZ/BinTree/BinTree3.h"
! 31: #endif
! 32: #ifdef COMPRESS_MF_BT4
! 33: #include "../LZ/BinTree/BinTree4.h"
! 34: #endif
! 35: #ifdef COMPRESS_MF_BT4B
! 36: #include "../LZ/BinTree/BinTree4b.h"
! 37: #endif
! 38: #endif
! 39:
! 40: #ifdef COMPRESS_MF_PAT
! 41: #include "../LZ/Patricia/Pat2.h"
! 42: #include "../LZ/Patricia/Pat2H.h"
! 43: #include "../LZ/Patricia/Pat3H.h"
! 44: #include "../LZ/Patricia/Pat4H.h"
! 45: #include "../LZ/Patricia/Pat2R.h"
! 46: #endif
! 47:
! 48: #ifdef COMPRESS_MF_HC
! 49: #include "../LZ/HashChain/HC3.h"
! 50: #include "../LZ/HashChain/HC4.h"
! 51: #endif
! 52:
! 53: #ifdef COMPRESS_MF_MT
! 54: #include "../LZ/MT/MT.h"
! 55: #endif
! 56:
! 57: namespace NCompress {
! 58: namespace NLZMA {
! 59:
! 60: const int kDefaultDictionaryLogSize = 20;
! 61: const UInt32 kNumFastBytesDefault = 0x20;
! 62:
! 63: enum
! 64: {
! 65: kBT2,
! 66: kBT3,
! 67: kBT4,
! 68: kBT4B,
! 69: kPat2,
! 70: kPat2H,
! 71: kPat3H,
! 72: kPat4H,
! 73: kPat2R,
! 74: kHC3,
! 75: kHC4
! 76: };
! 77:
! 78: static const wchar_t *kMatchFinderIDs[] =
! 79: {
! 80: L"BT2",
! 81: L"BT3",
! 82: L"BT4",
! 83: L"BT4B",
! 84: L"PAT2",
! 85: L"PAT2H",
! 86: L"PAT3H",
! 87: L"PAT4H",
! 88: L"PAT2R",
! 89: L"HC3",
! 90: L"HC4"
! 91: };
! 92:
! 93: Byte g_FastPos[1024];
! 94:
! 95: class CFastPosInit
! 96: {
! 97: public:
! 98: CFastPosInit() { Init(); }
! 99: void Init()
! 100: {
! 101: const Byte kFastSlots = 20;
! 102: int c = 2;
! 103: g_FastPos[0] = 0;
! 104: g_FastPos[1] = 1;
! 105:
! 106: for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
! 107: {
! 108: UInt32 k = (1 << ((slotFast >> 1) - 1));
! 109: for (UInt32 j = 0; j < k; j++, c++)
! 110: g_FastPos[c] = slotFast;
! 111: }
! 112: }
! 113: } g_FastPosInit;
! 114:
! 115:
! 116: void CLiteralEncoder2::Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol)
! 117: {
! 118: UInt32 context = 1;
! 119: int i = 8;
! 120: do
! 121: {
! 122: i--;
! 123: UInt32 bit = (symbol >> i) & 1;
! 124: _encoders[context].Encode(rangeEncoder, bit);
! 125: context = (context << 1) | bit;
! 126: }
! 127: while(i != 0);
! 128: }
! 129:
! 130: void CLiteralEncoder2::EncodeMatched(NRangeCoder::CEncoder *rangeEncoder,
! 131: Byte matchByte, Byte symbol)
! 132: {
! 133: UInt32 context = 1;
! 134: int i = 8;
! 135: do
! 136: {
! 137: i--;
! 138: UInt32 bit = (symbol >> i) & 1;
! 139: UInt32 matchBit = (matchByte >> i) & 1;
! 140: _encoders[0x100 + (matchBit << 8) + context].Encode(rangeEncoder, bit);
! 141: context = (context << 1) | bit;
! 142: if (matchBit != bit)
! 143: {
! 144: while(i != 0)
! 145: {
! 146: i--;
! 147: UInt32 bit = (symbol >> i) & 1;
! 148: _encoders[context].Encode(rangeEncoder, bit);
! 149: context = (context << 1) | bit;
! 150: }
! 151: break;
! 152: }
! 153: }
! 154: while(i != 0);
! 155: }
! 156:
! 157: UInt32 CLiteralEncoder2::GetPrice(bool matchMode, Byte matchByte, Byte symbol) const
! 158: {
! 159: UInt32 price = 0;
! 160: UInt32 context = 1;
! 161: int i = 8;
! 162: if (matchMode)
! 163: {
! 164: do
! 165: {
! 166: i--;
! 167: UInt32 matchBit = (matchByte >> i) & 1;
! 168: UInt32 bit = (symbol >> i) & 1;
! 169: price += _encoders[0x100 + (matchBit << 8) + context].GetPrice(bit);
! 170: context = (context << 1) | bit;
! 171: if (matchBit != bit)
! 172: break;
! 173: }
! 174: while (i != 0);
! 175: }
! 176: while(i != 0)
! 177: {
! 178: i--;
! 179: UInt32 bit = (symbol >> i) & 1;
! 180: price += _encoders[context].GetPrice(bit);
! 181: context = (context << 1) | bit;
! 182: }
! 183: return price;
! 184: };
! 185:
! 186:
! 187: namespace NLength {
! 188:
! 189: void CEncoder::Init(UInt32 numPosStates)
! 190: {
! 191: _choice.Init();
! 192: _choice2.Init();
! 193: for (UInt32 posState = 0; posState < numPosStates; posState++)
! 194: {
! 195: _lowCoder[posState].Init();
! 196: _midCoder[posState].Init();
! 197: }
! 198: _highCoder.Init();
! 199: }
! 200:
! 201: void CEncoder::Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState)
! 202: {
! 203: if(symbol < kNumLowSymbols)
! 204: {
! 205: _choice.Encode(rangeEncoder, 0);
! 206: _lowCoder[posState].Encode(rangeEncoder, symbol);
! 207: }
! 208: else
! 209: {
! 210: _choice.Encode(rangeEncoder, 1);
! 211: if(symbol < kNumLowSymbols + kNumMidSymbols)
! 212: {
! 213: _choice2.Encode(rangeEncoder, 0);
! 214: _midCoder[posState].Encode(rangeEncoder, symbol - kNumLowSymbols);
! 215: }
! 216: else
! 217: {
! 218: _choice2.Encode(rangeEncoder, 1);
! 219: _highCoder.Encode(rangeEncoder, symbol - kNumLowSymbols - kNumMidSymbols);
! 220: }
! 221: }
! 222: }
! 223:
! 224: UInt32 CEncoder::GetPrice(UInt32 symbol, UInt32 posState) const
! 225: {
! 226: if(symbol < kNumLowSymbols)
! 227: return _choice.GetPrice0() + _lowCoder[posState].GetPrice(symbol);
! 228: UInt32 price = _choice.GetPrice1();
! 229: if(symbol < kNumLowSymbols + kNumMidSymbols)
! 230: {
! 231: price += _choice2.GetPrice0();
! 232: price += _midCoder[posState].GetPrice(symbol - kNumLowSymbols);
! 233: }
! 234: else
! 235: {
! 236: price += _choice2.GetPrice1();
! 237: price += _highCoder.GetPrice(symbol - kNumLowSymbols - kNumMidSymbols);
! 238: }
! 239: return price;
! 240: }
! 241:
! 242: }
! 243: CEncoder::CEncoder():
! 244: _numFastBytes(kNumFastBytesDefault),
! 245: _distTableSize(kDefaultDictionaryLogSize * 2),
! 246: _posStateBits(2),
! 247: _posStateMask(4 - 1),
! 248: _numLiteralPosStateBits(0),
! 249: _numLiteralContextBits(3),
! 250: _dictionarySize(1 << kDefaultDictionaryLogSize),
! 251: _dictionarySizePrev(UInt32(-1)),
! 252: _numFastBytesPrev(UInt32(-1)),
! 253: _matchFinderIndex(kBT4),
! 254: #ifdef COMPRESS_MF_MT
! 255: _multiThread(false),
! 256: #endif
! 257: _writeEndMark(false)
! 258: {
! 259: _maxMode = false;
! 260: _fastMode = false;
! 261: }
! 262:
! 263: HRESULT CEncoder::Create()
! 264: {
! 265: if (!_rangeEncoder.Create(1 << 20))
! 266: return E_OUTOFMEMORY;
! 267: if (!_matchFinder)
! 268: {
! 269: switch(_matchFinderIndex)
! 270: {
! 271: #ifdef COMPRESS_MF_BT
! 272: #ifdef COMPRESS_MF_BT2
! 273: case kBT2:
! 274: _matchFinder = new NBT2::CMatchFinderBinTree;
! 275: break;
! 276: #endif
! 277: #ifdef COMPRESS_MF_BT3
! 278: case kBT3:
! 279: _matchFinder = new NBT3::CMatchFinderBinTree;
! 280: break;
! 281: #endif
! 282: #ifdef COMPRESS_MF_BT4
! 283: case kBT4:
! 284: _matchFinder = new NBT4::CMatchFinderBinTree;
! 285: break;
! 286: #endif
! 287: #ifdef COMPRESS_MF_BT4B
! 288: case kBT4B:
! 289: _matchFinder = new NBT4B::CMatchFinderBinTree;
! 290: break;
! 291: #endif
! 292: #endif
! 293:
! 294: #ifdef COMPRESS_MF_PAT
! 295: case kPat2:
! 296: _matchFinder = new NPat2::CPatricia;
! 297: break;
! 298: case kPat2H:
! 299: _matchFinder = new NPat2H::CPatricia;
! 300: break;
! 301: case kPat3H:
! 302: _matchFinder = new NPat3H::CPatricia;
! 303: break;
! 304: case kPat4H:
! 305: _matchFinder = new NPat4H::CPatricia;
! 306: break;
! 307: case kPat2R:
! 308: _matchFinder = new NPat2R::CPatricia;
! 309: break;
! 310: #endif
! 311:
! 312: #ifdef COMPRESS_MF_HC
! 313: case kHC3:
! 314: _matchFinder = new NHC3::CMatchFinderHC;
! 315: break;
! 316: case kHC4:
! 317: _matchFinder = new NHC4::CMatchFinderHC;
! 318: break;
! 319: #endif
! 320: }
! 321: if (_matchFinder == 0)
! 322: return E_OUTOFMEMORY;
! 323:
! 324: #ifdef COMPRESS_MF_MT
! 325: if (_multiThread && !(_fastMode && (_matchFinderIndex == kHC3 || _matchFinderIndex == kHC4)))
! 326: {
! 327: CMatchFinderMT *mfSpec = new CMatchFinderMT;
! 328: if (mfSpec == 0)
! 329: return E_OUTOFMEMORY;
! 330: CMyComPtr<IMatchFinder> mf = mfSpec;
! 331: RINOK(mfSpec->SetMatchFinder(_matchFinder));
! 332: _matchFinder.Release();
! 333: _matchFinder = mf;
! 334: }
! 335: #endif
! 336: }
! 337:
! 338: if (!_literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits))
! 339: return E_OUTOFMEMORY;
! 340:
! 341: if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
! 342: return S_OK;
! 343: RINOK(_matchFinder->Create(_dictionarySize, kNumOpts, _numFastBytes,
! 344: kMatchMaxLen - _numFastBytes));
! 345: _dictionarySizePrev = _dictionarySize;
! 346: _numFastBytesPrev = _numFastBytes;
! 347: return S_OK;
! 348: }
! 349:
! 350: static bool AreStringsEqual(const wchar_t *base, const wchar_t *testString)
! 351: {
! 352: while (true)
! 353: {
! 354: wchar_t c = *testString;
! 355: if (c >= 'a' && c <= 'z')
! 356: c -= 0x20;
! 357: if (*base != c)
! 358: return false;
! 359: if (c == 0)
! 360: return true;
! 361: base++;
! 362: testString++;
! 363: }
! 364: }
! 365:
! 366: static int FindMatchFinder(const wchar_t *s)
! 367: {
! 368: for (int m = 0; m < (int)(sizeof(kMatchFinderIDs) / sizeof(kMatchFinderIDs[0])); m++)
! 369: if (AreStringsEqual(kMatchFinderIDs[m], s))
! 370: return m;
! 371: return -1;
! 372: }
! 373:
! 374: STDMETHODIMP CEncoder::SetCoderProperties(const PROPID *propIDs,
! 375: const PROPVARIANT *properties, UInt32 numProperties)
! 376: {
! 377: for (UInt32 i = 0; i < numProperties; i++)
! 378: {
! 379: const PROPVARIANT &prop = properties[i];
! 380: switch(propIDs[i])
! 381: {
! 382: case NCoderPropID::kNumFastBytes:
! 383: {
! 384: if (prop.vt != VT_UI4)
! 385: return E_INVALIDARG;
! 386: UInt32 numFastBytes = prop.ulVal;
! 387: if(numFastBytes < 2 || numFastBytes > kMatchMaxLen)
! 388: return E_INVALIDARG;
! 389: _numFastBytes = numFastBytes;
! 390: break;
! 391: }
! 392: case NCoderPropID::kAlgorithm:
! 393: {
! 394: if (prop.vt != VT_UI4)
! 395: return E_INVALIDARG;
! 396: UInt32 maximize = prop.ulVal;
! 397: _fastMode = (maximize == 0);
! 398: _maxMode = (maximize >= 2);
! 399: break;
! 400: }
! 401: case NCoderPropID::kMatchFinder:
! 402: {
! 403: if (prop.vt != VT_BSTR)
! 404: return E_INVALIDARG;
! 405: int matchFinderIndexPrev = _matchFinderIndex;
! 406: int m = FindMatchFinder(prop.bstrVal);
! 407: if (m < 0)
! 408: return E_INVALIDARG;
! 409: _matchFinderIndex = m;
! 410: if (_matchFinder && matchFinderIndexPrev != _matchFinderIndex)
! 411: {
! 412: _dictionarySizePrev = UInt32(-1);
! 413: _matchFinder.Release();
! 414: }
! 415: break;
! 416: }
! 417: #ifdef COMPRESS_MF_MT
! 418: case NCoderPropID::kMultiThread:
! 419: {
! 420: if (prop.vt != VT_BOOL)
! 421: return E_INVALIDARG;
! 422: bool newMultiThread = (prop.boolVal == VARIANT_TRUE);
! 423: if (newMultiThread != _multiThread)
! 424: {
! 425: _dictionarySizePrev = UInt32(-1);
! 426: _matchFinder.Release();
! 427: }
! 428: _multiThread = newMultiThread;
! 429: break;
! 430: }
! 431: #endif
! 432: case NCoderPropID::kDictionarySize:
! 433: {
! 434: const int kDicLogSizeMaxCompress = 28;
! 435: if (prop.vt != VT_UI4)
! 436: return E_INVALIDARG;
! 437: UInt32 dictionarySize = prop.ulVal;
! 438: if (dictionarySize < UInt32(1 << kDicLogSizeMin) ||
! 439: dictionarySize > UInt32(1 << kDicLogSizeMaxCompress))
! 440: return E_INVALIDARG;
! 441: _dictionarySize = dictionarySize;
! 442: UInt32 dicLogSize;
! 443: for(dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
! 444: if (dictionarySize <= (UInt32(1) << dicLogSize))
! 445: break;
! 446: _distTableSize = dicLogSize * 2;
! 447: break;
! 448: }
! 449: case NCoderPropID::kPosStateBits:
! 450: {
! 451: if (prop.vt != VT_UI4)
! 452: return E_INVALIDARG;
! 453: UInt32 value = prop.ulVal;
! 454: if (value > (UInt32)NLength::kNumPosStatesBitsEncodingMax)
! 455: return E_INVALIDARG;
! 456: _posStateBits = value;
! 457: _posStateMask = (1 << _posStateBits) - 1;
! 458: break;
! 459: }
! 460: case NCoderPropID::kLitPosBits:
! 461: {
! 462: if (prop.vt != VT_UI4)
! 463: return E_INVALIDARG;
! 464: UInt32 value = prop.ulVal;
! 465: if (value > (UInt32)kNumLitPosStatesBitsEncodingMax)
! 466: return E_INVALIDARG;
! 467: _numLiteralPosStateBits = value;
! 468: break;
! 469: }
! 470: case NCoderPropID::kLitContextBits:
! 471: {
! 472: if (prop.vt != VT_UI4)
! 473: return E_INVALIDARG;
! 474: UInt32 value = prop.ulVal;
! 475: if (value > (UInt32)kNumLitContextBitsMax)
! 476: return E_INVALIDARG;
! 477: _numLiteralContextBits = value;
! 478: break;
! 479: }
! 480: case NCoderPropID::kEndMarker:
! 481: {
! 482: if (prop.vt != VT_BOOL)
! 483: return E_INVALIDARG;
! 484: SetWriteEndMarkerMode(prop.boolVal == VARIANT_TRUE);
! 485: break;
! 486: }
! 487: default:
! 488: return E_INVALIDARG;
! 489: }
! 490: }
! 491: return S_OK;
! 492: }
! 493:
! 494: STDMETHODIMP CEncoder::WriteCoderProperties(ISequentialOutStream *outStream)
! 495: {
! 496: const UInt32 kPropSize = 5;
! 497: Byte properties[kPropSize];
! 498: properties[0] = (_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits;
! 499: for (int i = 0; i < 4; i++)
! 500: properties[1 + i] = Byte(_dictionarySize >> (8 * i));
! 501: return outStream->Write(properties, kPropSize, NULL);
! 502: }
! 503:
! 504: STDMETHODIMP CEncoder::SetOutStream(ISequentialOutStream *outStream)
! 505: {
! 506: _rangeEncoder.SetStream(outStream);
! 507: return S_OK;
! 508: }
! 509:
! 510: STDMETHODIMP CEncoder::ReleaseOutStream()
! 511: {
! 512: _rangeEncoder.ReleaseStream();
! 513: return S_OK;
! 514: }
! 515:
! 516: HRESULT CEncoder::Init()
! 517: {
! 518: CBaseState::Init();
! 519:
! 520: // RINOK(_matchFinder->Init(inStream));
! 521: _rangeEncoder.Init();
! 522:
! 523: for(int i = 0; i < kNumStates; i++)
! 524: {
! 525: for (UInt32 j = 0; j <= _posStateMask; j++)
! 526: {
! 527: _isMatch[i][j].Init();
! 528: _isRep0Long[i][j].Init();
! 529: }
! 530: _isRep[i].Init();
! 531: _isRepG0[i].Init();
! 532: _isRepG1[i].Init();
! 533: _isRepG2[i].Init();
! 534: }
! 535:
! 536: _literalEncoder.Init();
! 537:
! 538: // _repMatchLenEncoder.Init();
! 539:
! 540: {
! 541: for(UInt32 i = 0; i < kNumLenToPosStates; i++)
! 542: _posSlotEncoder[i].Init();
! 543: }
! 544: {
! 545: for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
! 546: _posEncoders[i].Init();
! 547: }
! 548:
! 549: _lenEncoder.Init(1 << _posStateBits);
! 550: _repMatchLenEncoder.Init(1 << _posStateBits);
! 551:
! 552: _posAlignEncoder.Init();
! 553:
! 554: _longestMatchWasFound = false;
! 555: _optimumEndIndex = 0;
! 556: _optimumCurrentIndex = 0;
! 557: _additionalOffset = 0;
! 558:
! 559: return S_OK;
! 560: }
! 561:
! 562: HRESULT CEncoder::MovePos(UInt32 num)
! 563: {
! 564: for (;num != 0; num--)
! 565: {
! 566: _matchFinder->DummyLongestMatch();
! 567: RINOK(_matchFinder->MovePos());
! 568: _additionalOffset++;
! 569: }
! 570: return S_OK;
! 571: }
! 572:
! 573: UInt32 CEncoder::Backward(UInt32 &backRes, UInt32 cur)
! 574: {
! 575: _optimumEndIndex = cur;
! 576: UInt32 posMem = _optimum[cur].PosPrev;
! 577: UInt32 backMem = _optimum[cur].BackPrev;
! 578: do
! 579: {
! 580: if (_optimum[cur].Prev1IsChar)
! 581: {
! 582: _optimum[posMem].MakeAsChar();
! 583: _optimum[posMem].PosPrev = posMem - 1;
! 584: if (_optimum[cur].Prev2)
! 585: {
! 586: _optimum[posMem - 1].Prev1IsChar = false;
! 587: _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
! 588: _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
! 589: }
! 590: }
! 591: UInt32 posPrev = posMem;
! 592: UInt32 backCur = backMem;
! 593:
! 594: backMem = _optimum[posPrev].BackPrev;
! 595: posMem = _optimum[posPrev].PosPrev;
! 596:
! 597: _optimum[posPrev].BackPrev = backCur;
! 598: _optimum[posPrev].PosPrev = cur;
! 599: cur = posPrev;
! 600: }
! 601: while(cur != 0);
! 602: backRes = _optimum[0].BackPrev;
! 603: _optimumCurrentIndex = _optimum[0].PosPrev;
! 604: return _optimumCurrentIndex;
! 605: }
! 606:
! 607: /*
! 608: inline UInt32 GetMatchLen(const Byte *data, UInt32 back, UInt32 limit)
! 609: {
! 610: back++;
! 611: for(UInt32 i = 0; i < limit && data[i] == data[i - back]; i++);
! 612: return i;
! 613: }
! 614: */
! 615:
! 616: HRESULT CEncoder::GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
! 617: {
! 618: if(_optimumEndIndex != _optimumCurrentIndex)
! 619: {
! 620: lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
! 621: backRes = _optimum[_optimumCurrentIndex].BackPrev;
! 622: _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
! 623: return S_OK;
! 624: }
! 625: _optimumCurrentIndex = 0;
! 626: _optimumEndIndex = 0; // test it;
! 627:
! 628: UInt32 lenMain;
! 629: if (!_longestMatchWasFound)
! 630: {
! 631: RINOK(ReadMatchDistances(lenMain));
! 632: }
! 633: else
! 634: {
! 635: lenMain = _longestMatchLength;
! 636: _longestMatchWasFound = false;
! 637: }
! 638:
! 639:
! 640: UInt32 reps[kNumRepDistances];
! 641: UInt32 repLens[kNumRepDistances];
! 642: UInt32 repMaxIndex = 0;
! 643: UInt32 i;
! 644: for(i = 0; i < kNumRepDistances; i++)
! 645: {
! 646: reps[i] = _repDistances[i];
! 647: repLens[i] = _matchFinder->GetMatchLen(0 - 1, reps[i], kMatchMaxLen);
! 648: if (i == 0 || repLens[i] > repLens[repMaxIndex])
! 649: repMaxIndex = i;
! 650: }
! 651: if(repLens[repMaxIndex] > _numFastBytes)
! 652: {
! 653: backRes = repMaxIndex;
! 654: lenRes = repLens[repMaxIndex];
! 655: MovePos(lenRes - 1);
! 656: return S_OK;
! 657: }
! 658:
! 659: if(lenMain > _numFastBytes)
! 660: {
! 661: UInt32 backMain = (lenMain < _numFastBytes) ? _matchDistances[lenMain] :
! 662: _matchDistances[_numFastBytes];
! 663: backRes = backMain + kNumRepDistances;
! 664: MovePos(lenMain - 1);
! 665: lenRes = lenMain;
! 666: return S_OK;
! 667: }
! 668: Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
! 669:
! 670: _optimum[0].State = _state;
! 671:
! 672: Byte matchByte;
! 673:
! 674: matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - 1);
! 675:
! 676: UInt32 posState = (position & _posStateMask);
! 677:
! 678: _optimum[1].Price = _isMatch[_state.Index][posState].GetPrice0() +
! 679: _literalEncoder.GetPrice(position, _previousByte, !_state.IsCharState(), matchByte, currentByte);
! 680: _optimum[1].MakeAsChar();
! 681:
! 682: _optimum[1].PosPrev = 0;
! 683:
! 684: for (i = 0; i < kNumRepDistances; i++)
! 685: _optimum[0].Backs[i] = reps[i];
! 686:
! 687: UInt32 matchPrice = _isMatch[_state.Index][posState].GetPrice1();
! 688: UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
! 689:
! 690: if(matchByte == currentByte)
! 691: {
! 692: UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
! 693: if(shortRepPrice < _optimum[1].Price)
! 694: {
! 695: _optimum[1].Price = shortRepPrice;
! 696: _optimum[1].MakeAsShortRep();
! 697: }
! 698: }
! 699: if(lenMain < 2)
! 700: {
! 701: backRes = _optimum[1].BackPrev;
! 702: lenRes = 1;
! 703: return S_OK;
! 704: }
! 705:
! 706:
! 707: UInt32 normalMatchPrice = matchPrice +
! 708: _isRep[_state.Index].GetPrice0();
! 709:
! 710: if (lenMain <= repLens[repMaxIndex])
! 711: lenMain = 0;
! 712:
! 713: UInt32 len;
! 714: for(len = 2; len <= lenMain; len++)
! 715: {
! 716: _optimum[len].PosPrev = 0;
! 717: _optimum[len].BackPrev = _matchDistances[len] + kNumRepDistances;
! 718: _optimum[len].Price = normalMatchPrice +
! 719: GetPosLenPrice(_matchDistances[len], len, posState);
! 720: _optimum[len].Prev1IsChar = false;
! 721: }
! 722:
! 723: if (lenMain < repLens[repMaxIndex])
! 724: lenMain = repLens[repMaxIndex];
! 725:
! 726: for (; len <= lenMain; len++)
! 727: _optimum[len].Price = kIfinityPrice;
! 728:
! 729: for(i = 0; i < kNumRepDistances; i++)
! 730: {
! 731: UInt32 repLen = repLens[i];
! 732: for(UInt32 lenTest = 2; lenTest <= repLen; lenTest++)
! 733: {
! 734: UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(i, lenTest, _state, posState);
! 735: COptimal &optimum = _optimum[lenTest];
! 736: if (curAndLenPrice < optimum.Price)
! 737: {
! 738: optimum.Price = curAndLenPrice;
! 739: optimum.PosPrev = 0;
! 740: optimum.BackPrev = i;
! 741: optimum.Prev1IsChar = false;
! 742: }
! 743: }
! 744: }
! 745:
! 746: UInt32 cur = 0;
! 747: UInt32 lenEnd = lenMain;
! 748:
! 749: while(true)
! 750: {
! 751: cur++;
! 752: if(cur == lenEnd)
! 753: {
! 754: lenRes = Backward(backRes, cur);
! 755: return S_OK;
! 756: }
! 757: position++;
! 758: UInt32 posPrev = _optimum[cur].PosPrev;
! 759: CState state;
! 760: if (_optimum[cur].Prev1IsChar)
! 761: {
! 762: posPrev--;
! 763: if (_optimum[cur].Prev2)
! 764: {
! 765: state = _optimum[_optimum[cur].PosPrev2].State;
! 766: if (_optimum[cur].BackPrev2 < kNumRepDistances)
! 767: state.UpdateRep();
! 768: else
! 769: state.UpdateMatch();
! 770: }
! 771: else
! 772: state = _optimum[posPrev].State;
! 773: state.UpdateChar();
! 774: }
! 775: else
! 776: state = _optimum[posPrev].State;
! 777: if (posPrev == cur - 1)
! 778: {
! 779: if (_optimum[cur].IsShortRep())
! 780: state.UpdateShortRep();
! 781: else
! 782: state.UpdateChar();
! 783: /*
! 784: if (_optimum[cur].Prev1IsChar)
! 785: for(int i = 0; i < kNumRepDistances; i++)
! 786: reps[i] = _optimum[posPrev].Backs[i];
! 787: */
! 788: }
! 789: else
! 790: {
! 791: UInt32 pos;
! 792: if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
! 793: {
! 794: posPrev = _optimum[cur].PosPrev2;
! 795: pos = _optimum[cur].BackPrev2;
! 796: state.UpdateRep();
! 797: }
! 798: else
! 799: {
! 800: pos = _optimum[cur].BackPrev;
! 801: if (pos < kNumRepDistances)
! 802: state.UpdateRep();
! 803: else
! 804: state.UpdateMatch();
! 805: }
! 806: if (pos < kNumRepDistances)
! 807: {
! 808: reps[0] = _optimum[posPrev].Backs[pos];
! 809: UInt32 i;
! 810: for(i = 1; i <= pos; i++)
! 811: reps[i] = _optimum[posPrev].Backs[i - 1];
! 812: for(; i < kNumRepDistances; i++)
! 813: reps[i] = _optimum[posPrev].Backs[i];
! 814: }
! 815: else
! 816: {
! 817: reps[0] = (pos - kNumRepDistances);
! 818: for(UInt32 i = 1; i < kNumRepDistances; i++)
! 819: reps[i] = _optimum[posPrev].Backs[i - 1];
! 820: }
! 821: }
! 822: _optimum[cur].State = state;
! 823: for(UInt32 i = 0; i < kNumRepDistances; i++)
! 824: _optimum[cur].Backs[i] = reps[i];
! 825: UInt32 newLen;
! 826: RINOK(ReadMatchDistances(newLen));
! 827: if(newLen > _numFastBytes)
! 828: {
! 829: _longestMatchLength = newLen;
! 830: _longestMatchWasFound = true;
! 831: lenRes = Backward(backRes, cur);
! 832: return S_OK;
! 833: }
! 834: UInt32 curPrice = _optimum[cur].Price;
! 835: // Byte currentByte = _matchFinder->GetIndexByte(0 - 1);
! 836: // Byte matchByte = _matchFinder->GetIndexByte(0 - reps[0] - 1 - 1);
! 837: const Byte *data = _matchFinder->GetPointerToCurrentPos() - 1;
! 838: Byte currentByte = *data;
! 839: Byte matchByte = data[(size_t)0 - reps[0] - 1];
! 840:
! 841: UInt32 posState = (position & _posStateMask);
! 842:
! 843: UInt32 curAnd1Price = curPrice +
! 844: _isMatch[state.Index][posState].GetPrice0() +
! 845: _literalEncoder.GetPrice(position, data[(size_t)0 - 1], !state.IsCharState(), matchByte, currentByte);
! 846:
! 847: COptimal &nextOptimum = _optimum[cur + 1];
! 848:
! 849: bool nextIsChar = false;
! 850: if (curAnd1Price < nextOptimum.Price)
! 851: {
! 852: nextOptimum.Price = curAnd1Price;
! 853: nextOptimum.PosPrev = cur;
! 854: nextOptimum.MakeAsChar();
! 855: nextIsChar = true;
! 856: }
! 857:
! 858: UInt32 matchPrice = curPrice + _isMatch[state.Index][posState].GetPrice1();
! 859: UInt32 repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
! 860:
! 861: if(matchByte == currentByte &&
! 862: !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
! 863: {
! 864: UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
! 865: if(shortRepPrice <= nextOptimum.Price)
! 866: {
! 867: nextOptimum.Price = shortRepPrice;
! 868: nextOptimum.PosPrev = cur;
! 869: nextOptimum.MakeAsShortRep();
! 870: // nextIsChar = false;
! 871: }
! 872: }
! 873: /*
! 874: if(newLen == 2 && _matchDistances[2] >= kDistLimit2) // test it maybe set 2000 ?
! 875: continue;
! 876: */
! 877:
! 878: UInt32 numAvailableBytes = _matchFinder->GetNumAvailableBytes() + 1;
! 879: numAvailableBytes = MyMin(kNumOpts - 1 - cur, numAvailableBytes);
! 880:
! 881: if (numAvailableBytes < 2)
! 882: continue;
! 883: if (numAvailableBytes > _numFastBytes)
! 884: numAvailableBytes = _numFastBytes;
! 885: if (numAvailableBytes >= 3 && !nextIsChar)
! 886: {
! 887: UInt32 backOffset = reps[0] + 1;
! 888: UInt32 temp;
! 889: for (temp = 1; temp < numAvailableBytes; temp++)
! 890: if (data[temp] != data[(size_t)temp - backOffset])
! 891: break;
! 892: UInt32 lenTest2 = temp - 1;
! 893: if (lenTest2 >= 2)
! 894: {
! 895: CState state2 = state;
! 896: state2.UpdateChar();
! 897: UInt32 posStateNext = (position + 1) & _posStateMask;
! 898: UInt32 nextRepMatchPrice = curAnd1Price +
! 899: _isMatch[state2.Index][posStateNext].GetPrice1() +
! 900: _isRep[state2.Index].GetPrice1();
! 901: // for (; lenTest2 >= 2; lenTest2--)
! 902: {
! 903: while(lenEnd < cur + 1 + lenTest2)
! 904: _optimum[++lenEnd].Price = kIfinityPrice;
! 905: UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
! 906: 0, lenTest2, state2, posStateNext);
! 907: COptimal &optimum = _optimum[cur + 1 + lenTest2];
! 908: if (curAndLenPrice < optimum.Price)
! 909: {
! 910: optimum.Price = curAndLenPrice;
! 911: optimum.PosPrev = cur + 1;
! 912: optimum.BackPrev = 0;
! 913: optimum.Prev1IsChar = true;
! 914: optimum.Prev2 = false;
! 915: }
! 916: }
! 917: }
! 918: }
! 919: for(UInt32 repIndex = 0; repIndex < kNumRepDistances; repIndex++)
! 920: {
! 921: // UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, reps[repIndex], newLen); // test it;
! 922: UInt32 backOffset = reps[repIndex] + 1;
! 923: UInt32 lenTest;
! 924: for (lenTest = 0; lenTest < numAvailableBytes; lenTest++)
! 925: if (data[lenTest] != data[(size_t)lenTest - backOffset])
! 926: break;
! 927: for(; lenTest >= 2; lenTest--)
! 928: {
! 929: while(lenEnd < cur + lenTest)
! 930: _optimum[++lenEnd].Price = kIfinityPrice;
! 931: UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
! 932: COptimal &optimum = _optimum[cur + lenTest];
! 933: if (curAndLenPrice < optimum.Price)
! 934: {
! 935: optimum.Price = curAndLenPrice;
! 936: optimum.PosPrev = cur;
! 937: optimum.BackPrev = repIndex;
! 938: optimum.Prev1IsChar = false;
! 939: }
! 940:
! 941: /*
! 942: if (_maxMode)
! 943: {
! 944: UInt32 temp;
! 945: for (temp = lenTest + 1; temp < numAvailableBytes; temp++)
! 946: if (data[temp] != data[(size_t)temp - backOffset])
! 947: break;
! 948: UInt32 lenTest2 = temp - (lenTest + 1);
! 949: if (lenTest2 >= 2)
! 950: {
! 951: CState state2 = state;
! 952: state2.UpdateRep();
! 953: UInt32 posStateNext = (position + lenTest) & _posStateMask;
! 954: UInt32 curAndLenCharPrice = curAndLenPrice +
! 955: _isMatch[state2.Index][posStateNext].GetPrice0() +
! 956: _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
! 957: true, data[(size_t)lenTest - backOffset], data[lenTest]);
! 958: state2.UpdateChar();
! 959: posStateNext = (position + lenTest + 1) & _posStateMask;
! 960: UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
! 961: UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
! 962:
! 963: // for(; lenTest2 >= 2; lenTest2--)
! 964: {
! 965: UInt32 offset = lenTest + 1 + lenTest2;
! 966: while(lenEnd < cur + offset)
! 967: _optimum[++lenEnd].Price = kIfinityPrice;
! 968: UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
! 969: 0, lenTest2, state2, posStateNext);
! 970: COptimal &optimum = _optimum[cur + offset];
! 971: if (curAndLenPrice < optimum.Price)
! 972: {
! 973: optimum.Price = curAndLenPrice;
! 974: optimum.PosPrev = cur + lenTest + 1;
! 975: optimum.BackPrev = 0;
! 976: optimum.Prev1IsChar = true;
! 977: optimum.Prev2 = true;
! 978: optimum.PosPrev2 = cur;
! 979: optimum.BackPrev2 = repIndex;
! 980: }
! 981: }
! 982: }
! 983: }
! 984: */
! 985: }
! 986: }
! 987:
! 988: // for(UInt32 lenTest = 2; lenTest <= newLen; lenTest++)
! 989: if (newLen > numAvailableBytes)
! 990: newLen = numAvailableBytes;
! 991: if (newLen >= 2)
! 992: {
! 993: if (newLen == 2 && _matchDistances[2] >= 0x80)
! 994: continue;
! 995: UInt32 normalMatchPrice = matchPrice +
! 996: _isRep[state.Index].GetPrice0();
! 997: while(lenEnd < cur + newLen)
! 998: _optimum[++lenEnd].Price = kIfinityPrice;
! 999:
! 1000: for(UInt32 lenTest = newLen; lenTest >= 2; lenTest--)
! 1001: {
! 1002: UInt32 curBack = _matchDistances[lenTest];
! 1003: UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
! 1004: COptimal &optimum = _optimum[cur + lenTest];
! 1005: if (curAndLenPrice < optimum.Price)
! 1006: {
! 1007: optimum.Price = curAndLenPrice;
! 1008: optimum.PosPrev = cur;
! 1009: optimum.BackPrev = curBack + kNumRepDistances;
! 1010: optimum.Prev1IsChar = false;
! 1011: }
! 1012:
! 1013: if (_maxMode)
! 1014: {
! 1015: UInt32 backOffset = curBack + 1;
! 1016: UInt32 temp;
! 1017: for (temp = lenTest + 1; temp < numAvailableBytes; temp++)
! 1018: if (data[temp] != data[(size_t)temp - backOffset])
! 1019: break;
! 1020: UInt32 lenTest2 = temp - (lenTest + 1);
! 1021: if (lenTest2 >= 2)
! 1022: {
! 1023: CState state2 = state;
! 1024: state2.UpdateMatch();
! 1025: UInt32 posStateNext = (position + lenTest) & _posStateMask;
! 1026: UInt32 curAndLenCharPrice = curAndLenPrice +
! 1027: _isMatch[state2.Index][posStateNext].GetPrice0() +
! 1028: _literalEncoder.GetPrice(position + lenTest, data[(size_t)lenTest - 1],
! 1029: true, data[(size_t)lenTest - backOffset], data[lenTest]);
! 1030: state2.UpdateChar();
! 1031: posStateNext = (position + lenTest + 1) & _posStateMask;
! 1032: UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[state2.Index][posStateNext].GetPrice1();
! 1033: UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
! 1034:
! 1035: // for(; lenTest2 >= 2; lenTest2--)
! 1036: {
! 1037: UInt32 offset = lenTest + 1 + lenTest2;
! 1038: while(lenEnd < cur + offset)
! 1039: _optimum[++lenEnd].Price = kIfinityPrice;
! 1040: UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
! 1041: 0, lenTest2, state2, posStateNext);
! 1042: COptimal &optimum = _optimum[cur + offset];
! 1043: if (curAndLenPrice < optimum.Price)
! 1044: {
! 1045: optimum.Price = curAndLenPrice;
! 1046: optimum.PosPrev = cur + lenTest + 1;
! 1047: optimum.BackPrev = 0;
! 1048: optimum.Prev1IsChar = true;
! 1049: optimum.Prev2 = true;
! 1050: optimum.PosPrev2 = cur;
! 1051: optimum.BackPrev2 = curBack + kNumRepDistances;
! 1052: }
! 1053: }
! 1054: }
! 1055: }
! 1056: }
! 1057: }
! 1058: }
! 1059: }
! 1060:
! 1061: static inline bool ChangePair(UInt32 smallDist, UInt32 bigDist)
! 1062: {
! 1063: const int kDif = 7;
! 1064: return (smallDist < (UInt32(1) << (32-kDif)) && bigDist >= (smallDist << kDif));
! 1065: }
! 1066:
! 1067:
! 1068: HRESULT CEncoder::ReadMatchDistances(UInt32 &lenRes)
! 1069: {
! 1070: lenRes = _matchFinder->GetLongestMatch(_matchDistances);
! 1071: if (lenRes == _numFastBytes)
! 1072: lenRes += _matchFinder->GetMatchLen(lenRes, _matchDistances[lenRes],
! 1073: kMatchMaxLen - lenRes);
! 1074: _additionalOffset++;
! 1075: return _matchFinder->MovePos();
! 1076: }
! 1077:
! 1078: HRESULT CEncoder::GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes)
! 1079: {
! 1080: UInt32 lenMain;
! 1081: if (!_longestMatchWasFound)
! 1082: {
! 1083: RINOK(ReadMatchDistances(lenMain));
! 1084: }
! 1085: else
! 1086: {
! 1087: lenMain = _longestMatchLength;
! 1088: _longestMatchWasFound = false;
! 1089: }
! 1090: UInt32 repLens[kNumRepDistances];
! 1091: UInt32 repMaxIndex = 0;
! 1092: for(UInt32 i = 0; i < kNumRepDistances; i++)
! 1093: {
! 1094: repLens[i] = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
! 1095: if (i == 0 || repLens[i] > repLens[repMaxIndex])
! 1096: repMaxIndex = i;
! 1097: }
! 1098: if(repLens[repMaxIndex] >= _numFastBytes)
! 1099: {
! 1100: backRes = repMaxIndex;
! 1101: lenRes = repLens[repMaxIndex];
! 1102: MovePos(lenRes - 1);
! 1103: return S_OK;
! 1104: }
! 1105: if(lenMain >= _numFastBytes)
! 1106: {
! 1107: backRes = _matchDistances[_numFastBytes] + kNumRepDistances;
! 1108: MovePos(lenMain - 1);
! 1109: lenRes = lenMain;
! 1110: return S_OK;
! 1111: }
! 1112: while (lenMain > 2)
! 1113: {
! 1114: if (!ChangePair(_matchDistances[lenMain - 1], _matchDistances[lenMain]))
! 1115: break;
! 1116: lenMain--;
! 1117: }
! 1118: if (lenMain == 2 && _matchDistances[2] >= 0x80)
! 1119: lenMain = 1;
! 1120:
! 1121: UInt32 backMain = _matchDistances[lenMain];
! 1122: if (repLens[repMaxIndex] >= 2)
! 1123: {
! 1124: if (repLens[repMaxIndex] + 1 >= lenMain ||
! 1125: repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1<<12)))
! 1126: {
! 1127: backRes = repMaxIndex;
! 1128: lenRes = repLens[repMaxIndex];
! 1129: MovePos(lenRes - 1);
! 1130: return S_OK;
! 1131: }
! 1132: }
! 1133:
! 1134:
! 1135: if (lenMain >= 2)
! 1136: {
! 1137: RINOK(ReadMatchDistances(_longestMatchLength));
! 1138: if (_longestMatchLength >= 2 &&
! 1139: (
! 1140: (_longestMatchLength >= lenMain && _matchDistances[lenMain] < backMain) ||
! 1141: _longestMatchLength == lenMain + 1 &&
! 1142: !ChangePair(backMain, _matchDistances[_longestMatchLength]) ||
! 1143: _longestMatchLength > lenMain + 1 ||
! 1144: _longestMatchLength + 1 >= lenMain && lenMain >= 3 &&
! 1145: ChangePair(_matchDistances[lenMain - 1], backMain)
! 1146: )
! 1147: )
! 1148: {
! 1149: _longestMatchWasFound = true;
! 1150: backRes = UInt32(-1);
! 1151: lenRes = 1;
! 1152: return S_OK;
! 1153: }
! 1154: for(UInt32 i = 0; i < kNumRepDistances; i++)
! 1155: {
! 1156: UInt32 repLen = _matchFinder->GetMatchLen(0 - 1, _repDistances[i], kMatchMaxLen);
! 1157: if (repLen >= 2 && repLen + 1 >= lenMain)
! 1158: {
! 1159: _longestMatchWasFound = true;
! 1160: backRes = UInt32(-1);
! 1161: lenRes = 1;
! 1162: return S_OK;
! 1163: }
! 1164: }
! 1165: backRes = backMain + kNumRepDistances;
! 1166: MovePos(lenMain - 2);
! 1167: lenRes = lenMain;
! 1168: return S_OK;
! 1169: }
! 1170: backRes = UInt32(-1);
! 1171: lenRes = 1;
! 1172: return S_OK;
! 1173: }
! 1174:
! 1175: STDMETHODIMP CEncoder::InitMatchFinder(IMatchFinder *matchFinder)
! 1176: {
! 1177: _matchFinder = matchFinder;
! 1178: return S_OK;
! 1179: }
! 1180:
! 1181: HRESULT CEncoder::Flush(UInt32 nowPos)
! 1182: {
! 1183: ReleaseMFStream();
! 1184: WriteEndMarker(nowPos & _posStateMask);
! 1185: _rangeEncoder.FlushData();
! 1186: return _rangeEncoder.FlushStream();
! 1187: }
! 1188:
! 1189: void CEncoder::WriteEndMarker(UInt32 posState)
! 1190: {
! 1191: // This function for writing End Mark for stream version of LZMA.
! 1192: // In current version this feature is not used.
! 1193: if (!_writeEndMark)
! 1194: return;
! 1195:
! 1196: _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
! 1197: _isRep[_state.Index].Encode(&_rangeEncoder, 0);
! 1198: _state.UpdateMatch();
! 1199: UInt32 len = kMatchMinLen; // kMatchMaxLen;
! 1200: _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
! 1201: UInt32 posSlot = (1 << kNumPosSlotBits) - 1;
! 1202: UInt32 lenToPosState = GetLenToPosState(len);
! 1203: _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
! 1204: UInt32 footerBits = 30;
! 1205: UInt32 posReduced = (UInt32(1) << footerBits) - 1;
! 1206: _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
! 1207: _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
! 1208: }
! 1209:
! 1210: HRESULT CEncoder::CodeReal(ISequentialInStream *inStream,
! 1211: ISequentialOutStream *outStream,
! 1212: const UInt64 *inSize, const UInt64 *outSize,
! 1213: ICompressProgressInfo *progress)
! 1214: {
! 1215: _needReleaseMFStream = false;
! 1216: CCoderReleaser coderReleaser(this);
! 1217: RINOK(SetStreams(inStream, outStream, inSize, outSize));
! 1218: while(true)
! 1219: {
! 1220: UInt64 processedInSize;
! 1221: UInt64 processedOutSize;
! 1222: Int32 finished;
! 1223: RINOK(CodeOneBlock(&processedInSize, &processedOutSize, &finished));
! 1224: if (finished != 0)
! 1225: return S_OK;
! 1226: if (progress != 0)
! 1227: {
! 1228: RINOK(progress->SetRatioInfo(&processedInSize, &processedOutSize));
! 1229: }
! 1230: }
! 1231: }
! 1232:
! 1233: HRESULT CEncoder::SetStreams(ISequentialInStream *inStream,
! 1234: ISequentialOutStream *outStream,
! 1235: const UInt64 *inSize, const UInt64 *outSize)
! 1236: {
! 1237: _inStream = inStream;
! 1238: _finished = false;
! 1239: RINOK(Create());
! 1240: RINOK(SetOutStream(outStream));
! 1241: RINOK(Init());
! 1242:
! 1243: // CCoderReleaser releaser(this);
! 1244:
! 1245: /*
! 1246: if (_matchFinder->GetNumAvailableBytes() == 0)
! 1247: return Flush();
! 1248: */
! 1249:
! 1250: if (!_fastMode)
! 1251: {
! 1252: FillPosSlotPrices();
! 1253: FillDistancesPrices();
! 1254: FillAlignPrices();
! 1255: }
! 1256:
! 1257: _lenEncoder.SetTableSize(_numFastBytes);
! 1258: _lenEncoder.UpdateTables(1 << _posStateBits);
! 1259: _repMatchLenEncoder.SetTableSize(_numFastBytes);
! 1260: _repMatchLenEncoder.UpdateTables(1 << _posStateBits);
! 1261:
! 1262: lastPosSlotFillingPos = 0;
! 1263: nowPos64 = 0;
! 1264: return S_OK;
! 1265: }
! 1266:
! 1267: HRESULT CEncoder::CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished)
! 1268: {
! 1269: if (_inStream != 0)
! 1270: {
! 1271: RINOK(_matchFinder->Init(_inStream));
! 1272: _needReleaseMFStream = true;
! 1273: _inStream = 0;
! 1274: }
! 1275:
! 1276:
! 1277: *finished = 1;
! 1278: if (_finished)
! 1279: return S_OK;
! 1280: _finished = true;
! 1281:
! 1282:
! 1283: UInt64 progressPosValuePrev = nowPos64;
! 1284: if (nowPos64 == 0)
! 1285: {
! 1286: if (_matchFinder->GetNumAvailableBytes() == 0)
! 1287: return Flush(UInt32(nowPos64));
! 1288: UInt32 len; // it's not used
! 1289: RINOK(ReadMatchDistances(len));
! 1290: UInt32 posState = UInt32(nowPos64) & _posStateMask;
! 1291: _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
! 1292: _state.UpdateChar();
! 1293: Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
! 1294: _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte)->Encode(&_rangeEncoder, curByte);
! 1295: _previousByte = curByte;
! 1296: _additionalOffset--;
! 1297: nowPos64++;
! 1298: }
! 1299: if (_matchFinder->GetNumAvailableBytes() == 0)
! 1300: return Flush(UInt32(nowPos64));
! 1301: while(true)
! 1302: {
! 1303: #ifdef _NO_EXCEPTIONS
! 1304: if (_rangeEncoder.Stream.ErrorCode != S_OK)
! 1305: return _rangeEncoder.Stream.ErrorCode;
! 1306: #endif
! 1307: UInt32 pos;
! 1308: UInt32 posState = UInt32(nowPos64) & _posStateMask;
! 1309:
! 1310: UInt32 len;
! 1311: HRESULT result;
! 1312: if (_fastMode)
! 1313: result = GetOptimumFast(UInt32(nowPos64), pos, len);
! 1314: else
! 1315: result = GetOptimum(UInt32(nowPos64), pos, len);
! 1316: RINOK(result);
! 1317:
! 1318: if(len == 1 && pos == 0xFFFFFFFF)
! 1319: {
! 1320: _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 0);
! 1321: Byte curByte = _matchFinder->GetIndexByte(0 - _additionalOffset);
! 1322: CLiteralEncoder2 *subCoder = _literalEncoder.GetSubCoder(UInt32(nowPos64), _previousByte);
! 1323: if(!_state.IsCharState())
! 1324: {
! 1325: Byte matchByte = _matchFinder->GetIndexByte(0 - _repDistances[0] - 1 - _additionalOffset);
! 1326: subCoder->EncodeMatched(&_rangeEncoder, matchByte, curByte);
! 1327: }
! 1328: else
! 1329: subCoder->Encode(&_rangeEncoder, curByte);
! 1330: _state.UpdateChar();
! 1331: _previousByte = curByte;
! 1332: }
! 1333: else
! 1334: {
! 1335: _isMatch[_state.Index][posState].Encode(&_rangeEncoder, 1);
! 1336: if(pos < kNumRepDistances)
! 1337: {
! 1338: _isRep[_state.Index].Encode(&_rangeEncoder, 1);
! 1339: if(pos == 0)
! 1340: {
! 1341: _isRepG0[_state.Index].Encode(&_rangeEncoder, 0);
! 1342: if(len == 1)
! 1343: _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 0);
! 1344: else
! 1345: _isRep0Long[_state.Index][posState].Encode(&_rangeEncoder, 1);
! 1346: }
! 1347: else
! 1348: {
! 1349: _isRepG0[_state.Index].Encode(&_rangeEncoder, 1);
! 1350: if (pos == 1)
! 1351: _isRepG1[_state.Index].Encode(&_rangeEncoder, 0);
! 1352: else
! 1353: {
! 1354: _isRepG1[_state.Index].Encode(&_rangeEncoder, 1);
! 1355: _isRepG2[_state.Index].Encode(&_rangeEncoder, pos - 2);
! 1356: }
! 1357: }
! 1358: if (len == 1)
! 1359: _state.UpdateShortRep();
! 1360: else
! 1361: {
! 1362: _repMatchLenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
! 1363: _state.UpdateRep();
! 1364: }
! 1365:
! 1366:
! 1367: UInt32 distance = _repDistances[pos];
! 1368: if (pos != 0)
! 1369: {
! 1370: for(UInt32 i = pos; i >= 1; i--)
! 1371: _repDistances[i] = _repDistances[i - 1];
! 1372: _repDistances[0] = distance;
! 1373: }
! 1374: }
! 1375: else
! 1376: {
! 1377: _isRep[_state.Index].Encode(&_rangeEncoder, 0);
! 1378: _state.UpdateMatch();
! 1379: _lenEncoder.Encode(&_rangeEncoder, len - kMatchMinLen, posState);
! 1380: pos -= kNumRepDistances;
! 1381: UInt32 posSlot = GetPosSlot(pos);
! 1382: UInt32 lenToPosState = GetLenToPosState(len);
! 1383: _posSlotEncoder[lenToPosState].Encode(&_rangeEncoder, posSlot);
! 1384:
! 1385: if (posSlot >= kStartPosModelIndex)
! 1386: {
! 1387: UInt32 footerBits = ((posSlot >> 1) - 1);
! 1388: UInt32 base = ((2 | (posSlot & 1)) << footerBits);
! 1389: UInt32 posReduced = pos - base;
! 1390:
! 1391: if (posSlot < kEndPosModelIndex)
! 1392: NRangeCoder::ReverseBitTreeEncode(_posEncoders + base - posSlot - 1,
! 1393: &_rangeEncoder, footerBits, posReduced);
! 1394: else
! 1395: {
! 1396: _rangeEncoder.EncodeDirectBits(posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
! 1397: _posAlignEncoder.ReverseEncode(&_rangeEncoder, posReduced & kAlignMask);
! 1398: if (!_fastMode)
! 1399: if (--_alignPriceCount == 0)
! 1400: FillAlignPrices();
! 1401: }
! 1402: }
! 1403: UInt32 distance = pos;
! 1404: for(UInt32 i = kNumRepDistances - 1; i >= 1; i--)
! 1405: _repDistances[i] = _repDistances[i - 1];
! 1406: _repDistances[0] = distance;
! 1407: }
! 1408: _previousByte = _matchFinder->GetIndexByte(len - 1 - _additionalOffset);
! 1409: }
! 1410: _additionalOffset -= len;
! 1411: nowPos64 += len;
! 1412: if (!_fastMode)
! 1413: if (nowPos64 - lastPosSlotFillingPos >= (1 << 9))
! 1414: {
! 1415: FillPosSlotPrices();
! 1416: FillDistancesPrices();
! 1417: lastPosSlotFillingPos = nowPos64;
! 1418: }
! 1419: if (_additionalOffset == 0)
! 1420: {
! 1421: *inSize = nowPos64;
! 1422: *outSize = _rangeEncoder.GetProcessedSize();
! 1423: if (_matchFinder->GetNumAvailableBytes() == 0)
! 1424: return Flush(UInt32(nowPos64));
! 1425: if (nowPos64 - progressPosValuePrev >= (1 << 12))
! 1426: {
! 1427: _finished = false;
! 1428: *finished = 0;
! 1429: return S_OK;
! 1430: }
! 1431: }
! 1432: }
! 1433: }
! 1434:
! 1435: STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream,
! 1436: ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
! 1437: ICompressProgressInfo *progress)
! 1438: {
! 1439: #ifndef _NO_EXCEPTIONS
! 1440: try
! 1441: {
! 1442: #endif
! 1443: return CodeReal(inStream, outStream, inSize, outSize, progress);
! 1444: #ifndef _NO_EXCEPTIONS
! 1445: }
! 1446: catch(const COutBufferException &e) { return e.ErrorCode; }
! 1447: catch(...) { return E_FAIL; }
! 1448: #endif
! 1449: }
! 1450:
! 1451: void CEncoder::FillPosSlotPrices()
! 1452: {
! 1453: for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
! 1454: {
! 1455: UInt32 posSlot;
! 1456: for (posSlot = 0; posSlot < kEndPosModelIndex && posSlot < _distTableSize; posSlot++)
! 1457: _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot);
! 1458: for (; posSlot < _distTableSize; posSlot++)
! 1459: _posSlotPrices[lenToPosState][posSlot] = _posSlotEncoder[lenToPosState].GetPrice(posSlot) +
! 1460: ((((posSlot >> 1) - 1) - kNumAlignBits) << NRangeCoder::kNumBitPriceShiftBits);
! 1461: }
! 1462: }
! 1463:
! 1464: void CEncoder::FillDistancesPrices()
! 1465: {
! 1466: for (UInt32 lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
! 1467: {
! 1468: UInt32 i;
! 1469: for (i = 0; i < kStartPosModelIndex; i++)
! 1470: _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][i];
! 1471: for (; i < kNumFullDistances; i++)
! 1472: {
! 1473: UInt32 posSlot = GetPosSlot(i);
! 1474: UInt32 footerBits = ((posSlot >> 1) - 1);
! 1475: UInt32 base = ((2 | (posSlot & 1)) << footerBits);
! 1476:
! 1477: _distancesPrices[lenToPosState][i] = _posSlotPrices[lenToPosState][posSlot] +
! 1478: NRangeCoder::ReverseBitTreeGetPrice(_posEncoders +
! 1479: base - posSlot - 1, footerBits, i - base);
! 1480:
! 1481: }
! 1482: }
! 1483: }
! 1484:
! 1485: void CEncoder::FillAlignPrices()
! 1486: {
! 1487: for (UInt32 i = 0; i < kAlignTableSize; i++)
! 1488: _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
! 1489: _alignPriceCount = kAlignTableSize;
! 1490: }
! 1491:
! 1492: }}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>