LZMADecoder.cpp 8.4 KB

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