Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZMA/LZMADecoder.cpp, revision 1.1

1.1     ! misho       1: // LZMADecoder.cpp
        !             2: 
        !             3: #include "StdAfx.h"
        !             4: 
        !             5: #include "LZMADecoder.h"
        !             6: #include "../../../Common/Defs.h"
        !             7: 
        !             8: namespace NCompress {
        !             9: namespace NLZMA {
        !            10: 
        !            11: void CDecoder::Init()
        !            12: {
        !            13:   { 
        !            14:     for(int i = 0; i < kNumStates; i++)
        !            15:     {
        !            16:       for (UInt32 j = 0; j <= _posStateMask; j++)
        !            17:       {
        !            18:         _isMatch[i][j].Init();
        !            19:         _isRep0Long[i][j].Init();
        !            20:       }
        !            21:       _isRep[i].Init();
        !            22:       _isRepG0[i].Init();
        !            23:       _isRepG1[i].Init();
        !            24:       _isRepG2[i].Init();
        !            25:     }
        !            26:   }
        !            27:   { 
        !            28:     for (UInt32 i = 0; i < kNumLenToPosStates; i++)
        !            29:     _posSlotDecoder[i].Init();
        !            30:   }
        !            31:   { 
        !            32:     for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
        !            33:       _posDecoders[i].Init();
        !            34:   }
        !            35:   _posAlignDecoder.Init();
        !            36:   _lenDecoder.Init(_posStateMask + 1);
        !            37:   _repMatchLenDecoder.Init(_posStateMask + 1);
        !            38:   _literalDecoder.Init();
        !            39: 
        !            40:   _state.Init();
        !            41:   _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0;
        !            42: }
        !            43: 
        !            44: HRESULT CDecoder::CodeSpec(Byte *buffer, UInt32 curSize)
        !            45: {
        !            46:   if (_remainLen == -1)
        !            47:     return S_OK;
        !            48:   if (_remainLen == -2)
        !            49:   {
        !            50:     _rangeDecoder.Init();
        !            51:     Init();
        !            52:     _remainLen = 0;
        !            53:   }
        !            54:   if (curSize == 0)
        !            55:     return S_OK;
        !            56: 
        !            57:   UInt64 nowPos64 = _nowPos64;
        !            58: 
        !            59:   UInt32 rep0 = _reps[0];
        !            60:   UInt32 rep1 = _reps[1];
        !            61:   UInt32 rep2 = _reps[2];
        !            62:   UInt32 rep3 = _reps[3];
        !            63:   CState state = _state;
        !            64:   Byte previousByte;
        !            65: 
        !            66:   while(_remainLen > 0 && curSize > 0)
        !            67:   {
        !            68:     previousByte = _outWindowStream.GetByte(rep0);
        !            69:     _outWindowStream.PutByte(previousByte);
        !            70:     if (buffer)
        !            71:       *buffer++ = previousByte;
        !            72:     nowPos64++;
        !            73:     _remainLen--;
        !            74:     curSize--;
        !            75:   }
        !            76:   if (nowPos64 == 0)
        !            77:     previousByte = 0;
        !            78:   else
        !            79:     previousByte = _outWindowStream.GetByte(0);
        !            80: 
        !            81:   while(curSize > 0)
        !            82:   {
        !            83:     {
        !            84:       #ifdef _NO_EXCEPTIONS
        !            85:       if (_rangeDecoder.Stream.ErrorCode != S_OK)
        !            86:         return _rangeDecoder.Stream.ErrorCode;
        !            87:       #endif
        !            88:       if (_rangeDecoder.Stream.WasFinished())
        !            89:         return S_FALSE;
        !            90:       UInt32 posState = UInt32(nowPos64) & _posStateMask;
        !            91:       if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0)
        !            92:       {
        !            93:         if(!state.IsCharState())
        !            94:           previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, 
        !            95:               (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0));
        !            96:         else
        !            97:           previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, 
        !            98:               (UInt32)nowPos64, previousByte);
        !            99:         _outWindowStream.PutByte(previousByte);
        !           100:         if (buffer)
        !           101:           *buffer++ = previousByte;
        !           102:         state.UpdateChar();
        !           103:         curSize--;
        !           104:         nowPos64++;
        !           105:       }
        !           106:       else             
        !           107:       {
        !           108:         UInt32 len;
        !           109:         if(_isRep[state.Index].Decode(&_rangeDecoder) == 1)
        !           110:         {
        !           111:           if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0)
        !           112:           {
        !           113:             if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0)
        !           114:             {
        !           115:               if (nowPos64 == 0)
        !           116:                 return S_FALSE;
        !           117:               state.UpdateShortRep();
        !           118:               previousByte = _outWindowStream.GetByte(rep0);
        !           119:               _outWindowStream.PutByte(previousByte);
        !           120:               if (buffer)
        !           121:                 *buffer++ = previousByte;
        !           122:               curSize--;
        !           123:               nowPos64++;
        !           124:               continue;
        !           125:             }
        !           126:           }
        !           127:           else
        !           128:           {
        !           129:             UInt32 distance;
        !           130:             if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0)
        !           131:               distance = rep1;
        !           132:             else 
        !           133:             {
        !           134:               if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0)
        !           135:                 distance = rep2;
        !           136:               else
        !           137:               {
        !           138:                 distance = rep3;
        !           139:                 rep3 = rep2;
        !           140:               }
        !           141:               rep2 = rep1;
        !           142:             }
        !           143:             rep1 = rep0;
        !           144:             rep0 = distance;
        !           145:           }
        !           146:           len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen;
        !           147:           state.UpdateRep();
        !           148:         }
        !           149:         else
        !           150:         {
        !           151:           rep3 = rep2;
        !           152:           rep2 = rep1;
        !           153:           rep1 = rep0;
        !           154:           len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState);
        !           155:           state.UpdateMatch();
        !           156:           UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder);
        !           157:           if (posSlot >= kStartPosModelIndex)
        !           158:           {
        !           159:             UInt32 numDirectBits = (posSlot >> 1) - 1;
        !           160:             rep0 = ((2 | (posSlot & 1)) << numDirectBits);
        !           161: 
        !           162:             if (posSlot < kEndPosModelIndex)
        !           163:               rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + 
        !           164:                   rep0 - posSlot - 1, &_rangeDecoder, numDirectBits);
        !           165:             else
        !           166:             {
        !           167:               rep0 += (_rangeDecoder.DecodeDirectBits(
        !           168:                   numDirectBits - kNumAlignBits) << kNumAlignBits);
        !           169:               rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder);
        !           170:             }
        !           171:           }
        !           172:           else
        !           173:             rep0 = posSlot;
        !           174:           if (rep0 >= nowPos64 || rep0 >= _dictionarySizeCheck)
        !           175:           {
        !           176:             if (rep0 != (UInt32)(Int32)(-1))
        !           177:               return S_FALSE;
        !           178:             _nowPos64 = nowPos64;
        !           179:             _remainLen = -1;
        !           180:             return S_OK;
        !           181:           }
        !           182:         }
        !           183:         UInt32 locLen = len;
        !           184:         if (len > curSize)
        !           185:           locLen = (UInt32)curSize;
        !           186:         if (buffer)
        !           187:         {
        !           188:           for (UInt32 i = locLen; i != 0; i--)
        !           189:           {
        !           190:             previousByte = _outWindowStream.GetByte(rep0);
        !           191:             *buffer++ = previousByte;
        !           192:             _outWindowStream.PutByte(previousByte);
        !           193:           }
        !           194:         }
        !           195:         else
        !           196:         {
        !           197:           _outWindowStream.CopyBlock(rep0, locLen);
        !           198:           previousByte = _outWindowStream.GetByte(0);
        !           199:         }
        !           200:         curSize -= locLen;
        !           201:         nowPos64 += locLen;
        !           202:         len -= locLen;
        !           203:         if (len != 0)
        !           204:         {
        !           205:           _remainLen = (Int32)len;
        !           206:           break;
        !           207:         }
        !           208: 
        !           209:         #ifdef _NO_EXCEPTIONS
        !           210:         if (_outWindowStream.ErrorCode != S_OK)
        !           211:           return _outWindowStream.ErrorCode;
        !           212:         #endif
        !           213:       }
        !           214:     }
        !           215:   }
        !           216:   if (_rangeDecoder.Stream.WasFinished())
        !           217:     return S_FALSE;
        !           218:   _nowPos64 = nowPos64;
        !           219:   _reps[0] = rep0;
        !           220:   _reps[1] = rep1;
        !           221:   _reps[2] = rep2;
        !           222:   _reps[3] = rep3;
        !           223:   _state = state;
        !           224: 
        !           225:   return S_OK;
        !           226: }
        !           227: 
        !           228: STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream,
        !           229:     ISequentialOutStream *outStream, 
        !           230:     const UInt64 *, const UInt64 *outSize,
        !           231:     ICompressProgressInfo *progress)
        !           232: {
        !           233:   SetInStream(inStream);
        !           234:   _outWindowStream.SetStream(outStream);
        !           235:   SetOutStreamSize(outSize);
        !           236:   CDecoderFlusher flusher(this);
        !           237: 
        !           238:   while (true)
        !           239:   {
        !           240:     UInt32 curSize = 1 << 18;
        !           241:     if (_outSize != (UInt64)(Int64)(-1))
        !           242:       if (curSize > _outSize - _nowPos64)
        !           243:         curSize = (UInt32)(_outSize - _nowPos64);
        !           244:     RINOK(CodeSpec(0, curSize));
        !           245:     if (_remainLen == -1)
        !           246:       break;
        !           247:     if (progress != NULL)
        !           248:     {
        !           249:       UInt64 inSize = _rangeDecoder.GetProcessedSize();
        !           250:       RINOK(progress->SetRatioInfo(&inSize, &_nowPos64));
        !           251:     }
        !           252:     if (_outSize != (UInt64)(Int64)(-1))
        !           253:       if (_nowPos64 >= _outSize)
        !           254:         break;
        !           255:   } 
        !           256:   flusher.NeedFlush = false;
        !           257:   return Flush();
        !           258: }
        !           259: 
        !           260: STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,
        !           261:       ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
        !           262:       ICompressProgressInfo *progress)
        !           263: {
        !           264:   #ifndef _NO_EXCEPTIONS
        !           265:   try 
        !           266:   { 
        !           267:   #endif
        !           268:     return CodeReal(inStream, outStream, inSize, outSize, progress); 
        !           269:   #ifndef _NO_EXCEPTIONS
        !           270:   }
        !           271:   catch(const CInBufferException &e)  { return e.ErrorCode; }
        !           272:   catch(const CLZOutWindowException &e)  { return e.ErrorCode; }
        !           273:   catch(...) { return S_FALSE; }
        !           274:   #endif
        !           275: }
        !           276: 
        !           277: STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size)
        !           278: {
        !           279:   if (size < 5)
        !           280:     return E_INVALIDARG;
        !           281:   int lc = properties[0] % 9;
        !           282:   Byte remainder = (Byte)(properties[0] / 9);
        !           283:   int lp = remainder % 5;
        !           284:   int pb = remainder / 5;
        !           285:   if (pb > NLength::kNumPosStatesBitsMax)
        !           286:     return E_INVALIDARG;
        !           287:   _posStateMask = (1 << pb) - 1;
        !           288:   UInt32 dictionarySize = 0;
        !           289:   for (int i = 0; i < 4; i++)
        !           290:     dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
        !           291:   _dictionarySizeCheck = MyMax(dictionarySize, UInt32(1));
        !           292:   UInt32 blockSize = MyMax(_dictionarySizeCheck, UInt32(1 << 12));
        !           293:   if (!_outWindowStream.Create(blockSize))
        !           294:     return E_OUTOFMEMORY;
        !           295:   if (!_literalDecoder.Create(lp, lc))
        !           296:     return E_OUTOFMEMORY;
        !           297:   if (!_rangeDecoder.Create(1 << 20))
        !           298:     return E_OUTOFMEMORY;
        !           299:   return S_OK;
        !           300: }
        !           301: 
        !           302: STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value)
        !           303: {
        !           304:   *value = _rangeDecoder.GetProcessedSize();
        !           305:   return S_OK;
        !           306: }
        !           307: 
        !           308: STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream)
        !           309: {
        !           310:   _rangeDecoder.SetStream(inStream);
        !           311:   return S_OK;
        !           312: }
        !           313: 
        !           314: STDMETHODIMP CDecoder::ReleaseInStream()
        !           315: {
        !           316:   _rangeDecoder.ReleaseStream();
        !           317:   return S_OK;
        !           318: }
        !           319: 
        !           320: STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize)
        !           321: {
        !           322:   _outSize = (outSize == NULL) ? (UInt64)(Int64)(-1) : *outSize;
        !           323:   _nowPos64 = 0;
        !           324:   _remainLen = -2; // -2 means need_init
        !           325:   _outWindowStream.Init();
        !           326:   return S_OK;
        !           327: }
        !           328: 
        !           329: STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
        !           330: {
        !           331:   #ifndef _NO_EXCEPTIONS
        !           332:   try 
        !           333:   { 
        !           334:   #endif
        !           335:   UInt64 startPos = _nowPos64;
        !           336:   if (_outSize != (UInt64)(Int64)(-1))
        !           337:     if (size > _outSize - _nowPos64)
        !           338:       size = (UInt32)(_outSize - _nowPos64);
        !           339:   HRESULT res = CodeSpec((Byte *)data, size);
        !           340:   if (processedSize)
        !           341:     *processedSize = (UInt32)(_nowPos64 - startPos);
        !           342:   return res;
        !           343:   #ifndef _NO_EXCEPTIONS
        !           344:   }
        !           345:   catch(const CInBufferException &e)  { return e.ErrorCode; }
        !           346:   catch(const CLZOutWindowException &e)  { return e.ErrorCode; }
        !           347:   catch(...) { return S_FALSE; }
        !           348:   #endif
        !           349: }
        !           350: 
        !           351: STDMETHODIMP CDecoder::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
        !           352: {
        !           353:   return Read(data, size, processedSize);
        !           354: }
        !           355: 
        !           356: }}

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