178acc472SPeter Tyser /* LzmaDec.c -- LZMA Decoder 2*5fe8380dSStefan Reinauer 2009-09-20 : Igor Pavlov : Public domain */ 378acc472SPeter Tyser 478acc472SPeter Tyser #include <config.h> 578acc472SPeter Tyser #include <common.h> 678acc472SPeter Tyser #include <watchdog.h> 778acc472SPeter Tyser #include "LzmaDec.h" 878acc472SPeter Tyser 978acc472SPeter Tyser #include <linux/string.h> 1078acc472SPeter Tyser 1178acc472SPeter Tyser #define kNumTopBits 24 1278acc472SPeter Tyser #define kTopValue ((UInt32)1 << kNumTopBits) 1378acc472SPeter Tyser 1478acc472SPeter Tyser #define kNumBitModelTotalBits 11 1578acc472SPeter Tyser #define kBitModelTotal (1 << kNumBitModelTotalBits) 1678acc472SPeter Tyser #define kNumMoveBits 5 1778acc472SPeter Tyser 1878acc472SPeter Tyser #define RC_INIT_SIZE 5 1978acc472SPeter Tyser 2078acc472SPeter Tyser #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } 2178acc472SPeter Tyser 2278acc472SPeter Tyser #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) 2378acc472SPeter Tyser #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); 2478acc472SPeter Tyser #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); 2578acc472SPeter Tyser #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ 2678acc472SPeter Tyser { UPDATE_0(p); i = (i + i); A0; } else \ 2778acc472SPeter Tyser { UPDATE_1(p); i = (i + i) + 1; A1; } 2878acc472SPeter Tyser #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) 2978acc472SPeter Tyser 3078acc472SPeter Tyser #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } 3178acc472SPeter Tyser #define TREE_DECODE(probs, limit, i) \ 3278acc472SPeter Tyser { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } 3378acc472SPeter Tyser 3478acc472SPeter Tyser /* #define _LZMA_SIZE_OPT */ 3578acc472SPeter Tyser 3678acc472SPeter Tyser #ifdef _LZMA_SIZE_OPT 3778acc472SPeter Tyser #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) 3878acc472SPeter Tyser #else 3978acc472SPeter Tyser #define TREE_6_DECODE(probs, i) \ 4078acc472SPeter Tyser { i = 1; \ 4178acc472SPeter Tyser TREE_GET_BIT(probs, i); \ 4278acc472SPeter Tyser TREE_GET_BIT(probs, i); \ 4378acc472SPeter Tyser TREE_GET_BIT(probs, i); \ 4478acc472SPeter Tyser TREE_GET_BIT(probs, i); \ 4578acc472SPeter Tyser TREE_GET_BIT(probs, i); \ 4678acc472SPeter Tyser TREE_GET_BIT(probs, i); \ 4778acc472SPeter Tyser i -= 0x40; } 4878acc472SPeter Tyser #endif 4978acc472SPeter Tyser 5078acc472SPeter Tyser #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } 5178acc472SPeter Tyser 5278acc472SPeter Tyser #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) 5378acc472SPeter Tyser #define UPDATE_0_CHECK range = bound; 5478acc472SPeter Tyser #define UPDATE_1_CHECK range -= bound; code -= bound; 5578acc472SPeter Tyser #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ 5678acc472SPeter Tyser { UPDATE_0_CHECK; i = (i + i); A0; } else \ 5778acc472SPeter Tyser { UPDATE_1_CHECK; i = (i + i) + 1; A1; } 5878acc472SPeter Tyser #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) 5978acc472SPeter Tyser #define TREE_DECODE_CHECK(probs, limit, i) \ 6078acc472SPeter Tyser { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } 6178acc472SPeter Tyser 6278acc472SPeter Tyser 6378acc472SPeter Tyser #define kNumPosBitsMax 4 6478acc472SPeter Tyser #define kNumPosStatesMax (1 << kNumPosBitsMax) 6578acc472SPeter Tyser 6678acc472SPeter Tyser #define kLenNumLowBits 3 6778acc472SPeter Tyser #define kLenNumLowSymbols (1 << kLenNumLowBits) 6878acc472SPeter Tyser #define kLenNumMidBits 3 6978acc472SPeter Tyser #define kLenNumMidSymbols (1 << kLenNumMidBits) 7078acc472SPeter Tyser #define kLenNumHighBits 8 7178acc472SPeter Tyser #define kLenNumHighSymbols (1 << kLenNumHighBits) 7278acc472SPeter Tyser 7378acc472SPeter Tyser #define LenChoice 0 7478acc472SPeter Tyser #define LenChoice2 (LenChoice + 1) 7578acc472SPeter Tyser #define LenLow (LenChoice2 + 1) 7678acc472SPeter Tyser #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) 7778acc472SPeter Tyser #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) 7878acc472SPeter Tyser #define kNumLenProbs (LenHigh + kLenNumHighSymbols) 7978acc472SPeter Tyser 8078acc472SPeter Tyser 8178acc472SPeter Tyser #define kNumStates 12 8278acc472SPeter Tyser #define kNumLitStates 7 8378acc472SPeter Tyser 8478acc472SPeter Tyser #define kStartPosModelIndex 4 8578acc472SPeter Tyser #define kEndPosModelIndex 14 8678acc472SPeter Tyser #define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) 8778acc472SPeter Tyser 8878acc472SPeter Tyser #define kNumPosSlotBits 6 8978acc472SPeter Tyser #define kNumLenToPosStates 4 9078acc472SPeter Tyser 9178acc472SPeter Tyser #define kNumAlignBits 4 9278acc472SPeter Tyser #define kAlignTableSize (1 << kNumAlignBits) 9378acc472SPeter Tyser 9478acc472SPeter Tyser #define kMatchMinLen 2 9578acc472SPeter Tyser #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) 9678acc472SPeter Tyser 9778acc472SPeter Tyser #define IsMatch 0 9878acc472SPeter Tyser #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) 9978acc472SPeter Tyser #define IsRepG0 (IsRep + kNumStates) 10078acc472SPeter Tyser #define IsRepG1 (IsRepG0 + kNumStates) 10178acc472SPeter Tyser #define IsRepG2 (IsRepG1 + kNumStates) 10278acc472SPeter Tyser #define IsRep0Long (IsRepG2 + kNumStates) 10378acc472SPeter Tyser #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) 10478acc472SPeter Tyser #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) 10578acc472SPeter Tyser #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) 10678acc472SPeter Tyser #define LenCoder (Align + kAlignTableSize) 10778acc472SPeter Tyser #define RepLenCoder (LenCoder + kNumLenProbs) 10878acc472SPeter Tyser #define Literal (RepLenCoder + kNumLenProbs) 10978acc472SPeter Tyser 11078acc472SPeter Tyser #define LZMA_BASE_SIZE 1846 11178acc472SPeter Tyser #define LZMA_LIT_SIZE 768 11278acc472SPeter Tyser 11378acc472SPeter Tyser #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) 11478acc472SPeter Tyser 11578acc472SPeter Tyser #if Literal != LZMA_BASE_SIZE 11678acc472SPeter Tyser StopCompilingDueBUG 11778acc472SPeter Tyser #endif 11878acc472SPeter Tyser 11978acc472SPeter Tyser #define LZMA_DIC_MIN (1 << 12) 12078acc472SPeter Tyser 12178acc472SPeter Tyser /* First LZMA-symbol is always decoded. 12278acc472SPeter Tyser And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization 12378acc472SPeter Tyser Out: 12478acc472SPeter Tyser Result: 12578acc472SPeter Tyser SZ_OK - OK 12678acc472SPeter Tyser SZ_ERROR_DATA - Error 12778acc472SPeter Tyser p->remainLen: 12878acc472SPeter Tyser < kMatchSpecLenStart : normal remain 12978acc472SPeter Tyser = kMatchSpecLenStart : finished 13078acc472SPeter Tyser = kMatchSpecLenStart + 1 : Flush marker 13178acc472SPeter Tyser = kMatchSpecLenStart + 2 : State Init Marker 13278acc472SPeter Tyser */ 13378acc472SPeter Tyser 13478acc472SPeter Tyser static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) 13578acc472SPeter Tyser { 13678acc472SPeter Tyser CLzmaProb *probs = p->probs; 13778acc472SPeter Tyser 13878acc472SPeter Tyser unsigned state = p->state; 13978acc472SPeter Tyser UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; 14078acc472SPeter Tyser unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; 14178acc472SPeter Tyser unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; 14278acc472SPeter Tyser unsigned lc = p->prop.lc; 14378acc472SPeter Tyser 14478acc472SPeter Tyser Byte *dic = p->dic; 14578acc472SPeter Tyser SizeT dicBufSize = p->dicBufSize; 14678acc472SPeter Tyser SizeT dicPos = p->dicPos; 14778acc472SPeter Tyser 14878acc472SPeter Tyser UInt32 processedPos = p->processedPos; 14978acc472SPeter Tyser UInt32 checkDicSize = p->checkDicSize; 15078acc472SPeter Tyser unsigned len = 0; 15178acc472SPeter Tyser 15278acc472SPeter Tyser const Byte *buf = p->buf; 15378acc472SPeter Tyser UInt32 range = p->range; 15478acc472SPeter Tyser UInt32 code = p->code; 15578acc472SPeter Tyser 15678acc472SPeter Tyser WATCHDOG_RESET(); 15778acc472SPeter Tyser 15878acc472SPeter Tyser do 15978acc472SPeter Tyser { 16078acc472SPeter Tyser CLzmaProb *prob; 16178acc472SPeter Tyser UInt32 bound; 16278acc472SPeter Tyser unsigned ttt; 16378acc472SPeter Tyser unsigned posState = processedPos & pbMask; 16478acc472SPeter Tyser 16578acc472SPeter Tyser prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; 16678acc472SPeter Tyser IF_BIT_0(prob) 16778acc472SPeter Tyser { 16878acc472SPeter Tyser unsigned symbol; 16978acc472SPeter Tyser UPDATE_0(prob); 17078acc472SPeter Tyser prob = probs + Literal; 17178acc472SPeter Tyser if (checkDicSize != 0 || processedPos != 0) 17278acc472SPeter Tyser prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + 17378acc472SPeter Tyser (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); 17478acc472SPeter Tyser 17578acc472SPeter Tyser if (state < kNumLitStates) 17678acc472SPeter Tyser { 177*5fe8380dSStefan Reinauer state -= (state < 4) ? state : 3; 17878acc472SPeter Tyser symbol = 1; 17978acc472SPeter Tyser 18078acc472SPeter Tyser WATCHDOG_RESET(); 18178acc472SPeter Tyser 18278acc472SPeter Tyser do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); 18378acc472SPeter Tyser } 18478acc472SPeter Tyser else 18578acc472SPeter Tyser { 18678acc472SPeter Tyser unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; 18778acc472SPeter Tyser unsigned offs = 0x100; 188*5fe8380dSStefan Reinauer state -= (state < 10) ? 3 : 6; 18978acc472SPeter Tyser symbol = 1; 19078acc472SPeter Tyser 19178acc472SPeter Tyser WATCHDOG_RESET(); 19278acc472SPeter Tyser 19378acc472SPeter Tyser do 19478acc472SPeter Tyser { 19578acc472SPeter Tyser unsigned bit; 19678acc472SPeter Tyser CLzmaProb *probLit; 19778acc472SPeter Tyser matchByte <<= 1; 19878acc472SPeter Tyser bit = (matchByte & offs); 19978acc472SPeter Tyser probLit = prob + offs + bit + symbol; 20078acc472SPeter Tyser GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) 20178acc472SPeter Tyser } 20278acc472SPeter Tyser while (symbol < 0x100); 20378acc472SPeter Tyser } 20478acc472SPeter Tyser dic[dicPos++] = (Byte)symbol; 20578acc472SPeter Tyser processedPos++; 20678acc472SPeter Tyser continue; 20778acc472SPeter Tyser } 20878acc472SPeter Tyser else 20978acc472SPeter Tyser { 21078acc472SPeter Tyser UPDATE_1(prob); 21178acc472SPeter Tyser prob = probs + IsRep + state; 21278acc472SPeter Tyser IF_BIT_0(prob) 21378acc472SPeter Tyser { 21478acc472SPeter Tyser UPDATE_0(prob); 21578acc472SPeter Tyser state += kNumStates; 21678acc472SPeter Tyser prob = probs + LenCoder; 21778acc472SPeter Tyser } 21878acc472SPeter Tyser else 21978acc472SPeter Tyser { 22078acc472SPeter Tyser UPDATE_1(prob); 22178acc472SPeter Tyser if (checkDicSize == 0 && processedPos == 0) 22278acc472SPeter Tyser return SZ_ERROR_DATA; 22378acc472SPeter Tyser prob = probs + IsRepG0 + state; 22478acc472SPeter Tyser IF_BIT_0(prob) 22578acc472SPeter Tyser { 22678acc472SPeter Tyser UPDATE_0(prob); 22778acc472SPeter Tyser prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; 22878acc472SPeter Tyser IF_BIT_0(prob) 22978acc472SPeter Tyser { 23078acc472SPeter Tyser UPDATE_0(prob); 23178acc472SPeter Tyser dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; 23278acc472SPeter Tyser dicPos++; 23378acc472SPeter Tyser processedPos++; 23478acc472SPeter Tyser state = state < kNumLitStates ? 9 : 11; 23578acc472SPeter Tyser continue; 23678acc472SPeter Tyser } 23778acc472SPeter Tyser UPDATE_1(prob); 23878acc472SPeter Tyser } 23978acc472SPeter Tyser else 24078acc472SPeter Tyser { 24178acc472SPeter Tyser UInt32 distance; 24278acc472SPeter Tyser UPDATE_1(prob); 24378acc472SPeter Tyser prob = probs + IsRepG1 + state; 24478acc472SPeter Tyser IF_BIT_0(prob) 24578acc472SPeter Tyser { 24678acc472SPeter Tyser UPDATE_0(prob); 24778acc472SPeter Tyser distance = rep1; 24878acc472SPeter Tyser } 24978acc472SPeter Tyser else 25078acc472SPeter Tyser { 25178acc472SPeter Tyser UPDATE_1(prob); 25278acc472SPeter Tyser prob = probs + IsRepG2 + state; 25378acc472SPeter Tyser IF_BIT_0(prob) 25478acc472SPeter Tyser { 25578acc472SPeter Tyser UPDATE_0(prob); 25678acc472SPeter Tyser distance = rep2; 25778acc472SPeter Tyser } 25878acc472SPeter Tyser else 25978acc472SPeter Tyser { 26078acc472SPeter Tyser UPDATE_1(prob); 26178acc472SPeter Tyser distance = rep3; 26278acc472SPeter Tyser rep3 = rep2; 26378acc472SPeter Tyser } 26478acc472SPeter Tyser rep2 = rep1; 26578acc472SPeter Tyser } 26678acc472SPeter Tyser rep1 = rep0; 26778acc472SPeter Tyser rep0 = distance; 26878acc472SPeter Tyser } 26978acc472SPeter Tyser state = state < kNumLitStates ? 8 : 11; 27078acc472SPeter Tyser prob = probs + RepLenCoder; 27178acc472SPeter Tyser } 27278acc472SPeter Tyser { 27378acc472SPeter Tyser unsigned limit, offset; 27478acc472SPeter Tyser CLzmaProb *probLen = prob + LenChoice; 27578acc472SPeter Tyser IF_BIT_0(probLen) 27678acc472SPeter Tyser { 27778acc472SPeter Tyser UPDATE_0(probLen); 27878acc472SPeter Tyser probLen = prob + LenLow + (posState << kLenNumLowBits); 27978acc472SPeter Tyser offset = 0; 28078acc472SPeter Tyser limit = (1 << kLenNumLowBits); 28178acc472SPeter Tyser } 28278acc472SPeter Tyser else 28378acc472SPeter Tyser { 28478acc472SPeter Tyser UPDATE_1(probLen); 28578acc472SPeter Tyser probLen = prob + LenChoice2; 28678acc472SPeter Tyser IF_BIT_0(probLen) 28778acc472SPeter Tyser { 28878acc472SPeter Tyser UPDATE_0(probLen); 28978acc472SPeter Tyser probLen = prob + LenMid + (posState << kLenNumMidBits); 29078acc472SPeter Tyser offset = kLenNumLowSymbols; 29178acc472SPeter Tyser limit = (1 << kLenNumMidBits); 29278acc472SPeter Tyser } 29378acc472SPeter Tyser else 29478acc472SPeter Tyser { 29578acc472SPeter Tyser UPDATE_1(probLen); 29678acc472SPeter Tyser probLen = prob + LenHigh; 29778acc472SPeter Tyser offset = kLenNumLowSymbols + kLenNumMidSymbols; 29878acc472SPeter Tyser limit = (1 << kLenNumHighBits); 29978acc472SPeter Tyser } 30078acc472SPeter Tyser } 30178acc472SPeter Tyser TREE_DECODE(probLen, limit, len); 30278acc472SPeter Tyser len += offset; 30378acc472SPeter Tyser } 30478acc472SPeter Tyser 30578acc472SPeter Tyser if (state >= kNumStates) 30678acc472SPeter Tyser { 30778acc472SPeter Tyser UInt32 distance; 30878acc472SPeter Tyser prob = probs + PosSlot + 30978acc472SPeter Tyser ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); 31078acc472SPeter Tyser TREE_6_DECODE(prob, distance); 31178acc472SPeter Tyser if (distance >= kStartPosModelIndex) 31278acc472SPeter Tyser { 31378acc472SPeter Tyser unsigned posSlot = (unsigned)distance; 31478acc472SPeter Tyser int numDirectBits = (int)(((distance >> 1) - 1)); 31578acc472SPeter Tyser distance = (2 | (distance & 1)); 31678acc472SPeter Tyser if (posSlot < kEndPosModelIndex) 31778acc472SPeter Tyser { 31878acc472SPeter Tyser distance <<= numDirectBits; 31978acc472SPeter Tyser prob = probs + SpecPos + distance - posSlot - 1; 32078acc472SPeter Tyser { 32178acc472SPeter Tyser UInt32 mask = 1; 32278acc472SPeter Tyser unsigned i = 1; 32378acc472SPeter Tyser 32478acc472SPeter Tyser WATCHDOG_RESET(); 32578acc472SPeter Tyser 32678acc472SPeter Tyser do 32778acc472SPeter Tyser { 32878acc472SPeter Tyser GET_BIT2(prob + i, i, ; , distance |= mask); 32978acc472SPeter Tyser mask <<= 1; 33078acc472SPeter Tyser } 33178acc472SPeter Tyser while (--numDirectBits != 0); 33278acc472SPeter Tyser } 33378acc472SPeter Tyser } 33478acc472SPeter Tyser else 33578acc472SPeter Tyser { 33678acc472SPeter Tyser numDirectBits -= kNumAlignBits; 33778acc472SPeter Tyser 33878acc472SPeter Tyser WATCHDOG_RESET(); 33978acc472SPeter Tyser 34078acc472SPeter Tyser do 34178acc472SPeter Tyser { 34278acc472SPeter Tyser NORMALIZE 34378acc472SPeter Tyser range >>= 1; 34478acc472SPeter Tyser 34578acc472SPeter Tyser { 34678acc472SPeter Tyser UInt32 t; 34778acc472SPeter Tyser code -= range; 34878acc472SPeter Tyser t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ 34978acc472SPeter Tyser distance = (distance << 1) + (t + 1); 35078acc472SPeter Tyser code += range & t; 35178acc472SPeter Tyser } 35278acc472SPeter Tyser /* 35378acc472SPeter Tyser distance <<= 1; 35478acc472SPeter Tyser if (code >= range) 35578acc472SPeter Tyser { 35678acc472SPeter Tyser code -= range; 35778acc472SPeter Tyser distance |= 1; 35878acc472SPeter Tyser } 35978acc472SPeter Tyser */ 36078acc472SPeter Tyser } 36178acc472SPeter Tyser while (--numDirectBits != 0); 36278acc472SPeter Tyser prob = probs + Align; 36378acc472SPeter Tyser distance <<= kNumAlignBits; 36478acc472SPeter Tyser { 36578acc472SPeter Tyser unsigned i = 1; 36678acc472SPeter Tyser GET_BIT2(prob + i, i, ; , distance |= 1); 36778acc472SPeter Tyser GET_BIT2(prob + i, i, ; , distance |= 2); 36878acc472SPeter Tyser GET_BIT2(prob + i, i, ; , distance |= 4); 36978acc472SPeter Tyser GET_BIT2(prob + i, i, ; , distance |= 8); 37078acc472SPeter Tyser } 37178acc472SPeter Tyser if (distance == (UInt32)0xFFFFFFFF) 37278acc472SPeter Tyser { 37378acc472SPeter Tyser len += kMatchSpecLenStart; 37478acc472SPeter Tyser state -= kNumStates; 37578acc472SPeter Tyser break; 37678acc472SPeter Tyser } 37778acc472SPeter Tyser } 37878acc472SPeter Tyser } 37978acc472SPeter Tyser rep3 = rep2; 38078acc472SPeter Tyser rep2 = rep1; 38178acc472SPeter Tyser rep1 = rep0; 38278acc472SPeter Tyser rep0 = distance + 1; 38378acc472SPeter Tyser if (checkDicSize == 0) 38478acc472SPeter Tyser { 38578acc472SPeter Tyser if (distance >= processedPos) 38678acc472SPeter Tyser return SZ_ERROR_DATA; 38778acc472SPeter Tyser } 38878acc472SPeter Tyser else if (distance >= checkDicSize) 38978acc472SPeter Tyser return SZ_ERROR_DATA; 39078acc472SPeter Tyser state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; 39178acc472SPeter Tyser } 39278acc472SPeter Tyser 39378acc472SPeter Tyser len += kMatchMinLen; 39478acc472SPeter Tyser 39578acc472SPeter Tyser if (limit == dicPos) 39678acc472SPeter Tyser return SZ_ERROR_DATA; 39778acc472SPeter Tyser { 39878acc472SPeter Tyser SizeT rem = limit - dicPos; 39978acc472SPeter Tyser unsigned curLen = ((rem < len) ? (unsigned)rem : len); 40078acc472SPeter Tyser SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); 40178acc472SPeter Tyser 40278acc472SPeter Tyser processedPos += curLen; 40378acc472SPeter Tyser 40478acc472SPeter Tyser len -= curLen; 40578acc472SPeter Tyser if (pos + curLen <= dicBufSize) 40678acc472SPeter Tyser { 40778acc472SPeter Tyser Byte *dest = dic + dicPos; 40878acc472SPeter Tyser ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; 40978acc472SPeter Tyser const Byte *lim = dest + curLen; 41078acc472SPeter Tyser dicPos += curLen; 41178acc472SPeter Tyser 41278acc472SPeter Tyser WATCHDOG_RESET(); 41378acc472SPeter Tyser 41478acc472SPeter Tyser do 41578acc472SPeter Tyser *(dest) = (Byte)*(dest + src); 41678acc472SPeter Tyser while (++dest != lim); 41778acc472SPeter Tyser } 41878acc472SPeter Tyser else 41978acc472SPeter Tyser { 42078acc472SPeter Tyser 42178acc472SPeter Tyser WATCHDOG_RESET(); 42278acc472SPeter Tyser 42378acc472SPeter Tyser do 42478acc472SPeter Tyser { 42578acc472SPeter Tyser dic[dicPos++] = dic[pos]; 42678acc472SPeter Tyser if (++pos == dicBufSize) 42778acc472SPeter Tyser pos = 0; 42878acc472SPeter Tyser } 42978acc472SPeter Tyser while (--curLen != 0); 43078acc472SPeter Tyser } 43178acc472SPeter Tyser } 43278acc472SPeter Tyser } 43378acc472SPeter Tyser } 43478acc472SPeter Tyser while (dicPos < limit && buf < bufLimit); 43578acc472SPeter Tyser 43678acc472SPeter Tyser WATCHDOG_RESET(); 43778acc472SPeter Tyser 43878acc472SPeter Tyser NORMALIZE; 43978acc472SPeter Tyser p->buf = buf; 44078acc472SPeter Tyser p->range = range; 44178acc472SPeter Tyser p->code = code; 44278acc472SPeter Tyser p->remainLen = len; 44378acc472SPeter Tyser p->dicPos = dicPos; 44478acc472SPeter Tyser p->processedPos = processedPos; 44578acc472SPeter Tyser p->reps[0] = rep0; 44678acc472SPeter Tyser p->reps[1] = rep1; 44778acc472SPeter Tyser p->reps[2] = rep2; 44878acc472SPeter Tyser p->reps[3] = rep3; 44978acc472SPeter Tyser p->state = state; 45078acc472SPeter Tyser 45178acc472SPeter Tyser return SZ_OK; 45278acc472SPeter Tyser } 45378acc472SPeter Tyser 45478acc472SPeter Tyser static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) 45578acc472SPeter Tyser { 45678acc472SPeter Tyser if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) 45778acc472SPeter Tyser { 45878acc472SPeter Tyser Byte *dic = p->dic; 45978acc472SPeter Tyser SizeT dicPos = p->dicPos; 46078acc472SPeter Tyser SizeT dicBufSize = p->dicBufSize; 46178acc472SPeter Tyser unsigned len = p->remainLen; 46278acc472SPeter Tyser UInt32 rep0 = p->reps[0]; 46378acc472SPeter Tyser if (limit - dicPos < len) 46478acc472SPeter Tyser len = (unsigned)(limit - dicPos); 46578acc472SPeter Tyser 46678acc472SPeter Tyser if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) 46778acc472SPeter Tyser p->checkDicSize = p->prop.dicSize; 46878acc472SPeter Tyser 46978acc472SPeter Tyser p->processedPos += len; 47078acc472SPeter Tyser p->remainLen -= len; 47178acc472SPeter Tyser while (len-- != 0) 47278acc472SPeter Tyser { 47378acc472SPeter Tyser dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; 47478acc472SPeter Tyser dicPos++; 47578acc472SPeter Tyser } 47678acc472SPeter Tyser p->dicPos = dicPos; 47778acc472SPeter Tyser } 47878acc472SPeter Tyser } 47978acc472SPeter Tyser 48078acc472SPeter Tyser static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) 48178acc472SPeter Tyser { 48278acc472SPeter Tyser do 48378acc472SPeter Tyser { 48478acc472SPeter Tyser SizeT limit2 = limit; 48578acc472SPeter Tyser if (p->checkDicSize == 0) 48678acc472SPeter Tyser { 48778acc472SPeter Tyser UInt32 rem = p->prop.dicSize - p->processedPos; 48878acc472SPeter Tyser if (limit - p->dicPos > rem) 48978acc472SPeter Tyser limit2 = p->dicPos + rem; 49078acc472SPeter Tyser } 49178acc472SPeter Tyser RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); 49278acc472SPeter Tyser if (p->processedPos >= p->prop.dicSize) 49378acc472SPeter Tyser p->checkDicSize = p->prop.dicSize; 49478acc472SPeter Tyser LzmaDec_WriteRem(p, limit); 49578acc472SPeter Tyser } 49678acc472SPeter Tyser while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); 49778acc472SPeter Tyser 49878acc472SPeter Tyser if (p->remainLen > kMatchSpecLenStart) 49978acc472SPeter Tyser { 50078acc472SPeter Tyser p->remainLen = kMatchSpecLenStart; 50178acc472SPeter Tyser } 50278acc472SPeter Tyser return 0; 50378acc472SPeter Tyser } 50478acc472SPeter Tyser 50578acc472SPeter Tyser typedef enum 50678acc472SPeter Tyser { 50778acc472SPeter Tyser DUMMY_ERROR, /* unexpected end of input stream */ 50878acc472SPeter Tyser DUMMY_LIT, 50978acc472SPeter Tyser DUMMY_MATCH, 51078acc472SPeter Tyser DUMMY_REP 51178acc472SPeter Tyser } ELzmaDummy; 51278acc472SPeter Tyser 51378acc472SPeter Tyser static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) 51478acc472SPeter Tyser { 51578acc472SPeter Tyser UInt32 range = p->range; 51678acc472SPeter Tyser UInt32 code = p->code; 51778acc472SPeter Tyser const Byte *bufLimit = buf + inSize; 51878acc472SPeter Tyser CLzmaProb *probs = p->probs; 51978acc472SPeter Tyser unsigned state = p->state; 52078acc472SPeter Tyser ELzmaDummy res; 52178acc472SPeter Tyser 52278acc472SPeter Tyser { 52378acc472SPeter Tyser CLzmaProb *prob; 52478acc472SPeter Tyser UInt32 bound; 52578acc472SPeter Tyser unsigned ttt; 52678acc472SPeter Tyser unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); 52778acc472SPeter Tyser 52878acc472SPeter Tyser prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; 52978acc472SPeter Tyser IF_BIT_0_CHECK(prob) 53078acc472SPeter Tyser { 53178acc472SPeter Tyser UPDATE_0_CHECK 53278acc472SPeter Tyser 53378acc472SPeter Tyser /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ 53478acc472SPeter Tyser 53578acc472SPeter Tyser prob = probs + Literal; 53678acc472SPeter Tyser if (p->checkDicSize != 0 || p->processedPos != 0) 53778acc472SPeter Tyser prob += (LZMA_LIT_SIZE * 53878acc472SPeter Tyser ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + 53978acc472SPeter Tyser (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); 54078acc472SPeter Tyser 54178acc472SPeter Tyser if (state < kNumLitStates) 54278acc472SPeter Tyser { 54378acc472SPeter Tyser unsigned symbol = 1; 54478acc472SPeter Tyser do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); 54578acc472SPeter Tyser } 54678acc472SPeter Tyser else 54778acc472SPeter Tyser { 54878acc472SPeter Tyser unsigned matchByte = p->dic[p->dicPos - p->reps[0] + 54978acc472SPeter Tyser ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; 55078acc472SPeter Tyser unsigned offs = 0x100; 55178acc472SPeter Tyser unsigned symbol = 1; 55278acc472SPeter Tyser do 55378acc472SPeter Tyser { 55478acc472SPeter Tyser unsigned bit; 55578acc472SPeter Tyser CLzmaProb *probLit; 55678acc472SPeter Tyser matchByte <<= 1; 55778acc472SPeter Tyser bit = (matchByte & offs); 55878acc472SPeter Tyser probLit = prob + offs + bit + symbol; 55978acc472SPeter Tyser GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) 56078acc472SPeter Tyser } 56178acc472SPeter Tyser while (symbol < 0x100); 56278acc472SPeter Tyser } 56378acc472SPeter Tyser res = DUMMY_LIT; 56478acc472SPeter Tyser } 56578acc472SPeter Tyser else 56678acc472SPeter Tyser { 56778acc472SPeter Tyser unsigned len; 56878acc472SPeter Tyser UPDATE_1_CHECK; 56978acc472SPeter Tyser 57078acc472SPeter Tyser prob = probs + IsRep + state; 57178acc472SPeter Tyser IF_BIT_0_CHECK(prob) 57278acc472SPeter Tyser { 57378acc472SPeter Tyser UPDATE_0_CHECK; 57478acc472SPeter Tyser state = 0; 57578acc472SPeter Tyser prob = probs + LenCoder; 57678acc472SPeter Tyser res = DUMMY_MATCH; 57778acc472SPeter Tyser } 57878acc472SPeter Tyser else 57978acc472SPeter Tyser { 58078acc472SPeter Tyser UPDATE_1_CHECK; 58178acc472SPeter Tyser res = DUMMY_REP; 58278acc472SPeter Tyser prob = probs + IsRepG0 + state; 58378acc472SPeter Tyser IF_BIT_0_CHECK(prob) 58478acc472SPeter Tyser { 58578acc472SPeter Tyser UPDATE_0_CHECK; 58678acc472SPeter Tyser prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; 58778acc472SPeter Tyser IF_BIT_0_CHECK(prob) 58878acc472SPeter Tyser { 58978acc472SPeter Tyser UPDATE_0_CHECK; 59078acc472SPeter Tyser NORMALIZE_CHECK; 59178acc472SPeter Tyser return DUMMY_REP; 59278acc472SPeter Tyser } 59378acc472SPeter Tyser else 59478acc472SPeter Tyser { 59578acc472SPeter Tyser UPDATE_1_CHECK; 59678acc472SPeter Tyser } 59778acc472SPeter Tyser } 59878acc472SPeter Tyser else 59978acc472SPeter Tyser { 60078acc472SPeter Tyser UPDATE_1_CHECK; 60178acc472SPeter Tyser prob = probs + IsRepG1 + state; 60278acc472SPeter Tyser IF_BIT_0_CHECK(prob) 60378acc472SPeter Tyser { 60478acc472SPeter Tyser UPDATE_0_CHECK; 60578acc472SPeter Tyser } 60678acc472SPeter Tyser else 60778acc472SPeter Tyser { 60878acc472SPeter Tyser UPDATE_1_CHECK; 60978acc472SPeter Tyser prob = probs + IsRepG2 + state; 61078acc472SPeter Tyser IF_BIT_0_CHECK(prob) 61178acc472SPeter Tyser { 61278acc472SPeter Tyser UPDATE_0_CHECK; 61378acc472SPeter Tyser } 61478acc472SPeter Tyser else 61578acc472SPeter Tyser { 61678acc472SPeter Tyser UPDATE_1_CHECK; 61778acc472SPeter Tyser } 61878acc472SPeter Tyser } 61978acc472SPeter Tyser } 62078acc472SPeter Tyser state = kNumStates; 62178acc472SPeter Tyser prob = probs + RepLenCoder; 62278acc472SPeter Tyser } 62378acc472SPeter Tyser { 62478acc472SPeter Tyser unsigned limit, offset; 62578acc472SPeter Tyser CLzmaProb *probLen = prob + LenChoice; 62678acc472SPeter Tyser IF_BIT_0_CHECK(probLen) 62778acc472SPeter Tyser { 62878acc472SPeter Tyser UPDATE_0_CHECK; 62978acc472SPeter Tyser probLen = prob + LenLow + (posState << kLenNumLowBits); 63078acc472SPeter Tyser offset = 0; 63178acc472SPeter Tyser limit = 1 << kLenNumLowBits; 63278acc472SPeter Tyser } 63378acc472SPeter Tyser else 63478acc472SPeter Tyser { 63578acc472SPeter Tyser UPDATE_1_CHECK; 63678acc472SPeter Tyser probLen = prob + LenChoice2; 63778acc472SPeter Tyser IF_BIT_0_CHECK(probLen) 63878acc472SPeter Tyser { 63978acc472SPeter Tyser UPDATE_0_CHECK; 64078acc472SPeter Tyser probLen = prob + LenMid + (posState << kLenNumMidBits); 64178acc472SPeter Tyser offset = kLenNumLowSymbols; 64278acc472SPeter Tyser limit = 1 << kLenNumMidBits; 64378acc472SPeter Tyser } 64478acc472SPeter Tyser else 64578acc472SPeter Tyser { 64678acc472SPeter Tyser UPDATE_1_CHECK; 64778acc472SPeter Tyser probLen = prob + LenHigh; 64878acc472SPeter Tyser offset = kLenNumLowSymbols + kLenNumMidSymbols; 64978acc472SPeter Tyser limit = 1 << kLenNumHighBits; 65078acc472SPeter Tyser } 65178acc472SPeter Tyser } 65278acc472SPeter Tyser TREE_DECODE_CHECK(probLen, limit, len); 65378acc472SPeter Tyser len += offset; 65478acc472SPeter Tyser } 65578acc472SPeter Tyser 65678acc472SPeter Tyser if (state < 4) 65778acc472SPeter Tyser { 65878acc472SPeter Tyser unsigned posSlot; 65978acc472SPeter Tyser prob = probs + PosSlot + 66078acc472SPeter Tyser ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 66178acc472SPeter Tyser kNumPosSlotBits); 66278acc472SPeter Tyser TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); 66378acc472SPeter Tyser if (posSlot >= kStartPosModelIndex) 66478acc472SPeter Tyser { 66578acc472SPeter Tyser int numDirectBits = ((posSlot >> 1) - 1); 66678acc472SPeter Tyser 66778acc472SPeter Tyser /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ 66878acc472SPeter Tyser 66978acc472SPeter Tyser if (posSlot < kEndPosModelIndex) 67078acc472SPeter Tyser { 67178acc472SPeter Tyser prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; 67278acc472SPeter Tyser } 67378acc472SPeter Tyser else 67478acc472SPeter Tyser { 67578acc472SPeter Tyser numDirectBits -= kNumAlignBits; 67678acc472SPeter Tyser do 67778acc472SPeter Tyser { 67878acc472SPeter Tyser NORMALIZE_CHECK 67978acc472SPeter Tyser range >>= 1; 68078acc472SPeter Tyser code -= range & (((code - range) >> 31) - 1); 68178acc472SPeter Tyser /* if (code >= range) code -= range; */ 68278acc472SPeter Tyser } 68378acc472SPeter Tyser while (--numDirectBits != 0); 68478acc472SPeter Tyser prob = probs + Align; 68578acc472SPeter Tyser numDirectBits = kNumAlignBits; 68678acc472SPeter Tyser } 68778acc472SPeter Tyser { 68878acc472SPeter Tyser unsigned i = 1; 68978acc472SPeter Tyser do 69078acc472SPeter Tyser { 69178acc472SPeter Tyser GET_BIT_CHECK(prob + i, i); 69278acc472SPeter Tyser } 69378acc472SPeter Tyser while (--numDirectBits != 0); 69478acc472SPeter Tyser } 69578acc472SPeter Tyser } 69678acc472SPeter Tyser } 69778acc472SPeter Tyser } 69878acc472SPeter Tyser } 69978acc472SPeter Tyser NORMALIZE_CHECK; 70078acc472SPeter Tyser return res; 70178acc472SPeter Tyser } 70278acc472SPeter Tyser 70378acc472SPeter Tyser 70478acc472SPeter Tyser static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) 70578acc472SPeter Tyser { 70678acc472SPeter Tyser p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); 70778acc472SPeter Tyser p->range = 0xFFFFFFFF; 70878acc472SPeter Tyser p->needFlush = 0; 70978acc472SPeter Tyser } 71078acc472SPeter Tyser 71178acc472SPeter Tyser void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) 71278acc472SPeter Tyser { 71378acc472SPeter Tyser p->needFlush = 1; 71478acc472SPeter Tyser p->remainLen = 0; 71578acc472SPeter Tyser p->tempBufSize = 0; 71678acc472SPeter Tyser 71778acc472SPeter Tyser if (initDic) 71878acc472SPeter Tyser { 71978acc472SPeter Tyser p->processedPos = 0; 72078acc472SPeter Tyser p->checkDicSize = 0; 72178acc472SPeter Tyser p->needInitState = 1; 72278acc472SPeter Tyser } 72378acc472SPeter Tyser if (initState) 72478acc472SPeter Tyser p->needInitState = 1; 72578acc472SPeter Tyser } 72678acc472SPeter Tyser 72778acc472SPeter Tyser void LzmaDec_Init(CLzmaDec *p) 72878acc472SPeter Tyser { 72978acc472SPeter Tyser p->dicPos = 0; 73078acc472SPeter Tyser LzmaDec_InitDicAndState(p, True, True); 73178acc472SPeter Tyser } 73278acc472SPeter Tyser 73378acc472SPeter Tyser static void LzmaDec_InitStateReal(CLzmaDec *p) 73478acc472SPeter Tyser { 73578acc472SPeter Tyser UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); 73678acc472SPeter Tyser UInt32 i; 73778acc472SPeter Tyser CLzmaProb *probs = p->probs; 73878acc472SPeter Tyser for (i = 0; i < numProbs; i++) 73978acc472SPeter Tyser probs[i] = kBitModelTotal >> 1; 74078acc472SPeter Tyser p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; 74178acc472SPeter Tyser p->state = 0; 74278acc472SPeter Tyser p->needInitState = 0; 74378acc472SPeter Tyser } 74478acc472SPeter Tyser 74578acc472SPeter Tyser SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, 74678acc472SPeter Tyser ELzmaFinishMode finishMode, ELzmaStatus *status) 74778acc472SPeter Tyser { 74878acc472SPeter Tyser SizeT inSize = *srcLen; 74978acc472SPeter Tyser (*srcLen) = 0; 75078acc472SPeter Tyser LzmaDec_WriteRem(p, dicLimit); 75178acc472SPeter Tyser 75278acc472SPeter Tyser *status = LZMA_STATUS_NOT_SPECIFIED; 75378acc472SPeter Tyser 75478acc472SPeter Tyser while (p->remainLen != kMatchSpecLenStart) 75578acc472SPeter Tyser { 75678acc472SPeter Tyser int checkEndMarkNow; 75778acc472SPeter Tyser 75878acc472SPeter Tyser if (p->needFlush != 0) 75978acc472SPeter Tyser { 76078acc472SPeter Tyser for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) 76178acc472SPeter Tyser p->tempBuf[p->tempBufSize++] = *src++; 76278acc472SPeter Tyser if (p->tempBufSize < RC_INIT_SIZE) 76378acc472SPeter Tyser { 76478acc472SPeter Tyser *status = LZMA_STATUS_NEEDS_MORE_INPUT; 76578acc472SPeter Tyser return SZ_OK; 76678acc472SPeter Tyser } 76778acc472SPeter Tyser if (p->tempBuf[0] != 0) 76878acc472SPeter Tyser return SZ_ERROR_DATA; 76978acc472SPeter Tyser 77078acc472SPeter Tyser LzmaDec_InitRc(p, p->tempBuf); 77178acc472SPeter Tyser p->tempBufSize = 0; 77278acc472SPeter Tyser } 77378acc472SPeter Tyser 77478acc472SPeter Tyser checkEndMarkNow = 0; 77578acc472SPeter Tyser if (p->dicPos >= dicLimit) 77678acc472SPeter Tyser { 77778acc472SPeter Tyser if (p->remainLen == 0 && p->code == 0) 77878acc472SPeter Tyser { 77978acc472SPeter Tyser *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; 78078acc472SPeter Tyser return SZ_OK; 78178acc472SPeter Tyser } 78278acc472SPeter Tyser if (finishMode == LZMA_FINISH_ANY) 78378acc472SPeter Tyser { 78478acc472SPeter Tyser *status = LZMA_STATUS_NOT_FINISHED; 78578acc472SPeter Tyser return SZ_OK; 78678acc472SPeter Tyser } 78778acc472SPeter Tyser if (p->remainLen != 0) 78878acc472SPeter Tyser { 78978acc472SPeter Tyser *status = LZMA_STATUS_NOT_FINISHED; 79078acc472SPeter Tyser return SZ_ERROR_DATA; 79178acc472SPeter Tyser } 79278acc472SPeter Tyser checkEndMarkNow = 1; 79378acc472SPeter Tyser } 79478acc472SPeter Tyser 79578acc472SPeter Tyser if (p->needInitState) 79678acc472SPeter Tyser LzmaDec_InitStateReal(p); 79778acc472SPeter Tyser 79878acc472SPeter Tyser if (p->tempBufSize == 0) 79978acc472SPeter Tyser { 80078acc472SPeter Tyser SizeT processed; 80178acc472SPeter Tyser const Byte *bufLimit; 80278acc472SPeter Tyser if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) 80378acc472SPeter Tyser { 80478acc472SPeter Tyser int dummyRes = LzmaDec_TryDummy(p, src, inSize); 80578acc472SPeter Tyser if (dummyRes == DUMMY_ERROR) 80678acc472SPeter Tyser { 80778acc472SPeter Tyser memcpy(p->tempBuf, src, inSize); 80878acc472SPeter Tyser p->tempBufSize = (unsigned)inSize; 80978acc472SPeter Tyser (*srcLen) += inSize; 81078acc472SPeter Tyser *status = LZMA_STATUS_NEEDS_MORE_INPUT; 81178acc472SPeter Tyser return SZ_OK; 81278acc472SPeter Tyser } 81378acc472SPeter Tyser if (checkEndMarkNow && dummyRes != DUMMY_MATCH) 81478acc472SPeter Tyser { 81578acc472SPeter Tyser *status = LZMA_STATUS_NOT_FINISHED; 81678acc472SPeter Tyser return SZ_ERROR_DATA; 81778acc472SPeter Tyser } 81878acc472SPeter Tyser bufLimit = src; 81978acc472SPeter Tyser } 82078acc472SPeter Tyser else 82178acc472SPeter Tyser bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; 82278acc472SPeter Tyser p->buf = src; 82378acc472SPeter Tyser if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) 82478acc472SPeter Tyser return SZ_ERROR_DATA; 82578acc472SPeter Tyser processed = (SizeT)(p->buf - src); 82678acc472SPeter Tyser (*srcLen) += processed; 82778acc472SPeter Tyser src += processed; 82878acc472SPeter Tyser inSize -= processed; 82978acc472SPeter Tyser } 83078acc472SPeter Tyser else 83178acc472SPeter Tyser { 83278acc472SPeter Tyser unsigned rem = p->tempBufSize, lookAhead = 0; 83378acc472SPeter Tyser while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) 83478acc472SPeter Tyser p->tempBuf[rem++] = src[lookAhead++]; 83578acc472SPeter Tyser p->tempBufSize = rem; 83678acc472SPeter Tyser if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) 83778acc472SPeter Tyser { 83878acc472SPeter Tyser int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); 83978acc472SPeter Tyser if (dummyRes == DUMMY_ERROR) 84078acc472SPeter Tyser { 84178acc472SPeter Tyser (*srcLen) += lookAhead; 84278acc472SPeter Tyser *status = LZMA_STATUS_NEEDS_MORE_INPUT; 84378acc472SPeter Tyser return SZ_OK; 84478acc472SPeter Tyser } 84578acc472SPeter Tyser if (checkEndMarkNow && dummyRes != DUMMY_MATCH) 84678acc472SPeter Tyser { 84778acc472SPeter Tyser *status = LZMA_STATUS_NOT_FINISHED; 84878acc472SPeter Tyser return SZ_ERROR_DATA; 84978acc472SPeter Tyser } 85078acc472SPeter Tyser } 85178acc472SPeter Tyser p->buf = p->tempBuf; 85278acc472SPeter Tyser if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) 85378acc472SPeter Tyser return SZ_ERROR_DATA; 85478acc472SPeter Tyser lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); 85578acc472SPeter Tyser (*srcLen) += lookAhead; 85678acc472SPeter Tyser src += lookAhead; 85778acc472SPeter Tyser inSize -= lookAhead; 85878acc472SPeter Tyser p->tempBufSize = 0; 85978acc472SPeter Tyser } 86078acc472SPeter Tyser } 86178acc472SPeter Tyser if (p->code == 0) 86278acc472SPeter Tyser *status = LZMA_STATUS_FINISHED_WITH_MARK; 86378acc472SPeter Tyser return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; 86478acc472SPeter Tyser } 86578acc472SPeter Tyser 86678acc472SPeter Tyser SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) 86778acc472SPeter Tyser { 86878acc472SPeter Tyser SizeT outSize = *destLen; 86978acc472SPeter Tyser SizeT inSize = *srcLen; 87078acc472SPeter Tyser *srcLen = *destLen = 0; 87178acc472SPeter Tyser for (;;) 87278acc472SPeter Tyser { 87378acc472SPeter Tyser SizeT inSizeCur = inSize, outSizeCur, dicPos; 87478acc472SPeter Tyser ELzmaFinishMode curFinishMode; 87578acc472SPeter Tyser SRes res; 87678acc472SPeter Tyser if (p->dicPos == p->dicBufSize) 87778acc472SPeter Tyser p->dicPos = 0; 87878acc472SPeter Tyser dicPos = p->dicPos; 87978acc472SPeter Tyser if (outSize > p->dicBufSize - dicPos) 88078acc472SPeter Tyser { 88178acc472SPeter Tyser outSizeCur = p->dicBufSize; 88278acc472SPeter Tyser curFinishMode = LZMA_FINISH_ANY; 88378acc472SPeter Tyser } 88478acc472SPeter Tyser else 88578acc472SPeter Tyser { 88678acc472SPeter Tyser outSizeCur = dicPos + outSize; 88778acc472SPeter Tyser curFinishMode = finishMode; 88878acc472SPeter Tyser } 88978acc472SPeter Tyser 89078acc472SPeter Tyser res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); 89178acc472SPeter Tyser src += inSizeCur; 89278acc472SPeter Tyser inSize -= inSizeCur; 89378acc472SPeter Tyser *srcLen += inSizeCur; 89478acc472SPeter Tyser outSizeCur = p->dicPos - dicPos; 89578acc472SPeter Tyser memcpy(dest, p->dic + dicPos, outSizeCur); 89678acc472SPeter Tyser dest += outSizeCur; 89778acc472SPeter Tyser outSize -= outSizeCur; 89878acc472SPeter Tyser *destLen += outSizeCur; 89978acc472SPeter Tyser if (res != 0) 90078acc472SPeter Tyser return res; 90178acc472SPeter Tyser if (outSizeCur == 0 || outSize == 0) 90278acc472SPeter Tyser return SZ_OK; 90378acc472SPeter Tyser } 90478acc472SPeter Tyser } 90578acc472SPeter Tyser 90678acc472SPeter Tyser void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) 90778acc472SPeter Tyser { 90878acc472SPeter Tyser alloc->Free(alloc, p->probs); 90978acc472SPeter Tyser p->probs = 0; 91078acc472SPeter Tyser } 91178acc472SPeter Tyser 91278acc472SPeter Tyser static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) 91378acc472SPeter Tyser { 91478acc472SPeter Tyser alloc->Free(alloc, p->dic); 91578acc472SPeter Tyser p->dic = 0; 91678acc472SPeter Tyser } 91778acc472SPeter Tyser 91878acc472SPeter Tyser void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) 91978acc472SPeter Tyser { 92078acc472SPeter Tyser LzmaDec_FreeProbs(p, alloc); 92178acc472SPeter Tyser LzmaDec_FreeDict(p, alloc); 92278acc472SPeter Tyser } 92378acc472SPeter Tyser 92478acc472SPeter Tyser SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) 92578acc472SPeter Tyser { 92678acc472SPeter Tyser UInt32 dicSize; 92778acc472SPeter Tyser Byte d; 92878acc472SPeter Tyser 92978acc472SPeter Tyser if (size < LZMA_PROPS_SIZE) 93078acc472SPeter Tyser return SZ_ERROR_UNSUPPORTED; 93178acc472SPeter Tyser else 93278acc472SPeter Tyser dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); 93378acc472SPeter Tyser 93478acc472SPeter Tyser if (dicSize < LZMA_DIC_MIN) 93578acc472SPeter Tyser dicSize = LZMA_DIC_MIN; 93678acc472SPeter Tyser p->dicSize = dicSize; 93778acc472SPeter Tyser 93878acc472SPeter Tyser d = data[0]; 93978acc472SPeter Tyser if (d >= (9 * 5 * 5)) 94078acc472SPeter Tyser return SZ_ERROR_UNSUPPORTED; 94178acc472SPeter Tyser 94278acc472SPeter Tyser p->lc = d % 9; 94378acc472SPeter Tyser d /= 9; 94478acc472SPeter Tyser p->pb = d / 5; 94578acc472SPeter Tyser p->lp = d % 5; 94678acc472SPeter Tyser 94778acc472SPeter Tyser return SZ_OK; 94878acc472SPeter Tyser } 94978acc472SPeter Tyser 95078acc472SPeter Tyser static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) 95178acc472SPeter Tyser { 95278acc472SPeter Tyser UInt32 numProbs = LzmaProps_GetNumProbs(propNew); 95378acc472SPeter Tyser if (p->probs == 0 || numProbs != p->numProbs) 95478acc472SPeter Tyser { 95578acc472SPeter Tyser LzmaDec_FreeProbs(p, alloc); 95678acc472SPeter Tyser p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); 95778acc472SPeter Tyser p->numProbs = numProbs; 95878acc472SPeter Tyser if (p->probs == 0) 95978acc472SPeter Tyser return SZ_ERROR_MEM; 96078acc472SPeter Tyser } 96178acc472SPeter Tyser return SZ_OK; 96278acc472SPeter Tyser } 96378acc472SPeter Tyser 96478acc472SPeter Tyser SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) 96578acc472SPeter Tyser { 96678acc472SPeter Tyser CLzmaProps propNew; 96778acc472SPeter Tyser RINOK(LzmaProps_Decode(&propNew, props, propsSize)); 96878acc472SPeter Tyser RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); 96978acc472SPeter Tyser p->prop = propNew; 97078acc472SPeter Tyser return SZ_OK; 97178acc472SPeter Tyser } 97278acc472SPeter Tyser 97378acc472SPeter Tyser SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) 97478acc472SPeter Tyser { 97578acc472SPeter Tyser CLzmaProps propNew; 97678acc472SPeter Tyser SizeT dicBufSize; 97778acc472SPeter Tyser RINOK(LzmaProps_Decode(&propNew, props, propsSize)); 97878acc472SPeter Tyser RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); 97978acc472SPeter Tyser dicBufSize = propNew.dicSize; 98078acc472SPeter Tyser if (p->dic == 0 || dicBufSize != p->dicBufSize) 98178acc472SPeter Tyser { 98278acc472SPeter Tyser LzmaDec_FreeDict(p, alloc); 98378acc472SPeter Tyser p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); 98478acc472SPeter Tyser if (p->dic == 0) 98578acc472SPeter Tyser { 98678acc472SPeter Tyser LzmaDec_FreeProbs(p, alloc); 98778acc472SPeter Tyser return SZ_ERROR_MEM; 98878acc472SPeter Tyser } 98978acc472SPeter Tyser } 99078acc472SPeter Tyser p->dicBufSize = dicBufSize; 99178acc472SPeter Tyser p->prop = propNew; 99278acc472SPeter Tyser return SZ_OK; 99378acc472SPeter Tyser } 99478acc472SPeter Tyser 99578acc472SPeter Tyser SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, 99678acc472SPeter Tyser const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, 99778acc472SPeter Tyser ELzmaStatus *status, ISzAlloc *alloc) 99878acc472SPeter Tyser { 99978acc472SPeter Tyser CLzmaDec p; 100078acc472SPeter Tyser SRes res; 100178acc472SPeter Tyser SizeT inSize = *srcLen; 100278acc472SPeter Tyser SizeT outSize = *destLen; 100378acc472SPeter Tyser *srcLen = *destLen = 0; 100478acc472SPeter Tyser if (inSize < RC_INIT_SIZE) 100578acc472SPeter Tyser return SZ_ERROR_INPUT_EOF; 100678acc472SPeter Tyser 100778acc472SPeter Tyser LzmaDec_Construct(&p); 100878acc472SPeter Tyser res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); 100978acc472SPeter Tyser if (res != 0) 101078acc472SPeter Tyser return res; 101178acc472SPeter Tyser p.dic = dest; 101278acc472SPeter Tyser p.dicBufSize = outSize; 101378acc472SPeter Tyser 101478acc472SPeter Tyser LzmaDec_Init(&p); 101578acc472SPeter Tyser 101678acc472SPeter Tyser *srcLen = inSize; 101778acc472SPeter Tyser res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); 101878acc472SPeter Tyser 101978acc472SPeter Tyser if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) 102078acc472SPeter Tyser res = SZ_ERROR_INPUT_EOF; 102178acc472SPeter Tyser 102278acc472SPeter Tyser (*destLen) = p.dicPos; 102378acc472SPeter Tyser LzmaDec_FreeProbs(&p, alloc); 102478acc472SPeter Tyser return res; 102578acc472SPeter Tyser } 1026