1 | /* Lzma2Dec.c -- LZMA2 Decoder |
2 | 2010-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 | /* |
15 | 00000000 - EOS |
16 | 00000001 U U - Uncompressed Reset Dic |
17 | 00000010 U U - Uncompressed No Reset |
18 | 100uuuuu U U P P - LZMA no reset |
19 | 101uuuuu U U P P - LZMA reset state |
20 | 110uuuuu U U P P S - LZMA reset state + new prop |
21 | 111uuuuu 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 | |
47 | typedef 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 | |
61 | static 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 | |
75 | SRes 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 | |
82 | SRes 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 | |
89 | void 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 | |
98 | static 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 | |
159 | static 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 | |
168 | void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState); |
169 | |
170 | SRes 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 | |
291 | SRes 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 | |
330 | SRes 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 | |