5 #include "LZMADecoder.h"
6 #include "../../../Common/Defs.h"
11 const int kLenIdFinished
= -1;
12 const int kLenIdNeedInit
= -2;
17 for(int i
= 0; i
< kNumStates
; i
++)
19 for (UInt32 j
= 0; j
<= _posStateMask
; j
++)
21 _isMatch
[i
][j
].Init();
22 _isRep0Long
[i
][j
].Init();
31 for (UInt32 i
= 0; i
< kNumLenToPosStates
; i
++)
32 _posSlotDecoder
[i
].Init();
35 for(UInt32 i
= 0; i
< kNumFullDistances
- kEndPosModelIndex
; i
++)
36 _posDecoders
[i
].Init();
38 _posAlignDecoder
.Init();
39 _lenDecoder
.Init(_posStateMask
+ 1);
40 _repMatchLenDecoder
.Init(_posStateMask
+ 1);
41 _literalDecoder
.Init();
44 _reps
[0] = _reps
[1] = _reps
[2] = _reps
[3] = 0;
47 HRESULT
CDecoder::CodeSpec(UInt32 curSize
)
51 const UInt64 rem
= _outSize
- _outWindowStream
.GetProcessedSize();
53 curSize
= (UInt32
)rem
;
56 if (_remainLen
== kLenIdFinished
)
58 if (_remainLen
== kLenIdNeedInit
)
67 UInt32 rep0
= _reps
[0];
68 UInt32 rep1
= _reps
[1];
69 UInt32 rep2
= _reps
[2];
70 UInt32 rep3
= _reps
[3];
71 CState state
= _state
;
74 while(_remainLen
> 0 && curSize
> 0)
76 previousByte
= _outWindowStream
.GetByte(rep0
);
77 _outWindowStream
.PutByte(previousByte
);
81 UInt64 nowPos64
= _outWindowStream
.GetProcessedSize();
85 previousByte
= _outWindowStream
.GetByte(0);
91 if (_rangeDecoder
.Stream
.ErrorCode
!= S_OK
)
92 return _rangeDecoder
.Stream
.ErrorCode
;
94 if (_rangeDecoder
.Stream
.WasFinished())
96 UInt32 posState
= UInt32(nowPos64
) & _posStateMask
;
97 if (_isMatch
[state
.Index
][posState
].Decode(&_rangeDecoder
) == 0)
99 if(!state
.IsCharState())
100 previousByte
= _literalDecoder
.DecodeWithMatchByte(&_rangeDecoder
,
101 (UInt32
)nowPos64
, previousByte
, _outWindowStream
.GetByte(rep0
));
103 previousByte
= _literalDecoder
.DecodeNormal(&_rangeDecoder
,
104 (UInt32
)nowPos64
, previousByte
);
105 _outWindowStream
.PutByte(previousByte
);
113 if(_isRep
[state
.Index
].Decode(&_rangeDecoder
) == 1)
116 if(_isRepG0
[state
.Index
].Decode(&_rangeDecoder
) == 0)
118 if(_isRep0Long
[state
.Index
][posState
].Decode(&_rangeDecoder
) == 0)
120 state
.UpdateShortRep();
127 if(_isRepG1
[state
.Index
].Decode(&_rangeDecoder
) == 0)
131 if (_isRepG2
[state
.Index
].Decode(&_rangeDecoder
) == 0)
145 len
= _repMatchLenDecoder
.Decode(&_rangeDecoder
, posState
) + kMatchMinLen
;
154 len
= kMatchMinLen
+ _lenDecoder
.Decode(&_rangeDecoder
, posState
);
156 UInt32 posSlot
= _posSlotDecoder
[GetLenToPosState(len
)].Decode(&_rangeDecoder
);
157 if (posSlot
>= kStartPosModelIndex
)
159 UInt32 numDirectBits
= (posSlot
>> 1) - 1;
160 rep0
= ((2 | (posSlot
& 1)) << numDirectBits
);
162 if (posSlot
< kEndPosModelIndex
)
163 rep0
+= NRangeCoder::ReverseBitTreeDecode(_posDecoders
+
164 rep0
- posSlot
- 1, &_rangeDecoder
, numDirectBits
);
167 rep0
+= (_rangeDecoder
.DecodeDirectBits(
168 numDirectBits
- kNumAlignBits
) << kNumAlignBits
);
169 rep0
+= _posAlignDecoder
.ReverseDecode(&_rangeDecoder
);
170 if (rep0
== 0xFFFFFFFF)
172 _remainLen
= kLenIdFinished
;
182 locLen
= (UInt32
)curSize
;
183 if (!_outWindowStream
.CopyBlock(rep0
, locLen
))
185 previousByte
= _outWindowStream
.GetByte(0);
191 _remainLen
= (Int32
)len
;
195 #ifdef _NO_EXCEPTIONS
196 if (_outWindowStream
.ErrorCode
!= S_OK
)
197 return _outWindowStream
.ErrorCode
;
202 if (_rangeDecoder
.Stream
.WasFinished())
213 STDMETHODIMP
CDecoder::CodeReal(ISequentialInStream
*inStream
,
214 ISequentialOutStream
*outStream
,
215 const UInt64
*, const UInt64
*outSize
,
216 ICompressProgressInfo
*progress
)
218 SetInStream(inStream
);
219 _outWindowStream
.SetStream(outStream
);
220 SetOutStreamSize(outSize
);
221 CDecoderFlusher
flusher(this);
225 UInt32 curSize
= 1 << 18;
226 RINOK(CodeSpec(curSize
));
227 if (_remainLen
== kLenIdFinished
)
229 if (progress
!= NULL
)
231 UInt64 inSize
= _rangeDecoder
.GetProcessedSize();
232 UInt64 nowPos64
= _outWindowStream
.GetProcessedSize();
233 RINOK(progress
->SetRatioInfo(&inSize
, &nowPos64
));
236 if (_outWindowStream
.GetProcessedSize() >= _outSize
)
239 flusher
.NeedFlush
= false;
244 #ifdef _NO_EXCEPTIONS
246 #define LZMA_TRY_BEGIN
251 #define LZMA_TRY_BEGIN try {
252 #define LZMA_TRY_END } \
253 catch(const CInBufferException &e) { return e.ErrorCode; } \
254 catch(const CLZOutWindowException &e) { return e.ErrorCode; } \
255 catch(...) { return S_FALSE; }
260 STDMETHODIMP
CDecoder::Code(ISequentialInStream
*inStream
,
261 ISequentialOutStream
*outStream
, const UInt64
*inSize
, const UInt64
*outSize
,
262 ICompressProgressInfo
*progress
)
265 return CodeReal(inStream
, outStream
, inSize
, outSize
, progress
);
269 STDMETHODIMP
CDecoder::SetDecoderProperties2(const Byte
*properties
, UInt32 size
)
273 int lc
= properties
[0] % 9;
274 Byte remainder
= (Byte
)(properties
[0] / 9);
275 int lp
= remainder
% 5;
276 int pb
= remainder
/ 5;
277 UInt32 dictionarySize
= 0;
278 for (int i
= 0; i
< 4; i
++)
279 dictionarySize
+= ((UInt32
)(properties
[1 + i
])) << (i
* 8);
280 return SetDecoderPropertiesRaw(lc
, lp
, pb
, dictionarySize
);
283 STDMETHODIMP
CDecoder::SetDecoderPropertiesRaw(int lc
, int lp
, int pb
, UInt32 dictionarySize
)
285 if (pb
> NLength::kNumPosStatesBitsMax
)
287 _posStateMask
= (1 << pb
) - 1;
288 if (!_outWindowStream
.Create(dictionarySize
))
289 return E_OUTOFMEMORY
;
290 if (!_literalDecoder
.Create(lp
, lc
))
291 return E_OUTOFMEMORY
;
292 if (!_rangeDecoder
.Create(1 << 20))
293 return E_OUTOFMEMORY
;
297 STDMETHODIMP
CDecoder::GetInStreamProcessedSize(UInt64
*value
)
299 *value
= _rangeDecoder
.GetProcessedSize();
303 STDMETHODIMP
CDecoder::SetInStream(ISequentialInStream
*inStream
)
305 _rangeDecoder
.SetStream(inStream
);
309 STDMETHODIMP
CDecoder::ReleaseInStream()
311 _rangeDecoder
.ReleaseStream();
315 STDMETHODIMP
CDecoder::SetOutStreamSize(const UInt64
*outSize
)
317 if (_outSizeDefined
= (outSize
!= NULL
))
319 _remainLen
= kLenIdNeedInit
;
320 _outWindowStream
.Init();
326 STDMETHODIMP
CDecoder::Read(void *data
, UInt32 size
, UInt32
*processedSize
)
331 const UInt64 startPos
= _outWindowStream
.GetProcessedSize();
332 _outWindowStream
.SetMemStream((Byte
*)data
);
333 RINOK(CodeSpec(size
));
335 *processedSize
= (UInt32
)(_outWindowStream
.GetProcessedSize() - startPos
);