Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZMA/LZMAEncoder.h, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>