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