1 /* Lzma2Dec.c -- LZMA2 Decoder
2 2009-05-03 : Igor Pavlov : Public domain */
4 /* #define SHOW_DEBUG_INFO */
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
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
33 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
35 #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
36 #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
38 #define LZMA2_LCLP_MAX 4
39 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
41 #ifdef SHOW_DEBUG_INFO
56 LZMA2_STATE_DATA_CONT
,
61 static SRes
Lzma2Dec_GetOldProps(Byte prop
, Byte
*props
)
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);
75 SRes
Lzma2Dec_AllocateProbs(CLzma2Dec
*p
, Byte prop
, ISzAlloc
*alloc
)
77 Byte props
[LZMA_PROPS_SIZE
];
78 RINOK(Lzma2Dec_GetOldProps(prop
, props
));
79 return LzmaDec_AllocateProbs(&p
->decoder
, props
, LZMA_PROPS_SIZE
, alloc
);
82 SRes
Lzma2Dec_Allocate(CLzma2Dec
*p
, Byte prop
, ISzAlloc
*alloc
)
84 Byte props
[LZMA_PROPS_SIZE
];
85 RINOK(Lzma2Dec_GetOldProps(prop
, props
));
86 return LzmaDec_Allocate(&p
->decoder
, props
, LZMA_PROPS_SIZE
, alloc
);
89 void Lzma2Dec_Init(CLzma2Dec
*p
)
91 p
->state
= LZMA2_STATE_CONTROL
;
92 p
->needInitDic
= True
;
93 p
->needInitState
= True
;
94 p
->needInitProp
= True
;
95 LzmaDec_Init(&p
->decoder
);
98 static ELzma2State
Lzma2Dec_UpdateState(CLzma2Dec
*p
, Byte b
)
102 case LZMA2_STATE_CONTROL
:
104 PRF(printf("\n %4X ", p
->decoder
.dicPos
));
105 PRF(printf(" %2X", b
));
107 return LZMA2_STATE_FINISHED
;
108 if (LZMA2_IS_UNCOMPRESSED_STATE(p
))
110 if ((p
->control
& 0x7F) > 2)
111 return LZMA2_STATE_ERROR
;
115 p
->unpackSize
= (UInt32
)(p
->control
& 0x1F) << 16;
116 return LZMA2_STATE_UNPACK0
;
118 case LZMA2_STATE_UNPACK0
:
119 p
->unpackSize
|= (UInt32
)b
<< 8;
120 return LZMA2_STATE_UNPACK1
;
122 case LZMA2_STATE_UNPACK1
:
123 p
->unpackSize
|= (UInt32
)b
;
125 PRF(printf(" %8d", p
->unpackSize
));
126 return (LZMA2_IS_UNCOMPRESSED_STATE(p
)) ? LZMA2_STATE_DATA
: LZMA2_STATE_PACK0
;
128 case LZMA2_STATE_PACK0
:
129 p
->packSize
= (UInt32
)b
<< 8;
130 return LZMA2_STATE_PACK1
;
132 case LZMA2_STATE_PACK1
:
133 p
->packSize
|= (UInt32
)b
;
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
);
139 case LZMA2_STATE_PROP
:
142 if (b
>= (9 * 5 * 5))
143 return LZMA2_STATE_ERROR
;
146 p
->decoder
.prop
.pb
= 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
;
156 return LZMA2_STATE_ERROR
;
159 static void LzmaDec_UpdateWithUncompressed(CLzmaDec
*p
, const Byte
*src
, SizeT size
)
161 memcpy(p
->dic
+ p
->dicPos
, src
, size
);
163 if (p
->checkDicSize
== 0 && p
->prop
.dicSize
- p
->processedPos
<= size
)
164 p
->checkDicSize
= p
->prop
.dicSize
;
165 p
->processedPos
+= (UInt32
)size
;
168 void LzmaDec_InitDicAndState(CLzmaDec
*p
, Bool initDic
, Bool initState
);
170 SRes
Lzma2Dec_DecodeToDic(CLzma2Dec
*p
, SizeT dicLimit
,
171 const Byte
*src
, SizeT
*srcLen
, ELzmaFinishMode finishMode
, ELzmaStatus
*status
)
173 SizeT inSize
= *srcLen
;
175 *status
= LZMA_STATUS_NOT_SPECIFIED
;
177 while (p
->state
!= LZMA2_STATE_FINISHED
)
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
)
184 *status
= LZMA_STATUS_NOT_FINISHED
;
187 if (p
->state
!= LZMA2_STATE_DATA
&& p
->state
!= LZMA2_STATE_DATA_CONT
)
189 if (*srcLen
== inSize
)
191 *status
= LZMA_STATUS_NEEDS_MORE_INPUT
;
195 p
->state
= Lzma2Dec_UpdateState(p
, *src
++);
199 SizeT destSizeCur
= dicLimit
- dicPos
;
200 SizeT srcSizeCur
= inSize
- *srcLen
;
201 ELzmaFinishMode curFinishMode
= LZMA_FINISH_ANY
;
203 if (p
->unpackSize
<= destSizeCur
)
205 destSizeCur
= (SizeT
)p
->unpackSize
;
206 curFinishMode
= LZMA_FINISH_END
;
209 if (LZMA2_IS_UNCOMPRESSED_STATE(p
))
211 if (*srcLen
== inSize
)
213 *status
= LZMA_STATUS_NEEDS_MORE_INPUT
;
217 if (p
->state
== LZMA2_STATE_DATA
)
219 Bool initDic
= (p
->control
== LZMA2_CONTROL_COPY_RESET_DIC
);
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
);
228 if (srcSizeCur
> destSizeCur
)
229 srcSizeCur
= destSizeCur
;
232 return SZ_ERROR_DATA
;
234 LzmaDec_UpdateWithUncompressed(&p
->decoder
, src
, srcSizeCur
);
237 *srcLen
+= srcSizeCur
;
238 p
->unpackSize
-= (UInt32
)srcSizeCur
;
239 p
->state
= (p
->unpackSize
== 0) ? LZMA2_STATE_CONTROL
: LZMA2_STATE_DATA_CONT
;
243 SizeT outSizeProcessed
;
246 if (p
->state
== LZMA2_STATE_DATA
)
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
;
254 LzmaDec_InitDicAndState(&p
->decoder
, initDic
, initState
);
255 p
->needInitDic
= False
;
256 p
->needInitState
= False
;
257 p
->state
= LZMA2_STATE_DATA_CONT
;
259 if (srcSizeCur
> p
->packSize
)
260 srcSizeCur
= (SizeT
)p
->packSize
;
262 res
= LzmaDec_DecodeToDic(&p
->decoder
, dicPos
+ destSizeCur
, src
, &srcSizeCur
, curFinishMode
, status
);
265 *srcLen
+= srcSizeCur
;
266 p
->packSize
-= (UInt32
)srcSizeCur
;
268 outSizeProcessed
= p
->decoder
.dicPos
- dicPos
;
269 p
->unpackSize
-= (UInt32
)outSizeProcessed
;
272 if (*status
== LZMA_STATUS_NEEDS_MORE_INPUT
)
275 if (srcSizeCur
== 0 && outSizeProcessed
== 0)
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
;
282 if (*status
== LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
)
283 *status
= LZMA_STATUS_NOT_FINISHED
;
287 *status
= LZMA_STATUS_FINISHED_WITH_MARK
;
291 SRes
Lzma2Dec_DecodeToBuf(CLzma2Dec
*p
, Byte
*dest
, SizeT
*destLen
, const Byte
*src
, SizeT
*srcLen
, ELzmaFinishMode finishMode
, ELzmaStatus
*status
)
293 SizeT outSize
= *destLen
, inSize
= *srcLen
;
294 *srcLen
= *destLen
= 0;
297 SizeT srcSizeCur
= inSize
, outSizeCur
, dicPos
;
298 ELzmaFinishMode curFinishMode
;
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
)
305 outSizeCur
= p
->decoder
.dicBufSize
;
306 curFinishMode
= LZMA_FINISH_ANY
;
310 outSizeCur
= dicPos
+ outSize
;
311 curFinishMode
= finishMode
;
314 res
= Lzma2Dec_DecodeToDic(p
, outSizeCur
, src
, &srcSizeCur
, curFinishMode
, status
);
316 inSize
-= srcSizeCur
;
317 *srcLen
+= srcSizeCur
;
318 outSizeCur
= p
->decoder
.dicPos
- dicPos
;
319 memcpy(dest
, p
->decoder
.dic
+ dicPos
, outSizeCur
);
321 outSize
-= outSizeCur
;
322 *destLen
+= outSizeCur
;
325 if (outSizeCur
== 0 || outSize
== 0)
330 SRes
Lzma2Decode(Byte
*dest
, SizeT
*destLen
, const Byte
*src
, SizeT
*srcLen
,
331 Byte prop
, ELzmaFinishMode finishMode
, ELzmaStatus
*status
, ISzAlloc
*alloc
)
335 SizeT outSize
= *destLen
, inSize
= *srcLen
;
336 Byte props
[LZMA_PROPS_SIZE
];
338 Lzma2Dec_Construct(&decoder
);
340 *destLen
= *srcLen
= 0;
341 *status
= LZMA_STATUS_NOT_SPECIFIED
;
342 decoder
.decoder
.dic
= dest
;
343 decoder
.decoder
.dicBufSize
= outSize
;
345 RINOK(Lzma2Dec_GetOldProps(prop
, props
));
346 RINOK(LzmaDec_AllocateProbs(&decoder
.decoder
, props
, LZMA_PROPS_SIZE
, alloc
));
349 res
= Lzma2Dec_DecodeToDic(&decoder
, outSize
, src
, srcLen
, finishMode
, status
);
350 *destLen
= decoder
.decoder
.dicPos
;
351 if (res
== SZ_OK
&& *status
== LZMA_STATUS_NEEDS_MORE_INPUT
)
352 res
= SZ_ERROR_INPUT_EOF
;
354 LzmaDec_FreeProbs(&decoder
.decoder
, alloc
);