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