1/* Lzma2Dec.c -- LZMA2 Decoder
22010-12-15 : Igor Pavlov : Public domain */
3
4/* #define SHOW_DEBUG_INFO */
5
6#ifdef SHOW_DEBUG_INFO
7#include <stdio.h>
8#endif
9
10#include <string.h>
11
12#include "Lzma2Dec.h"
13
14/*
1500000000 - EOS
1600000001 U U - Uncompressed Reset Dic
1700000010 U U - Uncompressed No Reset
18100uuuuu U U P P - LZMA no reset
19101uuuuu U U P P - LZMA reset state
20110uuuuu U U P P S - LZMA reset state + new prop
21111uuuuu U U P P S - LZMA reset state + new prop + reset dic
22
23 u, U - Unpack Size
24 P - Pack Size
25 S - Props
26*/
27
28#define LZMA2_CONTROL_LZMA (1 << 7)
29#define LZMA2_CONTROL_COPY_NO_RESET 2
30#define LZMA2_CONTROL_COPY_RESET_DIC 1
31#define LZMA2_CONTROL_EOF 0
32
33#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
34
35#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
36#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
37
38#define LZMA2_LCLP_MAX 4
39#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
40
41#ifdef SHOW_DEBUG_INFO
42#define PRF(x) x
43#else
44#define PRF(x)
45#endif
46
47typedef enum
48{
49 LZMA2_STATE_CONTROL,
50 LZMA2_STATE_UNPACK0,
51 LZMA2_STATE_UNPACK1,
52 LZMA2_STATE_PACK0,
53 LZMA2_STATE_PACK1,
54 LZMA2_STATE_PROP,
55 LZMA2_STATE_DATA,
56 LZMA2_STATE_DATA_CONT,
57 LZMA2_STATE_FINISHED,
58 LZMA2_STATE_ERROR
59} ELzma2State;
60
61static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
62{
63 UInt32 dicSize;
64 if (prop > 40)
65 return SZ_ERROR_UNSUPPORTED;
66 dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
67 props[0] = (Byte)LZMA2_LCLP_MAX;
68 props[1] = (Byte)(dicSize);
69 props[2] = (Byte)(dicSize >> 8);
70 props[3] = (Byte)(dicSize >> 16);
71 props[4] = (Byte)(dicSize >> 24);
72 return SZ_OK;
73}
74
75SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
76{
77 Byte props[LZMA_PROPS_SIZE];
78 RINOK(Lzma2Dec_GetOldProps(prop, props));
79 return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
80}
81
82SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
83{
84 Byte props[LZMA_PROPS_SIZE];
85 RINOK(Lzma2Dec_GetOldProps(prop, props));
86 return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
87}
88
89void Lzma2Dec_Init(CLzma2Dec *p)
90{
91 p->state = LZMA2_STATE_CONTROL;
92 p->needInitDic = True;
93 p->needInitState = True;
94 p->needInitProp = True;
95 LzmaDec_Init(&p->decoder);
96}
97
98static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
99{
100 switch(p->state)
101 {
102 case LZMA2_STATE_CONTROL:
103 p->control = b;
104 PRF(printf("\n %4X ", p->decoder.dicPos));
105 PRF(printf(" %2X", b));
106 if (p->control == 0)
107 return LZMA2_STATE_FINISHED;
108 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
109 {
110 if ((p->control & 0x7F) > 2)
111 return LZMA2_STATE_ERROR;
112 p->unpackSize = 0;
113 }
114 else
115 p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
116 return LZMA2_STATE_UNPACK0;
117
118 case LZMA2_STATE_UNPACK0:
119 p->unpackSize |= (UInt32)b << 8;
120 return LZMA2_STATE_UNPACK1;
121
122 case LZMA2_STATE_UNPACK1:
123 p->unpackSize |= (UInt32)b;
124 p->unpackSize++;
125 PRF(printf(" %8d", p->unpackSize));
126 return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
127
128 case LZMA2_STATE_PACK0:
129 p->packSize = (UInt32)b << 8;
130 return LZMA2_STATE_PACK1;
131
132 case LZMA2_STATE_PACK1:
133 p->packSize |= (UInt32)b;
134 p->packSize++;
135 PRF(printf(" %8d", p->packSize));
136 return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
137 (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
138
139 case LZMA2_STATE_PROP:
140 {
141 int lc, lp;
142 if (b >= (9 * 5 * 5))
143 return LZMA2_STATE_ERROR;
144 lc = b % 9;
145 b /= 9;
146 p->decoder.prop.pb = b / 5;
147 lp = b % 5;
148 if (lc + lp > LZMA2_LCLP_MAX)
149 return LZMA2_STATE_ERROR;
150 p->decoder.prop.lc = lc;
151 p->decoder.prop.lp = lp;
152 p->needInitProp = False;
153 return LZMA2_STATE_DATA;
154 }
155 }
156 return LZMA2_STATE_ERROR;
157}
158
159static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
160{
161 memcpy(p->dic + p->dicPos, src, size);
162 p->dicPos += size;
163 if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
164 p->checkDicSize = p->prop.dicSize;
165 p->processedPos += (UInt32)size;
166}
167
168void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
169
170SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
171 const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
172{
173 SizeT inSize = *srcLen;
174 *srcLen = 0;
175 *status = LZMA_STATUS_NOT_SPECIFIED;
176
177 while (p->state != LZMA2_STATE_FINISHED)
178 {
179 SizeT dicPos = p->decoder.dicPos;
180 if (p->state == LZMA2_STATE_ERROR)
181 return SZ_ERROR_DATA;
182 if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
183 {
184 *status = LZMA_STATUS_NOT_FINISHED;
185 return SZ_OK;
186 }
187 if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
188 {
189 if (*srcLen == inSize)
190 {
191 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
192 return SZ_OK;
193 }
194 (*srcLen)++;
195 p->state = Lzma2Dec_UpdateState(p, *src++);
196 continue;
197 }
198 {
199 SizeT destSizeCur = dicLimit - dicPos;
200 SizeT srcSizeCur = inSize - *srcLen;
201 ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
202
203 if (p->unpackSize <= destSizeCur)
204 {
205 destSizeCur = (SizeT)p->unpackSize;
206 curFinishMode = LZMA_FINISH_END;
207 }
208
209 if (LZMA2_IS_UNCOMPRESSED_STATE(p))
210 {
211 if (*srcLen == inSize)
212 {
213 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
214 return SZ_OK;
215 }
216
217 if (p->state == LZMA2_STATE_DATA)
218 {
219 Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
220 if (initDic)
221 p->needInitProp = p->needInitState = True;
222 else if (p->needInitDic)
223 return SZ_ERROR_DATA;
224 p->needInitDic = False;
225 LzmaDec_InitDicAndState(&p->decoder, initDic, False);
226 }
227
228 if (srcSizeCur > destSizeCur)
229 srcSizeCur = destSizeCur;
230
231 if (srcSizeCur == 0)
232 return SZ_ERROR_DATA;
233
234 LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
235
236 src += srcSizeCur;
237 *srcLen += srcSizeCur;
238 p->unpackSize -= (UInt32)srcSizeCur;
239 p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
240 }
241 else
242 {
243 SizeT outSizeProcessed;
244 SRes res;
245
246 if (p->state == LZMA2_STATE_DATA)
247 {
248 int mode = LZMA2_GET_LZMA_MODE(p);
249 Bool initDic = (mode == 3);
250 Bool initState = (mode > 0);
251 if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
252 return SZ_ERROR_DATA;
253
254 LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
255 p->needInitDic = False;
256 p->needInitState = False;
257 p->state = LZMA2_STATE_DATA_CONT;
258 }
259 if (srcSizeCur > p->packSize)
260 srcSizeCur = (SizeT)p->packSize;
261
262 res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
263
264 src += srcSizeCur;
265 *srcLen += srcSizeCur;
266 p->packSize -= (UInt32)srcSizeCur;
267
268 outSizeProcessed = p->decoder.dicPos - dicPos;
269 p->unpackSize -= (UInt32)outSizeProcessed;
270
271 RINOK(res);
272 if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
273 return res;
274
275 if (srcSizeCur == 0 && outSizeProcessed == 0)
276 {
277 if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
278 p->unpackSize != 0 || p->packSize != 0)
279 return SZ_ERROR_DATA;
280 p->state = LZMA2_STATE_CONTROL;
281 }
282 if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
283 *status = LZMA_STATUS_NOT_FINISHED;
284 }
285 }
286 }
287 *status = LZMA_STATUS_FINISHED_WITH_MARK;
288 return SZ_OK;
289}
290
291SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
292{
293 SizeT outSize = *destLen, inSize = *srcLen;
294 *srcLen = *destLen = 0;
295 for (;;)
296 {
297 SizeT srcSizeCur = inSize, outSizeCur, dicPos;
298 ELzmaFinishMode curFinishMode;
299 SRes res;
300 if (p->decoder.dicPos == p->decoder.dicBufSize)
301 p->decoder.dicPos = 0;
302 dicPos = p->decoder.dicPos;
303 if (outSize > p->decoder.dicBufSize - dicPos)
304 {
305 outSizeCur = p->decoder.dicBufSize;
306 curFinishMode = LZMA_FINISH_ANY;
307 }
308 else
309 {
310 outSizeCur = dicPos + outSize;
311 curFinishMode = finishMode;
312 }
313
314 res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
315 src += srcSizeCur;
316 inSize -= srcSizeCur;
317 *srcLen += srcSizeCur;
318 outSizeCur = p->decoder.dicPos - dicPos;
319 memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
320 dest += outSizeCur;
321 outSize -= outSizeCur;
322 *destLen += outSizeCur;
323 if (res != 0)
324 return res;
325 if (outSizeCur == 0 || outSize == 0)
326 return SZ_OK;
327 }
328}
329
330SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
331 Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
332{
333 CLzma2Dec p;
334 SRes res;
335 SizeT outSize = *destLen, inSize = *srcLen;
336 *destLen = *srcLen = 0;
337 *status = LZMA_STATUS_NOT_SPECIFIED;
338 Lzma2Dec_Construct(&p);
339 RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
340 p.decoder.dic = dest;
341 p.decoder.dicBufSize = outSize;
342 Lzma2Dec_Init(&p);
343 *srcLen = inSize;
344 res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
345 *destLen = p.decoder.dicPos;
346 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
347 res = SZ_ERROR_INPUT_EOF;
348 Lzma2Dec_FreeProbs(&p, alloc);
349 return res;
350}
351