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