Home | History | Annotate | Download | only in C
      1 /* Lzma2Dec.c -- LZMA2 Decoder
      2 2010-12-15 : 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 /*
     17 00000000  -  EOS
     18 00000001 U U  -  Uncompressed Reset Dic
     19 00000010 U U  -  Uncompressed No Reset
     20 100uuuuu U U P P  -  LZMA no reset
     21 101uuuuu U U P P  -  LZMA reset state
     22 110uuuuu U U P P S  -  LZMA reset state + new prop
     23 111uuuuu U U P P S  -  LZMA reset state + new prop + reset dic
     24 
     25   u, U - Unpack Size
     26   P - Pack Size
     27   S - Props
     28 */
     29 
     30 #define LZMA2_CONTROL_LZMA (1 << 7)
     31 #define LZMA2_CONTROL_COPY_NO_RESET 2
     32 #define LZMA2_CONTROL_COPY_RESET_DIC 1
     33 #define LZMA2_CONTROL_EOF 0
     34 
     35 #define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
     36 
     37 #define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
     38 #define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
     39 
     40 #define LZMA2_LCLP_MAX 4
     41 #define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
     42 
     43 #ifdef SHOW_DEBUG_INFO
     44 #define PRF(x) x
     45 #else
     46 #define PRF(x)
     47 #endif
     48 
     49 typedef enum
     50 {
     51   LZMA2_STATE_CONTROL,
     52   LZMA2_STATE_UNPACK0,
     53   LZMA2_STATE_UNPACK1,
     54   LZMA2_STATE_PACK0,
     55   LZMA2_STATE_PACK1,
     56   LZMA2_STATE_PROP,
     57   LZMA2_STATE_DATA,
     58   LZMA2_STATE_DATA_CONT,
     59   LZMA2_STATE_FINISHED,
     60   LZMA2_STATE_ERROR
     61 } ELzma2State;
     62 
     63 static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
     64 {
     65   UInt32 dicSize;
     66   if (prop > 40)
     67     return SZ_ERROR_UNSUPPORTED;
     68   dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
     69   props[0] = (Byte)LZMA2_LCLP_MAX;
     70   props[1] = (Byte)(dicSize);
     71   props[2] = (Byte)(dicSize >> 8);
     72   props[3] = (Byte)(dicSize >> 16);
     73   props[4] = (Byte)(dicSize >> 24);
     74   return SZ_OK;
     75 }
     76 
     77 SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
     78 {
     79   Byte props[LZMA_PROPS_SIZE];
     80   RINOK(Lzma2Dec_GetOldProps(prop, props));
     81   return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
     82 }
     83 
     84 SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
     85 {
     86   Byte props[LZMA_PROPS_SIZE];
     87   RINOK(Lzma2Dec_GetOldProps(prop, props));
     88   return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
     89 }
     90 
     91 void Lzma2Dec_Init(CLzma2Dec *p)
     92 {
     93   p->state = LZMA2_STATE_CONTROL;
     94   p->needInitDic = True;
     95   p->needInitState = True;
     96   p->needInitProp = True;
     97   LzmaDec_Init(&p->decoder);
     98 }
     99 
    100 static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
    101 {
    102   switch(p->state)
    103   {
    104     case LZMA2_STATE_CONTROL:
    105       p->control = b;
    106       PRF(printf("\n %4X ", p->decoder.dicPos));
    107       PRF(printf(" %2X", b));
    108       if (p->control == 0)
    109         return LZMA2_STATE_FINISHED;
    110       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
    111       {
    112         if ((p->control & 0x7F) > 2)
    113           return LZMA2_STATE_ERROR;
    114         p->unpackSize = 0;
    115       }
    116       else
    117         p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
    118       return LZMA2_STATE_UNPACK0;
    119 
    120     case LZMA2_STATE_UNPACK0:
    121       p->unpackSize |= (UInt32)b << 8;
    122       return LZMA2_STATE_UNPACK1;
    123 
    124     case LZMA2_STATE_UNPACK1:
    125       p->unpackSize |= (UInt32)b;
    126       p->unpackSize++;
    127       PRF(printf(" %8d", p->unpackSize));
    128       return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
    129 
    130     case LZMA2_STATE_PACK0:
    131       p->packSize = (UInt32)b << 8;
    132       return LZMA2_STATE_PACK1;
    133 
    134     case LZMA2_STATE_PACK1:
    135       p->packSize |= (UInt32)b;
    136       p->packSize++;
    137       PRF(printf(" %8d", p->packSize));
    138       return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
    139         (p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
    140 
    141     case LZMA2_STATE_PROP:
    142     {
    143       int lc, lp;
    144       if (b >= (9 * 5 * 5))
    145         return LZMA2_STATE_ERROR;
    146       lc = b % 9;
    147       b /= 9;
    148       p->decoder.prop.pb = b / 5;
    149       lp = b % 5;
    150       if (lc + lp > LZMA2_LCLP_MAX)
    151         return LZMA2_STATE_ERROR;
    152       p->decoder.prop.lc = lc;
    153       p->decoder.prop.lp = lp;
    154       p->needInitProp = False;
    155       return LZMA2_STATE_DATA;
    156     }
    157   }
    158   return LZMA2_STATE_ERROR;
    159 }
    160 
    161 static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
    162 {
    163   memcpy(p->dic + p->dicPos, src, size);
    164   p->dicPos += size;
    165   if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
    166     p->checkDicSize = p->prop.dicSize;
    167   p->processedPos += (UInt32)size;
    168 }
    169 
    170 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
    171 
    172 SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
    173     const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
    174 {
    175   SizeT inSize = *srcLen;
    176   *srcLen = 0;
    177   *status = LZMA_STATUS_NOT_SPECIFIED;
    178 
    179   while (p->state != LZMA2_STATE_FINISHED)
    180   {
    181     SizeT dicPos = p->decoder.dicPos;
    182     if (p->state == LZMA2_STATE_ERROR)
    183       return SZ_ERROR_DATA;
    184     if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
    185     {
    186       *status = LZMA_STATUS_NOT_FINISHED;
    187       return SZ_OK;
    188     }
    189     if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
    190     {
    191       if (*srcLen == inSize)
    192       {
    193         *status = LZMA_STATUS_NEEDS_MORE_INPUT;
    194         return SZ_OK;
    195       }
    196       (*srcLen)++;
    197       p->state = Lzma2Dec_UpdateState(p, *src++);
    198       continue;
    199     }
    200     {
    201       SizeT destSizeCur = dicLimit - dicPos;
    202       SizeT srcSizeCur = inSize - *srcLen;
    203       ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
    204 
    205       if (p->unpackSize <= destSizeCur)
    206       {
    207         destSizeCur = (SizeT)p->unpackSize;
    208         curFinishMode = LZMA_FINISH_END;
    209       }
    210 
    211       if (LZMA2_IS_UNCOMPRESSED_STATE(p))
    212       {
    213         if (*srcLen == inSize)
    214         {
    215           *status = LZMA_STATUS_NEEDS_MORE_INPUT;
    216           return SZ_OK;
    217         }
    218 
    219         if (p->state == LZMA2_STATE_DATA)
    220         {
    221           Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
    222           if (initDic)
    223             p->needInitProp = p->needInitState = True;
    224           else if (p->needInitDic)
    225             return SZ_ERROR_DATA;
    226           p->needInitDic = False;
    227           LzmaDec_InitDicAndState(&p->decoder, initDic, False);
    228         }
    229 
    230         if (srcSizeCur > destSizeCur)
    231           srcSizeCur = destSizeCur;
    232 
    233         if (srcSizeCur == 0)
    234           return SZ_ERROR_DATA;
    235 
    236         LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
    237 
    238         src += srcSizeCur;
    239         *srcLen += srcSizeCur;
    240         p->unpackSize -= (UInt32)srcSizeCur;
    241         p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
    242       }
    243       else
    244       {
    245         SizeT outSizeProcessed;
    246         SRes res;
    247 
    248         if (p->state == LZMA2_STATE_DATA)
    249         {
    250           int mode = LZMA2_GET_LZMA_MODE(p);
    251           Bool initDic = (mode == 3);
    252           Bool initState = (mode > 0);
    253           if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
    254             return SZ_ERROR_DATA;
    255 
    256           LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
    257           p->needInitDic = False;
    258           p->needInitState = False;
    259           p->state = LZMA2_STATE_DATA_CONT;
    260         }
    261         if (srcSizeCur > p->packSize)
    262           srcSizeCur = (SizeT)p->packSize;
    263 
    264         res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
    265 
    266         src += srcSizeCur;
    267         *srcLen += srcSizeCur;
    268         p->packSize -= (UInt32)srcSizeCur;
    269 
    270         outSizeProcessed = p->decoder.dicPos - dicPos;
    271         p->unpackSize -= (UInt32)outSizeProcessed;
    272 
    273         RINOK(res);
    274         if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
    275           return res;
    276 
    277         if (srcSizeCur == 0 && outSizeProcessed == 0)
    278         {
    279           if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
    280               p->unpackSize != 0 || p->packSize != 0)
    281             return SZ_ERROR_DATA;
    282           p->state = LZMA2_STATE_CONTROL;
    283         }
    284         if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
    285           *status = LZMA_STATUS_NOT_FINISHED;
    286       }
    287     }
    288   }
    289   *status = LZMA_STATUS_FINISHED_WITH_MARK;
    290   return SZ_OK;
    291 }
    292 
    293 SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
    294 {
    295   SizeT outSize = *destLen, inSize = *srcLen;
    296   *srcLen = *destLen = 0;
    297   for (;;)
    298   {
    299     SizeT srcSizeCur = inSize, outSizeCur, dicPos;
    300     ELzmaFinishMode curFinishMode;
    301     SRes res;
    302     if (p->decoder.dicPos == p->decoder.dicBufSize)
    303       p->decoder.dicPos = 0;
    304     dicPos = p->decoder.dicPos;
    305     if (outSize > p->decoder.dicBufSize - dicPos)
    306     {
    307       outSizeCur = p->decoder.dicBufSize;
    308       curFinishMode = LZMA_FINISH_ANY;
    309     }
    310     else
    311     {
    312       outSizeCur = dicPos + outSize;
    313       curFinishMode = finishMode;
    314     }
    315 
    316     res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
    317     src += srcSizeCur;
    318     inSize -= srcSizeCur;
    319     *srcLen += srcSizeCur;
    320     outSizeCur = p->decoder.dicPos - dicPos;
    321     memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
    322     dest += outSizeCur;
    323     outSize -= outSizeCur;
    324     *destLen += outSizeCur;
    325     if (res != 0)
    326       return res;
    327     if (outSizeCur == 0 || outSize == 0)
    328       return SZ_OK;
    329   }
    330 }
    331 
    332 SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    333     Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
    334 {
    335   CLzma2Dec p;
    336   SRes res;
    337   SizeT outSize = *destLen, inSize = *srcLen;
    338   *destLen = *srcLen = 0;
    339   *status = LZMA_STATUS_NOT_SPECIFIED;
    340   Lzma2Dec_Construct(&p);
    341   RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
    342   p.decoder.dic = dest;
    343   p.decoder.dicBufSize = outSize;
    344   Lzma2Dec_Init(&p);
    345   *srcLen = inSize;
    346   res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
    347   *destLen = p.decoder.dicPos;
    348   if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
    349     res = SZ_ERROR_INPUT_EOF;
    350   Lzma2Dec_FreeProbs(&p, alloc);
    351   return res;
    352 }
    353