all repos — mgba @ b2d406a411b31acce5bbf0246af32a80c22ca834

mGBA Game Boy Advance Emulator

src/third-party/lzma/Lzma2Dec.c (view raw)

  1/* Lzma2Dec.c -- LZMA2 Decoder
  22019-02-02 : Igor Pavlov : Public domain */
  3
  4/* #define SHOW_DEBUG_INFO */
  5
  6#include "Precomp.h"
  7
  8#ifdef SHOW_DEBUG_INFO
  9#include <stdio.h>
 10#endif
 11
 12#include <string.h>
 13
 14#include "Lzma2Dec.h"
 15
 16/*
 1700000000  -  End of data
 1800000001 U U  -  Uncompressed, reset dic, need reset state and set new prop
 1900000010 U U  -  Uncompressed, no reset
 20100uuuuu U U P P  -  LZMA, no reset
 21101uuuuu U U P P  -  LZMA, reset state
 22110uuuuu U U P P S  -  LZMA, reset state + set new prop
 23111uuuuu U U P P S  -  LZMA, reset state + set new prop, reset dic
 24
 25  u, U - Unpack Size
 26  P - Pack Size
 27  S - Props
 28*/
 29
 30#define LZMA2_CONTROL_COPY_RESET_DIC 1
 31
 32#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
 33
 34#define LZMA2_LCLP_MAX 4
 35#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
 36
 37#ifdef SHOW_DEBUG_INFO
 38#define PRF(x) x
 39#else
 40#define PRF(x)
 41#endif
 42
 43typedef enum
 44{
 45  LZMA2_STATE_CONTROL,
 46  LZMA2_STATE_UNPACK0,
 47  LZMA2_STATE_UNPACK1,
 48  LZMA2_STATE_PACK0,
 49  LZMA2_STATE_PACK1,
 50  LZMA2_STATE_PROP,
 51  LZMA2_STATE_DATA,
 52  LZMA2_STATE_DATA_CONT,
 53  LZMA2_STATE_FINISHED,
 54  LZMA2_STATE_ERROR
 55} ELzma2State;
 56
 57static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
 58{
 59  UInt32 dicSize;
 60  if (prop > 40)
 61    return SZ_ERROR_UNSUPPORTED;
 62  dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
 63  props[0] = (Byte)LZMA2_LCLP_MAX;
 64  props[1] = (Byte)(dicSize);
 65  props[2] = (Byte)(dicSize >> 8);
 66  props[3] = (Byte)(dicSize >> 16);
 67  props[4] = (Byte)(dicSize >> 24);
 68  return SZ_OK;
 69}
 70
 71SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
 72{
 73  Byte props[LZMA_PROPS_SIZE];
 74  RINOK(Lzma2Dec_GetOldProps(prop, props));
 75  return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
 76}
 77
 78SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
 79{
 80  Byte props[LZMA_PROPS_SIZE];
 81  RINOK(Lzma2Dec_GetOldProps(prop, props));
 82  return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
 83}
 84
 85void Lzma2Dec_Init(CLzma2Dec *p)
 86{
 87  p->state = LZMA2_STATE_CONTROL;
 88  p->needInitLevel = 0xE0;
 89  p->isExtraMode = False;
 90  p->unpackSize = 0;
 91  
 92  // p->decoder.dicPos = 0; // we can use it instead of full init
 93  LzmaDec_Init(&p->decoder);
 94}
 95
 96static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
 97{
 98  switch (p->state)
 99  {
100    case LZMA2_STATE_CONTROL:
101      p->isExtraMode = False;
102      p->control = b;
103      PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
104      PRF(printf(" %02X", (unsigned)b));
105      if (b == 0)
106        return LZMA2_STATE_FINISHED;
107      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
108      {
109        if (b == LZMA2_CONTROL_COPY_RESET_DIC)
110          p->needInitLevel = 0xC0;
111        else if (b > 2 || p->needInitLevel == 0xE0)
112          return LZMA2_STATE_ERROR;
113      }
114      else
115      {
116        if (b < p->needInitLevel)
117          return LZMA2_STATE_ERROR;
118        p->needInitLevel = 0;
119        p->unpackSize = (UInt32)(b & 0x1F) << 16;
120      }
121      return LZMA2_STATE_UNPACK0;
122    
123    case LZMA2_STATE_UNPACK0:
124      p->unpackSize |= (UInt32)b << 8;
125      return LZMA2_STATE_UNPACK1;
126    
127    case LZMA2_STATE_UNPACK1:
128      p->unpackSize |= (UInt32)b;
129      p->unpackSize++;
130      PRF(printf(" %7u", (unsigned)p->unpackSize));
131      return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
132    
133    case LZMA2_STATE_PACK0:
134      p->packSize = (UInt32)b << 8;
135      return LZMA2_STATE_PACK1;
136
137    case LZMA2_STATE_PACK1:
138      p->packSize |= (UInt32)b;
139      p->packSize++;
140      // if (p->packSize < 5) return LZMA2_STATE_ERROR;
141      PRF(printf(" %5u", (unsigned)p->packSize));
142      return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
143
144    case LZMA2_STATE_PROP:
145    {
146      unsigned lc, lp;
147      if (b >= (9 * 5 * 5))
148        return LZMA2_STATE_ERROR;
149      lc = b % 9;
150      b /= 9;
151      p->decoder.prop.pb = (Byte)(b / 5);
152      lp = b % 5;
153      if (lc + lp > LZMA2_LCLP_MAX)
154        return LZMA2_STATE_ERROR;
155      p->decoder.prop.lc = (Byte)lc;
156      p->decoder.prop.lp = (Byte)lp;
157      return LZMA2_STATE_DATA;
158    }
159  }
160  return LZMA2_STATE_ERROR;
161}
162
163static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
164{
165  memcpy(p->dic + p->dicPos, src, size);
166  p->dicPos += size;
167  if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
168    p->checkDicSize = p->prop.dicSize;
169  p->processedPos += (UInt32)size;
170}
171
172void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
173
174
175SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
176    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
177{
178  SizeT inSize = *srcLen;
179  *srcLen = 0;
180  *status = LZMA_STATUS_NOT_SPECIFIED;
181
182  while (p->state != LZMA2_STATE_ERROR)
183  {
184    SizeT dicPos;
185
186    if (p->state == LZMA2_STATE_FINISHED)
187    {
188      *status = LZMA_STATUS_FINISHED_WITH_MARK;
189      return SZ_OK;
190    }
191    
192    dicPos = p->decoder.dicPos;
193    
194    if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
195    {
196      *status = LZMA_STATUS_NOT_FINISHED;
197      return SZ_OK;
198    }
199
200    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
201    {
202      if (*srcLen == inSize)
203      {
204        *status = LZMA_STATUS_NEEDS_MORE_INPUT;
205        return SZ_OK;
206      }
207      (*srcLen)++;
208      p->state = Lzma2Dec_UpdateState(p, *src++);
209      if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
210        break;
211      continue;
212    }
213    
214    {
215      SizeT inCur = inSize - *srcLen;
216      SizeT outCur = dicLimit - dicPos;
217      ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
218      
219      if (outCur >= p->unpackSize)
220      {
221        outCur = (SizeT)p->unpackSize;
222        curFinishMode = LZMA_FINISH_END;
223      }
224
225      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
226      {
227        if (inCur == 0)
228        {
229          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
230          return SZ_OK;
231        }
232
233        if (p->state == LZMA2_STATE_DATA)
234        {
235          BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
236          LzmaDec_InitDicAndState(&p->decoder, initDic, False);
237        }
238
239        if (inCur > outCur)
240          inCur = outCur;
241        if (inCur == 0)
242          break;
243
244        LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
245
246        src += inCur;
247        *srcLen += inCur;
248        p->unpackSize -= (UInt32)inCur;
249        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
250      }
251      else
252      {
253        SRes res;
254
255        if (p->state == LZMA2_STATE_DATA)
256        {
257          BoolInt initDic = (p->control >= 0xE0);
258          BoolInt initState = (p->control >= 0xA0);
259          LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
260          p->state = LZMA2_STATE_DATA_CONT;
261        }
262  
263        if (inCur > p->packSize)
264          inCur = (SizeT)p->packSize;
265        
266        res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
267
268        src += inCur;
269        *srcLen += inCur;
270        p->packSize -= (UInt32)inCur;
271        outCur = p->decoder.dicPos - dicPos;
272        p->unpackSize -= (UInt32)outCur;
273
274        if (res != 0)
275          break;
276        
277        if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
278        {
279          if (p->packSize == 0)
280            break;
281          return SZ_OK;
282        }
283
284        if (inCur == 0 && outCur == 0)
285        {
286          if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
287              || p->unpackSize != 0
288              || p->packSize != 0)
289            break;
290          p->state = LZMA2_STATE_CONTROL;
291        }
292        
293        *status = LZMA_STATUS_NOT_SPECIFIED;
294      }
295    }
296  }
297  
298  *status = LZMA_STATUS_NOT_SPECIFIED;
299  p->state = LZMA2_STATE_ERROR;
300  return SZ_ERROR_DATA;
301}
302
303
304
305
306ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
307    SizeT outSize,
308    const Byte *src, SizeT *srcLen,
309    int checkFinishBlock)
310{
311  SizeT inSize = *srcLen;
312  *srcLen = 0;
313
314  while (p->state != LZMA2_STATE_ERROR)
315  {
316    if (p->state == LZMA2_STATE_FINISHED)
317      return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
318
319    if (outSize == 0 && !checkFinishBlock)
320      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
321    
322    if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
323    {
324      if (*srcLen == inSize)
325        return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
326      (*srcLen)++;
327
328      p->state = Lzma2Dec_UpdateState(p, *src++);
329
330      if (p->state == LZMA2_STATE_UNPACK0)
331      {
332        // if (p->decoder.dicPos != 0)
333        if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
334          return LZMA2_PARSE_STATUS_NEW_BLOCK;
335        // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED;
336      }
337
338      // The following code can be commented.
339      // It's not big problem, if we read additional input bytes.
340      // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state.
341
342      if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
343      {
344        // checkFinishBlock is true. So we expect that block must be finished,
345        // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
346        // break;
347        return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
348      }
349
350      if (p->state == LZMA2_STATE_DATA)
351        return LZMA2_PARSE_STATUS_NEW_CHUNK;
352
353      continue;
354    }
355
356    if (outSize == 0)
357      return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
358
359    {
360      SizeT inCur = inSize - *srcLen;
361
362      if (LZMA2_IS_UNCOMPRESSED_STATE(p))
363      {
364        if (inCur == 0)
365          return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
366        if (inCur > p->unpackSize)
367          inCur = p->unpackSize;
368        if (inCur > outSize)
369          inCur = outSize;
370        p->decoder.dicPos += inCur;
371        src += inCur;
372        *srcLen += inCur;
373        outSize -= inCur;
374        p->unpackSize -= (UInt32)inCur;
375        p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
376      }
377      else
378      {
379        p->isExtraMode = True;
380
381        if (inCur == 0)
382        {
383          if (p->packSize != 0)
384            return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
385        }
386        else if (p->state == LZMA2_STATE_DATA)
387        {
388          p->state = LZMA2_STATE_DATA_CONT;
389          if (*src != 0)
390          {
391            // first byte of lzma chunk must be Zero
392            *srcLen += 1;
393            p->packSize--;
394            break;
395          }
396        }
397  
398        if (inCur > p->packSize)
399          inCur = (SizeT)p->packSize;
400
401        src += inCur;
402        *srcLen += inCur;
403        p->packSize -= (UInt32)inCur;
404
405        if (p->packSize == 0)
406        {
407          SizeT rem = outSize;
408          if (rem > p->unpackSize)
409            rem = p->unpackSize;
410          p->decoder.dicPos += rem;
411          p->unpackSize -= (UInt32)rem;
412          outSize -= rem;
413          if (p->unpackSize == 0)
414            p->state = LZMA2_STATE_CONTROL;
415        }
416      }
417    }
418  }
419  
420  p->state = LZMA2_STATE_ERROR;
421  return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
422}
423
424
425
426
427SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
428{
429  SizeT outSize = *destLen, inSize = *srcLen;
430  *srcLen = *destLen = 0;
431  
432  for (;;)
433  {
434    SizeT inCur = inSize, outCur, dicPos;
435    ELzmaFinishMode curFinishMode;
436    SRes res;
437    
438    if (p->decoder.dicPos == p->decoder.dicBufSize)
439      p->decoder.dicPos = 0;
440    dicPos = p->decoder.dicPos;
441    curFinishMode = LZMA_FINISH_ANY;
442    outCur = p->decoder.dicBufSize - dicPos;
443    
444    if (outCur >= outSize)
445    {
446      outCur = outSize;
447      curFinishMode = finishMode;
448    }
449
450    res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
451    
452    src += inCur;
453    inSize -= inCur;
454    *srcLen += inCur;
455    outCur = p->decoder.dicPos - dicPos;
456    memcpy(dest, p->decoder.dic + dicPos, outCur);
457    dest += outCur;
458    outSize -= outCur;
459    *destLen += outCur;
460    if (res != 0)
461      return res;
462    if (outCur == 0 || outSize == 0)
463      return SZ_OK;
464  }
465}
466
467
468SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
469    Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
470{
471  CLzma2Dec p;
472  SRes res;
473  SizeT outSize = *destLen, inSize = *srcLen;
474  *destLen = *srcLen = 0;
475  *status = LZMA_STATUS_NOT_SPECIFIED;
476  Lzma2Dec_Construct(&p);
477  RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
478  p.decoder.dic = dest;
479  p.decoder.dicBufSize = outSize;
480  Lzma2Dec_Init(&p);
481  *srcLen = inSize;
482  res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
483  *destLen = p.decoder.dicPos;
484  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
485    res = SZ_ERROR_INPUT_EOF;
486  Lzma2Dec_FreeProbs(&p, alloc);
487  return res;
488}