1 /* Lzma2Dec.c -- LZMA2 Decoder
\r
2 2015-11-09 : Igor Pavlov : Public domain */
\r
4 /* #define SHOW_DEBUG_INFO */
\r
8 #ifdef SHOW_DEBUG_INFO
\r
14 #include "Lzma2Dec.h"
\r
18 00000001 U U - Uncompressed Reset Dic
\r
19 00000010 U U - Uncompressed No Reset
\r
20 100uuuuu U U P P - LZMA no reset
\r
21 101uuuuu U U P P - LZMA reset state
\r
22 110uuuuu U U P P S - LZMA reset state + new prop
\r
23 111uuuuu U U P P S - LZMA reset state + new prop + reset dic
\r
30 #define LZMA2_CONTROL_LZMA (1 << 7)
\r
31 #define LZMA2_CONTROL_COPY_NO_RESET 2
\r
32 #define LZMA2_CONTROL_COPY_RESET_DIC 1
\r
33 #define LZMA2_CONTROL_EOF 0
\r
35 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
\r
37 #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
\r
38 #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
\r
40 #define LZMA2_LCLP_MAX 4
\r
41 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
\r
43 #ifdef SHOW_DEBUG_INFO
\r
51 LZMA2_STATE_CONTROL,
\r
52 LZMA2_STATE_UNPACK0,
\r
53 LZMA2_STATE_UNPACK1,
\r
58 LZMA2_STATE_DATA_CONT,
\r
59 LZMA2_STATE_FINISHED,
\r
63 static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
\r
67 return SZ_ERROR_UNSUPPORTED;
\r
68 dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
\r
69 props[0] = (Byte)LZMA2_LCLP_MAX;
\r
70 props[1] = (Byte)(dicSize);
\r
71 props[2] = (Byte)(dicSize >> 8);
\r
72 props[3] = (Byte)(dicSize >> 16);
\r
73 props[4] = (Byte)(dicSize >> 24);
\r
77 SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
\r
79 Byte props[LZMA_PROPS_SIZE];
\r
80 RINOK(Lzma2Dec_GetOldProps(prop, props));
\r
81 return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
\r
84 SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
\r
86 Byte props[LZMA_PROPS_SIZE];
\r
87 RINOK(Lzma2Dec_GetOldProps(prop, props));
\r
88 return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
\r
91 void Lzma2Dec_Init(CLzma2Dec *p)
\r
93 p->state = LZMA2_STATE_CONTROL;
\r
94 p->needInitDic = True;
\r
95 p->needInitState = True;
\r
96 p->needInitProp = True;
\r
97 LzmaDec_Init(&p->decoder);
\r
100 static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
\r
104 case LZMA2_STATE_CONTROL:
\r
106 PRF(printf("\n %4X ", (unsigned)p->decoder.dicPos));
\r
107 PRF(printf(" %2X", (unsigned)b));
\r
108 if (p->control == 0)
\r
109 return LZMA2_STATE_FINISHED;
\r
110 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
\r
112 if ((p->control & 0x7F) > 2)
\r
113 return LZMA2_STATE_ERROR;
\r
117 p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
\r
118 return LZMA2_STATE_UNPACK0;
\r
120 case LZMA2_STATE_UNPACK0:
\r
121 p->unpackSize |= (UInt32)b << 8;
\r
122 return LZMA2_STATE_UNPACK1;
\r
124 case LZMA2_STATE_UNPACK1:
\r
125 p->unpackSize |= (UInt32)b;
\r
127 PRF(printf(" %8u", (unsigned)p->unpackSize));
\r
128 return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
\r
130 case LZMA2_STATE_PACK0:
\r
131 p->packSize = (UInt32)b << 8;
\r
132 return LZMA2_STATE_PACK1;
\r
134 case LZMA2_STATE_PACK1:
\r
135 p->packSize |= (UInt32)b;
\r
137 PRF(printf(" %8u", (unsigned)p->packSize));
\r
138 return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
\r
139 (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
\r
141 case LZMA2_STATE_PROP:
\r
144 if (b >= (9 * 5 * 5))
\r
145 return LZMA2_STATE_ERROR;
\r
148 p->decoder.prop.pb = b / 5;
\r
150 if (lc + lp > LZMA2_LCLP_MAX)
\r
151 return LZMA2_STATE_ERROR;
\r
152 p->decoder.prop.lc = lc;
\r
153 p->decoder.prop.lp = lp;
\r
154 p->needInitProp = False;
\r
155 return LZMA2_STATE_DATA;
\r
158 return LZMA2_STATE_ERROR;
\r
161 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
\r
163 memcpy(p->dic + p->dicPos, src, size);
\r
165 if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
\r
166 p->checkDicSize = p->prop.dicSize;
\r
167 p->processedPos += (UInt32)size;
\r
170 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
\r
172 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
\r
173 const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
\r
175 SizeT inSize = *srcLen;
\r
177 *status = LZMA_STATUS_NOT_SPECIFIED;
\r
179 while (p->state != LZMA2_STATE_FINISHED)
\r
181 SizeT dicPos = p->decoder.dicPos;
\r
183 if (p->state == LZMA2_STATE_ERROR)
\r
184 return SZ_ERROR_DATA;
\r
186 if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
\r
188 *status = LZMA_STATUS_NOT_FINISHED;
\r
192 if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
\r
194 if (*srcLen == inSize)
\r
196 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
\r
200 p->state = Lzma2Dec_UpdateState(p, *src++);
\r
202 if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
\r
204 p->state = LZMA2_STATE_ERROR;
\r
205 return SZ_ERROR_DATA;
\r
211 SizeT destSizeCur = dicLimit - dicPos;
\r
212 SizeT srcSizeCur = inSize - *srcLen;
\r
213 ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
\r
215 if (p->unpackSize <= destSizeCur)
\r
217 destSizeCur = (SizeT)p->unpackSize;
\r
218 curFinishMode = LZMA_FINISH_END;
\r
221 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
\r
223 if (*srcLen == inSize)
\r
225 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
\r
229 if (p->state == LZMA2_STATE_DATA)
\r
231 Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
\r
233 p->needInitProp = p->needInitState = True;
\r
234 else if (p->needInitDic)
\r
236 p->state = LZMA2_STATE_ERROR;
\r
237 return SZ_ERROR_DATA;
\r
239 p->needInitDic = False;
\r
240 LzmaDec_InitDicAndState(&p->decoder, initDic, False);
\r
243 if (srcSizeCur > destSizeCur)
\r
244 srcSizeCur = destSizeCur;
\r
246 if (srcSizeCur == 0)
\r
248 p->state = LZMA2_STATE_ERROR;
\r
249 return SZ_ERROR_DATA;
\r
252 LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
\r
255 *srcLen += srcSizeCur;
\r
256 p->unpackSize -= (UInt32)srcSizeCur;
\r
257 p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
\r
261 SizeT outSizeProcessed;
\r
264 if (p->state == LZMA2_STATE_DATA)
\r
266 unsigned mode = LZMA2_GET_LZMA_MODE(p);
\r
267 Bool initDic = (mode == 3);
\r
268 Bool initState = (mode != 0);
\r
269 if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
\r
271 p->state = LZMA2_STATE_ERROR;
\r
272 return SZ_ERROR_DATA;
\r
275 LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
\r
276 p->needInitDic = False;
\r
277 p->needInitState = False;
\r
278 p->state = LZMA2_STATE_DATA_CONT;
\r
281 if (srcSizeCur > p->packSize)
\r
282 srcSizeCur = (SizeT)p->packSize;
\r
284 res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
\r
287 *srcLen += srcSizeCur;
\r
288 p->packSize -= (UInt32)srcSizeCur;
\r
290 outSizeProcessed = p->decoder.dicPos - dicPos;
\r
291 p->unpackSize -= (UInt32)outSizeProcessed;
\r
294 if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
\r
297 if (srcSizeCur == 0 && outSizeProcessed == 0)
\r
299 if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
\r
300 || p->unpackSize != 0
\r
301 || p->packSize != 0)
\r
303 p->state = LZMA2_STATE_ERROR;
\r
304 return SZ_ERROR_DATA;
\r
306 p->state = LZMA2_STATE_CONTROL;
\r
309 if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
\r
310 *status = LZMA_STATUS_NOT_FINISHED;
\r
315 *status = LZMA_STATUS_FINISHED_WITH_MARK;
\r
319 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
\r
321 SizeT outSize = *destLen, inSize = *srcLen;
\r
322 *srcLen = *destLen = 0;
\r
325 SizeT srcSizeCur = inSize, outSizeCur, dicPos;
\r
326 ELzmaFinishMode curFinishMode;
\r
328 if (p->decoder.dicPos == p->decoder.dicBufSize)
\r
329 p->decoder.dicPos = 0;
\r
330 dicPos = p->decoder.dicPos;
\r
331 if (outSize > p->decoder.dicBufSize - dicPos)
\r
333 outSizeCur = p->decoder.dicBufSize;
\r
334 curFinishMode = LZMA_FINISH_ANY;
\r
338 outSizeCur = dicPos + outSize;
\r
339 curFinishMode = finishMode;
\r
342 res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
\r
344 inSize -= srcSizeCur;
\r
345 *srcLen += srcSizeCur;
\r
346 outSizeCur = p->decoder.dicPos - dicPos;
\r
347 memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
\r
348 dest += outSizeCur;
\r
349 outSize -= outSizeCur;
\r
350 *destLen += outSizeCur;
\r
353 if (outSizeCur == 0 || outSize == 0)
\r
358 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
\r
359 Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
\r
363 SizeT outSize = *destLen, inSize = *srcLen;
\r
364 *destLen = *srcLen = 0;
\r
365 *status = LZMA_STATUS_NOT_SPECIFIED;
\r
366 Lzma2Dec_Construct(&p);
\r
367 RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
\r
368 p.decoder.dic = dest;
\r
369 p.decoder.dicBufSize = outSize;
\r
372 res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
\r
373 *destLen = p.decoder.dicPos;
\r
374 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
\r
375 res = SZ_ERROR_INPUT_EOF;
\r
376 Lzma2Dec_FreeProbs(&p, alloc);
\r