55ac80c07c2421174b8120eb117c9c7ab53c7442
[coreboot.git] / payloads / bayou / util / pbuilder / lzma / C / 7zip / Compress / LZMA / LZMAEncoder.h
1 // LZMA/Encoder.h\r
2 \r
3 #ifndef __LZMA_ENCODER_H\r
4 #define __LZMA_ENCODER_H\r
5 \r
6 #include "../../../Common/MyCom.h"\r
7 #include "../../../Common/Alloc.h"\r
8 #include "../../ICoder.h"\r
9 #include "../LZ/IMatchFinder.h"\r
10 #include "../RangeCoder/RangeCoderBitTree.h"\r
11 \r
12 #include "LZMA.h"\r
13 \r
14 namespace NCompress {\r
15 namespace NLZMA {\r
16 \r
17 typedef NRangeCoder::CBitEncoder<kNumMoveBits> CMyBitEncoder;\r
18 \r
19 class CBaseState\r
20 {\r
21 protected:\r
22   CState _state;\r
23   Byte _previousByte;\r
24   UInt32 _repDistances[kNumRepDistances];\r
25   void Init()\r
26   {\r
27     _state.Init();\r
28     _previousByte = 0;\r
29     for(UInt32 i = 0 ; i < kNumRepDistances; i++)\r
30       _repDistances[i] = 0;\r
31   }\r
32 };\r
33 \r
34 struct COptimal\r
35 {\r
36   CState State;\r
37 \r
38   bool Prev1IsChar;\r
39   bool Prev2;\r
40 \r
41   UInt32 PosPrev2;\r
42   UInt32 BackPrev2;     \r
43 \r
44   UInt32 Price;    \r
45   UInt32 PosPrev;         // posNext;\r
46   UInt32 BackPrev;     \r
47   UInt32 Backs[kNumRepDistances];\r
48   void MakeAsChar() { BackPrev = UInt32(-1); Prev1IsChar = false; }\r
49   void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }\r
50   bool IsShortRep() { return (BackPrev == 0); }\r
51 };\r
52 \r
53 \r
54 extern Byte g_FastPos[1 << 11];\r
55 inline UInt32 GetPosSlot(UInt32 pos)\r
56 {\r
57   if (pos < (1 << 11))\r
58     return g_FastPos[pos];\r
59   if (pos < (1 << 21))\r
60     return g_FastPos[pos >> 10] + 20;\r
61   return g_FastPos[pos >> 20] + 40;\r
62 }\r
63 \r
64 inline UInt32 GetPosSlot2(UInt32 pos)\r
65 {\r
66   if (pos < (1 << 17))\r
67     return g_FastPos[pos >> 6] + 12;\r
68   if (pos < (1 << 27))\r
69     return g_FastPos[pos >> 16] + 32;\r
70   return g_FastPos[pos >> 26] + 52;\r
71 }\r
72 \r
73 const UInt32 kIfinityPrice = 0xFFFFFFF;\r
74 \r
75 const UInt32 kNumOpts = 1 << 12;\r
76 \r
77 \r
78 class CLiteralEncoder2\r
79 {\r
80   CMyBitEncoder _encoders[0x300];\r
81 public:\r
82   void Init()\r
83   {\r
84     for (int i = 0; i < 0x300; i++)\r
85       _encoders[i].Init();\r
86   }\r
87   void Encode(NRangeCoder::CEncoder *rangeEncoder, Byte symbol);\r
88   void EncodeMatched(NRangeCoder::CEncoder *rangeEncoder, Byte matchByte, Byte symbol);\r
89   UInt32 GetPrice(bool matchMode, Byte matchByte, Byte symbol) const;\r
90 };\r
91 \r
92 class CLiteralEncoder\r
93 {\r
94   CLiteralEncoder2 *_coders;\r
95   int _numPrevBits;\r
96   int _numPosBits;\r
97   UInt32 _posMask;\r
98 public:\r
99   CLiteralEncoder(): _coders(0) {}\r
100   ~CLiteralEncoder()  { Free(); }\r
101   void Free()\r
102   { \r
103     MyFree(_coders);\r
104     _coders = 0;\r
105   }\r
106   bool Create(int numPosBits, int numPrevBits)\r
107   {\r
108     if (_coders == 0 || (numPosBits + numPrevBits) != (_numPrevBits + _numPosBits))\r
109     {\r
110       Free();\r
111       UInt32 numStates = 1 << (numPosBits + numPrevBits);\r
112       _coders = (CLiteralEncoder2 *)MyAlloc(numStates * sizeof(CLiteralEncoder2));\r
113     }\r
114     _numPosBits = numPosBits;\r
115     _posMask = (1 << numPosBits) - 1;\r
116     _numPrevBits = numPrevBits;\r
117     return (_coders != 0);\r
118   }\r
119   void Init()\r
120   {\r
121     UInt32 numStates = 1 << (_numPrevBits + _numPosBits);\r
122     for (UInt32 i = 0; i < numStates; i++)\r
123       _coders[i].Init();\r
124   }\r
125   CLiteralEncoder2 *GetSubCoder(UInt32 pos, Byte prevByte)\r
126     { return &_coders[((pos & _posMask) << _numPrevBits) + (prevByte >> (8 - _numPrevBits))]; }\r
127 };\r
128 \r
129 namespace NLength {\r
130 \r
131 class CEncoder\r
132 {\r
133   CMyBitEncoder _choice;\r
134   CMyBitEncoder _choice2;\r
135   NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumLowBits> _lowCoder[kNumPosStatesEncodingMax];\r
136   NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumMidBits> _midCoder[kNumPosStatesEncodingMax];\r
137   NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumHighBits> _highCoder;\r
138 public:\r
139   void Init(UInt32 numPosStates);\r
140   void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState);\r
141   void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32 *prices) const;\r
142 };\r
143 \r
144 const UInt32 kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;\r
145 \r
146 class CPriceTableEncoder: public CEncoder\r
147 {\r
148   UInt32 _prices[kNumPosStatesEncodingMax][kNumSymbolsTotal];\r
149   UInt32 _tableSize;\r
150   UInt32 _counters[kNumPosStatesEncodingMax];\r
151 public:\r
152   void SetTableSize(UInt32 tableSize) { _tableSize = tableSize;  }\r
153   UInt32 GetPrice(UInt32 symbol, UInt32 posState) const { return _prices[posState][symbol]; }\r
154   void UpdateTable(UInt32 posState)\r
155   {\r
156     SetPrices(posState, _tableSize, _prices[posState]);\r
157     _counters[posState] = _tableSize;\r
158   }\r
159   void UpdateTables(UInt32 numPosStates)\r
160   {\r
161     for (UInt32 posState = 0; posState < numPosStates; posState++)\r
162       UpdateTable(posState);\r
163   }\r
164   void Encode(NRangeCoder::CEncoder *rangeEncoder, UInt32 symbol, UInt32 posState, bool updatePrice)\r
165   {\r
166     CEncoder::Encode(rangeEncoder, symbol, posState);\r
167     if (updatePrice)\r
168       if (--_counters[posState] == 0)\r
169         UpdateTable(posState);\r
170   }\r
171 };\r
172 \r
173 }\r
174 \r
175 class CEncoder : \r
176   public ICompressCoder,\r
177   public ICompressSetOutStream,\r
178   public ICompressSetCoderProperties,\r
179   public ICompressWriteCoderProperties,\r
180   public CBaseState,\r
181   public CMyUnknownImp\r
182 {\r
183   COptimal _optimum[kNumOpts];\r
184   CMyComPtr<IMatchFinder> _matchFinder; // test it\r
185   NRangeCoder::CEncoder _rangeEncoder;\r
186 \r
187   CMyBitEncoder _isMatch[kNumStates][NLength::kNumPosStatesEncodingMax];\r
188   CMyBitEncoder _isRep[kNumStates];\r
189   CMyBitEncoder _isRepG0[kNumStates];\r
190   CMyBitEncoder _isRepG1[kNumStates];\r
191   CMyBitEncoder _isRepG2[kNumStates];\r
192   CMyBitEncoder _isRep0Long[kNumStates][NLength::kNumPosStatesEncodingMax];\r
193 \r
194   NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumPosSlotBits> _posSlotEncoder[kNumLenToPosStates];\r
195 \r
196   CMyBitEncoder _posEncoders[kNumFullDistances - kEndPosModelIndex];\r
197   NRangeCoder::CBitTreeEncoder<kNumMoveBits, kNumAlignBits> _posAlignEncoder;\r
198   \r
199   NLength::CPriceTableEncoder _lenEncoder;\r
200   NLength::CPriceTableEncoder _repMatchLenEncoder;\r
201 \r
202   CLiteralEncoder _literalEncoder;\r
203 \r
204   UInt32 _matchDistances[kMatchMaxLen * 2 + 2 + 1];\r
205 \r
206   bool _fastMode;\r
207   // bool _maxMode;\r
208   UInt32 _numFastBytes;\r
209   UInt32 _longestMatchLength;    \r
210   UInt32 _numDistancePairs;\r
211 \r
212   UInt32 _additionalOffset;\r
213 \r
214   UInt32 _optimumEndIndex;\r
215   UInt32 _optimumCurrentIndex;\r
216 \r
217   bool _longestMatchWasFound;\r
218 \r
219   UInt32 _posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];\r
220   \r
221   UInt32 _distancesPrices[kNumLenToPosStates][kNumFullDistances];\r
222 \r
223   UInt32 _alignPrices[kAlignTableSize];\r
224   UInt32 _alignPriceCount;\r
225 \r
226   UInt32 _distTableSize;\r
227 \r
228   UInt32 _posStateBits;\r
229   UInt32 _posStateMask;\r
230   UInt32 _numLiteralPosStateBits;\r
231   UInt32 _numLiteralContextBits;\r
232 \r
233   UInt32 _dictionarySize;\r
234 \r
235   UInt32 _dictionarySizePrev;\r
236   UInt32 _numFastBytesPrev;\r
237 \r
238   UInt32 _matchPriceCount;\r
239   UInt64 nowPos64;\r
240   bool _finished;\r
241   ISequentialInStream *_inStream;\r
242 \r
243   UInt32 _matchFinderCycles;\r
244   int _matchFinderIndex;\r
245   #ifdef COMPRESS_MF_MT\r
246   bool _multiThread;\r
247   #endif\r
248 \r
249   bool _writeEndMark;\r
250 \r
251   bool _needReleaseMFStream;\r
252 \r
253   IMatchFinderSetNumPasses *setMfPasses;\r
254 \r
255   void ReleaseMatchFinder()\r
256   {\r
257     setMfPasses = 0;\r
258     _matchFinder.Release();\r
259   }\r
260   \r
261   HRESULT ReadMatchDistances(UInt32 &len, UInt32 &numDistancePairs);\r
262 \r
263   HRESULT MovePos(UInt32 num);\r
264   UInt32 GetRepLen1Price(CState state, UInt32 posState) const\r
265   {\r
266     return _isRepG0[state.Index].GetPrice0() +\r
267         _isRep0Long[state.Index][posState].GetPrice0();\r
268   }\r
269   \r
270   UInt32 GetPureRepPrice(UInt32 repIndex, CState state, UInt32 posState) const\r
271   {\r
272     UInt32 price;\r
273     if(repIndex == 0)\r
274     {\r
275       price = _isRepG0[state.Index].GetPrice0();\r
276       price += _isRep0Long[state.Index][posState].GetPrice1();\r
277     }\r
278     else\r
279     {\r
280       price = _isRepG0[state.Index].GetPrice1();\r
281       if (repIndex == 1)\r
282         price += _isRepG1[state.Index].GetPrice0();\r
283       else\r
284       {\r
285         price += _isRepG1[state.Index].GetPrice1();\r
286         price += _isRepG2[state.Index].GetPrice(repIndex - 2);\r
287       }\r
288     }\r
289     return price;\r
290   }\r
291   UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, CState state, UInt32 posState) const\r
292   {\r
293     return _repMatchLenEncoder.GetPrice(len - kMatchMinLen, posState) +\r
294         GetPureRepPrice(repIndex, state, posState);\r
295   }\r
296   /*\r
297   UInt32 GetPosLen2Price(UInt32 pos, UInt32 posState) const\r
298   {\r
299     if (pos >= kNumFullDistances)\r
300       return kIfinityPrice;\r
301     return _distancesPrices[0][pos] + _lenEncoder.GetPrice(0, posState);\r
302   }\r
303   UInt32 GetPosLen3Price(UInt32 pos, UInt32 len, UInt32 posState) const\r
304   {\r
305     UInt32 price;\r
306     UInt32 lenToPosState = GetLenToPosState(len);\r
307     if (pos < kNumFullDistances)\r
308       price = _distancesPrices[lenToPosState][pos];\r
309     else\r
310       price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + \r
311           _alignPrices[pos & kAlignMask];\r
312     return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);\r
313   }\r
314   */\r
315   UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) const\r
316   {\r
317     UInt32 price;\r
318     UInt32 lenToPosState = GetLenToPosState(len);\r
319     if (pos < kNumFullDistances)\r
320       price = _distancesPrices[lenToPosState][pos];\r
321     else\r
322       price = _posSlotPrices[lenToPosState][GetPosSlot2(pos)] + \r
323           _alignPrices[pos & kAlignMask];\r
324     return price + _lenEncoder.GetPrice(len - kMatchMinLen, posState);\r
325   }\r
326 \r
327   UInt32 Backward(UInt32 &backRes, UInt32 cur);\r
328   HRESULT GetOptimum(UInt32 position, UInt32 &backRes, UInt32 &lenRes);\r
329   HRESULT GetOptimumFast(UInt32 position, UInt32 &backRes, UInt32 &lenRes);\r
330 \r
331   void FillDistancesPrices();\r
332   void FillAlignPrices();\r
333     \r
334   void ReleaseMFStream()\r
335   {\r
336     if (_matchFinder && _needReleaseMFStream)\r
337     {\r
338       _matchFinder->ReleaseStream();\r
339       _needReleaseMFStream = false;\r
340     }\r
341   }\r
342 \r
343   void ReleaseStreams()\r
344   {\r
345     ReleaseMFStream();\r
346     ReleaseOutStream();\r
347   }\r
348 \r
349   HRESULT Flush(UInt32 nowPos);\r
350   class CCoderReleaser\r
351   {\r
352     CEncoder *_coder;\r
353   public:\r
354     CCoderReleaser(CEncoder *coder): _coder(coder) {}\r
355     ~CCoderReleaser()\r
356     {\r
357       _coder->ReleaseStreams();\r
358     }\r
359   };\r
360   friend class CCoderReleaser;\r
361 \r
362   void WriteEndMarker(UInt32 posState);\r
363 \r
364 public:\r
365   CEncoder();\r
366   void SetWriteEndMarkerMode(bool writeEndMarker)\r
367     { _writeEndMark= writeEndMarker; }\r
368 \r
369   HRESULT Create();\r
370 \r
371   MY_UNKNOWN_IMP3(\r
372       ICompressSetOutStream,\r
373       ICompressSetCoderProperties,\r
374       ICompressWriteCoderProperties\r
375       )\r
376     \r
377   HRESULT Init();\r
378   \r
379   // ICompressCoder interface\r
380   HRESULT SetStreams(ISequentialInStream *inStream,\r
381       ISequentialOutStream *outStream,\r
382       const UInt64 *inSize, const UInt64 *outSize);\r
383   HRESULT CodeOneBlock(UInt64 *inSize, UInt64 *outSize, Int32 *finished);\r
384 \r
385   HRESULT CodeReal(ISequentialInStream *inStream,\r
386       ISequentialOutStream *outStream, \r
387       const UInt64 *inSize, const UInt64 *outSize,\r
388       ICompressProgressInfo *progress);\r
389 \r
390   // ICompressCoder interface\r
391   STDMETHOD(Code)(ISequentialInStream *inStream,\r
392       ISequentialOutStream *outStream, \r
393       const UInt64 *inSize, const UInt64 *outSize,\r
394       ICompressProgressInfo *progress);\r
395 \r
396   // ICompressSetCoderProperties2\r
397   STDMETHOD(SetCoderProperties)(const PROPID *propIDs, \r
398       const PROPVARIANT *properties, UInt32 numProperties);\r
399   \r
400   // ICompressWriteCoderProperties\r
401   STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);\r
402 \r
403   STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);\r
404   STDMETHOD(ReleaseOutStream)();\r
405 \r
406   virtual ~CEncoder() {}\r
407 };\r
408 \r
409 }}\r
410 \r
411 #endif\r