Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5728 | serge | 1 | /* 7zDec.c -- Decoding from 7z folder |
2 | 2015-08-01 : Igor Pavlov : Public domain */ |
||
3 | |||
4 | #include "Precomp.h" |
||
5 | |||
6 | #include |
||
7 | |||
8 | /* #define _7ZIP_PPMD_SUPPPORT */ |
||
9 | |||
10 | #include "7z.h" |
||
11 | |||
12 | #include "Bcj2.h" |
||
13 | #include "Bra.h" |
||
14 | #include "CpuArch.h" |
||
15 | #include "Delta.h" |
||
16 | #include "LzmaDec.h" |
||
17 | #include "Lzma2Dec.h" |
||
18 | #ifdef _7ZIP_PPMD_SUPPPORT |
||
19 | #include "Ppmd7.h" |
||
20 | #endif |
||
21 | |||
22 | #define k_Copy 0 |
||
23 | #define k_Delta 3 |
||
24 | #define k_LZMA2 0x21 |
||
25 | #define k_LZMA 0x30101 |
||
26 | #define k_BCJ 0x3030103 |
||
27 | #define k_BCJ2 0x303011B |
||
28 | #define k_PPC 0x3030205 |
||
29 | #define k_IA64 0x3030401 |
||
30 | #define k_ARM 0x3030501 |
||
31 | #define k_ARMT 0x3030701 |
||
32 | #define k_SPARC 0x3030805 |
||
33 | |||
34 | |||
35 | #ifdef _7ZIP_PPMD_SUPPPORT |
||
36 | |||
37 | #define k_PPMD 0x30401 |
||
38 | |||
39 | typedef struct |
||
40 | { |
||
41 | IByteIn p; |
||
42 | const Byte *cur; |
||
43 | const Byte *end; |
||
44 | const Byte *begin; |
||
45 | UInt64 processed; |
||
46 | Bool extra; |
||
47 | SRes res; |
||
48 | ILookInStream *inStream; |
||
49 | } CByteInToLook; |
||
50 | |||
51 | static Byte ReadByte(void *pp) |
||
52 | { |
||
53 | CByteInToLook *p = (CByteInToLook *)pp; |
||
54 | if (p->cur != p->end) |
||
55 | return *p->cur++; |
||
56 | if (p->res == SZ_OK) |
||
57 | { |
||
58 | size_t size = p->cur - p->begin; |
||
59 | p->processed += size; |
||
60 | p->res = p->inStream->Skip(p->inStream, size); |
||
61 | size = (1 << 25); |
||
62 | p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size); |
||
63 | p->cur = p->begin; |
||
64 | p->end = p->begin + size; |
||
65 | if (size != 0) |
||
66 | return *p->cur++;; |
||
67 | } |
||
68 | p->extra = True; |
||
69 | return 0; |
||
70 | } |
||
71 | |||
72 | static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, |
||
73 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) |
||
74 | { |
||
75 | CPpmd7 ppmd; |
||
76 | CByteInToLook s; |
||
77 | SRes res = SZ_OK; |
||
78 | |||
79 | s.p.Read = ReadByte; |
||
80 | s.inStream = inStream; |
||
81 | s.begin = s.end = s.cur = NULL; |
||
82 | s.extra = False; |
||
83 | s.res = SZ_OK; |
||
84 | s.processed = 0; |
||
85 | |||
86 | if (propsSize != 5) |
||
87 | return SZ_ERROR_UNSUPPORTED; |
||
88 | |||
89 | { |
||
90 | unsigned order = props[0]; |
||
91 | UInt32 memSize = GetUi32(props + 1); |
||
92 | if (order < PPMD7_MIN_ORDER || |
||
93 | order > PPMD7_MAX_ORDER || |
||
94 | memSize < PPMD7_MIN_MEM_SIZE || |
||
95 | memSize > PPMD7_MAX_MEM_SIZE) |
||
96 | return SZ_ERROR_UNSUPPORTED; |
||
97 | Ppmd7_Construct(&ppmd); |
||
98 | if (!Ppmd7_Alloc(&ppmd, memSize, allocMain)) |
||
99 | return SZ_ERROR_MEM; |
||
100 | Ppmd7_Init(&ppmd, order); |
||
101 | } |
||
102 | { |
||
103 | CPpmd7z_RangeDec rc; |
||
104 | Ppmd7z_RangeDec_CreateVTable(&rc); |
||
105 | rc.Stream = &s.p; |
||
106 | if (!Ppmd7z_RangeDec_Init(&rc)) |
||
107 | res = SZ_ERROR_DATA; |
||
108 | else if (s.extra) |
||
109 | res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); |
||
110 | else |
||
111 | { |
||
112 | SizeT i; |
||
113 | for (i = 0; i < outSize; i++) |
||
114 | { |
||
115 | int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p); |
||
116 | if (s.extra || sym < 0) |
||
117 | break; |
||
118 | outBuffer[i] = (Byte)sym; |
||
119 | } |
||
120 | if (i != outSize) |
||
121 | res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA); |
||
122 | else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc)) |
||
123 | res = SZ_ERROR_DATA; |
||
124 | } |
||
125 | } |
||
126 | Ppmd7_Free(&ppmd, allocMain); |
||
127 | return res; |
||
128 | } |
||
129 | |||
130 | #endif |
||
131 | |||
132 | |||
133 | static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, |
||
134 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) |
||
135 | { |
||
136 | CLzmaDec state; |
||
137 | SRes res = SZ_OK; |
||
138 | |||
139 | LzmaDec_Construct(&state); |
||
140 | RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain)); |
||
141 | state.dic = outBuffer; |
||
142 | state.dicBufSize = outSize; |
||
143 | LzmaDec_Init(&state); |
||
144 | |||
145 | for (;;) |
||
146 | { |
||
147 | const void *inBuf = NULL; |
||
148 | size_t lookahead = (1 << 18); |
||
149 | if (lookahead > inSize) |
||
150 | lookahead = (size_t)inSize; |
||
151 | res = inStream->Look(inStream, &inBuf, &lookahead); |
||
152 | if (res != SZ_OK) |
||
153 | break; |
||
154 | |||
155 | { |
||
156 | SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; |
||
157 | ELzmaStatus status; |
||
158 | res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); |
||
159 | lookahead -= inProcessed; |
||
160 | inSize -= inProcessed; |
||
161 | if (res != SZ_OK) |
||
162 | break; |
||
163 | if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) |
||
164 | { |
||
165 | if (state.dicBufSize != outSize || lookahead != 0 || |
||
166 | (status != LZMA_STATUS_FINISHED_WITH_MARK && |
||
167 | status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) |
||
168 | res = SZ_ERROR_DATA; |
||
169 | break; |
||
170 | } |
||
171 | res = inStream->Skip((void *)inStream, inProcessed); |
||
172 | if (res != SZ_OK) |
||
173 | break; |
||
174 | } |
||
175 | } |
||
176 | |||
177 | LzmaDec_FreeProbs(&state, allocMain); |
||
178 | return res; |
||
179 | } |
||
180 | |||
181 | |||
182 | #ifndef _7Z_NO_METHOD_LZMA2 |
||
183 | |||
184 | static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream, |
||
185 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) |
||
186 | { |
||
187 | CLzma2Dec state; |
||
188 | SRes res = SZ_OK; |
||
189 | |||
190 | Lzma2Dec_Construct(&state); |
||
191 | if (propsSize != 1) |
||
192 | return SZ_ERROR_DATA; |
||
193 | RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain)); |
||
194 | state.decoder.dic = outBuffer; |
||
195 | state.decoder.dicBufSize = outSize; |
||
196 | Lzma2Dec_Init(&state); |
||
197 | |||
198 | for (;;) |
||
199 | { |
||
200 | const void *inBuf = NULL; |
||
201 | size_t lookahead = (1 << 18); |
||
202 | if (lookahead > inSize) |
||
203 | lookahead = (size_t)inSize; |
||
204 | res = inStream->Look(inStream, &inBuf, &lookahead); |
||
205 | if (res != SZ_OK) |
||
206 | break; |
||
207 | |||
208 | { |
||
209 | SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos; |
||
210 | ELzmaStatus status; |
||
211 | res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); |
||
212 | lookahead -= inProcessed; |
||
213 | inSize -= inProcessed; |
||
214 | if (res != SZ_OK) |
||
215 | break; |
||
216 | if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos)) |
||
217 | { |
||
218 | if (state.decoder.dicBufSize != outSize || lookahead != 0 || |
||
219 | (status != LZMA_STATUS_FINISHED_WITH_MARK)) |
||
220 | res = SZ_ERROR_DATA; |
||
221 | break; |
||
222 | } |
||
223 | res = inStream->Skip((void *)inStream, inProcessed); |
||
224 | if (res != SZ_OK) |
||
225 | break; |
||
226 | } |
||
227 | } |
||
228 | |||
229 | Lzma2Dec_FreeProbs(&state, allocMain); |
||
230 | return res; |
||
231 | } |
||
232 | |||
233 | #endif |
||
234 | |||
235 | |||
236 | static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) |
||
237 | { |
||
238 | while (inSize > 0) |
||
239 | { |
||
240 | const void *inBuf; |
||
241 | size_t curSize = (1 << 18); |
||
242 | if (curSize > inSize) |
||
243 | curSize = (size_t)inSize; |
||
244 | RINOK(inStream->Look(inStream, &inBuf, &curSize)); |
||
245 | if (curSize == 0) |
||
246 | return SZ_ERROR_INPUT_EOF; |
||
247 | memcpy(outBuffer, inBuf, curSize); |
||
248 | outBuffer += curSize; |
||
249 | inSize -= curSize; |
||
250 | RINOK(inStream->Skip((void *)inStream, curSize)); |
||
251 | } |
||
252 | return SZ_OK; |
||
253 | } |
||
254 | |||
255 | static Bool IS_MAIN_METHOD(UInt32 m) |
||
256 | { |
||
257 | switch (m) |
||
258 | { |
||
259 | case k_Copy: |
||
260 | case k_LZMA: |
||
261 | #ifndef _7Z_NO_METHOD_LZMA2 |
||
262 | case k_LZMA2: |
||
263 | #endif |
||
264 | #ifdef _7ZIP_PPMD_SUPPPORT |
||
265 | case k_PPMD: |
||
266 | #endif |
||
267 | return True; |
||
268 | } |
||
269 | return False; |
||
270 | } |
||
271 | |||
272 | static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c) |
||
273 | { |
||
274 | return |
||
275 | c->NumStreams == 1 |
||
276 | /* && c->MethodID <= (UInt32)0xFFFFFFFF */ |
||
277 | && IS_MAIN_METHOD((UInt32)c->MethodID); |
||
278 | } |
||
279 | |||
280 | #define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4) |
||
281 | |||
282 | static SRes CheckSupportedFolder(const CSzFolder *f) |
||
283 | { |
||
284 | if (f->NumCoders < 1 || f->NumCoders > 4) |
||
285 | return SZ_ERROR_UNSUPPORTED; |
||
286 | if (!IS_SUPPORTED_CODER(&f->Coders[0])) |
||
287 | return SZ_ERROR_UNSUPPORTED; |
||
288 | if (f->NumCoders == 1) |
||
289 | { |
||
290 | if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0) |
||
291 | return SZ_ERROR_UNSUPPORTED; |
||
292 | return SZ_OK; |
||
293 | } |
||
294 | |||
295 | |||
296 | #ifndef _7Z_NO_METHODS_FILTERS |
||
297 | |||
298 | if (f->NumCoders == 2) |
||
299 | { |
||
300 | const CSzCoderInfo *c = &f->Coders[1]; |
||
301 | if ( |
||
302 | /* c->MethodID > (UInt32)0xFFFFFFFF || */ |
||
303 | c->NumStreams != 1 |
||
304 | || f->NumPackStreams != 1 |
||
305 | || f->PackStreams[0] != 0 |
||
306 | || f->NumBonds != 1 |
||
307 | || f->Bonds[0].InIndex != 1 |
||
308 | || f->Bonds[0].OutIndex != 0) |
||
309 | return SZ_ERROR_UNSUPPORTED; |
||
310 | switch ((UInt32)c->MethodID) |
||
311 | { |
||
312 | case k_Delta: |
||
313 | case k_BCJ: |
||
314 | case k_PPC: |
||
315 | case k_IA64: |
||
316 | case k_SPARC: |
||
317 | case k_ARM: |
||
318 | case k_ARMT: |
||
319 | break; |
||
320 | default: |
||
321 | return SZ_ERROR_UNSUPPORTED; |
||
322 | } |
||
323 | return SZ_OK; |
||
324 | } |
||
325 | |||
326 | #endif |
||
327 | |||
328 | |||
329 | if (f->NumCoders == 4) |
||
330 | { |
||
331 | if (!IS_SUPPORTED_CODER(&f->Coders[1]) |
||
332 | || !IS_SUPPORTED_CODER(&f->Coders[2]) |
||
333 | || !IS_BCJ2(&f->Coders[3])) |
||
334 | return SZ_ERROR_UNSUPPORTED; |
||
335 | if (f->NumPackStreams != 4 |
||
336 | || f->PackStreams[0] != 2 |
||
337 | || f->PackStreams[1] != 6 |
||
338 | || f->PackStreams[2] != 1 |
||
339 | || f->PackStreams[3] != 0 |
||
340 | || f->NumBonds != 3 |
||
341 | || f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0 |
||
342 | || f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1 |
||
343 | || f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2) |
||
344 | return SZ_ERROR_UNSUPPORTED; |
||
345 | return SZ_OK; |
||
346 | } |
||
347 | |||
348 | return SZ_ERROR_UNSUPPORTED; |
||
349 | } |
||
350 | |||
351 | #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break; |
||
352 | |||
353 | static SRes SzFolder_Decode2(const CSzFolder *folder, |
||
354 | const Byte *propsData, |
||
355 | const UInt64 *unpackSizes, |
||
356 | const UInt64 *packPositions, |
||
357 | ILookInStream *inStream, UInt64 startPos, |
||
358 | Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, |
||
359 | Byte *tempBuf[]) |
||
360 | { |
||
361 | UInt32 ci; |
||
362 | SizeT tempSizes[3] = { 0, 0, 0}; |
||
363 | SizeT tempSize3 = 0; |
||
364 | Byte *tempBuf3 = 0; |
||
365 | |||
366 | RINOK(CheckSupportedFolder(folder)); |
||
367 | |||
368 | for (ci = 0; ci < folder->NumCoders; ci++) |
||
369 | { |
||
370 | const CSzCoderInfo *coder = &folder->Coders[ci]; |
||
371 | |||
372 | if (IS_MAIN_METHOD((UInt32)coder->MethodID)) |
||
373 | { |
||
374 | UInt32 si = 0; |
||
375 | UInt64 offset; |
||
376 | UInt64 inSize; |
||
377 | Byte *outBufCur = outBuffer; |
||
378 | SizeT outSizeCur = outSize; |
||
379 | if (folder->NumCoders == 4) |
||
380 | { |
||
381 | UInt32 indices[] = { 3, 2, 0 }; |
||
382 | UInt64 unpackSize = unpackSizes[ci]; |
||
383 | si = indices[ci]; |
||
384 | if (ci < 2) |
||
385 | { |
||
386 | Byte *temp; |
||
387 | outSizeCur = (SizeT)unpackSize; |
||
388 | if (outSizeCur != unpackSize) |
||
389 | return SZ_ERROR_MEM; |
||
390 | temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); |
||
391 | if (!temp && outSizeCur != 0) |
||
392 | return SZ_ERROR_MEM; |
||
393 | outBufCur = tempBuf[1 - ci] = temp; |
||
394 | tempSizes[1 - ci] = outSizeCur; |
||
395 | } |
||
396 | else if (ci == 2) |
||
397 | { |
||
398 | if (unpackSize > outSize) /* check it */ |
||
399 | return SZ_ERROR_PARAM; |
||
400 | tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); |
||
401 | tempSize3 = outSizeCur = (SizeT)unpackSize; |
||
402 | } |
||
403 | else |
||
404 | return SZ_ERROR_UNSUPPORTED; |
||
405 | } |
||
406 | offset = packPositions[si]; |
||
407 | inSize = packPositions[si + 1] - offset; |
||
408 | RINOK(LookInStream_SeekTo(inStream, startPos + offset)); |
||
409 | |||
410 | if (coder->MethodID == k_Copy) |
||
411 | { |
||
412 | if (inSize != outSizeCur) /* check it */ |
||
413 | return SZ_ERROR_DATA; |
||
414 | RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); |
||
415 | } |
||
416 | else if (coder->MethodID == k_LZMA) |
||
417 | { |
||
418 | RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); |
||
419 | } |
||
420 | #ifndef _7Z_NO_METHOD_LZMA2 |
||
421 | else if (coder->MethodID == k_LZMA2) |
||
422 | { |
||
423 | RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); |
||
424 | } |
||
425 | #endif |
||
426 | #ifdef _7ZIP_PPMD_SUPPPORT |
||
427 | else if (coder->MethodID == k_PPMD) |
||
428 | { |
||
429 | RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain)); |
||
430 | } |
||
431 | #endif |
||
432 | else |
||
433 | return SZ_ERROR_UNSUPPORTED; |
||
434 | } |
||
435 | else if (coder->MethodID == k_BCJ2) |
||
436 | { |
||
437 | UInt64 offset = packPositions[1]; |
||
438 | UInt64 s3Size = packPositions[2] - offset; |
||
439 | |||
440 | if (ci != 3) |
||
441 | return SZ_ERROR_UNSUPPORTED; |
||
442 | |||
443 | tempSizes[2] = (SizeT)s3Size; |
||
444 | if (tempSizes[2] != s3Size) |
||
445 | return SZ_ERROR_MEM; |
||
446 | tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); |
||
447 | if (!tempBuf[2] && tempSizes[2] != 0) |
||
448 | return SZ_ERROR_MEM; |
||
449 | |||
450 | RINOK(LookInStream_SeekTo(inStream, startPos + offset)); |
||
451 | RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2])); |
||
452 | |||
453 | if ((tempSizes[0] & 3) != 0 || |
||
454 | (tempSizes[1] & 3) != 0 || |
||
455 | tempSize3 + tempSizes[0] + tempSizes[1] != outSize) |
||
456 | return SZ_ERROR_DATA; |
||
457 | |||
458 | { |
||
459 | CBcj2Dec p; |
||
460 | |||
461 | p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3; |
||
462 | p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0]; |
||
463 | p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1]; |
||
464 | p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2]; |
||
465 | |||
466 | p.dest = outBuffer; |
||
467 | p.destLim = outBuffer + outSize; |
||
468 | |||
469 | Bcj2Dec_Init(&p); |
||
470 | RINOK(Bcj2Dec_Decode(&p)); |
||
471 | |||
472 | { |
||
473 | unsigned i; |
||
474 | for (i = 0; i < 4; i++) |
||
475 | if (p.bufs[i] != p.lims[i]) |
||
476 | return SZ_ERROR_DATA; |
||
477 | |||
478 | if (!Bcj2Dec_IsFinished(&p)) |
||
479 | return SZ_ERROR_DATA; |
||
480 | |||
481 | if (p.dest != p.destLim |
||
482 | || p.state != BCJ2_STREAM_MAIN) |
||
483 | return SZ_ERROR_DATA; |
||
484 | } |
||
485 | } |
||
486 | } |
||
487 | #ifndef _7Z_NO_METHODS_FILTERS |
||
488 | else if (ci == 1) |
||
489 | { |
||
490 | if (coder->MethodID == k_Delta) |
||
491 | { |
||
492 | if (coder->PropsSize != 1) |
||
493 | return SZ_ERROR_UNSUPPORTED; |
||
494 | { |
||
495 | Byte state[DELTA_STATE_SIZE]; |
||
496 | Delta_Init(state); |
||
497 | Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize); |
||
498 | } |
||
499 | } |
||
500 | else |
||
501 | { |
||
502 | if (coder->PropsSize != 0) |
||
503 | return SZ_ERROR_UNSUPPORTED; |
||
504 | switch (coder->MethodID) |
||
505 | { |
||
506 | case k_BCJ: |
||
507 | { |
||
508 | UInt32 state; |
||
509 | x86_Convert_Init(state); |
||
510 | x86_Convert(outBuffer, outSize, 0, &state, 0); |
||
511 | break; |
||
512 | } |
||
513 | CASE_BRA_CONV(PPC) |
||
514 | CASE_BRA_CONV(IA64) |
||
515 | CASE_BRA_CONV(SPARC) |
||
516 | CASE_BRA_CONV(ARM) |
||
517 | CASE_BRA_CONV(ARMT) |
||
518 | default: |
||
519 | return SZ_ERROR_UNSUPPORTED; |
||
520 | } |
||
521 | } |
||
522 | } |
||
523 | #endif |
||
524 | else |
||
525 | return SZ_ERROR_UNSUPPORTED; |
||
526 | } |
||
527 | |||
528 | return SZ_OK; |
||
529 | } |
||
530 | |||
531 | |||
532 | SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex, |
||
533 | ILookInStream *inStream, UInt64 startPos, |
||
534 | Byte *outBuffer, size_t outSize, |
||
535 | ISzAlloc *allocMain) |
||
536 | { |
||
537 | SRes res; |
||
538 | CSzFolder folder; |
||
539 | CSzData sd; |
||
540 | CSzData sdSizes; |
||
541 | |||
542 | const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex]; |
||
543 | sd.Data = data; |
||
544 | sd.Size = p->FoCodersOffsets[folderIndex + 1] - p->FoCodersOffsets[folderIndex]; |
||
545 | |||
546 | sdSizes.Data = p->UnpackSizesData + p->FoSizesOffsets[folderIndex]; |
||
547 | sdSizes.Size = |
||
548 | p->FoSizesOffsets[folderIndex + 1] - |
||
549 | p->FoSizesOffsets[folderIndex]; |
||
550 | |||
551 | res = SzGetNextFolderItem(&folder, &sd, &sdSizes); |
||
552 | |||
553 | if (res != SZ_OK) |
||
554 | return res; |
||
555 | |||
556 | if (sd.Size != 0 || outSize != folder.CodersUnpackSizes[folder.UnpackStream]) |
||
557 | return SZ_ERROR_FAIL; |
||
558 | { |
||
559 | unsigned i; |
||
560 | Byte *tempBuf[3] = { 0, 0, 0}; |
||
561 | res = SzFolder_Decode2(&folder, data, folder.CodersUnpackSizes, |
||
562 | p->PackPositions + p->FoStartPackStreamIndex[folderIndex], |
||
563 | inStream, startPos, |
||
564 | outBuffer, (SizeT)outSize, allocMain, tempBuf); |
||
565 | for (i = 0; i < 3; i++) |
||
566 | IAlloc_Free(allocMain, tempBuf[i]); |
||
567 | return res; |
||
568 | } |
||
569 | }>>>>>=>><>><>><>>>>>><> |