1 /* Lzma2Dec.c -- LZMA2 Decoder
\r
2 2009-05-03 : Igor Pavlov : Public domain */
\r
4 /* #define SHOW_DEBUG_INFO */
\r
6 #ifdef SHOW_DEBUG_INFO
\r
12 #include "Lzma2Dec.h"
\r
16 00000001 U U - Uncompressed Reset Dic
\r
17 00000010 U U - Uncompressed No Reset
\r
18 100uuuuu U U P P - LZMA no reset
\r
19 101uuuuu U U P P - LZMA reset state
\r
20 110uuuuu U U P P S - LZMA reset state + new prop
\r
21 111uuuuu U U P P S - LZMA reset state + new prop + reset dic
\r
28 #define LZMA2_CONTROL_LZMA (1 << 7)
\r
29 #define LZMA2_CONTROL_COPY_NO_RESET 2
\r
30 #define LZMA2_CONTROL_COPY_RESET_DIC 1
\r
31 #define LZMA2_CONTROL_EOF 0
\r
33 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
\r
35 #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
\r
36 #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
\r
38 #define LZMA2_LCLP_MAX 4
\r
39 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
\r
41 #ifdef SHOW_DEBUG_INFO
\r
49 LZMA2_STATE_CONTROL,
\r
50 LZMA2_STATE_UNPACK0,
\r
51 LZMA2_STATE_UNPACK1,
\r
56 LZMA2_STATE_DATA_CONT,
\r
57 LZMA2_STATE_FINISHED,
\r
61 static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
\r
65 return SZ_ERROR_UNSUPPORTED;
\r
66 dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
\r
67 props[0] = (Byte)LZMA2_LCLP_MAX;
\r
68 props[1] = (Byte)(dicSize);
\r
69 props[2] = (Byte)(dicSize >> 8);
\r
70 props[3] = (Byte)(dicSize >> 16);
\r
71 props[4] = (Byte)(dicSize >> 24);
\r
75 SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
\r
77 Byte props[LZMA_PROPS_SIZE];
\r
78 RINOK(Lzma2Dec_GetOldProps(prop, props));
\r
79 return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
\r
82 SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
\r
84 Byte props[LZMA_PROPS_SIZE];
\r
85 RINOK(Lzma2Dec_GetOldProps(prop, props));
\r
86 return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
\r
89 void Lzma2Dec_Init(CLzma2Dec *p)
\r
91 p->state = LZMA2_STATE_CONTROL;
\r
92 p->needInitDic = True;
\r
93 p->needInitState = True;
\r
94 p->needInitProp = True;
\r
95 LzmaDec_Init(&p->decoder);
\r
98 static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
\r
102 case LZMA2_STATE_CONTROL:
\r
104 PRF(printf("\n %4X ", p->decoder.dicPos));
\r
105 PRF(printf(" %2X", b));
\r
106 if (p->control == 0)
\r
107 return LZMA2_STATE_FINISHED;
\r
108 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
\r
110 if ((p->control & 0x7F) > 2)
\r
111 return LZMA2_STATE_ERROR;
\r
115 p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
\r
116 return LZMA2_STATE_UNPACK0;
\r
118 case LZMA2_STATE_UNPACK0:
\r
119 p->unpackSize |= (UInt32)b << 8;
\r
120 return LZMA2_STATE_UNPACK1;
\r
122 case LZMA2_STATE_UNPACK1:
\r
123 p->unpackSize |= (UInt32)b;
\r
125 PRF(printf(" %8d", p->unpackSize));
\r
126 return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
\r
128 case LZMA2_STATE_PACK0:
\r
129 p->packSize = (UInt32)b << 8;
\r
130 return LZMA2_STATE_PACK1;
\r
132 case LZMA2_STATE_PACK1:
\r
133 p->packSize |= (UInt32)b;
\r
135 PRF(printf(" %8d", p->packSize));
\r
136 return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
\r
137 (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
\r
139 case LZMA2_STATE_PROP:
\r
142 if (b >= (9 * 5 * 5))
\r
143 return LZMA2_STATE_ERROR;
\r
146 p->decoder.prop.pb = b / 5;
\r
148 if (lc + lp > LZMA2_LCLP_MAX)
\r
149 return LZMA2_STATE_ERROR;
\r
150 p->decoder.prop.lc = lc;
\r
151 p->decoder.prop.lp = lp;
\r
152 p->needInitProp = False;
\r
153 return LZMA2_STATE_DATA;
\r
156 return LZMA2_STATE_ERROR;
\r
159 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
\r
161 memcpy(p->dic + p->dicPos, src, size);
\r
163 if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
\r
164 p->checkDicSize = p->prop.dicSize;
\r
165 p->processedPos += (UInt32)size;
\r
168 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
\r
170 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
\r
171 const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
\r
173 SizeT inSize = *srcLen;
\r
175 *status = LZMA_STATUS_NOT_SPECIFIED;
\r
177 while (p->state != LZMA2_STATE_FINISHED)
\r
179 SizeT dicPos = p->decoder.dicPos;
\r
180 if (p->state == LZMA2_STATE_ERROR)
\r
181 return SZ_ERROR_DATA;
\r
182 if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
\r
184 *status = LZMA_STATUS_NOT_FINISHED;
\r
187 if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
\r
189 if (*srcLen == inSize)
\r
191 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
\r
195 p->state = Lzma2Dec_UpdateState(p, *src++);
\r
199 SizeT destSizeCur = dicLimit - dicPos;
\r
200 SizeT srcSizeCur = inSize - *srcLen;
\r
201 ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
\r
203 if (p->unpackSize <= destSizeCur)
\r
205 destSizeCur = (SizeT)p->unpackSize;
\r
206 curFinishMode = LZMA_FINISH_END;
\r
209 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
\r
211 if (*srcLen == inSize)
\r
213 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
\r
217 if (p->state == LZMA2_STATE_DATA)
\r
219 Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
\r
221 p->needInitProp = p->needInitState = True;
\r
222 else if (p->needInitDic)
\r
223 return SZ_ERROR_DATA;
\r
224 p->needInitDic = False;
\r
225 LzmaDec_InitDicAndState(&p->decoder, initDic, False);
\r
228 if (srcSizeCur > destSizeCur)
\r
229 srcSizeCur = destSizeCur;
\r
231 if (srcSizeCur == 0)
\r
232 return SZ_ERROR_DATA;
\r
234 LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
\r
237 *srcLen += srcSizeCur;
\r
238 p->unpackSize -= (UInt32)srcSizeCur;
\r
239 p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
\r
243 SizeT outSizeProcessed;
\r
246 if (p->state == LZMA2_STATE_DATA)
\r
248 int mode = LZMA2_GET_LZMA_MODE(p);
\r
249 Bool initDic = (mode == 3);
\r
250 Bool initState = (mode > 0);
\r
251 if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
\r
252 return SZ_ERROR_DATA;
\r
254 LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
\r
255 p->needInitDic = False;
\r
256 p->needInitState = False;
\r
257 p->state = LZMA2_STATE_DATA_CONT;
\r
259 if (srcSizeCur > p->packSize)
\r
260 srcSizeCur = (SizeT)p->packSize;
\r
262 res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
\r
265 *srcLen += srcSizeCur;
\r
266 p->packSize -= (UInt32)srcSizeCur;
\r
268 outSizeProcessed = p->decoder.dicPos - dicPos;
\r
269 p->unpackSize -= (UInt32)outSizeProcessed;
\r
272 if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
\r
275 if (srcSizeCur == 0 && outSizeProcessed == 0)
\r
277 if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
\r
278 p->unpackSize != 0 || p->packSize != 0)
\r
279 return SZ_ERROR_DATA;
\r
280 p->state = LZMA2_STATE_CONTROL;
\r
282 if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
\r
283 *status = LZMA_STATUS_NOT_FINISHED;
\r
287 *status = LZMA_STATUS_FINISHED_WITH_MARK;
\r
291 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
\r
293 SizeT outSize = *destLen, inSize = *srcLen;
\r
294 *srcLen = *destLen = 0;
\r
297 SizeT srcSizeCur = inSize, outSizeCur, dicPos;
\r
298 ELzmaFinishMode curFinishMode;
\r
300 if (p->decoder.dicPos == p->decoder.dicBufSize)
\r
301 p->decoder.dicPos = 0;
\r
302 dicPos = p->decoder.dicPos;
\r
303 if (outSize > p->decoder.dicBufSize - dicPos)
\r
305 outSizeCur = p->decoder.dicBufSize;
\r
306 curFinishMode = LZMA_FINISH_ANY;
\r
310 outSizeCur = dicPos + outSize;
\r
311 curFinishMode = finishMode;
\r
314 res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
\r
316 inSize -= srcSizeCur;
\r
317 *srcLen += srcSizeCur;
\r
318 outSizeCur = p->decoder.dicPos - dicPos;
\r
319 memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
\r
320 dest += outSizeCur;
\r
321 outSize -= outSizeCur;
\r
322 *destLen += outSizeCur;
\r
325 if (outSizeCur == 0 || outSize == 0)
\r
330 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
\r
331 Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
\r
335 SizeT outSize = *destLen, inSize = *srcLen;
\r
336 Byte props[LZMA_PROPS_SIZE];
\r
338 Lzma2Dec_Construct(&decoder);
\r
340 *destLen = *srcLen = 0;
\r
341 *status = LZMA_STATUS_NOT_SPECIFIED;
\r
342 decoder.decoder.dic = dest;
\r
343 decoder.decoder.dicBufSize = outSize;
\r
345 RINOK(Lzma2Dec_GetOldProps(prop, props));
\r
346 RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
\r
349 res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
\r
350 *destLen = decoder.decoder.dicPos;
\r
351 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
\r
352 res = SZ_ERROR_INPUT_EOF;
\r
354 LzmaDec_FreeProbs(&decoder.decoder, alloc);
\r