repo sync | baa3858 | 2013-07-26 17:53:31 -0700 | [diff] [blame] | 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 | }
|