1370b324cSopenharmony_ci/* Lzma2Dec.c -- LZMA2 Decoder 2370b324cSopenharmony_ci2023-03-03 : Igor Pavlov : Public domain */ 3370b324cSopenharmony_ci 4370b324cSopenharmony_ci/* #define SHOW_DEBUG_INFO */ 5370b324cSopenharmony_ci 6370b324cSopenharmony_ci#include "Precomp.h" 7370b324cSopenharmony_ci 8370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO 9370b324cSopenharmony_ci#include <stdio.h> 10370b324cSopenharmony_ci#endif 11370b324cSopenharmony_ci 12370b324cSopenharmony_ci#include <string.h> 13370b324cSopenharmony_ci 14370b324cSopenharmony_ci#include "Lzma2Dec.h" 15370b324cSopenharmony_ci 16370b324cSopenharmony_ci/* 17370b324cSopenharmony_ci00000000 - End of data 18370b324cSopenharmony_ci00000001 U U - Uncompressed, reset dic, need reset state and set new prop 19370b324cSopenharmony_ci00000010 U U - Uncompressed, no reset 20370b324cSopenharmony_ci100uuuuu U U P P - LZMA, no reset 21370b324cSopenharmony_ci101uuuuu U U P P - LZMA, reset state 22370b324cSopenharmony_ci110uuuuu U U P P S - LZMA, reset state + set new prop 23370b324cSopenharmony_ci111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic 24370b324cSopenharmony_ci 25370b324cSopenharmony_ci u, U - Unpack Size 26370b324cSopenharmony_ci P - Pack Size 27370b324cSopenharmony_ci S - Props 28370b324cSopenharmony_ci*/ 29370b324cSopenharmony_ci 30370b324cSopenharmony_ci#define LZMA2_CONTROL_COPY_RESET_DIC 1 31370b324cSopenharmony_ci 32370b324cSopenharmony_ci#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0) 33370b324cSopenharmony_ci 34370b324cSopenharmony_ci#define LZMA2_LCLP_MAX 4 35370b324cSopenharmony_ci#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11)) 36370b324cSopenharmony_ci 37370b324cSopenharmony_ci#ifdef SHOW_DEBUG_INFO 38370b324cSopenharmony_ci#define PRF(x) x 39370b324cSopenharmony_ci#else 40370b324cSopenharmony_ci#define PRF(x) 41370b324cSopenharmony_ci#endif 42370b324cSopenharmony_ci 43370b324cSopenharmony_citypedef enum 44370b324cSopenharmony_ci{ 45370b324cSopenharmony_ci LZMA2_STATE_CONTROL, 46370b324cSopenharmony_ci LZMA2_STATE_UNPACK0, 47370b324cSopenharmony_ci LZMA2_STATE_UNPACK1, 48370b324cSopenharmony_ci LZMA2_STATE_PACK0, 49370b324cSopenharmony_ci LZMA2_STATE_PACK1, 50370b324cSopenharmony_ci LZMA2_STATE_PROP, 51370b324cSopenharmony_ci LZMA2_STATE_DATA, 52370b324cSopenharmony_ci LZMA2_STATE_DATA_CONT, 53370b324cSopenharmony_ci LZMA2_STATE_FINISHED, 54370b324cSopenharmony_ci LZMA2_STATE_ERROR 55370b324cSopenharmony_ci} ELzma2State; 56370b324cSopenharmony_ci 57370b324cSopenharmony_cistatic SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props) 58370b324cSopenharmony_ci{ 59370b324cSopenharmony_ci UInt32 dicSize; 60370b324cSopenharmony_ci if (prop > 40) 61370b324cSopenharmony_ci return SZ_ERROR_UNSUPPORTED; 62370b324cSopenharmony_ci dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop); 63370b324cSopenharmony_ci props[0] = (Byte)LZMA2_LCLP_MAX; 64370b324cSopenharmony_ci props[1] = (Byte)(dicSize); 65370b324cSopenharmony_ci props[2] = (Byte)(dicSize >> 8); 66370b324cSopenharmony_ci props[3] = (Byte)(dicSize >> 16); 67370b324cSopenharmony_ci props[4] = (Byte)(dicSize >> 24); 68370b324cSopenharmony_ci return SZ_OK; 69370b324cSopenharmony_ci} 70370b324cSopenharmony_ci 71370b324cSopenharmony_ciSRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) 72370b324cSopenharmony_ci{ 73370b324cSopenharmony_ci Byte props[LZMA_PROPS_SIZE]; 74370b324cSopenharmony_ci RINOK(Lzma2Dec_GetOldProps(prop, props)) 75370b324cSopenharmony_ci return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc); 76370b324cSopenharmony_ci} 77370b324cSopenharmony_ci 78370b324cSopenharmony_ciSRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc) 79370b324cSopenharmony_ci{ 80370b324cSopenharmony_ci Byte props[LZMA_PROPS_SIZE]; 81370b324cSopenharmony_ci RINOK(Lzma2Dec_GetOldProps(prop, props)) 82370b324cSopenharmony_ci return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc); 83370b324cSopenharmony_ci} 84370b324cSopenharmony_ci 85370b324cSopenharmony_civoid Lzma2Dec_Init(CLzma2Dec *p) 86370b324cSopenharmony_ci{ 87370b324cSopenharmony_ci p->state = LZMA2_STATE_CONTROL; 88370b324cSopenharmony_ci p->needInitLevel = 0xE0; 89370b324cSopenharmony_ci p->isExtraMode = False; 90370b324cSopenharmony_ci p->unpackSize = 0; 91370b324cSopenharmony_ci 92370b324cSopenharmony_ci // p->decoder.dicPos = 0; // we can use it instead of full init 93370b324cSopenharmony_ci LzmaDec_Init(&p->decoder); 94370b324cSopenharmony_ci} 95370b324cSopenharmony_ci 96370b324cSopenharmony_ci// ELzma2State 97370b324cSopenharmony_cistatic unsigned Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b) 98370b324cSopenharmony_ci{ 99370b324cSopenharmony_ci switch (p->state) 100370b324cSopenharmony_ci { 101370b324cSopenharmony_ci case LZMA2_STATE_CONTROL: 102370b324cSopenharmony_ci p->isExtraMode = False; 103370b324cSopenharmony_ci p->control = b; 104370b324cSopenharmony_ci PRF(printf("\n %8X", (unsigned)p->decoder.dicPos)); 105370b324cSopenharmony_ci PRF(printf(" %02X", (unsigned)b)); 106370b324cSopenharmony_ci if (b == 0) 107370b324cSopenharmony_ci return LZMA2_STATE_FINISHED; 108370b324cSopenharmony_ci if (LZMA2_IS_UNCOMPRESSED_STATE(p)) 109370b324cSopenharmony_ci { 110370b324cSopenharmony_ci if (b == LZMA2_CONTROL_COPY_RESET_DIC) 111370b324cSopenharmony_ci p->needInitLevel = 0xC0; 112370b324cSopenharmony_ci else if (b > 2 || p->needInitLevel == 0xE0) 113370b324cSopenharmony_ci return LZMA2_STATE_ERROR; 114370b324cSopenharmony_ci } 115370b324cSopenharmony_ci else 116370b324cSopenharmony_ci { 117370b324cSopenharmony_ci if (b < p->needInitLevel) 118370b324cSopenharmony_ci return LZMA2_STATE_ERROR; 119370b324cSopenharmony_ci p->needInitLevel = 0; 120370b324cSopenharmony_ci p->unpackSize = (UInt32)(b & 0x1F) << 16; 121370b324cSopenharmony_ci } 122370b324cSopenharmony_ci return LZMA2_STATE_UNPACK0; 123370b324cSopenharmony_ci 124370b324cSopenharmony_ci case LZMA2_STATE_UNPACK0: 125370b324cSopenharmony_ci p->unpackSize |= (UInt32)b << 8; 126370b324cSopenharmony_ci return LZMA2_STATE_UNPACK1; 127370b324cSopenharmony_ci 128370b324cSopenharmony_ci case LZMA2_STATE_UNPACK1: 129370b324cSopenharmony_ci p->unpackSize |= (UInt32)b; 130370b324cSopenharmony_ci p->unpackSize++; 131370b324cSopenharmony_ci PRF(printf(" %7u", (unsigned)p->unpackSize)); 132370b324cSopenharmony_ci return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0; 133370b324cSopenharmony_ci 134370b324cSopenharmony_ci case LZMA2_STATE_PACK0: 135370b324cSopenharmony_ci p->packSize = (UInt32)b << 8; 136370b324cSopenharmony_ci return LZMA2_STATE_PACK1; 137370b324cSopenharmony_ci 138370b324cSopenharmony_ci case LZMA2_STATE_PACK1: 139370b324cSopenharmony_ci p->packSize |= (UInt32)b; 140370b324cSopenharmony_ci p->packSize++; 141370b324cSopenharmony_ci // if (p->packSize < 5) return LZMA2_STATE_ERROR; 142370b324cSopenharmony_ci PRF(printf(" %5u", (unsigned)p->packSize)); 143370b324cSopenharmony_ci return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA; 144370b324cSopenharmony_ci 145370b324cSopenharmony_ci case LZMA2_STATE_PROP: 146370b324cSopenharmony_ci { 147370b324cSopenharmony_ci unsigned lc, lp; 148370b324cSopenharmony_ci if (b >= (9 * 5 * 5)) 149370b324cSopenharmony_ci return LZMA2_STATE_ERROR; 150370b324cSopenharmony_ci lc = b % 9; 151370b324cSopenharmony_ci b /= 9; 152370b324cSopenharmony_ci p->decoder.prop.pb = (Byte)(b / 5); 153370b324cSopenharmony_ci lp = b % 5; 154370b324cSopenharmony_ci if (lc + lp > LZMA2_LCLP_MAX) 155370b324cSopenharmony_ci return LZMA2_STATE_ERROR; 156370b324cSopenharmony_ci p->decoder.prop.lc = (Byte)lc; 157370b324cSopenharmony_ci p->decoder.prop.lp = (Byte)lp; 158370b324cSopenharmony_ci return LZMA2_STATE_DATA; 159370b324cSopenharmony_ci } 160370b324cSopenharmony_ci } 161370b324cSopenharmony_ci return LZMA2_STATE_ERROR; 162370b324cSopenharmony_ci} 163370b324cSopenharmony_ci 164370b324cSopenharmony_cistatic void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size) 165370b324cSopenharmony_ci{ 166370b324cSopenharmony_ci memcpy(p->dic + p->dicPos, src, size); 167370b324cSopenharmony_ci p->dicPos += size; 168370b324cSopenharmony_ci if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size) 169370b324cSopenharmony_ci p->checkDicSize = p->prop.dicSize; 170370b324cSopenharmony_ci p->processedPos += (UInt32)size; 171370b324cSopenharmony_ci} 172370b324cSopenharmony_ci 173370b324cSopenharmony_civoid LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState); 174370b324cSopenharmony_ci 175370b324cSopenharmony_ci 176370b324cSopenharmony_ciSRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit, 177370b324cSopenharmony_ci const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) 178370b324cSopenharmony_ci{ 179370b324cSopenharmony_ci SizeT inSize = *srcLen; 180370b324cSopenharmony_ci *srcLen = 0; 181370b324cSopenharmony_ci *status = LZMA_STATUS_NOT_SPECIFIED; 182370b324cSopenharmony_ci 183370b324cSopenharmony_ci while (p->state != LZMA2_STATE_ERROR) 184370b324cSopenharmony_ci { 185370b324cSopenharmony_ci SizeT dicPos; 186370b324cSopenharmony_ci 187370b324cSopenharmony_ci if (p->state == LZMA2_STATE_FINISHED) 188370b324cSopenharmony_ci { 189370b324cSopenharmony_ci *status = LZMA_STATUS_FINISHED_WITH_MARK; 190370b324cSopenharmony_ci return SZ_OK; 191370b324cSopenharmony_ci } 192370b324cSopenharmony_ci 193370b324cSopenharmony_ci dicPos = p->decoder.dicPos; 194370b324cSopenharmony_ci 195370b324cSopenharmony_ci if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY) 196370b324cSopenharmony_ci { 197370b324cSopenharmony_ci *status = LZMA_STATUS_NOT_FINISHED; 198370b324cSopenharmony_ci return SZ_OK; 199370b324cSopenharmony_ci } 200370b324cSopenharmony_ci 201370b324cSopenharmony_ci if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) 202370b324cSopenharmony_ci { 203370b324cSopenharmony_ci if (*srcLen == inSize) 204370b324cSopenharmony_ci { 205370b324cSopenharmony_ci *status = LZMA_STATUS_NEEDS_MORE_INPUT; 206370b324cSopenharmony_ci return SZ_OK; 207370b324cSopenharmony_ci } 208370b324cSopenharmony_ci (*srcLen)++; 209370b324cSopenharmony_ci p->state = Lzma2Dec_UpdateState(p, *src++); 210370b324cSopenharmony_ci if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED) 211370b324cSopenharmony_ci break; 212370b324cSopenharmony_ci continue; 213370b324cSopenharmony_ci } 214370b324cSopenharmony_ci 215370b324cSopenharmony_ci { 216370b324cSopenharmony_ci SizeT inCur = inSize - *srcLen; 217370b324cSopenharmony_ci SizeT outCur = dicLimit - dicPos; 218370b324cSopenharmony_ci ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY; 219370b324cSopenharmony_ci 220370b324cSopenharmony_ci if (outCur >= p->unpackSize) 221370b324cSopenharmony_ci { 222370b324cSopenharmony_ci outCur = (SizeT)p->unpackSize; 223370b324cSopenharmony_ci curFinishMode = LZMA_FINISH_END; 224370b324cSopenharmony_ci } 225370b324cSopenharmony_ci 226370b324cSopenharmony_ci if (LZMA2_IS_UNCOMPRESSED_STATE(p)) 227370b324cSopenharmony_ci { 228370b324cSopenharmony_ci if (inCur == 0) 229370b324cSopenharmony_ci { 230370b324cSopenharmony_ci *status = LZMA_STATUS_NEEDS_MORE_INPUT; 231370b324cSopenharmony_ci return SZ_OK; 232370b324cSopenharmony_ci } 233370b324cSopenharmony_ci 234370b324cSopenharmony_ci if (p->state == LZMA2_STATE_DATA) 235370b324cSopenharmony_ci { 236370b324cSopenharmony_ci BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC); 237370b324cSopenharmony_ci LzmaDec_InitDicAndState(&p->decoder, initDic, False); 238370b324cSopenharmony_ci } 239370b324cSopenharmony_ci 240370b324cSopenharmony_ci if (inCur > outCur) 241370b324cSopenharmony_ci inCur = outCur; 242370b324cSopenharmony_ci if (inCur == 0) 243370b324cSopenharmony_ci break; 244370b324cSopenharmony_ci 245370b324cSopenharmony_ci LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur); 246370b324cSopenharmony_ci 247370b324cSopenharmony_ci src += inCur; 248370b324cSopenharmony_ci *srcLen += inCur; 249370b324cSopenharmony_ci p->unpackSize -= (UInt32)inCur; 250370b324cSopenharmony_ci p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; 251370b324cSopenharmony_ci } 252370b324cSopenharmony_ci else 253370b324cSopenharmony_ci { 254370b324cSopenharmony_ci SRes res; 255370b324cSopenharmony_ci 256370b324cSopenharmony_ci if (p->state == LZMA2_STATE_DATA) 257370b324cSopenharmony_ci { 258370b324cSopenharmony_ci BoolInt initDic = (p->control >= 0xE0); 259370b324cSopenharmony_ci BoolInt initState = (p->control >= 0xA0); 260370b324cSopenharmony_ci LzmaDec_InitDicAndState(&p->decoder, initDic, initState); 261370b324cSopenharmony_ci p->state = LZMA2_STATE_DATA_CONT; 262370b324cSopenharmony_ci } 263370b324cSopenharmony_ci 264370b324cSopenharmony_ci if (inCur > p->packSize) 265370b324cSopenharmony_ci inCur = (SizeT)p->packSize; 266370b324cSopenharmony_ci 267370b324cSopenharmony_ci res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status); 268370b324cSopenharmony_ci 269370b324cSopenharmony_ci src += inCur; 270370b324cSopenharmony_ci *srcLen += inCur; 271370b324cSopenharmony_ci p->packSize -= (UInt32)inCur; 272370b324cSopenharmony_ci outCur = p->decoder.dicPos - dicPos; 273370b324cSopenharmony_ci p->unpackSize -= (UInt32)outCur; 274370b324cSopenharmony_ci 275370b324cSopenharmony_ci if (res != 0) 276370b324cSopenharmony_ci break; 277370b324cSopenharmony_ci 278370b324cSopenharmony_ci if (*status == LZMA_STATUS_NEEDS_MORE_INPUT) 279370b324cSopenharmony_ci { 280370b324cSopenharmony_ci if (p->packSize == 0) 281370b324cSopenharmony_ci break; 282370b324cSopenharmony_ci return SZ_OK; 283370b324cSopenharmony_ci } 284370b324cSopenharmony_ci 285370b324cSopenharmony_ci if (inCur == 0 && outCur == 0) 286370b324cSopenharmony_ci { 287370b324cSopenharmony_ci if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK 288370b324cSopenharmony_ci || p->unpackSize != 0 289370b324cSopenharmony_ci || p->packSize != 0) 290370b324cSopenharmony_ci break; 291370b324cSopenharmony_ci p->state = LZMA2_STATE_CONTROL; 292370b324cSopenharmony_ci } 293370b324cSopenharmony_ci 294370b324cSopenharmony_ci *status = LZMA_STATUS_NOT_SPECIFIED; 295370b324cSopenharmony_ci } 296370b324cSopenharmony_ci } 297370b324cSopenharmony_ci } 298370b324cSopenharmony_ci 299370b324cSopenharmony_ci *status = LZMA_STATUS_NOT_SPECIFIED; 300370b324cSopenharmony_ci p->state = LZMA2_STATE_ERROR; 301370b324cSopenharmony_ci return SZ_ERROR_DATA; 302370b324cSopenharmony_ci} 303370b324cSopenharmony_ci 304370b324cSopenharmony_ci 305370b324cSopenharmony_ci 306370b324cSopenharmony_ci 307370b324cSopenharmony_ciELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p, 308370b324cSopenharmony_ci SizeT outSize, 309370b324cSopenharmony_ci const Byte *src, SizeT *srcLen, 310370b324cSopenharmony_ci int checkFinishBlock) 311370b324cSopenharmony_ci{ 312370b324cSopenharmony_ci SizeT inSize = *srcLen; 313370b324cSopenharmony_ci *srcLen = 0; 314370b324cSopenharmony_ci 315370b324cSopenharmony_ci while (p->state != LZMA2_STATE_ERROR) 316370b324cSopenharmony_ci { 317370b324cSopenharmony_ci if (p->state == LZMA2_STATE_FINISHED) 318370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK; 319370b324cSopenharmony_ci 320370b324cSopenharmony_ci if (outSize == 0 && !checkFinishBlock) 321370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; 322370b324cSopenharmony_ci 323370b324cSopenharmony_ci if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT) 324370b324cSopenharmony_ci { 325370b324cSopenharmony_ci if (*srcLen == inSize) 326370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; 327370b324cSopenharmony_ci (*srcLen)++; 328370b324cSopenharmony_ci 329370b324cSopenharmony_ci p->state = Lzma2Dec_UpdateState(p, *src++); 330370b324cSopenharmony_ci 331370b324cSopenharmony_ci if (p->state == LZMA2_STATE_UNPACK0) 332370b324cSopenharmony_ci { 333370b324cSopenharmony_ci // if (p->decoder.dicPos != 0) 334370b324cSopenharmony_ci if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0) 335370b324cSopenharmony_ci return LZMA2_PARSE_STATUS_NEW_BLOCK; 336370b324cSopenharmony_ci // if (outSize == 0) return LZMA_STATUS_NOT_FINISHED; 337370b324cSopenharmony_ci } 338370b324cSopenharmony_ci 339370b324cSopenharmony_ci // The following code can be commented. 340370b324cSopenharmony_ci // It's not big problem, if we read additional input bytes. 341370b324cSopenharmony_ci // It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state. 342370b324cSopenharmony_ci 343370b324cSopenharmony_ci if (outSize == 0 && p->state != LZMA2_STATE_FINISHED) 344370b324cSopenharmony_ci { 345370b324cSopenharmony_ci // checkFinishBlock is true. So we expect that block must be finished, 346370b324cSopenharmony_ci // We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here 347370b324cSopenharmony_ci // break; 348370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; 349370b324cSopenharmony_ci } 350370b324cSopenharmony_ci 351370b324cSopenharmony_ci if (p->state == LZMA2_STATE_DATA) 352370b324cSopenharmony_ci return LZMA2_PARSE_STATUS_NEW_CHUNK; 353370b324cSopenharmony_ci 354370b324cSopenharmony_ci continue; 355370b324cSopenharmony_ci } 356370b324cSopenharmony_ci 357370b324cSopenharmony_ci if (outSize == 0) 358370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED; 359370b324cSopenharmony_ci 360370b324cSopenharmony_ci { 361370b324cSopenharmony_ci SizeT inCur = inSize - *srcLen; 362370b324cSopenharmony_ci 363370b324cSopenharmony_ci if (LZMA2_IS_UNCOMPRESSED_STATE(p)) 364370b324cSopenharmony_ci { 365370b324cSopenharmony_ci if (inCur == 0) 366370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; 367370b324cSopenharmony_ci if (inCur > p->unpackSize) 368370b324cSopenharmony_ci inCur = p->unpackSize; 369370b324cSopenharmony_ci if (inCur > outSize) 370370b324cSopenharmony_ci inCur = outSize; 371370b324cSopenharmony_ci p->decoder.dicPos += inCur; 372370b324cSopenharmony_ci src += inCur; 373370b324cSopenharmony_ci *srcLen += inCur; 374370b324cSopenharmony_ci outSize -= inCur; 375370b324cSopenharmony_ci p->unpackSize -= (UInt32)inCur; 376370b324cSopenharmony_ci p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT; 377370b324cSopenharmony_ci } 378370b324cSopenharmony_ci else 379370b324cSopenharmony_ci { 380370b324cSopenharmony_ci p->isExtraMode = True; 381370b324cSopenharmony_ci 382370b324cSopenharmony_ci if (inCur == 0) 383370b324cSopenharmony_ci { 384370b324cSopenharmony_ci if (p->packSize != 0) 385370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT; 386370b324cSopenharmony_ci } 387370b324cSopenharmony_ci else if (p->state == LZMA2_STATE_DATA) 388370b324cSopenharmony_ci { 389370b324cSopenharmony_ci p->state = LZMA2_STATE_DATA_CONT; 390370b324cSopenharmony_ci if (*src != 0) 391370b324cSopenharmony_ci { 392370b324cSopenharmony_ci // first byte of lzma chunk must be Zero 393370b324cSopenharmony_ci *srcLen += 1; 394370b324cSopenharmony_ci p->packSize--; 395370b324cSopenharmony_ci break; 396370b324cSopenharmony_ci } 397370b324cSopenharmony_ci } 398370b324cSopenharmony_ci 399370b324cSopenharmony_ci if (inCur > p->packSize) 400370b324cSopenharmony_ci inCur = (SizeT)p->packSize; 401370b324cSopenharmony_ci 402370b324cSopenharmony_ci src += inCur; 403370b324cSopenharmony_ci *srcLen += inCur; 404370b324cSopenharmony_ci p->packSize -= (UInt32)inCur; 405370b324cSopenharmony_ci 406370b324cSopenharmony_ci if (p->packSize == 0) 407370b324cSopenharmony_ci { 408370b324cSopenharmony_ci SizeT rem = outSize; 409370b324cSopenharmony_ci if (rem > p->unpackSize) 410370b324cSopenharmony_ci rem = p->unpackSize; 411370b324cSopenharmony_ci p->decoder.dicPos += rem; 412370b324cSopenharmony_ci p->unpackSize -= (UInt32)rem; 413370b324cSopenharmony_ci outSize -= rem; 414370b324cSopenharmony_ci if (p->unpackSize == 0) 415370b324cSopenharmony_ci p->state = LZMA2_STATE_CONTROL; 416370b324cSopenharmony_ci } 417370b324cSopenharmony_ci } 418370b324cSopenharmony_ci } 419370b324cSopenharmony_ci } 420370b324cSopenharmony_ci 421370b324cSopenharmony_ci p->state = LZMA2_STATE_ERROR; 422370b324cSopenharmony_ci return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED; 423370b324cSopenharmony_ci} 424370b324cSopenharmony_ci 425370b324cSopenharmony_ci 426370b324cSopenharmony_ci 427370b324cSopenharmony_ci 428370b324cSopenharmony_ciSRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) 429370b324cSopenharmony_ci{ 430370b324cSopenharmony_ci SizeT outSize = *destLen, inSize = *srcLen; 431370b324cSopenharmony_ci *srcLen = *destLen = 0; 432370b324cSopenharmony_ci 433370b324cSopenharmony_ci for (;;) 434370b324cSopenharmony_ci { 435370b324cSopenharmony_ci SizeT inCur = inSize, outCur, dicPos; 436370b324cSopenharmony_ci ELzmaFinishMode curFinishMode; 437370b324cSopenharmony_ci SRes res; 438370b324cSopenharmony_ci 439370b324cSopenharmony_ci if (p->decoder.dicPos == p->decoder.dicBufSize) 440370b324cSopenharmony_ci p->decoder.dicPos = 0; 441370b324cSopenharmony_ci dicPos = p->decoder.dicPos; 442370b324cSopenharmony_ci curFinishMode = LZMA_FINISH_ANY; 443370b324cSopenharmony_ci outCur = p->decoder.dicBufSize - dicPos; 444370b324cSopenharmony_ci 445370b324cSopenharmony_ci if (outCur >= outSize) 446370b324cSopenharmony_ci { 447370b324cSopenharmony_ci outCur = outSize; 448370b324cSopenharmony_ci curFinishMode = finishMode; 449370b324cSopenharmony_ci } 450370b324cSopenharmony_ci 451370b324cSopenharmony_ci res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status); 452370b324cSopenharmony_ci 453370b324cSopenharmony_ci src += inCur; 454370b324cSopenharmony_ci inSize -= inCur; 455370b324cSopenharmony_ci *srcLen += inCur; 456370b324cSopenharmony_ci outCur = p->decoder.dicPos - dicPos; 457370b324cSopenharmony_ci memcpy(dest, p->decoder.dic + dicPos, outCur); 458370b324cSopenharmony_ci dest += outCur; 459370b324cSopenharmony_ci outSize -= outCur; 460370b324cSopenharmony_ci *destLen += outCur; 461370b324cSopenharmony_ci if (res != 0) 462370b324cSopenharmony_ci return res; 463370b324cSopenharmony_ci if (outCur == 0 || outSize == 0) 464370b324cSopenharmony_ci return SZ_OK; 465370b324cSopenharmony_ci } 466370b324cSopenharmony_ci} 467370b324cSopenharmony_ci 468370b324cSopenharmony_ci 469370b324cSopenharmony_ciSRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 470370b324cSopenharmony_ci Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc) 471370b324cSopenharmony_ci{ 472370b324cSopenharmony_ci CLzma2Dec p; 473370b324cSopenharmony_ci SRes res; 474370b324cSopenharmony_ci SizeT outSize = *destLen, inSize = *srcLen; 475370b324cSopenharmony_ci *destLen = *srcLen = 0; 476370b324cSopenharmony_ci *status = LZMA_STATUS_NOT_SPECIFIED; 477370b324cSopenharmony_ci Lzma2Dec_CONSTRUCT(&p) 478370b324cSopenharmony_ci RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc)) 479370b324cSopenharmony_ci p.decoder.dic = dest; 480370b324cSopenharmony_ci p.decoder.dicBufSize = outSize; 481370b324cSopenharmony_ci Lzma2Dec_Init(&p); 482370b324cSopenharmony_ci *srcLen = inSize; 483370b324cSopenharmony_ci res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); 484370b324cSopenharmony_ci *destLen = p.decoder.dicPos; 485370b324cSopenharmony_ci if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) 486370b324cSopenharmony_ci res = SZ_ERROR_INPUT_EOF; 487370b324cSopenharmony_ci Lzma2Dec_FreeProbs(&p, alloc); 488370b324cSopenharmony_ci return res; 489370b324cSopenharmony_ci} 490370b324cSopenharmony_ci 491370b324cSopenharmony_ci#undef PRF 492