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>