Imported Upstream version 9.20
[platform/upstream/7zip.git] / C / Lzma2Dec.c
1 /* Lzma2Dec.c -- LZMA2 Decoder\r
2 2009-05-03 : Igor Pavlov : Public domain */\r
3 \r
4 /* #define SHOW_DEBUG_INFO */\r
5 \r
6 #ifdef SHOW_DEBUG_INFO\r
7 #include <stdio.h>\r
8 #endif\r
9 \r
10 #include <string.h>\r
11 \r
12 #include "Lzma2Dec.h"\r
13 \r
14 /*\r
15 00000000  -  EOS\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
22 \r
23   u, U - Unpack Size\r
24   P - Pack Size\r
25   S - Props\r
26 */\r
27 \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
32 \r
33 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)\r
34 \r
35 #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)\r
36 #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)\r
37 \r
38 #define LZMA2_LCLP_MAX 4\r
39 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))\r
40 \r
41 #ifdef SHOW_DEBUG_INFO\r
42 #define PRF(x) x\r
43 #else\r
44 #define PRF(x)\r
45 #endif\r
46 \r
47 typedef enum\r
48 {\r
49   LZMA2_STATE_CONTROL,\r
50   LZMA2_STATE_UNPACK0,\r
51   LZMA2_STATE_UNPACK1,\r
52   LZMA2_STATE_PACK0,\r
53   LZMA2_STATE_PACK1,\r
54   LZMA2_STATE_PROP,\r
55   LZMA2_STATE_DATA,\r
56   LZMA2_STATE_DATA_CONT,\r
57   LZMA2_STATE_FINISHED,\r
58   LZMA2_STATE_ERROR\r
59 } ELzma2State;\r
60 \r
61 static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)\r
62 {\r
63   UInt32 dicSize;\r
64   if (prop > 40)\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
72   return SZ_OK;\r
73 }\r
74 \r
75 SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)\r
76 {\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
80 }\r
81 \r
82 SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)\r
83 {\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
87 }\r
88 \r
89 void Lzma2Dec_Init(CLzma2Dec *p)\r
90 {\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
96 }\r
97 \r
98 static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)\r
99 {\r
100   switch(p->state)\r
101   {\r
102     case LZMA2_STATE_CONTROL:\r
103       p->control = b;\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
109       {\r
110         if ((p->control & 0x7F) > 2)\r
111           return LZMA2_STATE_ERROR;\r
112         p->unpackSize = 0;\r
113       }\r
114       else\r
115         p->unpackSize = (UInt32)(p->control & 0x1F) << 16;\r
116       return LZMA2_STATE_UNPACK0;\r
117     \r
118     case LZMA2_STATE_UNPACK0:\r
119       p->unpackSize |= (UInt32)b << 8;\r
120       return LZMA2_STATE_UNPACK1;\r
121     \r
122     case LZMA2_STATE_UNPACK1:\r
123       p->unpackSize |= (UInt32)b;\r
124       p->unpackSize++;\r
125       PRF(printf(" %8d", p->unpackSize));\r
126       return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;\r
127     \r
128     case LZMA2_STATE_PACK0:\r
129       p->packSize = (UInt32)b << 8;\r
130       return LZMA2_STATE_PACK1;\r
131 \r
132     case LZMA2_STATE_PACK1:\r
133       p->packSize |= (UInt32)b;\r
134       p->packSize++;\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
138 \r
139     case LZMA2_STATE_PROP:\r
140     {\r
141       int lc, lp;\r
142       if (b >= (9 * 5 * 5))\r
143         return LZMA2_STATE_ERROR;\r
144       lc = b % 9;\r
145       b /= 9;\r
146       p->decoder.prop.pb = b / 5;\r
147       lp = 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
154     }\r
155   }\r
156   return LZMA2_STATE_ERROR;\r
157 }\r
158 \r
159 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)\r
160 {\r
161   memcpy(p->dic + p->dicPos, src, size);\r
162   p->dicPos += 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
166 }\r
167 \r
168 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);\r
169 \r
170 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,\r
171     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
172 {\r
173   SizeT inSize = *srcLen;\r
174   *srcLen = 0;\r
175   *status = LZMA_STATUS_NOT_SPECIFIED;\r
176 \r
177   while (p->state != LZMA2_STATE_FINISHED)\r
178   {\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
183     {\r
184       *status = LZMA_STATUS_NOT_FINISHED;\r
185       return SZ_OK;\r
186     }\r
187     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)\r
188     {\r
189       if (*srcLen == inSize)\r
190       {\r
191         *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
192         return SZ_OK;\r
193       }\r
194       (*srcLen)++;\r
195       p->state = Lzma2Dec_UpdateState(p, *src++);\r
196       continue;\r
197     }\r
198     {\r
199       SizeT destSizeCur = dicLimit - dicPos;\r
200       SizeT srcSizeCur = inSize - *srcLen;\r
201       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;\r
202       \r
203       if (p->unpackSize <= destSizeCur)\r
204       {\r
205         destSizeCur = (SizeT)p->unpackSize;\r
206         curFinishMode = LZMA_FINISH_END;\r
207       }\r
208 \r
209       if (LZMA2_IS_UNCOMPRESSED_STATE(p))\r
210       {\r
211         if (*srcLen == inSize)\r
212         {\r
213           *status = LZMA_STATUS_NEEDS_MORE_INPUT;\r
214           return SZ_OK;\r
215         }\r
216 \r
217         if (p->state == LZMA2_STATE_DATA)\r
218         {\r
219           Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);\r
220           if (initDic)\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
226         }\r
227 \r
228         if (srcSizeCur > destSizeCur)\r
229           srcSizeCur = destSizeCur;\r
230 \r
231         if (srcSizeCur == 0)\r
232           return SZ_ERROR_DATA;\r
233 \r
234         LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);\r
235 \r
236         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
240       }\r
241       else\r
242       {\r
243         SizeT outSizeProcessed;\r
244         SRes res;\r
245 \r
246         if (p->state == LZMA2_STATE_DATA)\r
247         {\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
253           \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
258         }\r
259         if (srcSizeCur > p->packSize)\r
260           srcSizeCur = (SizeT)p->packSize;\r
261           \r
262         res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);\r
263         \r
264         src += srcSizeCur;\r
265         *srcLen += srcSizeCur;\r
266         p->packSize -= (UInt32)srcSizeCur;\r
267 \r
268         outSizeProcessed = p->decoder.dicPos - dicPos;\r
269         p->unpackSize -= (UInt32)outSizeProcessed;\r
270 \r
271         RINOK(res);\r
272         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)\r
273           return res;\r
274 \r
275         if (srcSizeCur == 0 && outSizeProcessed == 0)\r
276         {\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
281         }\r
282         if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)\r
283           *status = LZMA_STATUS_NOT_FINISHED;\r
284       }\r
285     }\r
286   }\r
287   *status = LZMA_STATUS_FINISHED_WITH_MARK;\r
288   return SZ_OK;\r
289 }\r
290 \r
291 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)\r
292 {\r
293   SizeT outSize = *destLen, inSize = *srcLen;\r
294   *srcLen = *destLen = 0;\r
295   for (;;)\r
296   {\r
297     SizeT srcSizeCur = inSize, outSizeCur, dicPos;\r
298     ELzmaFinishMode curFinishMode;\r
299     SRes res;\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
304     {\r
305       outSizeCur = p->decoder.dicBufSize;\r
306       curFinishMode = LZMA_FINISH_ANY;\r
307     }\r
308     else\r
309     {\r
310       outSizeCur = dicPos + outSize;\r
311       curFinishMode = finishMode;\r
312     }\r
313 \r
314     res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);\r
315     src += srcSizeCur;\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
323     if (res != 0)\r
324       return res;\r
325     if (outSizeCur == 0 || outSize == 0)\r
326       return SZ_OK;\r
327   }\r
328 }\r
329 \r
330 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,\r
331     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)\r
332 {\r
333   CLzma2Dec decoder;\r
334   SRes res;\r
335   SizeT outSize = *destLen, inSize = *srcLen;\r
336   Byte props[LZMA_PROPS_SIZE];\r
337 \r
338   Lzma2Dec_Construct(&decoder);\r
339 \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
344 \r
345   RINOK(Lzma2Dec_GetOldProps(prop, props));\r
346   RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));\r
347   \r
348   *srcLen = inSize;\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
353 \r
354   LzmaDec_FreeProbs(&decoder.decoder, alloc);\r
355   return res;\r
356 }\r