1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/7zstub/src/7zip/Compress/LZMA/LZMADecoder.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,337 @@ 1.4 +// LZMADecoder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "LZMADecoder.h" 1.9 +#include "../../../Common/Defs.h" 1.10 + 1.11 +namespace NCompress { 1.12 +namespace NLZMA { 1.13 + 1.14 +const int kLenIdFinished = -1; 1.15 +const int kLenIdNeedInit = -2; 1.16 + 1.17 +void CDecoder::Init() 1.18 +{ 1.19 + { 1.20 + for(int i = 0; i < kNumStates; i++) 1.21 + { 1.22 + for (UInt32 j = 0; j <= _posStateMask; j++) 1.23 + { 1.24 + _isMatch[i][j].Init(); 1.25 + _isRep0Long[i][j].Init(); 1.26 + } 1.27 + _isRep[i].Init(); 1.28 + _isRepG0[i].Init(); 1.29 + _isRepG1[i].Init(); 1.30 + _isRepG2[i].Init(); 1.31 + } 1.32 + } 1.33 + { 1.34 + for (UInt32 i = 0; i < kNumLenToPosStates; i++) 1.35 + _posSlotDecoder[i].Init(); 1.36 + } 1.37 + { 1.38 + for(UInt32 i = 0; i < kNumFullDistances - kEndPosModelIndex; i++) 1.39 + _posDecoders[i].Init(); 1.40 + } 1.41 + _posAlignDecoder.Init(); 1.42 + _lenDecoder.Init(_posStateMask + 1); 1.43 + _repMatchLenDecoder.Init(_posStateMask + 1); 1.44 + _literalDecoder.Init(); 1.45 + 1.46 + _state.Init(); 1.47 + _reps[0] = _reps[1] = _reps[2] = _reps[3] = 0; 1.48 +} 1.49 + 1.50 +HRESULT CDecoder::CodeSpec(UInt32 curSize) 1.51 +{ 1.52 + if (_outSizeDefined) 1.53 + { 1.54 + const UInt64 rem = _outSize - _outWindowStream.GetProcessedSize(); 1.55 + if (curSize > rem) 1.56 + curSize = (UInt32)rem; 1.57 + } 1.58 + 1.59 + if (_remainLen == kLenIdFinished) 1.60 + return S_OK; 1.61 + if (_remainLen == kLenIdNeedInit) 1.62 + { 1.63 + _rangeDecoder.Init(); 1.64 + Init(); 1.65 + _remainLen = 0; 1.66 + } 1.67 + if (curSize == 0) 1.68 + return S_OK; 1.69 + 1.70 + UInt32 rep0 = _reps[0]; 1.71 + UInt32 rep1 = _reps[1]; 1.72 + UInt32 rep2 = _reps[2]; 1.73 + UInt32 rep3 = _reps[3]; 1.74 + CState state = _state; 1.75 + Byte previousByte; 1.76 + 1.77 + while(_remainLen > 0 && curSize > 0) 1.78 + { 1.79 + previousByte = _outWindowStream.GetByte(rep0); 1.80 + _outWindowStream.PutByte(previousByte); 1.81 + _remainLen--; 1.82 + curSize--; 1.83 + } 1.84 + UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); 1.85 + if (nowPos64 == 0) 1.86 + previousByte = 0; 1.87 + else 1.88 + previousByte = _outWindowStream.GetByte(0); 1.89 + 1.90 + while(curSize > 0) 1.91 + { 1.92 + { 1.93 + #ifdef _NO_EXCEPTIONS 1.94 + if (_rangeDecoder.Stream.ErrorCode != S_OK) 1.95 + return _rangeDecoder.Stream.ErrorCode; 1.96 + #endif 1.97 + if (_rangeDecoder.Stream.WasFinished()) 1.98 + return S_FALSE; 1.99 + UInt32 posState = UInt32(nowPos64) & _posStateMask; 1.100 + if (_isMatch[state.Index][posState].Decode(&_rangeDecoder) == 0) 1.101 + { 1.102 + if(!state.IsCharState()) 1.103 + previousByte = _literalDecoder.DecodeWithMatchByte(&_rangeDecoder, 1.104 + (UInt32)nowPos64, previousByte, _outWindowStream.GetByte(rep0)); 1.105 + else 1.106 + previousByte = _literalDecoder.DecodeNormal(&_rangeDecoder, 1.107 + (UInt32)nowPos64, previousByte); 1.108 + _outWindowStream.PutByte(previousByte); 1.109 + state.UpdateChar(); 1.110 + curSize--; 1.111 + nowPos64++; 1.112 + } 1.113 + else 1.114 + { 1.115 + UInt32 len; 1.116 + if(_isRep[state.Index].Decode(&_rangeDecoder) == 1) 1.117 + { 1.118 + len = 0; 1.119 + if(_isRepG0[state.Index].Decode(&_rangeDecoder) == 0) 1.120 + { 1.121 + if(_isRep0Long[state.Index][posState].Decode(&_rangeDecoder) == 0) 1.122 + { 1.123 + state.UpdateShortRep(); 1.124 + len = 1; 1.125 + } 1.126 + } 1.127 + else 1.128 + { 1.129 + UInt32 distance; 1.130 + if(_isRepG1[state.Index].Decode(&_rangeDecoder) == 0) 1.131 + distance = rep1; 1.132 + else 1.133 + { 1.134 + if (_isRepG2[state.Index].Decode(&_rangeDecoder) == 0) 1.135 + distance = rep2; 1.136 + else 1.137 + { 1.138 + distance = rep3; 1.139 + rep3 = rep2; 1.140 + } 1.141 + rep2 = rep1; 1.142 + } 1.143 + rep1 = rep0; 1.144 + rep0 = distance; 1.145 + } 1.146 + if (len == 0) 1.147 + { 1.148 + len = _repMatchLenDecoder.Decode(&_rangeDecoder, posState) + kMatchMinLen; 1.149 + state.UpdateRep(); 1.150 + } 1.151 + } 1.152 + else 1.153 + { 1.154 + rep3 = rep2; 1.155 + rep2 = rep1; 1.156 + rep1 = rep0; 1.157 + len = kMatchMinLen + _lenDecoder.Decode(&_rangeDecoder, posState); 1.158 + state.UpdateMatch(); 1.159 + UInt32 posSlot = _posSlotDecoder[GetLenToPosState(len)].Decode(&_rangeDecoder); 1.160 + if (posSlot >= kStartPosModelIndex) 1.161 + { 1.162 + UInt32 numDirectBits = (posSlot >> 1) - 1; 1.163 + rep0 = ((2 | (posSlot & 1)) << numDirectBits); 1.164 + 1.165 + if (posSlot < kEndPosModelIndex) 1.166 + rep0 += NRangeCoder::ReverseBitTreeDecode(_posDecoders + 1.167 + rep0 - posSlot - 1, &_rangeDecoder, numDirectBits); 1.168 + else 1.169 + { 1.170 + rep0 += (_rangeDecoder.DecodeDirectBits( 1.171 + numDirectBits - kNumAlignBits) << kNumAlignBits); 1.172 + rep0 += _posAlignDecoder.ReverseDecode(&_rangeDecoder); 1.173 + if (rep0 == 0xFFFFFFFF) 1.174 + { 1.175 + _remainLen = kLenIdFinished; 1.176 + return S_OK; 1.177 + } 1.178 + } 1.179 + } 1.180 + else 1.181 + rep0 = posSlot; 1.182 + } 1.183 + UInt32 locLen = len; 1.184 + if (len > curSize) 1.185 + locLen = (UInt32)curSize; 1.186 + if (!_outWindowStream.CopyBlock(rep0, locLen)) 1.187 + return S_FALSE; 1.188 + previousByte = _outWindowStream.GetByte(0); 1.189 + curSize -= locLen; 1.190 + nowPos64 += locLen; 1.191 + len -= locLen; 1.192 + if (len != 0) 1.193 + { 1.194 + _remainLen = (Int32)len; 1.195 + break; 1.196 + } 1.197 + 1.198 + #ifdef _NO_EXCEPTIONS 1.199 + if (_outWindowStream.ErrorCode != S_OK) 1.200 + return _outWindowStream.ErrorCode; 1.201 + #endif 1.202 + } 1.203 + } 1.204 + } 1.205 + if (_rangeDecoder.Stream.WasFinished()) 1.206 + return S_FALSE; 1.207 + _reps[0] = rep0; 1.208 + _reps[1] = rep1; 1.209 + _reps[2] = rep2; 1.210 + _reps[3] = rep3; 1.211 + _state = state; 1.212 + 1.213 + return S_OK; 1.214 +} 1.215 + 1.216 +STDMETHODIMP CDecoder::CodeReal(ISequentialInStream *inStream, 1.217 + ISequentialOutStream *outStream, 1.218 + const UInt64 *, const UInt64 *outSize, 1.219 + ICompressProgressInfo *progress) 1.220 +{ 1.221 + SetInStream(inStream); 1.222 + _outWindowStream.SetStream(outStream); 1.223 + SetOutStreamSize(outSize); 1.224 + CDecoderFlusher flusher(this); 1.225 + 1.226 + while (true) 1.227 + { 1.228 + UInt32 curSize = 1 << 18; 1.229 + RINOK(CodeSpec(curSize)); 1.230 + if (_remainLen == kLenIdFinished) 1.231 + break; 1.232 + if (progress != NULL) 1.233 + { 1.234 + UInt64 inSize = _rangeDecoder.GetProcessedSize(); 1.235 + UInt64 nowPos64 = _outWindowStream.GetProcessedSize(); 1.236 + RINOK(progress->SetRatioInfo(&inSize, &nowPos64)); 1.237 + } 1.238 + if (_outSizeDefined) 1.239 + if (_outWindowStream.GetProcessedSize() >= _outSize) 1.240 + break; 1.241 + } 1.242 + flusher.NeedFlush = false; 1.243 + return Flush(); 1.244 +} 1.245 + 1.246 + 1.247 +#ifdef _NO_EXCEPTIONS 1.248 + 1.249 +#define LZMA_TRY_BEGIN 1.250 +#define LZMA_TRY_END 1.251 + 1.252 +#else 1.253 + 1.254 +#define LZMA_TRY_BEGIN try { 1.255 +#define LZMA_TRY_END } \ 1.256 + catch(const CInBufferException &e) { return e.ErrorCode; } \ 1.257 + catch(const CLZOutWindowException &e) { return e.ErrorCode; } \ 1.258 + catch(...) { return S_FALSE; } 1.259 + 1.260 +#endif 1.261 + 1.262 + 1.263 +STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, 1.264 + ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, 1.265 + ICompressProgressInfo *progress) 1.266 +{ 1.267 + LZMA_TRY_BEGIN 1.268 + return CodeReal(inStream, outStream, inSize, outSize, progress); 1.269 + LZMA_TRY_END 1.270 +} 1.271 + 1.272 +STDMETHODIMP CDecoder::SetDecoderProperties2(const Byte *properties, UInt32 size) 1.273 +{ 1.274 + if (size < 5) 1.275 + return E_INVALIDARG; 1.276 + int lc = properties[0] % 9; 1.277 + Byte remainder = (Byte)(properties[0] / 9); 1.278 + int lp = remainder % 5; 1.279 + int pb = remainder / 5; 1.280 + if (pb > NLength::kNumPosStatesBitsMax) 1.281 + return E_INVALIDARG; 1.282 + _posStateMask = (1 << pb) - 1; 1.283 + UInt32 dictionarySize = 0; 1.284 + for (int i = 0; i < 4; i++) 1.285 + dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); 1.286 + if (!_outWindowStream.Create(dictionarySize)) 1.287 + return E_OUTOFMEMORY; 1.288 + if (!_literalDecoder.Create(lp, lc)) 1.289 + return E_OUTOFMEMORY; 1.290 + if (!_rangeDecoder.Create(1 << 20)) 1.291 + return E_OUTOFMEMORY; 1.292 + return S_OK; 1.293 +} 1.294 + 1.295 +STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value) 1.296 +{ 1.297 + *value = _rangeDecoder.GetProcessedSize(); 1.298 + return S_OK; 1.299 +} 1.300 + 1.301 +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) 1.302 +{ 1.303 + _rangeDecoder.SetStream(inStream); 1.304 + return S_OK; 1.305 +} 1.306 + 1.307 +STDMETHODIMP CDecoder::ReleaseInStream() 1.308 +{ 1.309 + _rangeDecoder.ReleaseStream(); 1.310 + return S_OK; 1.311 +} 1.312 + 1.313 +STDMETHODIMP CDecoder::SetOutStreamSize(const UInt64 *outSize) 1.314 +{ 1.315 + if (_outSizeDefined = (outSize != NULL)) 1.316 + _outSize = *outSize; 1.317 + _remainLen = kLenIdNeedInit; 1.318 + _outWindowStream.Init(); 1.319 + return S_OK; 1.320 +} 1.321 + 1.322 +#ifdef _ST_MODE 1.323 + 1.324 +STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) 1.325 +{ 1.326 + LZMA_TRY_BEGIN 1.327 + if (processedSize) 1.328 + *processedSize = 0; 1.329 + const UInt64 startPos = _outWindowStream.GetProcessedSize(); 1.330 + _outWindowStream.SetMemStream((Byte *)data); 1.331 + RINOK(CodeSpec(size)); 1.332 + if (processedSize) 1.333 + *processedSize = (UInt32)(_outWindowStream.GetProcessedSize() - startPos); 1.334 + return Flush(); 1.335 + LZMA_TRY_END 1.336 +} 1.337 + 1.338 +#endif 1.339 + 1.340 +}}