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>