1/* Lzma2Dec.c -- LZMA2 Decoder
22009-05-03 : 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 decoder;
334  SRes res;
335  SizeT outSize = *destLen, inSize = *srcLen;
336  Byte props[LZMA_PROPS_SIZE];
337
338  Lzma2Dec_Construct(&decoder);
339
340  *destLen = *srcLen = 0;
341  *status = LZMA_STATUS_NOT_SPECIFIED;
342  decoder.decoder.dic = dest;
343  decoder.decoder.dicBufSize = outSize;
344
345  RINOK(Lzma2Dec_GetOldProps(prop, props));
346  RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
347
348  *srcLen = inSize;
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;
353
354  LzmaDec_FreeProbs(&decoder.decoder, alloc);
355  return res;
356}
357