| 1 | /* 7zDec.c -- Decoding from 7z folder | 
|---|
| 2 | 2010-11-02 : Igor Pavlov : Public domain */ | 
|---|
| 3 |  | 
|---|
| 4 | #include <string.h> | 
|---|
| 5 |  | 
|---|
| 6 | /* #define _7ZIP_PPMD_SUPPPORT */ | 
|---|
| 7 |  | 
|---|
| 8 | #include "7z.h" | 
|---|
| 9 |  | 
|---|
| 10 | #include "Bcj2.h" | 
|---|
| 11 | #include "Bra.h" | 
|---|
| 12 | #include "CpuArch.h" | 
|---|
| 13 | #include "LzmaDec.h" | 
|---|
| 14 | #include "Lzma2Dec.h" | 
|---|
| 15 | #ifdef _7ZIP_PPMD_SUPPPORT | 
|---|
| 16 | #include "Ppmd7.h" | 
|---|
| 17 | #endif | 
|---|
| 18 |  | 
|---|
| 19 | #define k_Copy 0 | 
|---|
| 20 | #define k_LZMA2 0x21 | 
|---|
| 21 | #define k_LZMA  0x30101 | 
|---|
| 22 | #define k_BCJ   0x03030103 | 
|---|
| 23 | #define k_PPC   0x03030205 | 
|---|
| 24 | #define k_ARM   0x03030501 | 
|---|
| 25 | #define k_ARMT  0x03030701 | 
|---|
| 26 | #define k_SPARC 0x03030805 | 
|---|
| 27 | #define k_BCJ2  0x0303011B | 
|---|
| 28 |  | 
|---|
| 29 | #ifdef _7ZIP_PPMD_SUPPPORT | 
|---|
| 30 |  | 
|---|
| 31 | #define k_PPMD 0x30401 | 
|---|
| 32 |  | 
|---|
| 33 | typedef struct | 
|---|
| 34 | { | 
|---|
| 35 | IByteIn p; | 
|---|
| 36 | const Byte *cur; | 
|---|
| 37 | const Byte *end; | 
|---|
| 38 | const Byte *begin; | 
|---|
| 39 | UInt64 processed; | 
|---|
| 40 | Bool extra; | 
|---|
| 41 | SRes res; | 
|---|
| 42 | ILookInStream *inStream; | 
|---|
| 43 | } CByteInToLook; | 
|---|
| 44 |  | 
|---|
| 45 | static Byte ReadByte(void *pp) | 
|---|
| 46 | { | 
|---|
| 47 | CByteInToLook *p = (CByteInToLook *)pp; | 
|---|
| 48 | if (p->cur != p->end) | 
|---|
| 49 | return *p->cur++; | 
|---|
| 50 | if (p->res == SZ_OK) | 
|---|
| 51 | { | 
|---|
| 52 | size_t size = p->cur - p->begin; | 
|---|
| 53 | p->processed += size; | 
|---|
| 54 | p->res = p->inStream->Skip(p->inStream, size); | 
|---|
| 55 | size = (1 << 25); | 
|---|
| 56 | p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); | 
|---|
| 57 | p->cur = p->begin; | 
|---|
| 58 | p->end = p->begin + size; | 
|---|
| 59 | if (size != 0) | 
|---|
| 60 | return *p->cur++;; | 
|---|
| 61 | } | 
|---|
| 62 | p->extra = True; | 
|---|
| 63 | return 0; | 
|---|
| 64 | } | 
|---|
| 65 |  | 
|---|
| 66 | static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, | 
|---|
| 67 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) | 
|---|
| 68 | { | 
|---|
| 69 | CPpmd7 ppmd; | 
|---|
| 70 | CByteInToLook s; | 
|---|
| 71 | SRes res = SZ_OK; | 
|---|
| 72 |  | 
|---|
| 73 | s.p.Read = ReadByte; | 
|---|
| 74 | s.inStream = inStream; | 
|---|
| 75 | s.begin = s.end = s.cur = NULL; | 
|---|
| 76 | s.extra = False; | 
|---|
| 77 | s.res = SZ_OK; | 
|---|
| 78 | s.processed = 0; | 
|---|
| 79 |  | 
|---|
| 80 | if (coder->Props.size != 5) | 
|---|
| 81 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 82 |  | 
|---|
| 83 | { | 
|---|
| 84 | unsigned order = coder->Props.data[0]; | 
|---|
| 85 | UInt32 memSize = GetUi32(coder->Props.data + 1); | 
|---|
| 86 | if (order < PPMD7_MIN_ORDER || | 
|---|
| 87 | order > PPMD7_MAX_ORDER || | 
|---|
| 88 | memSize < PPMD7_MIN_MEM_SIZE || | 
|---|
| 89 | memSize > PPMD7_MAX_MEM_SIZE) | 
|---|
| 90 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 91 | Ppmd7_Construct(&ppmd); | 
|---|
| 92 | if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) | 
|---|
| 93 | return SZ_ERROR_MEM; | 
|---|
| 94 | Ppmd7_Init(&ppmd, order); | 
|---|
| 95 | } | 
|---|
| 96 | { | 
|---|
| 97 | CPpmd7z_RangeDec rc; | 
|---|
| 98 | Ppmd7z_RangeDec_CreateVTable(&rc); | 
|---|
| 99 | rc.Stream = &s.p; | 
|---|
| 100 | if (!Ppmd7z_RangeDec_Init(&rc)) | 
|---|
| 101 | res = SZ_ERROR_DATA; | 
|---|
| 102 | else if (s.extra) | 
|---|
| 103 | res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); | 
|---|
| 104 | else | 
|---|
| 105 | { | 
|---|
| 106 | SizeT i; | 
|---|
| 107 | for (i = 0; i < outSize; i++) | 
|---|
| 108 | { | 
|---|
| 109 | int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); | 
|---|
| 110 | if (s.extra || sym < 0) | 
|---|
| 111 | break; | 
|---|
| 112 | outBuffer[i] = (Byte)sym; | 
|---|
| 113 | } | 
|---|
| 114 | if (i != outSize) | 
|---|
| 115 | res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); | 
|---|
| 116 | else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) | 
|---|
| 117 | res = SZ_ERROR_DATA; | 
|---|
| 118 | } | 
|---|
| 119 | } | 
|---|
| 120 | Ppmd7_Free(&ppmd, allocMain); | 
|---|
| 121 | return res; | 
|---|
| 122 | } | 
|---|
| 123 |  | 
|---|
| 124 | #endif | 
|---|
| 125 |  | 
|---|
| 126 |  | 
|---|
| 127 | static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, | 
|---|
| 128 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) | 
|---|
| 129 | { | 
|---|
| 130 | CLzmaDec state; | 
|---|
| 131 | SRes res = SZ_OK; | 
|---|
| 132 |  | 
|---|
| 133 | LzmaDec_Construct(&state); | 
|---|
| 134 | RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); | 
|---|
| 135 | state.dic = outBuffer; | 
|---|
| 136 | state.dicBufSize = outSize; | 
|---|
| 137 | LzmaDec_Init(&state); | 
|---|
| 138 |  | 
|---|
| 139 | for (;;) | 
|---|
| 140 | { | 
|---|
| 141 | Byte *inBuf = NULL; | 
|---|
| 142 | size_t lookahead = (1 << 18); | 
|---|
| 143 | if (lookahead > inSize) | 
|---|
| 144 | lookahead = (size_t)inSize; | 
|---|
| 145 | res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); | 
|---|
| 146 | if (res != SZ_OK) | 
|---|
| 147 | break; | 
|---|
| 148 |  | 
|---|
| 149 | { | 
|---|
| 150 | SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; | 
|---|
| 151 | ELzmaStatus status; | 
|---|
| 152 | res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); | 
|---|
| 153 | lookahead -= inProcessed; | 
|---|
| 154 | inSize -= inProcessed; | 
|---|
| 155 | if (res != SZ_OK) | 
|---|
| 156 | break; | 
|---|
| 157 | if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) | 
|---|
| 158 | { | 
|---|
| 159 | if (state.dicBufSize != outSize || lookahead != 0 || | 
|---|
| 160 | (status != LZMA_STATUS_FINISHED_WITH_MARK && | 
|---|
| 161 | status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) | 
|---|
| 162 | res = SZ_ERROR_DATA; | 
|---|
| 163 | break; | 
|---|
| 164 | } | 
|---|
| 165 | res = inStream->Skip((void *)inStream, inProcessed); | 
|---|
| 166 | if (res != SZ_OK) | 
|---|
| 167 | break; | 
|---|
| 168 | } | 
|---|
| 169 | } | 
|---|
| 170 |  | 
|---|
| 171 | LzmaDec_FreeProbs(&state, allocMain); | 
|---|
| 172 | return res; | 
|---|
| 173 | } | 
|---|
| 174 |  | 
|---|
| 175 | static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, | 
|---|
| 176 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) | 
|---|
| 177 | { | 
|---|
| 178 | CLzma2Dec state; | 
|---|
| 179 | SRes res = SZ_OK; | 
|---|
| 180 |  | 
|---|
| 181 | Lzma2Dec_Construct(&state); | 
|---|
| 182 | if (coder->Props.size != 1) | 
|---|
| 183 | return SZ_ERROR_DATA; | 
|---|
| 184 | RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain)); | 
|---|
| 185 | state.decoder.dic = outBuffer; | 
|---|
| 186 | state.decoder.dicBufSize = outSize; | 
|---|
| 187 | Lzma2Dec_Init(&state); | 
|---|
| 188 |  | 
|---|
| 189 | for (;;) | 
|---|
| 190 | { | 
|---|
| 191 | Byte *inBuf = NULL; | 
|---|
| 192 | size_t lookahead = (1 << 18); | 
|---|
| 193 | if (lookahead > inSize) | 
|---|
| 194 | lookahead = (size_t)inSize; | 
|---|
| 195 | res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead); | 
|---|
| 196 | if (res != SZ_OK) | 
|---|
| 197 | break; | 
|---|
| 198 |  | 
|---|
| 199 | { | 
|---|
| 200 | SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; | 
|---|
| 201 | ELzmaStatus status; | 
|---|
| 202 | res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); | 
|---|
| 203 | lookahead -= inProcessed; | 
|---|
| 204 | inSize -= inProcessed; | 
|---|
| 205 | if (res != SZ_OK) | 
|---|
| 206 | break; | 
|---|
| 207 | if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) | 
|---|
| 208 | { | 
|---|
| 209 | if (state.decoder.dicBufSize != outSize || lookahead != 0 || | 
|---|
| 210 | (status != LZMA_STATUS_FINISHED_WITH_MARK)) | 
|---|
| 211 | res = SZ_ERROR_DATA; | 
|---|
| 212 | break; | 
|---|
| 213 | } | 
|---|
| 214 | res = inStream->Skip((void *)inStream, inProcessed); | 
|---|
| 215 | if (res != SZ_OK) | 
|---|
| 216 | break; | 
|---|
| 217 | } | 
|---|
| 218 | } | 
|---|
| 219 |  | 
|---|
| 220 | Lzma2Dec_FreeProbs(&state, allocMain); | 
|---|
| 221 | return res; | 
|---|
| 222 | } | 
|---|
| 223 |  | 
|---|
| 224 | static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) | 
|---|
| 225 | { | 
|---|
| 226 | while (inSize > 0) | 
|---|
| 227 | { | 
|---|
| 228 | void *inBuf; | 
|---|
| 229 | size_t curSize = (1 << 18); | 
|---|
| 230 | if (curSize > inSize) | 
|---|
| 231 | curSize = (size_t)inSize; | 
|---|
| 232 | RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize)); | 
|---|
| 233 | if (curSize == 0) | 
|---|
| 234 | return SZ_ERROR_INPUT_EOF; | 
|---|
| 235 | memcpy(outBuffer, inBuf, curSize); | 
|---|
| 236 | outBuffer += curSize; | 
|---|
| 237 | inSize -= curSize; | 
|---|
| 238 | RINOK(inStream->Skip((void *)inStream, curSize)); | 
|---|
| 239 | } | 
|---|
| 240 | return SZ_OK; | 
|---|
| 241 | } | 
|---|
| 242 |  | 
|---|
| 243 | static Bool IS_MAIN_METHOD(UInt32 m) | 
|---|
| 244 | { | 
|---|
| 245 | switch(m) | 
|---|
| 246 | { | 
|---|
| 247 | case k_Copy: | 
|---|
| 248 | case k_LZMA: | 
|---|
| 249 | case k_LZMA2: | 
|---|
| 250 | #ifdef _7ZIP_PPMD_SUPPPORT | 
|---|
| 251 | case k_PPMD: | 
|---|
| 252 | #endif | 
|---|
| 253 | return True; | 
|---|
| 254 | } | 
|---|
| 255 | return False; | 
|---|
| 256 | } | 
|---|
| 257 |  | 
|---|
| 258 | static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) | 
|---|
| 259 | { | 
|---|
| 260 | return | 
|---|
| 261 | c->NumInStreams == 1 && | 
|---|
| 262 | c->NumOutStreams == 1 && | 
|---|
| 263 | c->MethodID <= (UInt32)0xFFFFFFFF && | 
|---|
| 264 | IS_MAIN_METHOD((UInt32)c->MethodID); | 
|---|
| 265 | } | 
|---|
| 266 |  | 
|---|
| 267 | #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1) | 
|---|
| 268 |  | 
|---|
| 269 | static SRes CheckSupportedFolder(const CSzFolder *f) | 
|---|
| 270 | { | 
|---|
| 271 | if (f->NumCoders < 1 || f->NumCoders > 4) | 
|---|
| 272 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 273 | if (!IS_SUPPORTED_CODER(&f->Coders[0])) | 
|---|
| 274 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 275 | if (f->NumCoders == 1) | 
|---|
| 276 | { | 
|---|
| 277 | if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) | 
|---|
| 278 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 279 | return SZ_OK; | 
|---|
| 280 | } | 
|---|
| 281 | if (f->NumCoders == 2) | 
|---|
| 282 | { | 
|---|
| 283 | CSzCoderInfo *c = &f->Coders[1]; | 
|---|
| 284 | if (c->MethodID > (UInt32)0xFFFFFFFF || | 
|---|
| 285 | c->NumInStreams != 1 || | 
|---|
| 286 | c->NumOutStreams != 1 || | 
|---|
| 287 | f->NumPackStreams != 1 || | 
|---|
| 288 | f->PackStreams[0] != 0 || | 
|---|
| 289 | f->NumBindPairs != 1 || | 
|---|
| 290 | f->BindPairs[0].InIndex != 1 || | 
|---|
| 291 | f->BindPairs[0].OutIndex != 0) | 
|---|
| 292 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 293 | switch ((UInt32)c->MethodID) | 
|---|
| 294 | { | 
|---|
| 295 | case k_BCJ: | 
|---|
| 296 | case k_ARM: | 
|---|
| 297 | break; | 
|---|
| 298 | default: | 
|---|
| 299 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 300 | } | 
|---|
| 301 | return SZ_OK; | 
|---|
| 302 | } | 
|---|
| 303 | if (f->NumCoders == 4) | 
|---|
| 304 | { | 
|---|
| 305 | if (!IS_SUPPORTED_CODER(&f->Coders[1]) || | 
|---|
| 306 | !IS_SUPPORTED_CODER(&f->Coders[2]) || | 
|---|
| 307 | !IS_BCJ2(&f->Coders[3])) | 
|---|
| 308 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 309 | if (f->NumPackStreams != 4 || | 
|---|
| 310 | f->PackStreams[0] != 2 || | 
|---|
| 311 | f->PackStreams[1] != 6 || | 
|---|
| 312 | f->PackStreams[2] != 1 || | 
|---|
| 313 | f->PackStreams[3] != 0 || | 
|---|
| 314 | f->NumBindPairs != 3 || | 
|---|
| 315 | f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || | 
|---|
| 316 | f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || | 
|---|
| 317 | f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) | 
|---|
| 318 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 319 | return SZ_OK; | 
|---|
| 320 | } | 
|---|
| 321 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 322 | } | 
|---|
| 323 |  | 
|---|
| 324 | static UInt64 GetSum(const UInt64 *values, UInt32 index) | 
|---|
| 325 | { | 
|---|
| 326 | UInt64 sum = 0; | 
|---|
| 327 | UInt32 i; | 
|---|
| 328 | for (i = 0; i < index; i++) | 
|---|
| 329 | sum += values[i]; | 
|---|
| 330 | return sum; | 
|---|
| 331 | } | 
|---|
| 332 |  | 
|---|
| 333 | #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; | 
|---|
| 334 |  | 
|---|
| 335 | static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes, | 
|---|
| 336 | ILookInStream *inStream, UInt64 startPos, | 
|---|
| 337 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, | 
|---|
| 338 | Byte *tempBuf[]) | 
|---|
| 339 | { | 
|---|
| 340 | UInt32 ci; | 
|---|
| 341 | SizeT tempSizes[3] = { 0, 0, 0}; | 
|---|
| 342 | SizeT tempSize3 = 0; | 
|---|
| 343 | Byte *tempBuf3 = 0; | 
|---|
| 344 |  | 
|---|
| 345 | RINOK(CheckSupportedFolder(folder)); | 
|---|
| 346 |  | 
|---|
| 347 | for (ci = 0; ci < folder->NumCoders; ci++) | 
|---|
| 348 | { | 
|---|
| 349 | CSzCoderInfo *coder = &folder->Coders[ci]; | 
|---|
| 350 |  | 
|---|
| 351 | if (IS_MAIN_METHOD((UInt32)coder->MethodID)) | 
|---|
| 352 | { | 
|---|
| 353 | UInt32 si = 0; | 
|---|
| 354 | UInt64 offset; | 
|---|
| 355 | UInt64 inSize; | 
|---|
| 356 | Byte *outBufCur = outBuffer; | 
|---|
| 357 | SizeT outSizeCur = outSize; | 
|---|
| 358 | if (folder->NumCoders == 4) | 
|---|
| 359 | { | 
|---|
| 360 | UInt32 indices[] = { 3, 2, 0 }; | 
|---|
| 361 | UInt64 unpackSize = folder->UnpackSizes[ci]; | 
|---|
| 362 | si = indices[ci]; | 
|---|
| 363 | if (ci < 2) | 
|---|
| 364 | { | 
|---|
| 365 | Byte *temp; | 
|---|
| 366 | outSizeCur = (SizeT)unpackSize; | 
|---|
| 367 | if (outSizeCur != unpackSize) | 
|---|
| 368 | return SZ_ERROR_MEM; | 
|---|
| 369 | temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); | 
|---|
| 370 | if (temp == 0 && outSizeCur != 0) | 
|---|
| 371 | return SZ_ERROR_MEM; | 
|---|
| 372 | outBufCur = tempBuf[1 - ci] = temp; | 
|---|
| 373 | tempSizes[1 - ci] = outSizeCur; | 
|---|
| 374 | } | 
|---|
| 375 | else if (ci == 2) | 
|---|
| 376 | { | 
|---|
| 377 | if (unpackSize > outSize) /* check it */ | 
|---|
| 378 | return SZ_ERROR_PARAM; | 
|---|
| 379 | tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); | 
|---|
| 380 | tempSize3 = outSizeCur = (SizeT)unpackSize; | 
|---|
| 381 | } | 
|---|
| 382 | else | 
|---|
| 383 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 384 | } | 
|---|
| 385 | offset = GetSum(packSizes, si); | 
|---|
| 386 | inSize = packSizes[si]; | 
|---|
| 387 | RINOK(LookInStream_SeekTo(inStream, startPos + offset)); | 
|---|
| 388 |  | 
|---|
| 389 | if (coder->MethodID == k_Copy) | 
|---|
| 390 | { | 
|---|
| 391 | if (inSize != outSizeCur) /* check it */ | 
|---|
| 392 | return SZ_ERROR_DATA; | 
|---|
| 393 | RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); | 
|---|
| 394 | } | 
|---|
| 395 | else if (coder->MethodID == k_LZMA) | 
|---|
| 396 | { | 
|---|
| 397 | RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); | 
|---|
| 398 | } | 
|---|
| 399 | else if (coder->MethodID == k_LZMA2) | 
|---|
| 400 | { | 
|---|
| 401 | RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); | 
|---|
| 402 | } | 
|---|
| 403 | else | 
|---|
| 404 | { | 
|---|
| 405 | #ifdef _7ZIP_PPMD_SUPPPORT | 
|---|
| 406 | RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); | 
|---|
| 407 | #else | 
|---|
| 408 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 409 | #endif | 
|---|
| 410 | } | 
|---|
| 411 | } | 
|---|
| 412 | else if (coder->MethodID == k_BCJ2) | 
|---|
| 413 | { | 
|---|
| 414 | UInt64 offset = GetSum(packSizes, 1); | 
|---|
| 415 | UInt64 s3Size = packSizes[1]; | 
|---|
| 416 | SRes res; | 
|---|
| 417 | if (ci != 3) | 
|---|
| 418 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 419 | RINOK(LookInStream_SeekTo(inStream, startPos + offset)); | 
|---|
| 420 | tempSizes[2] = (SizeT)s3Size; | 
|---|
| 421 | if (tempSizes[2] != s3Size) | 
|---|
| 422 | return SZ_ERROR_MEM; | 
|---|
| 423 | tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); | 
|---|
| 424 | if (tempBuf[2] == 0 && tempSizes[2] != 0) | 
|---|
| 425 | return SZ_ERROR_MEM; | 
|---|
| 426 | res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); | 
|---|
| 427 | RINOK(res) | 
|---|
| 428 |  | 
|---|
| 429 | res = Bcj2_Decode( | 
|---|
| 430 | tempBuf3, tempSize3, | 
|---|
| 431 | tempBuf[0], tempSizes[0], | 
|---|
| 432 | tempBuf[1], tempSizes[1], | 
|---|
| 433 | tempBuf[2], tempSizes[2], | 
|---|
| 434 | outBuffer, outSize); | 
|---|
| 435 | RINOK(res) | 
|---|
| 436 | } | 
|---|
| 437 | else | 
|---|
| 438 | { | 
|---|
| 439 | if (ci != 1) | 
|---|
| 440 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 441 | switch(coder->MethodID) | 
|---|
| 442 | { | 
|---|
| 443 | case k_BCJ: | 
|---|
| 444 | { | 
|---|
| 445 | UInt32 state; | 
|---|
| 446 | x86_Convert_Init(state); | 
|---|
| 447 | x86_Convert(outBuffer, outSize, 0, &state, 0); | 
|---|
| 448 | break; | 
|---|
| 449 | } | 
|---|
| 450 | CASE_BRA_CONV(ARM) | 
|---|
| 451 | default: | 
|---|
| 452 | return SZ_ERROR_UNSUPPORTED; | 
|---|
| 453 | } | 
|---|
| 454 | } | 
|---|
| 455 | } | 
|---|
| 456 | return SZ_OK; | 
|---|
| 457 | } | 
|---|
| 458 |  | 
|---|
| 459 | SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes, | 
|---|
| 460 | ILookInStream *inStream, UInt64 startPos, | 
|---|
| 461 | Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) | 
|---|
| 462 | { | 
|---|
| 463 | Byte *tempBuf[3] = { 0, 0, 0}; | 
|---|
| 464 | int i; | 
|---|
| 465 | SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos, | 
|---|
| 466 | outBuffer, (SizeT)outSize, allocMain, tempBuf); | 
|---|
| 467 | for (i = 0; i < 3; i++) | 
|---|
| 468 | IAlloc_Free(allocMain, tempBuf[i]); | 
|---|
| 469 | return res; | 
|---|
| 470 | } | 
|---|
| 471 |  | 
|---|