Home | History | Annotate | Download | only in lzma_sdk
      1 /* Lzma2Dec.c -- LZMA2 Decoder
      2 2009-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 /*
     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 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