Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZMA/LZMAEncoder.cpp, revision 1.1.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>