3 #ifndef __LZMA_ENCODER_H
4 #define __LZMA_ENCODER_H
6 #include "../../../Common/MyCom.h"
7 #include "../../../Common/Alloc.h"
8 #include "../../ICoder.h"
9 #include "../LZ/IMatchFinder.h"
10 #include "../RangeCoder/RangeCoderBitTree.h"
17 typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder;
24 UInt32 _repDistances[kNumRepDistances];
29 for(UInt32 i = 0 ; i < kNumRepDistances; i++)
45 UInt32 PosPrev; // posNext;
47 UInt32 Backs[kNumRepDistances];
48 void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; }
49 void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
50 bool IsShortRep() { return (BackPrev == 0); }
54 extern Byte g_FastPos[1 << 11];
55 inline UInt32 GetPosSlot(UInt32 pos)
58 return g_FastPos[pos];
60 return g_FastPos[pos >> 10] + 20;
61 return g_FastPos[pos >> 20] + 40;
64 inline UInt32 GetPosSlot2(UInt32 pos)
67 return g_FastPos[pos >> 6] + 12;
69 return g_FastPos[pos >> 16] + 32;
70 return g_FastPos[pos >> 26] + 52;
73 const UInt32 kIfinityPrice = 0xFFFFFFF;
75 const UInt32 kNumOpts = 1 << 12;
78 class CLiteralEncoder2
80 CMyBitEncoder _encoders[0x300];
84 for (int i = 0; i < 0x300; i++)
87 void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol);
88 void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol);
89 UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const;
94 CLiteralEncoder2 *_coders;
99 CLiteralEncoder(): _coders(0) {}
100 ~CLiteralEncoder() { Free(); }
106 bool Create(int numPosBits, int numPrevBits)
108 if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits))
111 UInt32 numStates = 1 << (numPosBits + numPrevBits);
112 _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2));
114 _numPosBits = numPosBits;
115 _posMask = (1 << numPosBits) - 1;
116 _numPrevBits = numPrevBits;
117 return (_coders != 0);
121 UInt32 numStates = 1 << (_numPrevBits + _numPosBits);
122 for (UInt32 i = 0; i < numStates; i++)
125 CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)
126 { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; }
133 CMyBitEncoder _choice;
134 CMyBitEncoder _choice2;
135 NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];
136 NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];
137 NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;
139 void Init(UInt32 numPosStates);
140 void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);
141 void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const;
144 const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
146 class CPriceTableEncoder: public CEncoder
148 UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal];
150 UInt32 _counters[kNumPosStatesEncodingMax];
152 void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
153 UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; }
154 void UpdateTable(UInt32 posState)
156 SetPrices(posState, _tableSize, _prices[posState]);
157 _counters[posState] = _tableSize;
159 void UpdateTables(UInt32 numPosStates)
161 for (UInt32 posState = 0; posState < numPosStates; posState++)
162 UpdateTable(posState);
164 void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice)
166 CEncoder::Encode(rangeEncoder, symbol, posState);
168 if (--_counters[posState] == 0)
169 UpdateTable(posState);
176 public ICompressCoder,
177 public ICompressSetOutStream,
178 public ICompressSetCoderProperties,
179 public ICompressWriteCoderProperties,
183 COptimal _optimum[kNumOpts];
184 CMyComPtr<IMatchFinder> _matchFinder; // test it
185 NRangeCoder::CEncoder _rangeEncoder;
187 CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];
188 CMyBitEncoder _isRep[kNumStates];
189 CMyBitEncoder _isRepG0[kNumStates];
190 CMyBitEncoder _isRepG1[kNumStates];
191 CMyBitEncoder _isRepG2[kNumStates];
192 CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax];
194 NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];
196 CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];
197 NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder;
199 NLength::CPriceTableEncoder _lenEncoder;
200 NLength::CPriceTableEncoder _repMatchLenEncoder;
202 CLiteralEncoder _literalEncoder;
204 UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1];
208 UInt32 _numFastBytes;
209 UInt32 _longestMatchLength;
210 UInt32 _numDistancePairs;
212 UInt32 _additionalOffset;
214 UInt32 _optimumEndIndex;
215 UInt32 _optimumCurrentIndex;
217 bool _longestMatchWasFound;
219 UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
221 UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances];
223 UInt32 _alignPrices[kAlignTableSize];
224 UInt32 _alignPriceCount;
226 UInt32 _distTableSize;
228 UInt32 _posStateBits;
229 UInt32 _posStateMask;
230 UInt32 _numLiteralPosStateBits;
231 UInt32 _numLiteralContextBits;
233 UInt32 _dictionarySize;
235 UInt32 _dictionarySizePrev;
236 UInt32 _numFastBytesPrev;
238 UInt32 _matchPriceCount;
241 ISequentialInStream *_inStream;
243 UInt32 _matchFinderCycles;
244 int _matchFinderIndex;
245 #ifdef COMPRESS_MF_MT
251 bool _needReleaseMFStream;
253 IMatchFinderSetNumPasses *setMfPasses;
255 void ReleaseMatchFinder()
258 _matchFinder.Release();
261 HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs);
263 HRESULT MovePos(UInt32 num);
264 UInt32 GetRepLen1Price(CState state, UInt32 posState) const
266 return _isRepG0[state.Index].GetPrice0() +
267 _isRep0Long[state.Index][posState].GetPrice0();
270 UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const
275 price = _isRepG0[state.Index].GetPrice0();
276 price += _isRep0Long[state.Index][posState].GetPrice1();
280 price = _isRepG0[state.Index].GetPrice1();
282 price += _isRepG1[state.Index].GetPrice0();
285 price += _isRepG1[state.Index].GetPrice1();
286 price += _isRepG2[state.Index].GetPrice(repIndex - 2);
291 UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const
293 return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) +
294 GetPureRepPrice(repIndex, state, posState);
297 UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const
299 if (pos >= kNumFullDistances)
300 return kIfinityPrice;
301 return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState);
303 UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const
306 UInt32 lenToPosState = GetLenToPosState(len);
307 if (pos < kNumFullDistances)
308 price = _distancesPrices[lenToPosState][pos];
310 price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
311 _alignPrices[pos & kAlignMask];
312 return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
315 UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const
318 UInt32 lenToPosState = GetLenToPosState(len);
319 if (pos < kNumFullDistances)
320 price = _distancesPrices[lenToPosState][pos];
322 price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] +
323 _alignPrices[pos & kAlignMask];
324 return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);
327 UInt32 Backward(UInt32 &backRes, UInt32 cur);
328 HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
329 HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);
331 void FillDistancesPrices();
332 void FillAlignPrices();
334 void ReleaseMFStream()
336 if (_matchFinder && _needReleaseMFStream)
338 _matchFinder->ReleaseStream();
339 _needReleaseMFStream = false;
343 void ReleaseStreams()
349 HRESULT Flush(UInt32 nowPos);
354 CCoderReleaser(CEncoder *coder): _coder(coder) {}
357 _coder->ReleaseStreams();
360 friend class CCoderReleaser;
362 void WriteEndMarker(UInt32 posState);
366 void SetWriteEndMarkerMode(bool writeEndMarker)
367 { _writeEndMark= writeEndMarker; }
372 ICompressSetOutStream,
373 ICompressSetCoderProperties,
374 ICompressWriteCoderProperties
379 // ICompressCoder interface
380 HRESULT SetStreams(ISequentialInStream *inStream,
381 ISequentialOutStream *outStream,
382 const UInt64 *inSize, const UInt64 *outSize);
383 HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished);
385 HRESULT CodeReal(ISequentialInStream *inStream,
386 ISequentialOutStream *outStream,
387 const UInt64 *inSize, const UInt64 *outSize,
388 ICompressProgressInfo *progress);
390 // ICompressCoder interface
391 STDMETHOD(Code)(ISequentialInStream *inStream,
392 ISequentialOutStream *outStream,
393 const UInt64 *inSize, const UInt64 *outSize,
394 ICompressProgressInfo *progress);
396 // ICompressSetCoderProperties2
397 STDMETHOD(SetCoderProperties)(const PROPID *propIDs,
398 const PROPVARIANT *properties, UInt32 numProperties);
400 // ICompressWriteCoderProperties
401 STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
403 STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
404 STDMETHOD(ReleaseOutStream)();
406 virtual ~CEncoder() {}