goat3d

annotate libs/openctm/liblzma/LzmaDec.c @ 14:188c697b3b49

- added a document describing the goat3d file format chunk hierarchy - started an alternative XML-based file format - added the openctm library
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 26 Sep 2013 04:47:05 +0300
parents
children
rev   line source
nuclear@14 1 /* LzmaDec.c -- LZMA Decoder
nuclear@14 2 2008-11-06 : Igor Pavlov : Public domain */
nuclear@14 3
nuclear@14 4 #include "LzmaDec.h"
nuclear@14 5
nuclear@14 6 #include <string.h>
nuclear@14 7
nuclear@14 8 #define kNumTopBits 24
nuclear@14 9 #define kTopValue ((UInt32)1 << kNumTopBits)
nuclear@14 10
nuclear@14 11 #define kNumBitModelTotalBits 11
nuclear@14 12 #define kBitModelTotal (1 << kNumBitModelTotalBits)
nuclear@14 13 #define kNumMoveBits 5
nuclear@14 14
nuclear@14 15 #define RC_INIT_SIZE 5
nuclear@14 16
nuclear@14 17 #define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
nuclear@14 18
nuclear@14 19 #define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
nuclear@14 20 #define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
nuclear@14 21 #define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
nuclear@14 22 #define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
nuclear@14 23 { UPDATE_0(p); i = (i + i); A0; } else \
nuclear@14 24 { UPDATE_1(p); i = (i + i) + 1; A1; }
nuclear@14 25 #define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
nuclear@14 26
nuclear@14 27 #define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
nuclear@14 28 #define TREE_DECODE(probs, limit, i) \
nuclear@14 29 { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
nuclear@14 30
nuclear@14 31 /* #define _LZMA_SIZE_OPT */
nuclear@14 32
nuclear@14 33 #ifdef _LZMA_SIZE_OPT
nuclear@14 34 #define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
nuclear@14 35 #else
nuclear@14 36 #define TREE_6_DECODE(probs, i) \
nuclear@14 37 { i = 1; \
nuclear@14 38 TREE_GET_BIT(probs, i); \
nuclear@14 39 TREE_GET_BIT(probs, i); \
nuclear@14 40 TREE_GET_BIT(probs, i); \
nuclear@14 41 TREE_GET_BIT(probs, i); \
nuclear@14 42 TREE_GET_BIT(probs, i); \
nuclear@14 43 TREE_GET_BIT(probs, i); \
nuclear@14 44 i -= 0x40; }
nuclear@14 45 #endif
nuclear@14 46
nuclear@14 47 #define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
nuclear@14 48
nuclear@14 49 #define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
nuclear@14 50 #define UPDATE_0_CHECK range = bound;
nuclear@14 51 #define UPDATE_1_CHECK range -= bound; code -= bound;
nuclear@14 52 #define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
nuclear@14 53 { UPDATE_0_CHECK; i = (i + i); A0; } else \
nuclear@14 54 { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
nuclear@14 55 #define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
nuclear@14 56 #define TREE_DECODE_CHECK(probs, limit, i) \
nuclear@14 57 { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
nuclear@14 58
nuclear@14 59
nuclear@14 60 #define kNumPosBitsMax 4
nuclear@14 61 #define kNumPosStatesMax (1 << kNumPosBitsMax)
nuclear@14 62
nuclear@14 63 #define kLenNumLowBits 3
nuclear@14 64 #define kLenNumLowSymbols (1 << kLenNumLowBits)
nuclear@14 65 #define kLenNumMidBits 3
nuclear@14 66 #define kLenNumMidSymbols (1 << kLenNumMidBits)
nuclear@14 67 #define kLenNumHighBits 8
nuclear@14 68 #define kLenNumHighSymbols (1 << kLenNumHighBits)
nuclear@14 69
nuclear@14 70 #define LenChoice 0
nuclear@14 71 #define LenChoice2 (LenChoice + 1)
nuclear@14 72 #define LenLow (LenChoice2 + 1)
nuclear@14 73 #define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
nuclear@14 74 #define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
nuclear@14 75 #define kNumLenProbs (LenHigh + kLenNumHighSymbols)
nuclear@14 76
nuclear@14 77
nuclear@14 78 #define kNumStates 12
nuclear@14 79 #define kNumLitStates 7
nuclear@14 80
nuclear@14 81 #define kStartPosModelIndex 4
nuclear@14 82 #define kEndPosModelIndex 14
nuclear@14 83 #define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
nuclear@14 84
nuclear@14 85 #define kNumPosSlotBits 6
nuclear@14 86 #define kNumLenToPosStates 4
nuclear@14 87
nuclear@14 88 #define kNumAlignBits 4
nuclear@14 89 #define kAlignTableSize (1 << kNumAlignBits)
nuclear@14 90
nuclear@14 91 #define kMatchMinLen 2
nuclear@14 92 #define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
nuclear@14 93
nuclear@14 94 #define IsMatch 0
nuclear@14 95 #define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
nuclear@14 96 #define IsRepG0 (IsRep + kNumStates)
nuclear@14 97 #define IsRepG1 (IsRepG0 + kNumStates)
nuclear@14 98 #define IsRepG2 (IsRepG1 + kNumStates)
nuclear@14 99 #define IsRep0Long (IsRepG2 + kNumStates)
nuclear@14 100 #define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
nuclear@14 101 #define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
nuclear@14 102 #define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
nuclear@14 103 #define LenCoder (Align + kAlignTableSize)
nuclear@14 104 #define RepLenCoder (LenCoder + kNumLenProbs)
nuclear@14 105 #define Literal (RepLenCoder + kNumLenProbs)
nuclear@14 106
nuclear@14 107 #define LZMA_BASE_SIZE 1846
nuclear@14 108 #define LZMA_LIT_SIZE 768
nuclear@14 109
nuclear@14 110 #define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
nuclear@14 111
nuclear@14 112 #if Literal != LZMA_BASE_SIZE
nuclear@14 113 StopCompilingDueBUG
nuclear@14 114 #endif
nuclear@14 115
nuclear@14 116 static const Byte kLiteralNextStates[kNumStates * 2] =
nuclear@14 117 {
nuclear@14 118 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5,
nuclear@14 119 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
nuclear@14 120 };
nuclear@14 121
nuclear@14 122 #define LZMA_DIC_MIN (1 << 12)
nuclear@14 123
nuclear@14 124 /* First LZMA-symbol is always decoded.
nuclear@14 125 And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
nuclear@14 126 Out:
nuclear@14 127 Result:
nuclear@14 128 SZ_OK - OK
nuclear@14 129 SZ_ERROR_DATA - Error
nuclear@14 130 p->remainLen:
nuclear@14 131 < kMatchSpecLenStart : normal remain
nuclear@14 132 = kMatchSpecLenStart : finished
nuclear@14 133 = kMatchSpecLenStart + 1 : Flush marker
nuclear@14 134 = kMatchSpecLenStart + 2 : State Init Marker
nuclear@14 135 */
nuclear@14 136
nuclear@14 137 static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
nuclear@14 138 {
nuclear@14 139 CLzmaProb *probs = p->probs;
nuclear@14 140
nuclear@14 141 unsigned state = p->state;
nuclear@14 142 UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
nuclear@14 143 unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
nuclear@14 144 unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
nuclear@14 145 unsigned lc = p->prop.lc;
nuclear@14 146
nuclear@14 147 Byte *dic = p->dic;
nuclear@14 148 SizeT dicBufSize = p->dicBufSize;
nuclear@14 149 SizeT dicPos = p->dicPos;
nuclear@14 150
nuclear@14 151 UInt32 processedPos = p->processedPos;
nuclear@14 152 UInt32 checkDicSize = p->checkDicSize;
nuclear@14 153 unsigned len = 0;
nuclear@14 154
nuclear@14 155 const Byte *buf = p->buf;
nuclear@14 156 UInt32 range = p->range;
nuclear@14 157 UInt32 code = p->code;
nuclear@14 158
nuclear@14 159 do
nuclear@14 160 {
nuclear@14 161 CLzmaProb *prob;
nuclear@14 162 UInt32 bound;
nuclear@14 163 unsigned ttt;
nuclear@14 164 unsigned posState = processedPos & pbMask;
nuclear@14 165
nuclear@14 166 prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
nuclear@14 167 IF_BIT_0(prob)
nuclear@14 168 {
nuclear@14 169 unsigned symbol;
nuclear@14 170 UPDATE_0(prob);
nuclear@14 171 prob = probs + Literal;
nuclear@14 172 if (checkDicSize != 0 || processedPos != 0)
nuclear@14 173 prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
nuclear@14 174 (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
nuclear@14 175
nuclear@14 176 if (state < kNumLitStates)
nuclear@14 177 {
nuclear@14 178 symbol = 1;
nuclear@14 179 do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
nuclear@14 180 }
nuclear@14 181 else
nuclear@14 182 {
nuclear@14 183 unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
nuclear@14 184 unsigned offs = 0x100;
nuclear@14 185 symbol = 1;
nuclear@14 186 do
nuclear@14 187 {
nuclear@14 188 unsigned bit;
nuclear@14 189 CLzmaProb *probLit;
nuclear@14 190 matchByte <<= 1;
nuclear@14 191 bit = (matchByte & offs);
nuclear@14 192 probLit = prob + offs + bit + symbol;
nuclear@14 193 GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
nuclear@14 194 }
nuclear@14 195 while (symbol < 0x100);
nuclear@14 196 }
nuclear@14 197 dic[dicPos++] = (Byte)symbol;
nuclear@14 198 processedPos++;
nuclear@14 199
nuclear@14 200 state = kLiteralNextStates[state];
nuclear@14 201 /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
nuclear@14 202 continue;
nuclear@14 203 }
nuclear@14 204 else
nuclear@14 205 {
nuclear@14 206 UPDATE_1(prob);
nuclear@14 207 prob = probs + IsRep + state;
nuclear@14 208 IF_BIT_0(prob)
nuclear@14 209 {
nuclear@14 210 UPDATE_0(prob);
nuclear@14 211 state += kNumStates;
nuclear@14 212 prob = probs + LenCoder;
nuclear@14 213 }
nuclear@14 214 else
nuclear@14 215 {
nuclear@14 216 UPDATE_1(prob);
nuclear@14 217 if (checkDicSize == 0 && processedPos == 0)
nuclear@14 218 return SZ_ERROR_DATA;
nuclear@14 219 prob = probs + IsRepG0 + state;
nuclear@14 220 IF_BIT_0(prob)
nuclear@14 221 {
nuclear@14 222 UPDATE_0(prob);
nuclear@14 223 prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
nuclear@14 224 IF_BIT_0(prob)
nuclear@14 225 {
nuclear@14 226 UPDATE_0(prob);
nuclear@14 227 dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
nuclear@14 228 dicPos++;
nuclear@14 229 processedPos++;
nuclear@14 230 state = state < kNumLitStates ? 9 : 11;
nuclear@14 231 continue;
nuclear@14 232 }
nuclear@14 233 UPDATE_1(prob);
nuclear@14 234 }
nuclear@14 235 else
nuclear@14 236 {
nuclear@14 237 UInt32 distance;
nuclear@14 238 UPDATE_1(prob);
nuclear@14 239 prob = probs + IsRepG1 + state;
nuclear@14 240 IF_BIT_0(prob)
nuclear@14 241 {
nuclear@14 242 UPDATE_0(prob);
nuclear@14 243 distance = rep1;
nuclear@14 244 }
nuclear@14 245 else
nuclear@14 246 {
nuclear@14 247 UPDATE_1(prob);
nuclear@14 248 prob = probs + IsRepG2 + state;
nuclear@14 249 IF_BIT_0(prob)
nuclear@14 250 {
nuclear@14 251 UPDATE_0(prob);
nuclear@14 252 distance = rep2;
nuclear@14 253 }
nuclear@14 254 else
nuclear@14 255 {
nuclear@14 256 UPDATE_1(prob);
nuclear@14 257 distance = rep3;
nuclear@14 258 rep3 = rep2;
nuclear@14 259 }
nuclear@14 260 rep2 = rep1;
nuclear@14 261 }
nuclear@14 262 rep1 = rep0;
nuclear@14 263 rep0 = distance;
nuclear@14 264 }
nuclear@14 265 state = state < kNumLitStates ? 8 : 11;
nuclear@14 266 prob = probs + RepLenCoder;
nuclear@14 267 }
nuclear@14 268 {
nuclear@14 269 unsigned limit, offset;
nuclear@14 270 CLzmaProb *probLen = prob + LenChoice;
nuclear@14 271 IF_BIT_0(probLen)
nuclear@14 272 {
nuclear@14 273 UPDATE_0(probLen);
nuclear@14 274 probLen = prob + LenLow + (posState << kLenNumLowBits);
nuclear@14 275 offset = 0;
nuclear@14 276 limit = (1 << kLenNumLowBits);
nuclear@14 277 }
nuclear@14 278 else
nuclear@14 279 {
nuclear@14 280 UPDATE_1(probLen);
nuclear@14 281 probLen = prob + LenChoice2;
nuclear@14 282 IF_BIT_0(probLen)
nuclear@14 283 {
nuclear@14 284 UPDATE_0(probLen);
nuclear@14 285 probLen = prob + LenMid + (posState << kLenNumMidBits);
nuclear@14 286 offset = kLenNumLowSymbols;
nuclear@14 287 limit = (1 << kLenNumMidBits);
nuclear@14 288 }
nuclear@14 289 else
nuclear@14 290 {
nuclear@14 291 UPDATE_1(probLen);
nuclear@14 292 probLen = prob + LenHigh;
nuclear@14 293 offset = kLenNumLowSymbols + kLenNumMidSymbols;
nuclear@14 294 limit = (1 << kLenNumHighBits);
nuclear@14 295 }
nuclear@14 296 }
nuclear@14 297 TREE_DECODE(probLen, limit, len);
nuclear@14 298 len += offset;
nuclear@14 299 }
nuclear@14 300
nuclear@14 301 if (state >= kNumStates)
nuclear@14 302 {
nuclear@14 303 UInt32 distance;
nuclear@14 304 prob = probs + PosSlot +
nuclear@14 305 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
nuclear@14 306 TREE_6_DECODE(prob, distance);
nuclear@14 307 if (distance >= kStartPosModelIndex)
nuclear@14 308 {
nuclear@14 309 unsigned posSlot = (unsigned)distance;
nuclear@14 310 int numDirectBits = (int)(((distance >> 1) - 1));
nuclear@14 311 distance = (2 | (distance & 1));
nuclear@14 312 if (posSlot < kEndPosModelIndex)
nuclear@14 313 {
nuclear@14 314 distance <<= numDirectBits;
nuclear@14 315 prob = probs + SpecPos + distance - posSlot - 1;
nuclear@14 316 {
nuclear@14 317 UInt32 mask = 1;
nuclear@14 318 unsigned i = 1;
nuclear@14 319 do
nuclear@14 320 {
nuclear@14 321 GET_BIT2(prob + i, i, ; , distance |= mask);
nuclear@14 322 mask <<= 1;
nuclear@14 323 }
nuclear@14 324 while (--numDirectBits != 0);
nuclear@14 325 }
nuclear@14 326 }
nuclear@14 327 else
nuclear@14 328 {
nuclear@14 329 numDirectBits -= kNumAlignBits;
nuclear@14 330 do
nuclear@14 331 {
nuclear@14 332 NORMALIZE
nuclear@14 333 range >>= 1;
nuclear@14 334
nuclear@14 335 {
nuclear@14 336 UInt32 t;
nuclear@14 337 code -= range;
nuclear@14 338 t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
nuclear@14 339 distance = (distance << 1) + (t + 1);
nuclear@14 340 code += range & t;
nuclear@14 341 }
nuclear@14 342 /*
nuclear@14 343 distance <<= 1;
nuclear@14 344 if (code >= range)
nuclear@14 345 {
nuclear@14 346 code -= range;
nuclear@14 347 distance |= 1;
nuclear@14 348 }
nuclear@14 349 */
nuclear@14 350 }
nuclear@14 351 while (--numDirectBits != 0);
nuclear@14 352 prob = probs + Align;
nuclear@14 353 distance <<= kNumAlignBits;
nuclear@14 354 {
nuclear@14 355 unsigned i = 1;
nuclear@14 356 GET_BIT2(prob + i, i, ; , distance |= 1);
nuclear@14 357 GET_BIT2(prob + i, i, ; , distance |= 2);
nuclear@14 358 GET_BIT2(prob + i, i, ; , distance |= 4);
nuclear@14 359 GET_BIT2(prob + i, i, ; , distance |= 8);
nuclear@14 360 }
nuclear@14 361 if (distance == (UInt32)0xFFFFFFFF)
nuclear@14 362 {
nuclear@14 363 len += kMatchSpecLenStart;
nuclear@14 364 state -= kNumStates;
nuclear@14 365 break;
nuclear@14 366 }
nuclear@14 367 }
nuclear@14 368 }
nuclear@14 369 rep3 = rep2;
nuclear@14 370 rep2 = rep1;
nuclear@14 371 rep1 = rep0;
nuclear@14 372 rep0 = distance + 1;
nuclear@14 373 if (checkDicSize == 0)
nuclear@14 374 {
nuclear@14 375 if (distance >= processedPos)
nuclear@14 376 return SZ_ERROR_DATA;
nuclear@14 377 }
nuclear@14 378 else if (distance >= checkDicSize)
nuclear@14 379 return SZ_ERROR_DATA;
nuclear@14 380 state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
nuclear@14 381 /* state = kLiteralNextStates[state]; */
nuclear@14 382 }
nuclear@14 383
nuclear@14 384 len += kMatchMinLen;
nuclear@14 385
nuclear@14 386 if (limit == dicPos)
nuclear@14 387 return SZ_ERROR_DATA;
nuclear@14 388 {
nuclear@14 389 SizeT rem = limit - dicPos;
nuclear@14 390 unsigned curLen = ((rem < len) ? (unsigned)rem : len);
nuclear@14 391 SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
nuclear@14 392
nuclear@14 393 processedPos += curLen;
nuclear@14 394
nuclear@14 395 len -= curLen;
nuclear@14 396 if (pos + curLen <= dicBufSize)
nuclear@14 397 {
nuclear@14 398 Byte *dest = dic + dicPos;
nuclear@14 399 ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
nuclear@14 400 const Byte *lim = dest + curLen;
nuclear@14 401 dicPos += curLen;
nuclear@14 402 do
nuclear@14 403 *(dest) = (Byte)*(dest + src);
nuclear@14 404 while (++dest != lim);
nuclear@14 405 }
nuclear@14 406 else
nuclear@14 407 {
nuclear@14 408 do
nuclear@14 409 {
nuclear@14 410 dic[dicPos++] = dic[pos];
nuclear@14 411 if (++pos == dicBufSize)
nuclear@14 412 pos = 0;
nuclear@14 413 }
nuclear@14 414 while (--curLen != 0);
nuclear@14 415 }
nuclear@14 416 }
nuclear@14 417 }
nuclear@14 418 }
nuclear@14 419 while (dicPos < limit && buf < bufLimit);
nuclear@14 420 NORMALIZE;
nuclear@14 421 p->buf = buf;
nuclear@14 422 p->range = range;
nuclear@14 423 p->code = code;
nuclear@14 424 p->remainLen = len;
nuclear@14 425 p->dicPos = dicPos;
nuclear@14 426 p->processedPos = processedPos;
nuclear@14 427 p->reps[0] = rep0;
nuclear@14 428 p->reps[1] = rep1;
nuclear@14 429 p->reps[2] = rep2;
nuclear@14 430 p->reps[3] = rep3;
nuclear@14 431 p->state = state;
nuclear@14 432
nuclear@14 433 return SZ_OK;
nuclear@14 434 }
nuclear@14 435
nuclear@14 436 static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
nuclear@14 437 {
nuclear@14 438 if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
nuclear@14 439 {
nuclear@14 440 Byte *dic = p->dic;
nuclear@14 441 SizeT dicPos = p->dicPos;
nuclear@14 442 SizeT dicBufSize = p->dicBufSize;
nuclear@14 443 unsigned len = p->remainLen;
nuclear@14 444 UInt32 rep0 = p->reps[0];
nuclear@14 445 if (limit - dicPos < len)
nuclear@14 446 len = (unsigned)(limit - dicPos);
nuclear@14 447
nuclear@14 448 if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
nuclear@14 449 p->checkDicSize = p->prop.dicSize;
nuclear@14 450
nuclear@14 451 p->processedPos += len;
nuclear@14 452 p->remainLen -= len;
nuclear@14 453 while (len-- != 0)
nuclear@14 454 {
nuclear@14 455 dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
nuclear@14 456 dicPos++;
nuclear@14 457 }
nuclear@14 458 p->dicPos = dicPos;
nuclear@14 459 }
nuclear@14 460 }
nuclear@14 461
nuclear@14 462 static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
nuclear@14 463 {
nuclear@14 464 do
nuclear@14 465 {
nuclear@14 466 SizeT limit2 = limit;
nuclear@14 467 if (p->checkDicSize == 0)
nuclear@14 468 {
nuclear@14 469 UInt32 rem = p->prop.dicSize - p->processedPos;
nuclear@14 470 if (limit - p->dicPos > rem)
nuclear@14 471 limit2 = p->dicPos + rem;
nuclear@14 472 }
nuclear@14 473 RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
nuclear@14 474 if (p->processedPos >= p->prop.dicSize)
nuclear@14 475 p->checkDicSize = p->prop.dicSize;
nuclear@14 476 LzmaDec_WriteRem(p, limit);
nuclear@14 477 }
nuclear@14 478 while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
nuclear@14 479
nuclear@14 480 if (p->remainLen > kMatchSpecLenStart)
nuclear@14 481 {
nuclear@14 482 p->remainLen = kMatchSpecLenStart;
nuclear@14 483 }
nuclear@14 484 return 0;
nuclear@14 485 }
nuclear@14 486
nuclear@14 487 typedef enum
nuclear@14 488 {
nuclear@14 489 DUMMY_ERROR, /* unexpected end of input stream */
nuclear@14 490 DUMMY_LIT,
nuclear@14 491 DUMMY_MATCH,
nuclear@14 492 DUMMY_REP
nuclear@14 493 } ELzmaDummy;
nuclear@14 494
nuclear@14 495 static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
nuclear@14 496 {
nuclear@14 497 UInt32 range = p->range;
nuclear@14 498 UInt32 code = p->code;
nuclear@14 499 const Byte *bufLimit = buf + inSize;
nuclear@14 500 CLzmaProb *probs = p->probs;
nuclear@14 501 unsigned state = p->state;
nuclear@14 502 ELzmaDummy res;
nuclear@14 503
nuclear@14 504 {
nuclear@14 505 CLzmaProb *prob;
nuclear@14 506 UInt32 bound;
nuclear@14 507 unsigned ttt;
nuclear@14 508 unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
nuclear@14 509
nuclear@14 510 prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
nuclear@14 511 IF_BIT_0_CHECK(prob)
nuclear@14 512 {
nuclear@14 513 UPDATE_0_CHECK
nuclear@14 514
nuclear@14 515 /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
nuclear@14 516
nuclear@14 517 prob = probs + Literal;
nuclear@14 518 if (p->checkDicSize != 0 || p->processedPos != 0)
nuclear@14 519 prob += (LZMA_LIT_SIZE *
nuclear@14 520 ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
nuclear@14 521 (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
nuclear@14 522
nuclear@14 523 if (state < kNumLitStates)
nuclear@14 524 {
nuclear@14 525 unsigned symbol = 1;
nuclear@14 526 do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
nuclear@14 527 }
nuclear@14 528 else
nuclear@14 529 {
nuclear@14 530 unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
nuclear@14 531 ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
nuclear@14 532 unsigned offs = 0x100;
nuclear@14 533 unsigned symbol = 1;
nuclear@14 534 do
nuclear@14 535 {
nuclear@14 536 unsigned bit;
nuclear@14 537 CLzmaProb *probLit;
nuclear@14 538 matchByte <<= 1;
nuclear@14 539 bit = (matchByte & offs);
nuclear@14 540 probLit = prob + offs + bit + symbol;
nuclear@14 541 GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
nuclear@14 542 }
nuclear@14 543 while (symbol < 0x100);
nuclear@14 544 }
nuclear@14 545 res = DUMMY_LIT;
nuclear@14 546 }
nuclear@14 547 else
nuclear@14 548 {
nuclear@14 549 unsigned len;
nuclear@14 550 UPDATE_1_CHECK;
nuclear@14 551
nuclear@14 552 prob = probs + IsRep + state;
nuclear@14 553 IF_BIT_0_CHECK(prob)
nuclear@14 554 {
nuclear@14 555 UPDATE_0_CHECK;
nuclear@14 556 state = 0;
nuclear@14 557 prob = probs + LenCoder;
nuclear@14 558 res = DUMMY_MATCH;
nuclear@14 559 }
nuclear@14 560 else
nuclear@14 561 {
nuclear@14 562 UPDATE_1_CHECK;
nuclear@14 563 res = DUMMY_REP;
nuclear@14 564 prob = probs + IsRepG0 + state;
nuclear@14 565 IF_BIT_0_CHECK(prob)
nuclear@14 566 {
nuclear@14 567 UPDATE_0_CHECK;
nuclear@14 568 prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
nuclear@14 569 IF_BIT_0_CHECK(prob)
nuclear@14 570 {
nuclear@14 571 UPDATE_0_CHECK;
nuclear@14 572 NORMALIZE_CHECK;
nuclear@14 573 return DUMMY_REP;
nuclear@14 574 }
nuclear@14 575 else
nuclear@14 576 {
nuclear@14 577 UPDATE_1_CHECK;
nuclear@14 578 }
nuclear@14 579 }
nuclear@14 580 else
nuclear@14 581 {
nuclear@14 582 UPDATE_1_CHECK;
nuclear@14 583 prob = probs + IsRepG1 + state;
nuclear@14 584 IF_BIT_0_CHECK(prob)
nuclear@14 585 {
nuclear@14 586 UPDATE_0_CHECK;
nuclear@14 587 }
nuclear@14 588 else
nuclear@14 589 {
nuclear@14 590 UPDATE_1_CHECK;
nuclear@14 591 prob = probs + IsRepG2 + state;
nuclear@14 592 IF_BIT_0_CHECK(prob)
nuclear@14 593 {
nuclear@14 594 UPDATE_0_CHECK;
nuclear@14 595 }
nuclear@14 596 else
nuclear@14 597 {
nuclear@14 598 UPDATE_1_CHECK;
nuclear@14 599 }
nuclear@14 600 }
nuclear@14 601 }
nuclear@14 602 state = kNumStates;
nuclear@14 603 prob = probs + RepLenCoder;
nuclear@14 604 }
nuclear@14 605 {
nuclear@14 606 unsigned limit, offset;
nuclear@14 607 CLzmaProb *probLen = prob + LenChoice;
nuclear@14 608 IF_BIT_0_CHECK(probLen)
nuclear@14 609 {
nuclear@14 610 UPDATE_0_CHECK;
nuclear@14 611 probLen = prob + LenLow + (posState << kLenNumLowBits);
nuclear@14 612 offset = 0;
nuclear@14 613 limit = 1 << kLenNumLowBits;
nuclear@14 614 }
nuclear@14 615 else
nuclear@14 616 {
nuclear@14 617 UPDATE_1_CHECK;
nuclear@14 618 probLen = prob + LenChoice2;
nuclear@14 619 IF_BIT_0_CHECK(probLen)
nuclear@14 620 {
nuclear@14 621 UPDATE_0_CHECK;
nuclear@14 622 probLen = prob + LenMid + (posState << kLenNumMidBits);
nuclear@14 623 offset = kLenNumLowSymbols;
nuclear@14 624 limit = 1 << kLenNumMidBits;
nuclear@14 625 }
nuclear@14 626 else
nuclear@14 627 {
nuclear@14 628 UPDATE_1_CHECK;
nuclear@14 629 probLen = prob + LenHigh;
nuclear@14 630 offset = kLenNumLowSymbols + kLenNumMidSymbols;
nuclear@14 631 limit = 1 << kLenNumHighBits;
nuclear@14 632 }
nuclear@14 633 }
nuclear@14 634 TREE_DECODE_CHECK(probLen, limit, len);
nuclear@14 635 len += offset;
nuclear@14 636 }
nuclear@14 637
nuclear@14 638 if (state < 4)
nuclear@14 639 {
nuclear@14 640 unsigned posSlot;
nuclear@14 641 prob = probs + PosSlot +
nuclear@14 642 ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
nuclear@14 643 kNumPosSlotBits);
nuclear@14 644 TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
nuclear@14 645 if (posSlot >= kStartPosModelIndex)
nuclear@14 646 {
nuclear@14 647 int numDirectBits = ((posSlot >> 1) - 1);
nuclear@14 648
nuclear@14 649 /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
nuclear@14 650
nuclear@14 651 if (posSlot < kEndPosModelIndex)
nuclear@14 652 {
nuclear@14 653 prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
nuclear@14 654 }
nuclear@14 655 else
nuclear@14 656 {
nuclear@14 657 numDirectBits -= kNumAlignBits;
nuclear@14 658 do
nuclear@14 659 {
nuclear@14 660 NORMALIZE_CHECK
nuclear@14 661 range >>= 1;
nuclear@14 662 code -= range & (((code - range) >> 31) - 1);
nuclear@14 663 /* if (code >= range) code -= range; */
nuclear@14 664 }
nuclear@14 665 while (--numDirectBits != 0);
nuclear@14 666 prob = probs + Align;
nuclear@14 667 numDirectBits = kNumAlignBits;
nuclear@14 668 }
nuclear@14 669 {
nuclear@14 670 unsigned i = 1;
nuclear@14 671 do
nuclear@14 672 {
nuclear@14 673 GET_BIT_CHECK(prob + i, i);
nuclear@14 674 }
nuclear@14 675 while (--numDirectBits != 0);
nuclear@14 676 }
nuclear@14 677 }
nuclear@14 678 }
nuclear@14 679 }
nuclear@14 680 }
nuclear@14 681 NORMALIZE_CHECK;
nuclear@14 682 return res;
nuclear@14 683 }
nuclear@14 684
nuclear@14 685
nuclear@14 686 static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
nuclear@14 687 {
nuclear@14 688 p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
nuclear@14 689 p->range = 0xFFFFFFFF;
nuclear@14 690 p->needFlush = 0;
nuclear@14 691 }
nuclear@14 692
nuclear@14 693 void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
nuclear@14 694 {
nuclear@14 695 p->needFlush = 1;
nuclear@14 696 p->remainLen = 0;
nuclear@14 697 p->tempBufSize = 0;
nuclear@14 698
nuclear@14 699 if (initDic)
nuclear@14 700 {
nuclear@14 701 p->processedPos = 0;
nuclear@14 702 p->checkDicSize = 0;
nuclear@14 703 p->needInitState = 1;
nuclear@14 704 }
nuclear@14 705 if (initState)
nuclear@14 706 p->needInitState = 1;
nuclear@14 707 }
nuclear@14 708
nuclear@14 709 void LzmaDec_Init(CLzmaDec *p)
nuclear@14 710 {
nuclear@14 711 p->dicPos = 0;
nuclear@14 712 LzmaDec_InitDicAndState(p, True, True);
nuclear@14 713 }
nuclear@14 714
nuclear@14 715 static void LzmaDec_InitStateReal(CLzmaDec *p)
nuclear@14 716 {
nuclear@14 717 UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
nuclear@14 718 UInt32 i;
nuclear@14 719 CLzmaProb *probs = p->probs;
nuclear@14 720 for (i = 0; i < numProbs; i++)
nuclear@14 721 probs[i] = kBitModelTotal >> 1;
nuclear@14 722 p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
nuclear@14 723 p->state = 0;
nuclear@14 724 p->needInitState = 0;
nuclear@14 725 }
nuclear@14 726
nuclear@14 727 SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
nuclear@14 728 ELzmaFinishMode finishMode, ELzmaStatus *status)
nuclear@14 729 {
nuclear@14 730 SizeT inSize = *srcLen;
nuclear@14 731 (*srcLen) = 0;
nuclear@14 732 LzmaDec_WriteRem(p, dicLimit);
nuclear@14 733
nuclear@14 734 *status = LZMA_STATUS_NOT_SPECIFIED;
nuclear@14 735
nuclear@14 736 while (p->remainLen != kMatchSpecLenStart)
nuclear@14 737 {
nuclear@14 738 int checkEndMarkNow;
nuclear@14 739
nuclear@14 740 if (p->needFlush != 0)
nuclear@14 741 {
nuclear@14 742 for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
nuclear@14 743 p->tempBuf[p->tempBufSize++] = *src++;
nuclear@14 744 if (p->tempBufSize < RC_INIT_SIZE)
nuclear@14 745 {
nuclear@14 746 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
nuclear@14 747 return SZ_OK;
nuclear@14 748 }
nuclear@14 749 if (p->tempBuf[0] != 0)
nuclear@14 750 return SZ_ERROR_DATA;
nuclear@14 751
nuclear@14 752 LzmaDec_InitRc(p, p->tempBuf);
nuclear@14 753 p->tempBufSize = 0;
nuclear@14 754 }
nuclear@14 755
nuclear@14 756 checkEndMarkNow = 0;
nuclear@14 757 if (p->dicPos >= dicLimit)
nuclear@14 758 {
nuclear@14 759 if (p->remainLen == 0 && p->code == 0)
nuclear@14 760 {
nuclear@14 761 *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
nuclear@14 762 return SZ_OK;
nuclear@14 763 }
nuclear@14 764 if (finishMode == LZMA_FINISH_ANY)
nuclear@14 765 {
nuclear@14 766 *status = LZMA_STATUS_NOT_FINISHED;
nuclear@14 767 return SZ_OK;
nuclear@14 768 }
nuclear@14 769 if (p->remainLen != 0)
nuclear@14 770 {
nuclear@14 771 *status = LZMA_STATUS_NOT_FINISHED;
nuclear@14 772 return SZ_ERROR_DATA;
nuclear@14 773 }
nuclear@14 774 checkEndMarkNow = 1;
nuclear@14 775 }
nuclear@14 776
nuclear@14 777 if (p->needInitState)
nuclear@14 778 LzmaDec_InitStateReal(p);
nuclear@14 779
nuclear@14 780 if (p->tempBufSize == 0)
nuclear@14 781 {
nuclear@14 782 SizeT processed;
nuclear@14 783 const Byte *bufLimit;
nuclear@14 784 if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
nuclear@14 785 {
nuclear@14 786 int dummyRes = LzmaDec_TryDummy(p, src, inSize);
nuclear@14 787 if (dummyRes == DUMMY_ERROR)
nuclear@14 788 {
nuclear@14 789 memcpy(p->tempBuf, src, inSize);
nuclear@14 790 p->tempBufSize = (unsigned)inSize;
nuclear@14 791 (*srcLen) += inSize;
nuclear@14 792 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
nuclear@14 793 return SZ_OK;
nuclear@14 794 }
nuclear@14 795 if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
nuclear@14 796 {
nuclear@14 797 *status = LZMA_STATUS_NOT_FINISHED;
nuclear@14 798 return SZ_ERROR_DATA;
nuclear@14 799 }
nuclear@14 800 bufLimit = src;
nuclear@14 801 }
nuclear@14 802 else
nuclear@14 803 bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
nuclear@14 804 p->buf = src;
nuclear@14 805 if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
nuclear@14 806 return SZ_ERROR_DATA;
nuclear@14 807 processed = (SizeT)(p->buf - src);
nuclear@14 808 (*srcLen) += processed;
nuclear@14 809 src += processed;
nuclear@14 810 inSize -= processed;
nuclear@14 811 }
nuclear@14 812 else
nuclear@14 813 {
nuclear@14 814 unsigned rem = p->tempBufSize, lookAhead = 0;
nuclear@14 815 while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
nuclear@14 816 p->tempBuf[rem++] = src[lookAhead++];
nuclear@14 817 p->tempBufSize = rem;
nuclear@14 818 if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
nuclear@14 819 {
nuclear@14 820 int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
nuclear@14 821 if (dummyRes == DUMMY_ERROR)
nuclear@14 822 {
nuclear@14 823 (*srcLen) += lookAhead;
nuclear@14 824 *status = LZMA_STATUS_NEEDS_MORE_INPUT;
nuclear@14 825 return SZ_OK;
nuclear@14 826 }
nuclear@14 827 if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
nuclear@14 828 {
nuclear@14 829 *status = LZMA_STATUS_NOT_FINISHED;
nuclear@14 830 return SZ_ERROR_DATA;
nuclear@14 831 }
nuclear@14 832 }
nuclear@14 833 p->buf = p->tempBuf;
nuclear@14 834 if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
nuclear@14 835 return SZ_ERROR_DATA;
nuclear@14 836 lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
nuclear@14 837 (*srcLen) += lookAhead;
nuclear@14 838 src += lookAhead;
nuclear@14 839 inSize -= lookAhead;
nuclear@14 840 p->tempBufSize = 0;
nuclear@14 841 }
nuclear@14 842 }
nuclear@14 843 if (p->code == 0)
nuclear@14 844 *status = LZMA_STATUS_FINISHED_WITH_MARK;
nuclear@14 845 return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
nuclear@14 846 }
nuclear@14 847
nuclear@14 848 SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
nuclear@14 849 {
nuclear@14 850 SizeT outSize = *destLen;
nuclear@14 851 SizeT inSize = *srcLen;
nuclear@14 852 *srcLen = *destLen = 0;
nuclear@14 853 for (;;)
nuclear@14 854 {
nuclear@14 855 SizeT inSizeCur = inSize, outSizeCur, dicPos;
nuclear@14 856 ELzmaFinishMode curFinishMode;
nuclear@14 857 SRes res;
nuclear@14 858 if (p->dicPos == p->dicBufSize)
nuclear@14 859 p->dicPos = 0;
nuclear@14 860 dicPos = p->dicPos;
nuclear@14 861 if (outSize > p->dicBufSize - dicPos)
nuclear@14 862 {
nuclear@14 863 outSizeCur = p->dicBufSize;
nuclear@14 864 curFinishMode = LZMA_FINISH_ANY;
nuclear@14 865 }
nuclear@14 866 else
nuclear@14 867 {
nuclear@14 868 outSizeCur = dicPos + outSize;
nuclear@14 869 curFinishMode = finishMode;
nuclear@14 870 }
nuclear@14 871
nuclear@14 872 res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
nuclear@14 873 src += inSizeCur;
nuclear@14 874 inSize -= inSizeCur;
nuclear@14 875 *srcLen += inSizeCur;
nuclear@14 876 outSizeCur = p->dicPos - dicPos;
nuclear@14 877 memcpy(dest, p->dic + dicPos, outSizeCur);
nuclear@14 878 dest += outSizeCur;
nuclear@14 879 outSize -= outSizeCur;
nuclear@14 880 *destLen += outSizeCur;
nuclear@14 881 if (res != 0)
nuclear@14 882 return res;
nuclear@14 883 if (outSizeCur == 0 || outSize == 0)
nuclear@14 884 return SZ_OK;
nuclear@14 885 }
nuclear@14 886 }
nuclear@14 887
nuclear@14 888 void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
nuclear@14 889 {
nuclear@14 890 alloc->Free(alloc, p->probs);
nuclear@14 891 p->probs = 0;
nuclear@14 892 }
nuclear@14 893
nuclear@14 894 static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
nuclear@14 895 {
nuclear@14 896 alloc->Free(alloc, p->dic);
nuclear@14 897 p->dic = 0;
nuclear@14 898 }
nuclear@14 899
nuclear@14 900 void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
nuclear@14 901 {
nuclear@14 902 LzmaDec_FreeProbs(p, alloc);
nuclear@14 903 LzmaDec_FreeDict(p, alloc);
nuclear@14 904 }
nuclear@14 905
nuclear@14 906 SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
nuclear@14 907 {
nuclear@14 908 UInt32 dicSize;
nuclear@14 909 Byte d;
nuclear@14 910
nuclear@14 911 if (size < LZMA_PROPS_SIZE)
nuclear@14 912 return SZ_ERROR_UNSUPPORTED;
nuclear@14 913 else
nuclear@14 914 dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
nuclear@14 915
nuclear@14 916 if (dicSize < LZMA_DIC_MIN)
nuclear@14 917 dicSize = LZMA_DIC_MIN;
nuclear@14 918 p->dicSize = dicSize;
nuclear@14 919
nuclear@14 920 d = data[0];
nuclear@14 921 if (d >= (9 * 5 * 5))
nuclear@14 922 return SZ_ERROR_UNSUPPORTED;
nuclear@14 923
nuclear@14 924 p->lc = d % 9;
nuclear@14 925 d /= 9;
nuclear@14 926 p->pb = d / 5;
nuclear@14 927 p->lp = d % 5;
nuclear@14 928
nuclear@14 929 return SZ_OK;
nuclear@14 930 }
nuclear@14 931
nuclear@14 932 static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
nuclear@14 933 {
nuclear@14 934 UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
nuclear@14 935 if (p->probs == 0 || numProbs != p->numProbs)
nuclear@14 936 {
nuclear@14 937 LzmaDec_FreeProbs(p, alloc);
nuclear@14 938 p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
nuclear@14 939 p->numProbs = numProbs;
nuclear@14 940 if (p->probs == 0)
nuclear@14 941 return SZ_ERROR_MEM;
nuclear@14 942 }
nuclear@14 943 return SZ_OK;
nuclear@14 944 }
nuclear@14 945
nuclear@14 946 SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
nuclear@14 947 {
nuclear@14 948 CLzmaProps propNew;
nuclear@14 949 RINOK(LzmaProps_Decode(&propNew, props, propsSize));
nuclear@14 950 RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
nuclear@14 951 p->prop = propNew;
nuclear@14 952 return SZ_OK;
nuclear@14 953 }
nuclear@14 954
nuclear@14 955 SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
nuclear@14 956 {
nuclear@14 957 CLzmaProps propNew;
nuclear@14 958 SizeT dicBufSize;
nuclear@14 959 RINOK(LzmaProps_Decode(&propNew, props, propsSize));
nuclear@14 960 RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
nuclear@14 961 dicBufSize = propNew.dicSize;
nuclear@14 962 if (p->dic == 0 || dicBufSize != p->dicBufSize)
nuclear@14 963 {
nuclear@14 964 LzmaDec_FreeDict(p, alloc);
nuclear@14 965 p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
nuclear@14 966 if (p->dic == 0)
nuclear@14 967 {
nuclear@14 968 LzmaDec_FreeProbs(p, alloc);
nuclear@14 969 return SZ_ERROR_MEM;
nuclear@14 970 }
nuclear@14 971 }
nuclear@14 972 p->dicBufSize = dicBufSize;
nuclear@14 973 p->prop = propNew;
nuclear@14 974 return SZ_OK;
nuclear@14 975 }
nuclear@14 976
nuclear@14 977 SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
nuclear@14 978 const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
nuclear@14 979 ELzmaStatus *status, ISzAlloc *alloc)
nuclear@14 980 {
nuclear@14 981 CLzmaDec p;
nuclear@14 982 SRes res;
nuclear@14 983 SizeT inSize = *srcLen;
nuclear@14 984 SizeT outSize = *destLen;
nuclear@14 985 *srcLen = *destLen = 0;
nuclear@14 986 if (inSize < RC_INIT_SIZE)
nuclear@14 987 return SZ_ERROR_INPUT_EOF;
nuclear@14 988
nuclear@14 989 LzmaDec_Construct(&p);
nuclear@14 990 res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
nuclear@14 991 if (res != 0)
nuclear@14 992 return res;
nuclear@14 993 p.dic = dest;
nuclear@14 994 p.dicBufSize = outSize;
nuclear@14 995
nuclear@14 996 LzmaDec_Init(&p);
nuclear@14 997
nuclear@14 998 *srcLen = inSize;
nuclear@14 999 res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
nuclear@14 1000
nuclear@14 1001 if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
nuclear@14 1002 res = SZ_ERROR_INPUT_EOF;
nuclear@14 1003
nuclear@14 1004 (*destLen) = p.dicPos;
nuclear@14 1005 LzmaDec_FreeProbs(&p, alloc);
nuclear@14 1006 return res;
nuclear@14 1007 }