diff options
Diffstat (limited to '')
-rw-r--r-- | C/XzDec.c | 2837 |
1 files changed, 2837 insertions, 0 deletions
diff --git a/C/XzDec.c b/C/XzDec.c new file mode 100644 index 0000000..3f96a37 --- /dev/null +++ b/C/XzDec.c | |||
@@ -0,0 +1,2837 @@ | |||
1 | /* XzDec.c -- Xz Decode | ||
2 | 2021-09-04 : Igor Pavlov : Public domain */ | ||
3 | |||
4 | #include "Precomp.h" | ||
5 | |||
6 | // #include <stdio.h> | ||
7 | |||
8 | // #define XZ_DUMP | ||
9 | |||
10 | /* #define XZ_DUMP */ | ||
11 | |||
12 | #ifdef XZ_DUMP | ||
13 | #include <stdio.h> | ||
14 | #endif | ||
15 | |||
16 | // #define SHOW_DEBUG_INFO | ||
17 | |||
18 | #ifdef SHOW_DEBUG_INFO | ||
19 | #include <stdio.h> | ||
20 | #endif | ||
21 | |||
22 | #ifdef SHOW_DEBUG_INFO | ||
23 | #define PRF(x) x | ||
24 | #else | ||
25 | #define PRF(x) | ||
26 | #endif | ||
27 | |||
28 | #define PRF_STR(s) PRF(printf("\n" s "\n")) | ||
29 | #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d)) | ||
30 | |||
31 | #include <stdlib.h> | ||
32 | #include <string.h> | ||
33 | |||
34 | #include "7zCrc.h" | ||
35 | #include "Alloc.h" | ||
36 | #include "Bra.h" | ||
37 | #include "CpuArch.h" | ||
38 | #include "Delta.h" | ||
39 | #include "Lzma2Dec.h" | ||
40 | |||
41 | // #define USE_SUBBLOCK | ||
42 | |||
43 | #ifdef USE_SUBBLOCK | ||
44 | #include "Bcj3Dec.c" | ||
45 | #include "SbDec.h" | ||
46 | #endif | ||
47 | |||
48 | #include "Xz.h" | ||
49 | |||
50 | #define XZ_CHECK_SIZE_MAX 64 | ||
51 | |||
52 | #define CODER_BUF_SIZE ((size_t)1 << 17) | ||
53 | |||
54 | unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value) | ||
55 | { | ||
56 | unsigned i, limit; | ||
57 | *value = 0; | ||
58 | limit = (maxSize > 9) ? 9 : (unsigned)maxSize; | ||
59 | |||
60 | for (i = 0; i < limit;) | ||
61 | { | ||
62 | Byte b = p[i]; | ||
63 | *value |= (UInt64)(b & 0x7F) << (7 * i++); | ||
64 | if ((b & 0x80) == 0) | ||
65 | return (b == 0 && i != 1) ? 0 : i; | ||
66 | } | ||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | /* ---------- BraState ---------- */ | ||
71 | |||
72 | #define BRA_BUF_SIZE (1 << 14) | ||
73 | |||
74 | typedef struct | ||
75 | { | ||
76 | size_t bufPos; | ||
77 | size_t bufConv; | ||
78 | size_t bufTotal; | ||
79 | |||
80 | int encodeMode; | ||
81 | |||
82 | UInt32 methodId; | ||
83 | UInt32 delta; | ||
84 | UInt32 ip; | ||
85 | UInt32 x86State; | ||
86 | Byte deltaState[DELTA_STATE_SIZE]; | ||
87 | |||
88 | Byte buf[BRA_BUF_SIZE]; | ||
89 | } CBraState; | ||
90 | |||
91 | static void BraState_Free(void *pp, ISzAllocPtr alloc) | ||
92 | { | ||
93 | ISzAlloc_Free(alloc, pp); | ||
94 | } | ||
95 | |||
96 | static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) | ||
97 | { | ||
98 | CBraState *p = ((CBraState *)pp); | ||
99 | UNUSED_VAR(alloc); | ||
100 | p->ip = 0; | ||
101 | if (p->methodId == XZ_ID_Delta) | ||
102 | { | ||
103 | if (propSize != 1) | ||
104 | return SZ_ERROR_UNSUPPORTED; | ||
105 | p->delta = (unsigned)props[0] + 1; | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | if (propSize == 4) | ||
110 | { | ||
111 | UInt32 v = GetUi32(props); | ||
112 | switch (p->methodId) | ||
113 | { | ||
114 | case XZ_ID_PPC: | ||
115 | case XZ_ID_ARM: | ||
116 | case XZ_ID_SPARC: | ||
117 | if ((v & 3) != 0) | ||
118 | return SZ_ERROR_UNSUPPORTED; | ||
119 | break; | ||
120 | case XZ_ID_ARMT: | ||
121 | if ((v & 1) != 0) | ||
122 | return SZ_ERROR_UNSUPPORTED; | ||
123 | break; | ||
124 | case XZ_ID_IA64: | ||
125 | if ((v & 0xF) != 0) | ||
126 | return SZ_ERROR_UNSUPPORTED; | ||
127 | break; | ||
128 | } | ||
129 | p->ip = v; | ||
130 | } | ||
131 | else if (propSize != 0) | ||
132 | return SZ_ERROR_UNSUPPORTED; | ||
133 | } | ||
134 | return SZ_OK; | ||
135 | } | ||
136 | |||
137 | static void BraState_Init(void *pp) | ||
138 | { | ||
139 | CBraState *p = ((CBraState *)pp); | ||
140 | p->bufPos = p->bufConv = p->bufTotal = 0; | ||
141 | x86_Convert_Init(p->x86State); | ||
142 | if (p->methodId == XZ_ID_Delta) | ||
143 | Delta_Init(p->deltaState); | ||
144 | } | ||
145 | |||
146 | |||
147 | #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break; | ||
148 | |||
149 | static SizeT BraState_Filter(void *pp, Byte *data, SizeT size) | ||
150 | { | ||
151 | CBraState *p = ((CBraState *)pp); | ||
152 | switch (p->methodId) | ||
153 | { | ||
154 | case XZ_ID_Delta: | ||
155 | if (p->encodeMode) | ||
156 | Delta_Encode(p->deltaState, p->delta, data, size); | ||
157 | else | ||
158 | Delta_Decode(p->deltaState, p->delta, data, size); | ||
159 | break; | ||
160 | case XZ_ID_X86: | ||
161 | size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode); | ||
162 | break; | ||
163 | CASE_BRA_CONV(PPC) | ||
164 | CASE_BRA_CONV(IA64) | ||
165 | CASE_BRA_CONV(ARM) | ||
166 | CASE_BRA_CONV(ARMT) | ||
167 | CASE_BRA_CONV(SPARC) | ||
168 | } | ||
169 | p->ip += (UInt32)size; | ||
170 | return size; | ||
171 | } | ||
172 | |||
173 | |||
174 | static SRes BraState_Code2(void *pp, | ||
175 | Byte *dest, SizeT *destLen, | ||
176 | const Byte *src, SizeT *srcLen, int srcWasFinished, | ||
177 | ECoderFinishMode finishMode, | ||
178 | // int *wasFinished | ||
179 | ECoderStatus *status) | ||
180 | { | ||
181 | CBraState *p = ((CBraState *)pp); | ||
182 | SizeT destRem = *destLen; | ||
183 | SizeT srcRem = *srcLen; | ||
184 | UNUSED_VAR(finishMode); | ||
185 | |||
186 | *destLen = 0; | ||
187 | *srcLen = 0; | ||
188 | // *wasFinished = False; | ||
189 | *status = CODER_STATUS_NOT_FINISHED; | ||
190 | |||
191 | while (destRem > 0) | ||
192 | { | ||
193 | if (p->bufPos != p->bufConv) | ||
194 | { | ||
195 | size_t size = p->bufConv - p->bufPos; | ||
196 | if (size > destRem) | ||
197 | size = destRem; | ||
198 | memcpy(dest, p->buf + p->bufPos, size); | ||
199 | p->bufPos += size; | ||
200 | *destLen += size; | ||
201 | dest += size; | ||
202 | destRem -= size; | ||
203 | continue; | ||
204 | } | ||
205 | |||
206 | p->bufTotal -= p->bufPos; | ||
207 | memmove(p->buf, p->buf + p->bufPos, p->bufTotal); | ||
208 | p->bufPos = 0; | ||
209 | p->bufConv = 0; | ||
210 | { | ||
211 | size_t size = BRA_BUF_SIZE - p->bufTotal; | ||
212 | if (size > srcRem) | ||
213 | size = srcRem; | ||
214 | memcpy(p->buf + p->bufTotal, src, size); | ||
215 | *srcLen += size; | ||
216 | src += size; | ||
217 | srcRem -= size; | ||
218 | p->bufTotal += size; | ||
219 | } | ||
220 | if (p->bufTotal == 0) | ||
221 | break; | ||
222 | |||
223 | p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal); | ||
224 | |||
225 | if (p->bufConv == 0) | ||
226 | { | ||
227 | if (!srcWasFinished) | ||
228 | break; | ||
229 | p->bufConv = p->bufTotal; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished) | ||
234 | { | ||
235 | *status = CODER_STATUS_FINISHED_WITH_MARK; | ||
236 | // *wasFinished = 1; | ||
237 | } | ||
238 | |||
239 | return SZ_OK; | ||
240 | } | ||
241 | |||
242 | |||
243 | SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc); | ||
244 | SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc) | ||
245 | { | ||
246 | CBraState *decoder; | ||
247 | if (id < XZ_ID_Delta || id > XZ_ID_SPARC) | ||
248 | return SZ_ERROR_UNSUPPORTED; | ||
249 | decoder = (CBraState *)p->p; | ||
250 | if (!decoder) | ||
251 | { | ||
252 | decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState)); | ||
253 | if (!decoder) | ||
254 | return SZ_ERROR_MEM; | ||
255 | p->p = decoder; | ||
256 | p->Free = BraState_Free; | ||
257 | p->SetProps = BraState_SetProps; | ||
258 | p->Init = BraState_Init; | ||
259 | p->Code2 = BraState_Code2; | ||
260 | p->Filter = BraState_Filter; | ||
261 | } | ||
262 | decoder->methodId = (UInt32)id; | ||
263 | decoder->encodeMode = encodeMode; | ||
264 | return SZ_OK; | ||
265 | } | ||
266 | |||
267 | |||
268 | |||
269 | /* ---------- SbState ---------- */ | ||
270 | |||
271 | #ifdef USE_SUBBLOCK | ||
272 | |||
273 | static void SbState_Free(void *pp, ISzAllocPtr alloc) | ||
274 | { | ||
275 | CSbDec *p = (CSbDec *)pp; | ||
276 | SbDec_Free(p); | ||
277 | ISzAlloc_Free(alloc, pp); | ||
278 | } | ||
279 | |||
280 | static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) | ||
281 | { | ||
282 | UNUSED_VAR(pp); | ||
283 | UNUSED_VAR(props); | ||
284 | UNUSED_VAR(alloc); | ||
285 | return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED; | ||
286 | } | ||
287 | |||
288 | static void SbState_Init(void *pp) | ||
289 | { | ||
290 | SbDec_Init((CSbDec *)pp); | ||
291 | } | ||
292 | |||
293 | static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, | ||
294 | int srcWasFinished, ECoderFinishMode finishMode, | ||
295 | // int *wasFinished | ||
296 | ECoderStatus *status) | ||
297 | { | ||
298 | CSbDec *p = (CSbDec *)pp; | ||
299 | SRes res; | ||
300 | UNUSED_VAR(srcWasFinished); | ||
301 | p->dest = dest; | ||
302 | p->destLen = *destLen; | ||
303 | p->src = src; | ||
304 | p->srcLen = *srcLen; | ||
305 | p->finish = finishMode; /* change it */ | ||
306 | res = SbDec_Decode((CSbDec *)pp); | ||
307 | *destLen -= p->destLen; | ||
308 | *srcLen -= p->srcLen; | ||
309 | // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */ | ||
310 | *status = (*destLen == 0 && *srcLen == 0) ? | ||
311 | CODER_STATUS_FINISHED_WITH_MARK : | ||
312 | CODER_STATUS_NOT_FINISHED; | ||
313 | return res; | ||
314 | } | ||
315 | |||
316 | static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc) | ||
317 | { | ||
318 | CSbDec *decoder = (CSbDec *)p->p; | ||
319 | if (!decoder) | ||
320 | { | ||
321 | decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec)); | ||
322 | if (!decoder) | ||
323 | return SZ_ERROR_MEM; | ||
324 | p->p = decoder; | ||
325 | p->Free = SbState_Free; | ||
326 | p->SetProps = SbState_SetProps; | ||
327 | p->Init = SbState_Init; | ||
328 | p->Code2 = SbState_Code2; | ||
329 | p->Filter = NULL; | ||
330 | } | ||
331 | SbDec_Construct(decoder); | ||
332 | SbDec_SetAlloc(decoder, alloc); | ||
333 | return SZ_OK; | ||
334 | } | ||
335 | |||
336 | #endif | ||
337 | |||
338 | |||
339 | |||
340 | /* ---------- Lzma2 ---------- */ | ||
341 | |||
342 | typedef struct | ||
343 | { | ||
344 | CLzma2Dec decoder; | ||
345 | BoolInt outBufMode; | ||
346 | } CLzma2Dec_Spec; | ||
347 | |||
348 | |||
349 | static void Lzma2State_Free(void *pp, ISzAllocPtr alloc) | ||
350 | { | ||
351 | CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; | ||
352 | if (p->outBufMode) | ||
353 | Lzma2Dec_FreeProbs(&p->decoder, alloc); | ||
354 | else | ||
355 | Lzma2Dec_Free(&p->decoder, alloc); | ||
356 | ISzAlloc_Free(alloc, pp); | ||
357 | } | ||
358 | |||
359 | static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc) | ||
360 | { | ||
361 | if (propSize != 1) | ||
362 | return SZ_ERROR_UNSUPPORTED; | ||
363 | { | ||
364 | CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp; | ||
365 | if (p->outBufMode) | ||
366 | return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc); | ||
367 | else | ||
368 | return Lzma2Dec_Allocate(&p->decoder, props[0], alloc); | ||
369 | } | ||
370 | } | ||
371 | |||
372 | static void Lzma2State_Init(void *pp) | ||
373 | { | ||
374 | Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder); | ||
375 | } | ||
376 | |||
377 | |||
378 | /* | ||
379 | if (outBufMode), then (dest) is not used. Use NULL. | ||
380 | Data is unpacked to (spec->decoder.decoder.dic) output buffer. | ||
381 | */ | ||
382 | |||
383 | static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, | ||
384 | int srcWasFinished, ECoderFinishMode finishMode, | ||
385 | // int *wasFinished, | ||
386 | ECoderStatus *status) | ||
387 | { | ||
388 | CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp; | ||
389 | ELzmaStatus status2; | ||
390 | /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */ | ||
391 | SRes res; | ||
392 | UNUSED_VAR(srcWasFinished); | ||
393 | if (spec->outBufMode) | ||
394 | { | ||
395 | SizeT dicPos = spec->decoder.decoder.dicPos; | ||
396 | SizeT dicLimit = dicPos + *destLen; | ||
397 | res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2); | ||
398 | *destLen = spec->decoder.decoder.dicPos - dicPos; | ||
399 | } | ||
400 | else | ||
401 | res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2); | ||
402 | // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK); | ||
403 | // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder | ||
404 | *status = (ECoderStatus)status2; | ||
405 | return res; | ||
406 | } | ||
407 | |||
408 | |||
409 | static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc) | ||
410 | { | ||
411 | CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; | ||
412 | if (!spec) | ||
413 | { | ||
414 | spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec)); | ||
415 | if (!spec) | ||
416 | return SZ_ERROR_MEM; | ||
417 | p->p = spec; | ||
418 | p->Free = Lzma2State_Free; | ||
419 | p->SetProps = Lzma2State_SetProps; | ||
420 | p->Init = Lzma2State_Init; | ||
421 | p->Code2 = Lzma2State_Code2; | ||
422 | p->Filter = NULL; | ||
423 | Lzma2Dec_Construct(&spec->decoder); | ||
424 | } | ||
425 | spec->outBufMode = False; | ||
426 | if (outBuf) | ||
427 | { | ||
428 | spec->outBufMode = True; | ||
429 | spec->decoder.decoder.dic = outBuf; | ||
430 | spec->decoder.decoder.dicBufSize = outBufSize; | ||
431 | } | ||
432 | return SZ_OK; | ||
433 | } | ||
434 | |||
435 | |||
436 | static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize) | ||
437 | { | ||
438 | CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p; | ||
439 | if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf)) | ||
440 | return SZ_ERROR_FAIL; | ||
441 | if (outBuf) | ||
442 | { | ||
443 | spec->decoder.decoder.dic = outBuf; | ||
444 | spec->decoder.decoder.dicBufSize = outBufSize; | ||
445 | } | ||
446 | return SZ_OK; | ||
447 | } | ||
448 | |||
449 | |||
450 | |||
451 | static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc) | ||
452 | { | ||
453 | unsigned i; | ||
454 | p->alloc = alloc; | ||
455 | p->buf = NULL; | ||
456 | p->numCoders = 0; | ||
457 | |||
458 | p->outBufSize = 0; | ||
459 | p->outBuf = NULL; | ||
460 | // p->SingleBufMode = False; | ||
461 | |||
462 | for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) | ||
463 | p->coders[i].p = NULL; | ||
464 | } | ||
465 | |||
466 | |||
467 | static void MixCoder_Free(CMixCoder *p) | ||
468 | { | ||
469 | unsigned i; | ||
470 | p->numCoders = 0; | ||
471 | for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++) | ||
472 | { | ||
473 | IStateCoder *sc = &p->coders[i]; | ||
474 | if (sc->p) | ||
475 | { | ||
476 | sc->Free(sc->p, p->alloc); | ||
477 | sc->p = NULL; | ||
478 | } | ||
479 | } | ||
480 | if (p->buf) | ||
481 | { | ||
482 | ISzAlloc_Free(p->alloc, p->buf); | ||
483 | p->buf = NULL; /* 9.31: the BUG was fixed */ | ||
484 | } | ||
485 | } | ||
486 | |||
487 | static void MixCoder_Init(CMixCoder *p) | ||
488 | { | ||
489 | unsigned i; | ||
490 | for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++) | ||
491 | { | ||
492 | p->size[i] = 0; | ||
493 | p->pos[i] = 0; | ||
494 | p->finished[i] = 0; | ||
495 | } | ||
496 | for (i = 0; i < p->numCoders; i++) | ||
497 | { | ||
498 | IStateCoder *coder = &p->coders[i]; | ||
499 | coder->Init(coder->p); | ||
500 | p->results[i] = SZ_OK; | ||
501 | } | ||
502 | p->outWritten = 0; | ||
503 | p->wasFinished = False; | ||
504 | p->res = SZ_OK; | ||
505 | p->status = CODER_STATUS_NOT_SPECIFIED; | ||
506 | } | ||
507 | |||
508 | |||
509 | static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) | ||
510 | { | ||
511 | IStateCoder *sc = &p->coders[coderIndex]; | ||
512 | p->ids[coderIndex] = methodId; | ||
513 | switch (methodId) | ||
514 | { | ||
515 | case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc); | ||
516 | #ifdef USE_SUBBLOCK | ||
517 | case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc); | ||
518 | #endif | ||
519 | } | ||
520 | if (coderIndex == 0) | ||
521 | return SZ_ERROR_UNSUPPORTED; | ||
522 | return BraState_SetFromMethod(sc, methodId, 0, p->alloc); | ||
523 | } | ||
524 | |||
525 | |||
526 | static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize) | ||
527 | { | ||
528 | IStateCoder *sc = &p->coders[coderIndex]; | ||
529 | switch (methodId) | ||
530 | { | ||
531 | case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize); | ||
532 | } | ||
533 | return SZ_ERROR_UNSUPPORTED; | ||
534 | } | ||
535 | |||
536 | |||
537 | |||
538 | /* | ||
539 | if (destFinish) - then unpack data block is finished at (*destLen) position, | ||
540 | and we can return data that were not processed by filter | ||
541 | |||
542 | output (status) can be : | ||
543 | CODER_STATUS_NOT_FINISHED | ||
544 | CODER_STATUS_FINISHED_WITH_MARK | ||
545 | CODER_STATUS_NEEDS_MORE_INPUT - not implemented still | ||
546 | */ | ||
547 | |||
548 | static SRes MixCoder_Code(CMixCoder *p, | ||
549 | Byte *dest, SizeT *destLen, int destFinish, | ||
550 | const Byte *src, SizeT *srcLen, int srcWasFinished, | ||
551 | ECoderFinishMode finishMode) | ||
552 | { | ||
553 | SizeT destLenOrig = *destLen; | ||
554 | SizeT srcLenOrig = *srcLen; | ||
555 | |||
556 | *destLen = 0; | ||
557 | *srcLen = 0; | ||
558 | |||
559 | if (p->wasFinished) | ||
560 | return p->res; | ||
561 | |||
562 | p->status = CODER_STATUS_NOT_FINISHED; | ||
563 | |||
564 | // if (p->SingleBufMode) | ||
565 | if (p->outBuf) | ||
566 | { | ||
567 | SRes res; | ||
568 | SizeT destLen2, srcLen2; | ||
569 | int wasFinished; | ||
570 | |||
571 | PRF_STR("------- MixCoder Single ----------"); | ||
572 | |||
573 | srcLen2 = srcLenOrig; | ||
574 | destLen2 = destLenOrig; | ||
575 | |||
576 | { | ||
577 | IStateCoder *coder = &p->coders[0]; | ||
578 | res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode, | ||
579 | // &wasFinished, | ||
580 | &p->status); | ||
581 | wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK); | ||
582 | } | ||
583 | |||
584 | p->res = res; | ||
585 | |||
586 | /* | ||
587 | if (wasFinished) | ||
588 | p->status = CODER_STATUS_FINISHED_WITH_MARK; | ||
589 | else | ||
590 | { | ||
591 | if (res == SZ_OK) | ||
592 | if (destLen2 != destLenOrig) | ||
593 | p->status = CODER_STATUS_NEEDS_MORE_INPUT; | ||
594 | } | ||
595 | */ | ||
596 | |||
597 | |||
598 | *srcLen = srcLen2; | ||
599 | src += srcLen2; | ||
600 | p->outWritten += destLen2; | ||
601 | |||
602 | if (res != SZ_OK || srcWasFinished || wasFinished) | ||
603 | p->wasFinished = True; | ||
604 | |||
605 | if (p->numCoders == 1) | ||
606 | *destLen = destLen2; | ||
607 | else if (p->wasFinished) | ||
608 | { | ||
609 | unsigned i; | ||
610 | size_t processed = p->outWritten; | ||
611 | |||
612 | for (i = 1; i < p->numCoders; i++) | ||
613 | { | ||
614 | IStateCoder *coder = &p->coders[i]; | ||
615 | processed = coder->Filter(coder->p, p->outBuf, processed); | ||
616 | if (wasFinished || (destFinish && p->outWritten == destLenOrig)) | ||
617 | processed = p->outWritten; | ||
618 | PRF_STR_INT("filter", i); | ||
619 | } | ||
620 | *destLen = processed; | ||
621 | } | ||
622 | return res; | ||
623 | } | ||
624 | |||
625 | PRF_STR("standard mix"); | ||
626 | |||
627 | if (p->numCoders != 1) | ||
628 | { | ||
629 | if (!p->buf) | ||
630 | { | ||
631 | p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1)); | ||
632 | if (!p->buf) | ||
633 | return SZ_ERROR_MEM; | ||
634 | } | ||
635 | |||
636 | finishMode = CODER_FINISH_ANY; | ||
637 | } | ||
638 | |||
639 | for (;;) | ||
640 | { | ||
641 | BoolInt processed = False; | ||
642 | BoolInt allFinished = True; | ||
643 | SRes resMain = SZ_OK; | ||
644 | unsigned i; | ||
645 | |||
646 | p->status = CODER_STATUS_NOT_FINISHED; | ||
647 | /* | ||
648 | if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY) | ||
649 | break; | ||
650 | */ | ||
651 | |||
652 | for (i = 0; i < p->numCoders; i++) | ||
653 | { | ||
654 | SRes res; | ||
655 | IStateCoder *coder = &p->coders[i]; | ||
656 | Byte *dest2; | ||
657 | SizeT destLen2, srcLen2; // destLen2_Orig; | ||
658 | const Byte *src2; | ||
659 | int srcFinished2; | ||
660 | int encodingWasFinished; | ||
661 | ECoderStatus status2; | ||
662 | |||
663 | if (i == 0) | ||
664 | { | ||
665 | src2 = src; | ||
666 | srcLen2 = srcLenOrig - *srcLen; | ||
667 | srcFinished2 = srcWasFinished; | ||
668 | } | ||
669 | else | ||
670 | { | ||
671 | size_t k = i - 1; | ||
672 | src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k]; | ||
673 | srcLen2 = p->size[k] - p->pos[k]; | ||
674 | srcFinished2 = p->finished[k]; | ||
675 | } | ||
676 | |||
677 | if (i == p->numCoders - 1) | ||
678 | { | ||
679 | dest2 = dest; | ||
680 | destLen2 = destLenOrig - *destLen; | ||
681 | } | ||
682 | else | ||
683 | { | ||
684 | if (p->pos[i] != p->size[i]) | ||
685 | continue; | ||
686 | dest2 = p->buf + (CODER_BUF_SIZE * i); | ||
687 | destLen2 = CODER_BUF_SIZE; | ||
688 | } | ||
689 | |||
690 | // destLen2_Orig = destLen2; | ||
691 | |||
692 | if (p->results[i] != SZ_OK) | ||
693 | { | ||
694 | if (resMain == SZ_OK) | ||
695 | resMain = p->results[i]; | ||
696 | continue; | ||
697 | } | ||
698 | |||
699 | res = coder->Code2(coder->p, | ||
700 | dest2, &destLen2, | ||
701 | src2, &srcLen2, srcFinished2, | ||
702 | finishMode, | ||
703 | // &encodingWasFinished, | ||
704 | &status2); | ||
705 | |||
706 | if (res != SZ_OK) | ||
707 | { | ||
708 | p->results[i] = res; | ||
709 | if (resMain == SZ_OK) | ||
710 | resMain = res; | ||
711 | } | ||
712 | |||
713 | encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK); | ||
714 | |||
715 | if (!encodingWasFinished) | ||
716 | { | ||
717 | allFinished = False; | ||
718 | if (p->numCoders == 1 && res == SZ_OK) | ||
719 | p->status = status2; | ||
720 | } | ||
721 | |||
722 | if (i == 0) | ||
723 | { | ||
724 | *srcLen += srcLen2; | ||
725 | src += srcLen2; | ||
726 | } | ||
727 | else | ||
728 | p->pos[(size_t)i - 1] += srcLen2; | ||
729 | |||
730 | if (i == p->numCoders - 1) | ||
731 | { | ||
732 | *destLen += destLen2; | ||
733 | dest += destLen2; | ||
734 | } | ||
735 | else | ||
736 | { | ||
737 | p->size[i] = destLen2; | ||
738 | p->pos[i] = 0; | ||
739 | p->finished[i] = encodingWasFinished; | ||
740 | } | ||
741 | |||
742 | if (destLen2 != 0 || srcLen2 != 0) | ||
743 | processed = True; | ||
744 | } | ||
745 | |||
746 | if (!processed) | ||
747 | { | ||
748 | if (allFinished) | ||
749 | p->status = CODER_STATUS_FINISHED_WITH_MARK; | ||
750 | return resMain; | ||
751 | } | ||
752 | } | ||
753 | } | ||
754 | |||
755 | |||
756 | SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf) | ||
757 | { | ||
758 | *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE); | ||
759 | if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) != | ||
760 | GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE)) | ||
761 | return SZ_ERROR_NO_ARCHIVE; | ||
762 | return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED; | ||
763 | } | ||
764 | |||
765 | static BoolInt Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf) | ||
766 | { | ||
767 | return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) | ||
768 | && GetUi32(buf) == CrcCalc(buf + 4, 6) | ||
769 | && flags == GetBe16(buf + 8) | ||
770 | && buf[10] == XZ_FOOTER_SIG_0 | ||
771 | && buf[11] == XZ_FOOTER_SIG_1; | ||
772 | } | ||
773 | |||
774 | #define READ_VARINT_AND_CHECK(buf, pos, size, res) \ | ||
775 | { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \ | ||
776 | if (s == 0) return SZ_ERROR_ARCHIVE; \ | ||
777 | pos += s; } | ||
778 | |||
779 | |||
780 | static BoolInt XzBlock_AreSupportedFilters(const CXzBlock *p) | ||
781 | { | ||
782 | unsigned numFilters = XzBlock_GetNumFilters(p) - 1; | ||
783 | unsigned i; | ||
784 | { | ||
785 | const CXzFilter *f = &p->filters[numFilters]; | ||
786 | if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40) | ||
787 | return False; | ||
788 | } | ||
789 | |||
790 | for (i = 0; i < numFilters; i++) | ||
791 | { | ||
792 | const CXzFilter *f = &p->filters[i]; | ||
793 | if (f->id == XZ_ID_Delta) | ||
794 | { | ||
795 | if (f->propsSize != 1) | ||
796 | return False; | ||
797 | } | ||
798 | else if (f->id < XZ_ID_Delta | ||
799 | || f->id > XZ_ID_SPARC | ||
800 | || (f->propsSize != 0 && f->propsSize != 4)) | ||
801 | return False; | ||
802 | } | ||
803 | return True; | ||
804 | } | ||
805 | |||
806 | |||
807 | SRes XzBlock_Parse(CXzBlock *p, const Byte *header) | ||
808 | { | ||
809 | unsigned pos; | ||
810 | unsigned numFilters, i; | ||
811 | unsigned headerSize = (unsigned)header[0] << 2; | ||
812 | |||
813 | /* (headerSize != 0) : another code checks */ | ||
814 | |||
815 | if (CrcCalc(header, headerSize) != GetUi32(header + headerSize)) | ||
816 | return SZ_ERROR_ARCHIVE; | ||
817 | |||
818 | pos = 1; | ||
819 | p->flags = header[pos++]; | ||
820 | |||
821 | p->packSize = (UInt64)(Int64)-1; | ||
822 | if (XzBlock_HasPackSize(p)) | ||
823 | { | ||
824 | READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize); | ||
825 | if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63) | ||
826 | return SZ_ERROR_ARCHIVE; | ||
827 | } | ||
828 | |||
829 | p->unpackSize = (UInt64)(Int64)-1; | ||
830 | if (XzBlock_HasUnpackSize(p)) | ||
831 | READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize); | ||
832 | |||
833 | numFilters = XzBlock_GetNumFilters(p); | ||
834 | for (i = 0; i < numFilters; i++) | ||
835 | { | ||
836 | CXzFilter *filter = p->filters + i; | ||
837 | UInt64 size; | ||
838 | READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id); | ||
839 | READ_VARINT_AND_CHECK(header, pos, headerSize, &size); | ||
840 | if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX) | ||
841 | return SZ_ERROR_ARCHIVE; | ||
842 | filter->propsSize = (UInt32)size; | ||
843 | memcpy(filter->props, header + pos, (size_t)size); | ||
844 | pos += (unsigned)size; | ||
845 | |||
846 | #ifdef XZ_DUMP | ||
847 | printf("\nf[%u] = %2X: ", i, (unsigned)filter->id); | ||
848 | { | ||
849 | unsigned i; | ||
850 | for (i = 0; i < size; i++) | ||
851 | printf(" %2X", filter->props[i]); | ||
852 | } | ||
853 | #endif | ||
854 | } | ||
855 | |||
856 | if (XzBlock_HasUnsupportedFlags(p)) | ||
857 | return SZ_ERROR_UNSUPPORTED; | ||
858 | |||
859 | while (pos < headerSize) | ||
860 | if (header[pos++] != 0) | ||
861 | return SZ_ERROR_ARCHIVE; | ||
862 | return SZ_OK; | ||
863 | } | ||
864 | |||
865 | |||
866 | |||
867 | |||
868 | static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize) | ||
869 | { | ||
870 | unsigned i; | ||
871 | BoolInt needReInit = True; | ||
872 | unsigned numFilters = XzBlock_GetNumFilters(block); | ||
873 | |||
874 | if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf))) | ||
875 | { | ||
876 | needReInit = False; | ||
877 | for (i = 0; i < numFilters; i++) | ||
878 | if (p->ids[i] != block->filters[numFilters - 1 - i].id) | ||
879 | { | ||
880 | needReInit = True; | ||
881 | break; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | // p->SingleBufMode = (outBuf != NULL); | ||
886 | p->outBuf = outBuf; | ||
887 | p->outBufSize = outBufSize; | ||
888 | |||
889 | // p->SingleBufMode = False; | ||
890 | // outBuf = NULL; | ||
891 | |||
892 | if (needReInit) | ||
893 | { | ||
894 | MixCoder_Free(p); | ||
895 | for (i = 0; i < numFilters; i++) | ||
896 | { | ||
897 | RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize)); | ||
898 | } | ||
899 | p->numCoders = numFilters; | ||
900 | } | ||
901 | else | ||
902 | { | ||
903 | RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize)); | ||
904 | } | ||
905 | |||
906 | for (i = 0; i < numFilters; i++) | ||
907 | { | ||
908 | const CXzFilter *f = &block->filters[numFilters - 1 - i]; | ||
909 | IStateCoder *sc = &p->coders[i]; | ||
910 | RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc)); | ||
911 | } | ||
912 | |||
913 | MixCoder_Init(p); | ||
914 | return SZ_OK; | ||
915 | } | ||
916 | |||
917 | |||
918 | |||
919 | void XzUnpacker_Init(CXzUnpacker *p) | ||
920 | { | ||
921 | p->state = XZ_STATE_STREAM_HEADER; | ||
922 | p->pos = 0; | ||
923 | p->numStartedStreams = 0; | ||
924 | p->numFinishedStreams = 0; | ||
925 | p->numTotalBlocks = 0; | ||
926 | p->padSize = 0; | ||
927 | p->decodeOnlyOneBlock = 0; | ||
928 | |||
929 | p->parseMode = False; | ||
930 | p->decodeToStreamSignature = False; | ||
931 | |||
932 | // p->outBuf = NULL; | ||
933 | // p->outBufSize = 0; | ||
934 | p->outDataWritten = 0; | ||
935 | } | ||
936 | |||
937 | |||
938 | void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize) | ||
939 | { | ||
940 | p->outBuf = outBuf; | ||
941 | p->outBufSize = outBufSize; | ||
942 | } | ||
943 | |||
944 | |||
945 | void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc) | ||
946 | { | ||
947 | MixCoder_Construct(&p->decoder, alloc); | ||
948 | p->outBuf = NULL; | ||
949 | p->outBufSize = 0; | ||
950 | XzUnpacker_Init(p); | ||
951 | } | ||
952 | |||
953 | |||
954 | void XzUnpacker_Free(CXzUnpacker *p) | ||
955 | { | ||
956 | MixCoder_Free(&p->decoder); | ||
957 | } | ||
958 | |||
959 | |||
960 | void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p) | ||
961 | { | ||
962 | p->indexSize = 0; | ||
963 | p->numBlocks = 0; | ||
964 | Sha256_Init(&p->sha); | ||
965 | p->state = XZ_STATE_BLOCK_HEADER; | ||
966 | p->pos = 0; | ||
967 | p->decodeOnlyOneBlock = 1; | ||
968 | } | ||
969 | |||
970 | |||
971 | static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize) | ||
972 | { | ||
973 | Byte temp[32]; | ||
974 | unsigned num = Xz_WriteVarInt(temp, packSize); | ||
975 | num += Xz_WriteVarInt(temp + num, unpackSize); | ||
976 | Sha256_Update(&p->sha, temp, num); | ||
977 | p->indexSize += num; | ||
978 | p->numBlocks++; | ||
979 | } | ||
980 | |||
981 | |||
982 | |||
983 | SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, | ||
984 | const Byte *src, SizeT *srcLen, int srcFinished, | ||
985 | ECoderFinishMode finishMode, ECoderStatus *status) | ||
986 | { | ||
987 | SizeT destLenOrig = *destLen; | ||
988 | SizeT srcLenOrig = *srcLen; | ||
989 | *destLen = 0; | ||
990 | *srcLen = 0; | ||
991 | *status = CODER_STATUS_NOT_SPECIFIED; | ||
992 | |||
993 | for (;;) | ||
994 | { | ||
995 | SizeT srcRem; | ||
996 | |||
997 | if (p->state == XZ_STATE_BLOCK) | ||
998 | { | ||
999 | SizeT destLen2 = destLenOrig - *destLen; | ||
1000 | SizeT srcLen2 = srcLenOrig - *srcLen; | ||
1001 | SRes res; | ||
1002 | |||
1003 | ECoderFinishMode finishMode2 = finishMode; | ||
1004 | BoolInt srcFinished2 = srcFinished; | ||
1005 | BoolInt destFinish = False; | ||
1006 | |||
1007 | if (p->block.packSize != (UInt64)(Int64)-1) | ||
1008 | { | ||
1009 | UInt64 rem = p->block.packSize - p->packSize; | ||
1010 | if (srcLen2 >= rem) | ||
1011 | { | ||
1012 | srcFinished2 = True; | ||
1013 | srcLen2 = (SizeT)rem; | ||
1014 | } | ||
1015 | if (rem == 0 && p->block.unpackSize == p->unpackSize) | ||
1016 | return SZ_ERROR_DATA; | ||
1017 | } | ||
1018 | |||
1019 | if (p->block.unpackSize != (UInt64)(Int64)-1) | ||
1020 | { | ||
1021 | UInt64 rem = p->block.unpackSize - p->unpackSize; | ||
1022 | if (destLen2 >= rem) | ||
1023 | { | ||
1024 | destFinish = True; | ||
1025 | finishMode2 = CODER_FINISH_END; | ||
1026 | destLen2 = (SizeT)rem; | ||
1027 | } | ||
1028 | } | ||
1029 | |||
1030 | /* | ||
1031 | if (srcLen2 == 0 && destLen2 == 0) | ||
1032 | { | ||
1033 | *status = CODER_STATUS_NOT_FINISHED; | ||
1034 | return SZ_OK; | ||
1035 | } | ||
1036 | */ | ||
1037 | |||
1038 | { | ||
1039 | res = MixCoder_Code(&p->decoder, | ||
1040 | (p->outBuf ? NULL : dest), &destLen2, destFinish, | ||
1041 | src, &srcLen2, srcFinished2, | ||
1042 | finishMode2); | ||
1043 | |||
1044 | *status = p->decoder.status; | ||
1045 | XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2); | ||
1046 | if (!p->outBuf) | ||
1047 | dest += destLen2; | ||
1048 | p->outDataWritten += destLen2; | ||
1049 | } | ||
1050 | |||
1051 | (*srcLen) += srcLen2; | ||
1052 | src += srcLen2; | ||
1053 | p->packSize += srcLen2; | ||
1054 | (*destLen) += destLen2; | ||
1055 | p->unpackSize += destLen2; | ||
1056 | |||
1057 | RINOK(res); | ||
1058 | |||
1059 | if (*status != CODER_STATUS_FINISHED_WITH_MARK) | ||
1060 | { | ||
1061 | if (p->block.packSize == p->packSize | ||
1062 | && *status == CODER_STATUS_NEEDS_MORE_INPUT) | ||
1063 | { | ||
1064 | PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT"); | ||
1065 | *status = CODER_STATUS_NOT_SPECIFIED; | ||
1066 | return SZ_ERROR_DATA; | ||
1067 | } | ||
1068 | |||
1069 | return SZ_OK; | ||
1070 | } | ||
1071 | { | ||
1072 | XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize); | ||
1073 | p->state = XZ_STATE_BLOCK_FOOTER; | ||
1074 | p->pos = 0; | ||
1075 | p->alignPos = 0; | ||
1076 | *status = CODER_STATUS_NOT_SPECIFIED; | ||
1077 | |||
1078 | if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize) | ||
1079 | || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize)) | ||
1080 | { | ||
1081 | PRF_STR("ERROR: block.size mismatch"); | ||
1082 | return SZ_ERROR_DATA; | ||
1083 | } | ||
1084 | } | ||
1085 | // continue; | ||
1086 | } | ||
1087 | |||
1088 | srcRem = srcLenOrig - *srcLen; | ||
1089 | |||
1090 | // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes | ||
1091 | if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER) | ||
1092 | { | ||
1093 | *status = CODER_STATUS_NEEDS_MORE_INPUT; | ||
1094 | return SZ_OK; | ||
1095 | } | ||
1096 | |||
1097 | switch (p->state) | ||
1098 | { | ||
1099 | case XZ_STATE_STREAM_HEADER: | ||
1100 | { | ||
1101 | if (p->pos < XZ_STREAM_HEADER_SIZE) | ||
1102 | { | ||
1103 | if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos]) | ||
1104 | return SZ_ERROR_NO_ARCHIVE; | ||
1105 | if (p->decodeToStreamSignature) | ||
1106 | return SZ_OK; | ||
1107 | p->buf[p->pos++] = *src++; | ||
1108 | (*srcLen)++; | ||
1109 | } | ||
1110 | else | ||
1111 | { | ||
1112 | RINOK(Xz_ParseHeader(&p->streamFlags, p->buf)); | ||
1113 | p->numStartedStreams++; | ||
1114 | p->indexSize = 0; | ||
1115 | p->numBlocks = 0; | ||
1116 | Sha256_Init(&p->sha); | ||
1117 | p->state = XZ_STATE_BLOCK_HEADER; | ||
1118 | p->pos = 0; | ||
1119 | } | ||
1120 | break; | ||
1121 | } | ||
1122 | |||
1123 | case XZ_STATE_BLOCK_HEADER: | ||
1124 | { | ||
1125 | if (p->pos == 0) | ||
1126 | { | ||
1127 | p->buf[p->pos++] = *src++; | ||
1128 | (*srcLen)++; | ||
1129 | if (p->buf[0] == 0) | ||
1130 | { | ||
1131 | if (p->decodeOnlyOneBlock) | ||
1132 | return SZ_ERROR_DATA; | ||
1133 | p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks); | ||
1134 | p->indexPos = p->indexPreSize; | ||
1135 | p->indexSize += p->indexPreSize; | ||
1136 | Sha256_Final(&p->sha, p->shaDigest); | ||
1137 | Sha256_Init(&p->sha); | ||
1138 | p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize); | ||
1139 | p->state = XZ_STATE_STREAM_INDEX; | ||
1140 | break; | ||
1141 | } | ||
1142 | p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4; | ||
1143 | break; | ||
1144 | } | ||
1145 | |||
1146 | if (p->pos != p->blockHeaderSize) | ||
1147 | { | ||
1148 | UInt32 cur = p->blockHeaderSize - p->pos; | ||
1149 | if (cur > srcRem) | ||
1150 | cur = (UInt32)srcRem; | ||
1151 | memcpy(p->buf + p->pos, src, cur); | ||
1152 | p->pos += cur; | ||
1153 | (*srcLen) += cur; | ||
1154 | src += cur; | ||
1155 | } | ||
1156 | else | ||
1157 | { | ||
1158 | RINOK(XzBlock_Parse(&p->block, p->buf)); | ||
1159 | if (!XzBlock_AreSupportedFilters(&p->block)) | ||
1160 | return SZ_ERROR_UNSUPPORTED; | ||
1161 | p->numTotalBlocks++; | ||
1162 | p->state = XZ_STATE_BLOCK; | ||
1163 | p->packSize = 0; | ||
1164 | p->unpackSize = 0; | ||
1165 | XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags)); | ||
1166 | if (p->parseMode) | ||
1167 | { | ||
1168 | p->headerParsedOk = True; | ||
1169 | return SZ_OK; | ||
1170 | } | ||
1171 | RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize)); | ||
1172 | } | ||
1173 | break; | ||
1174 | } | ||
1175 | |||
1176 | case XZ_STATE_BLOCK_FOOTER: | ||
1177 | { | ||
1178 | if ((((unsigned)p->packSize + p->alignPos) & 3) != 0) | ||
1179 | { | ||
1180 | if (srcRem == 0) | ||
1181 | { | ||
1182 | *status = CODER_STATUS_NEEDS_MORE_INPUT; | ||
1183 | return SZ_OK; | ||
1184 | } | ||
1185 | (*srcLen)++; | ||
1186 | p->alignPos++; | ||
1187 | if (*src++ != 0) | ||
1188 | return SZ_ERROR_CRC; | ||
1189 | } | ||
1190 | else | ||
1191 | { | ||
1192 | UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags); | ||
1193 | UInt32 cur = checkSize - p->pos; | ||
1194 | if (cur != 0) | ||
1195 | { | ||
1196 | if (srcRem == 0) | ||
1197 | { | ||
1198 | *status = CODER_STATUS_NEEDS_MORE_INPUT; | ||
1199 | return SZ_OK; | ||
1200 | } | ||
1201 | if (cur > srcRem) | ||
1202 | cur = (UInt32)srcRem; | ||
1203 | memcpy(p->buf + p->pos, src, cur); | ||
1204 | p->pos += cur; | ||
1205 | (*srcLen) += cur; | ||
1206 | src += cur; | ||
1207 | if (checkSize != p->pos) | ||
1208 | break; | ||
1209 | } | ||
1210 | { | ||
1211 | Byte digest[XZ_CHECK_SIZE_MAX]; | ||
1212 | p->state = XZ_STATE_BLOCK_HEADER; | ||
1213 | p->pos = 0; | ||
1214 | if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0) | ||
1215 | return SZ_ERROR_CRC; | ||
1216 | if (p->decodeOnlyOneBlock) | ||
1217 | { | ||
1218 | *status = CODER_STATUS_FINISHED_WITH_MARK; | ||
1219 | return SZ_OK; | ||
1220 | } | ||
1221 | } | ||
1222 | } | ||
1223 | break; | ||
1224 | } | ||
1225 | |||
1226 | case XZ_STATE_STREAM_INDEX: | ||
1227 | { | ||
1228 | if (p->pos < p->indexPreSize) | ||
1229 | { | ||
1230 | (*srcLen)++; | ||
1231 | if (*src++ != p->buf[p->pos++]) | ||
1232 | return SZ_ERROR_CRC; | ||
1233 | } | ||
1234 | else | ||
1235 | { | ||
1236 | if (p->indexPos < p->indexSize) | ||
1237 | { | ||
1238 | UInt64 cur = p->indexSize - p->indexPos; | ||
1239 | if (srcRem > cur) | ||
1240 | srcRem = (SizeT)cur; | ||
1241 | p->crc = CrcUpdate(p->crc, src, srcRem); | ||
1242 | Sha256_Update(&p->sha, src, srcRem); | ||
1243 | (*srcLen) += srcRem; | ||
1244 | src += srcRem; | ||
1245 | p->indexPos += srcRem; | ||
1246 | } | ||
1247 | else if ((p->indexPos & 3) != 0) | ||
1248 | { | ||
1249 | Byte b = *src++; | ||
1250 | p->crc = CRC_UPDATE_BYTE(p->crc, b); | ||
1251 | (*srcLen)++; | ||
1252 | p->indexPos++; | ||
1253 | p->indexSize++; | ||
1254 | if (b != 0) | ||
1255 | return SZ_ERROR_CRC; | ||
1256 | } | ||
1257 | else | ||
1258 | { | ||
1259 | Byte digest[SHA256_DIGEST_SIZE]; | ||
1260 | p->state = XZ_STATE_STREAM_INDEX_CRC; | ||
1261 | p->indexSize += 4; | ||
1262 | p->pos = 0; | ||
1263 | Sha256_Final(&p->sha, digest); | ||
1264 | if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0) | ||
1265 | return SZ_ERROR_CRC; | ||
1266 | } | ||
1267 | } | ||
1268 | break; | ||
1269 | } | ||
1270 | |||
1271 | case XZ_STATE_STREAM_INDEX_CRC: | ||
1272 | { | ||
1273 | if (p->pos < 4) | ||
1274 | { | ||
1275 | (*srcLen)++; | ||
1276 | p->buf[p->pos++] = *src++; | ||
1277 | } | ||
1278 | else | ||
1279 | { | ||
1280 | const Byte *ptr = p->buf; | ||
1281 | p->state = XZ_STATE_STREAM_FOOTER; | ||
1282 | p->pos = 0; | ||
1283 | if (CRC_GET_DIGEST(p->crc) != GetUi32(ptr)) | ||
1284 | return SZ_ERROR_CRC; | ||
1285 | } | ||
1286 | break; | ||
1287 | } | ||
1288 | |||
1289 | case XZ_STATE_STREAM_FOOTER: | ||
1290 | { | ||
1291 | UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos; | ||
1292 | if (cur > srcRem) | ||
1293 | cur = (UInt32)srcRem; | ||
1294 | memcpy(p->buf + p->pos, src, cur); | ||
1295 | p->pos += cur; | ||
1296 | (*srcLen) += cur; | ||
1297 | src += cur; | ||
1298 | if (p->pos == XZ_STREAM_FOOTER_SIZE) | ||
1299 | { | ||
1300 | p->state = XZ_STATE_STREAM_PADDING; | ||
1301 | p->numFinishedStreams++; | ||
1302 | p->padSize = 0; | ||
1303 | if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf)) | ||
1304 | return SZ_ERROR_CRC; | ||
1305 | } | ||
1306 | break; | ||
1307 | } | ||
1308 | |||
1309 | case XZ_STATE_STREAM_PADDING: | ||
1310 | { | ||
1311 | if (*src != 0) | ||
1312 | { | ||
1313 | if (((UInt32)p->padSize & 3) != 0) | ||
1314 | return SZ_ERROR_NO_ARCHIVE; | ||
1315 | p->pos = 0; | ||
1316 | p->state = XZ_STATE_STREAM_HEADER; | ||
1317 | } | ||
1318 | else | ||
1319 | { | ||
1320 | (*srcLen)++; | ||
1321 | src++; | ||
1322 | p->padSize++; | ||
1323 | } | ||
1324 | break; | ||
1325 | } | ||
1326 | |||
1327 | case XZ_STATE_BLOCK: break; /* to disable GCC warning */ | ||
1328 | } | ||
1329 | } | ||
1330 | /* | ||
1331 | if (p->state == XZ_STATE_FINISHED) | ||
1332 | *status = CODER_STATUS_FINISHED_WITH_MARK; | ||
1333 | return SZ_OK; | ||
1334 | */ | ||
1335 | } | ||
1336 | |||
1337 | |||
1338 | SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen, | ||
1339 | const Byte *src, SizeT *srcLen, | ||
1340 | ECoderFinishMode finishMode, ECoderStatus *status) | ||
1341 | { | ||
1342 | XzUnpacker_Init(p); | ||
1343 | XzUnpacker_SetOutBuf(p, dest, *destLen); | ||
1344 | |||
1345 | return XzUnpacker_Code(p, | ||
1346 | NULL, destLen, | ||
1347 | src, srcLen, True, | ||
1348 | finishMode, status); | ||
1349 | } | ||
1350 | |||
1351 | |||
1352 | BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p) | ||
1353 | { | ||
1354 | return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0); | ||
1355 | } | ||
1356 | |||
1357 | BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p) | ||
1358 | { | ||
1359 | return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0); | ||
1360 | } | ||
1361 | |||
1362 | UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p) | ||
1363 | { | ||
1364 | UInt64 num = 0; | ||
1365 | if (p->state == XZ_STATE_STREAM_PADDING) | ||
1366 | num = p->padSize; | ||
1367 | else if (p->state == XZ_STATE_STREAM_HEADER) | ||
1368 | num = p->padSize + p->pos; | ||
1369 | return num; | ||
1370 | } | ||
1371 | |||
1372 | |||
1373 | |||
1374 | |||
1375 | |||
1376 | |||
1377 | |||
1378 | |||
1379 | |||
1380 | |||
1381 | |||
1382 | |||
1383 | |||
1384 | |||
1385 | |||
1386 | |||
1387 | |||
1388 | |||
1389 | |||
1390 | |||
1391 | |||
1392 | #ifndef _7ZIP_ST | ||
1393 | #include "MtDec.h" | ||
1394 | #endif | ||
1395 | |||
1396 | |||
1397 | void XzDecMtProps_Init(CXzDecMtProps *p) | ||
1398 | { | ||
1399 | p->inBufSize_ST = 1 << 18; | ||
1400 | p->outStep_ST = 1 << 20; | ||
1401 | p->ignoreErrors = False; | ||
1402 | |||
1403 | #ifndef _7ZIP_ST | ||
1404 | p->numThreads = 1; | ||
1405 | p->inBufSize_MT = 1 << 18; | ||
1406 | p->memUseMax = sizeof(size_t) << 28; | ||
1407 | #endif | ||
1408 | } | ||
1409 | |||
1410 | |||
1411 | |||
1412 | #ifndef _7ZIP_ST | ||
1413 | |||
1414 | /* ---------- CXzDecMtThread ---------- */ | ||
1415 | |||
1416 | typedef struct | ||
1417 | { | ||
1418 | Byte *outBuf; | ||
1419 | size_t outBufSize; | ||
1420 | size_t outPreSize; | ||
1421 | size_t inPreSize; | ||
1422 | size_t inPreHeaderSize; | ||
1423 | size_t blockPackSize_for_Index; // including block header and checksum. | ||
1424 | size_t blockPackTotal; // including stream header, block header and checksum. | ||
1425 | size_t inCodeSize; | ||
1426 | size_t outCodeSize; | ||
1427 | ECoderStatus status; | ||
1428 | SRes codeRes; | ||
1429 | BoolInt skipMode; | ||
1430 | // BoolInt finishedWithMark; | ||
1431 | EMtDecParseState parseState; | ||
1432 | BoolInt parsing_Truncated; | ||
1433 | BoolInt atBlockHeader; | ||
1434 | CXzStreamFlags streamFlags; | ||
1435 | // UInt64 numFinishedStreams | ||
1436 | UInt64 numStreams; | ||
1437 | UInt64 numTotalBlocks; | ||
1438 | UInt64 numBlocks; | ||
1439 | |||
1440 | BoolInt dec_created; | ||
1441 | CXzUnpacker dec; | ||
1442 | |||
1443 | Byte mtPad[1 << 7]; | ||
1444 | } CXzDecMtThread; | ||
1445 | |||
1446 | #endif | ||
1447 | |||
1448 | |||
1449 | /* ---------- CXzDecMt ---------- */ | ||
1450 | |||
1451 | typedef struct | ||
1452 | { | ||
1453 | CAlignOffsetAlloc alignOffsetAlloc; | ||
1454 | ISzAllocPtr allocMid; | ||
1455 | |||
1456 | CXzDecMtProps props; | ||
1457 | size_t unpackBlockMaxSize; | ||
1458 | |||
1459 | ISeqInStream *inStream; | ||
1460 | ISeqOutStream *outStream; | ||
1461 | ICompressProgress *progress; | ||
1462 | |||
1463 | BoolInt finishMode; | ||
1464 | BoolInt outSize_Defined; | ||
1465 | UInt64 outSize; | ||
1466 | |||
1467 | UInt64 outProcessed; | ||
1468 | UInt64 inProcessed; | ||
1469 | UInt64 readProcessed; | ||
1470 | BoolInt readWasFinished; | ||
1471 | SRes readRes; | ||
1472 | SRes writeRes; | ||
1473 | |||
1474 | Byte *outBuf; | ||
1475 | size_t outBufSize; | ||
1476 | Byte *inBuf; | ||
1477 | size_t inBufSize; | ||
1478 | |||
1479 | CXzUnpacker dec; | ||
1480 | |||
1481 | ECoderStatus status; | ||
1482 | SRes codeRes; | ||
1483 | |||
1484 | #ifndef _7ZIP_ST | ||
1485 | BoolInt mainDecoderWasCalled; | ||
1486 | // int statErrorDefined; | ||
1487 | int finishedDecoderIndex; | ||
1488 | |||
1489 | // global values that are used in Parse stage | ||
1490 | CXzStreamFlags streamFlags; | ||
1491 | // UInt64 numFinishedStreams | ||
1492 | UInt64 numStreams; | ||
1493 | UInt64 numTotalBlocks; | ||
1494 | UInt64 numBlocks; | ||
1495 | |||
1496 | // UInt64 numBadBlocks; | ||
1497 | SRes mainErrorCode; // it's set to error code, if the size Code() output doesn't patch the size from Parsing stage | ||
1498 | // it can be = SZ_ERROR_INPUT_EOF | ||
1499 | // it can be = SZ_ERROR_DATA, in some another cases | ||
1500 | BoolInt isBlockHeaderState_Parse; | ||
1501 | BoolInt isBlockHeaderState_Write; | ||
1502 | UInt64 outProcessed_Parse; | ||
1503 | BoolInt parsing_Truncated; | ||
1504 | |||
1505 | BoolInt mtc_WasConstructed; | ||
1506 | CMtDec mtc; | ||
1507 | CXzDecMtThread coders[MTDEC__THREADS_MAX]; | ||
1508 | #endif | ||
1509 | |||
1510 | } CXzDecMt; | ||
1511 | |||
1512 | |||
1513 | |||
1514 | CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid) | ||
1515 | { | ||
1516 | CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt)); | ||
1517 | if (!p) | ||
1518 | return NULL; | ||
1519 | |||
1520 | AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc); | ||
1521 | p->alignOffsetAlloc.baseAlloc = alloc; | ||
1522 | p->alignOffsetAlloc.numAlignBits = 7; | ||
1523 | p->alignOffsetAlloc.offset = 0; | ||
1524 | |||
1525 | p->allocMid = allocMid; | ||
1526 | |||
1527 | p->outBuf = NULL; | ||
1528 | p->outBufSize = 0; | ||
1529 | p->inBuf = NULL; | ||
1530 | p->inBufSize = 0; | ||
1531 | |||
1532 | XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt); | ||
1533 | |||
1534 | p->unpackBlockMaxSize = 0; | ||
1535 | |||
1536 | XzDecMtProps_Init(&p->props); | ||
1537 | |||
1538 | #ifndef _7ZIP_ST | ||
1539 | p->mtc_WasConstructed = False; | ||
1540 | { | ||
1541 | unsigned i; | ||
1542 | for (i = 0; i < MTDEC__THREADS_MAX; i++) | ||
1543 | { | ||
1544 | CXzDecMtThread *coder = &p->coders[i]; | ||
1545 | coder->dec_created = False; | ||
1546 | coder->outBuf = NULL; | ||
1547 | coder->outBufSize = 0; | ||
1548 | } | ||
1549 | } | ||
1550 | #endif | ||
1551 | |||
1552 | return p; | ||
1553 | } | ||
1554 | |||
1555 | |||
1556 | #ifndef _7ZIP_ST | ||
1557 | |||
1558 | static void XzDecMt_FreeOutBufs(CXzDecMt *p) | ||
1559 | { | ||
1560 | unsigned i; | ||
1561 | for (i = 0; i < MTDEC__THREADS_MAX; i++) | ||
1562 | { | ||
1563 | CXzDecMtThread *coder = &p->coders[i]; | ||
1564 | if (coder->outBuf) | ||
1565 | { | ||
1566 | ISzAlloc_Free(p->allocMid, coder->outBuf); | ||
1567 | coder->outBuf = NULL; | ||
1568 | coder->outBufSize = 0; | ||
1569 | } | ||
1570 | } | ||
1571 | p->unpackBlockMaxSize = 0; | ||
1572 | } | ||
1573 | |||
1574 | #endif | ||
1575 | |||
1576 | |||
1577 | |||
1578 | static void XzDecMt_FreeSt(CXzDecMt *p) | ||
1579 | { | ||
1580 | XzUnpacker_Free(&p->dec); | ||
1581 | |||
1582 | if (p->outBuf) | ||
1583 | { | ||
1584 | ISzAlloc_Free(p->allocMid, p->outBuf); | ||
1585 | p->outBuf = NULL; | ||
1586 | } | ||
1587 | p->outBufSize = 0; | ||
1588 | |||
1589 | if (p->inBuf) | ||
1590 | { | ||
1591 | ISzAlloc_Free(p->allocMid, p->inBuf); | ||
1592 | p->inBuf = NULL; | ||
1593 | } | ||
1594 | p->inBufSize = 0; | ||
1595 | } | ||
1596 | |||
1597 | |||
1598 | void XzDecMt_Destroy(CXzDecMtHandle pp) | ||
1599 | { | ||
1600 | CXzDecMt *p = (CXzDecMt *)pp; | ||
1601 | |||
1602 | XzDecMt_FreeSt(p); | ||
1603 | |||
1604 | #ifndef _7ZIP_ST | ||
1605 | |||
1606 | if (p->mtc_WasConstructed) | ||
1607 | { | ||
1608 | MtDec_Destruct(&p->mtc); | ||
1609 | p->mtc_WasConstructed = False; | ||
1610 | } | ||
1611 | { | ||
1612 | unsigned i; | ||
1613 | for (i = 0; i < MTDEC__THREADS_MAX; i++) | ||
1614 | { | ||
1615 | CXzDecMtThread *t = &p->coders[i]; | ||
1616 | if (t->dec_created) | ||
1617 | { | ||
1618 | // we don't need to free dict here | ||
1619 | XzUnpacker_Free(&t->dec); | ||
1620 | t->dec_created = False; | ||
1621 | } | ||
1622 | } | ||
1623 | } | ||
1624 | XzDecMt_FreeOutBufs(p); | ||
1625 | |||
1626 | #endif | ||
1627 | |||
1628 | ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp); | ||
1629 | } | ||
1630 | |||
1631 | |||
1632 | |||
1633 | #ifndef _7ZIP_ST | ||
1634 | |||
1635 | static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc) | ||
1636 | { | ||
1637 | CXzDecMt *me = (CXzDecMt *)obj; | ||
1638 | CXzDecMtThread *coder = &me->coders[coderIndex]; | ||
1639 | size_t srcSize = cc->srcSize; | ||
1640 | |||
1641 | cc->srcSize = 0; | ||
1642 | cc->outPos = 0; | ||
1643 | cc->state = MTDEC_PARSE_CONTINUE; | ||
1644 | |||
1645 | cc->canCreateNewThread = True; | ||
1646 | |||
1647 | if (cc->startCall) | ||
1648 | { | ||
1649 | coder->outPreSize = 0; | ||
1650 | coder->inPreSize = 0; | ||
1651 | coder->inPreHeaderSize = 0; | ||
1652 | coder->parseState = MTDEC_PARSE_CONTINUE; | ||
1653 | coder->parsing_Truncated = False; | ||
1654 | coder->skipMode = False; | ||
1655 | coder->codeRes = SZ_OK; | ||
1656 | coder->status = CODER_STATUS_NOT_SPECIFIED; | ||
1657 | coder->inCodeSize = 0; | ||
1658 | coder->outCodeSize = 0; | ||
1659 | |||
1660 | coder->numStreams = me->numStreams; | ||
1661 | coder->numTotalBlocks = me->numTotalBlocks; | ||
1662 | coder->numBlocks = me->numBlocks; | ||
1663 | |||
1664 | if (!coder->dec_created) | ||
1665 | { | ||
1666 | XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt); | ||
1667 | coder->dec_created = True; | ||
1668 | } | ||
1669 | |||
1670 | XzUnpacker_Init(&coder->dec); | ||
1671 | |||
1672 | if (me->isBlockHeaderState_Parse) | ||
1673 | { | ||
1674 | coder->dec.streamFlags = me->streamFlags; | ||
1675 | coder->atBlockHeader = True; | ||
1676 | XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec); | ||
1677 | } | ||
1678 | else | ||
1679 | { | ||
1680 | coder->atBlockHeader = False; | ||
1681 | me->isBlockHeaderState_Parse = True; | ||
1682 | } | ||
1683 | |||
1684 | coder->dec.numStartedStreams = me->numStreams; | ||
1685 | coder->dec.numTotalBlocks = me->numTotalBlocks; | ||
1686 | coder->dec.numBlocks = me->numBlocks; | ||
1687 | } | ||
1688 | |||
1689 | while (!coder->skipMode) | ||
1690 | { | ||
1691 | ECoderStatus status; | ||
1692 | SRes res; | ||
1693 | size_t srcSize2 = srcSize; | ||
1694 | size_t destSize = (size_t)0 - 1; | ||
1695 | |||
1696 | coder->dec.parseMode = True; | ||
1697 | coder->dec.headerParsedOk = False; | ||
1698 | |||
1699 | PRF_STR_INT("Parse", srcSize2); | ||
1700 | |||
1701 | res = XzUnpacker_Code(&coder->dec, | ||
1702 | NULL, &destSize, | ||
1703 | cc->src, &srcSize2, cc->srcFinished, | ||
1704 | CODER_FINISH_END, &status); | ||
1705 | |||
1706 | // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2)); | ||
1707 | |||
1708 | coder->codeRes = res; | ||
1709 | coder->status = status; | ||
1710 | cc->srcSize += srcSize2; | ||
1711 | srcSize -= srcSize2; | ||
1712 | coder->inPreHeaderSize += srcSize2; | ||
1713 | coder->inPreSize = coder->inPreHeaderSize; | ||
1714 | |||
1715 | if (res != SZ_OK) | ||
1716 | { | ||
1717 | cc->state = | ||
1718 | coder->parseState = MTDEC_PARSE_END; | ||
1719 | /* | ||
1720 | if (res == SZ_ERROR_MEM) | ||
1721 | return res; | ||
1722 | return SZ_OK; | ||
1723 | */ | ||
1724 | return; // res; | ||
1725 | } | ||
1726 | |||
1727 | if (coder->dec.headerParsedOk) | ||
1728 | { | ||
1729 | const CXzBlock *block = &coder->dec.block; | ||
1730 | if (XzBlock_HasUnpackSize(block) | ||
1731 | // && block->unpackSize <= me->props.outBlockMax | ||
1732 | && XzBlock_HasPackSize(block)) | ||
1733 | { | ||
1734 | { | ||
1735 | if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax) | ||
1736 | { | ||
1737 | cc->state = MTDEC_PARSE_OVERFLOW; | ||
1738 | return; // SZ_OK; | ||
1739 | } | ||
1740 | } | ||
1741 | { | ||
1742 | UInt64 packSize = block->packSize; | ||
1743 | UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3); | ||
1744 | UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags); | ||
1745 | UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize; | ||
1746 | // if (blockPackSum <= me->props.inBlockMax) | ||
1747 | // unpackBlockMaxSize | ||
1748 | { | ||
1749 | coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize); | ||
1750 | coder->blockPackTotal = (size_t)blockPackSum; | ||
1751 | coder->outPreSize = (size_t)block->unpackSize; | ||
1752 | coder->streamFlags = coder->dec.streamFlags; | ||
1753 | me->streamFlags = coder->dec.streamFlags; | ||
1754 | coder->skipMode = True; | ||
1755 | break; | ||
1756 | } | ||
1757 | } | ||
1758 | } | ||
1759 | } | ||
1760 | else | ||
1761 | // if (coder->inPreSize <= me->props.inBlockMax) | ||
1762 | { | ||
1763 | if (!cc->srcFinished) | ||
1764 | return; // SZ_OK; | ||
1765 | cc->state = | ||
1766 | coder->parseState = MTDEC_PARSE_END; | ||
1767 | return; // SZ_OK; | ||
1768 | } | ||
1769 | cc->state = MTDEC_PARSE_OVERFLOW; | ||
1770 | return; // SZ_OK; | ||
1771 | } | ||
1772 | |||
1773 | // ---------- skipMode ---------- | ||
1774 | { | ||
1775 | UInt64 rem = coder->blockPackTotal - coder->inPreSize; | ||
1776 | size_t cur = srcSize; | ||
1777 | if (cur > rem) | ||
1778 | cur = (size_t)rem; | ||
1779 | cc->srcSize += cur; | ||
1780 | coder->inPreSize += cur; | ||
1781 | srcSize -= cur; | ||
1782 | |||
1783 | if (coder->inPreSize == coder->blockPackTotal) | ||
1784 | { | ||
1785 | if (srcSize == 0) | ||
1786 | { | ||
1787 | if (!cc->srcFinished) | ||
1788 | return; // SZ_OK; | ||
1789 | cc->state = MTDEC_PARSE_END; | ||
1790 | } | ||
1791 | else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block | ||
1792 | cc->state = MTDEC_PARSE_END; | ||
1793 | else | ||
1794 | { | ||
1795 | cc->state = MTDEC_PARSE_NEW; | ||
1796 | |||
1797 | { | ||
1798 | size_t blockMax = me->unpackBlockMaxSize; | ||
1799 | if (blockMax < coder->outPreSize) | ||
1800 | blockMax = coder->outPreSize; | ||
1801 | { | ||
1802 | UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2; | ||
1803 | if (me->props.memUseMax < required) | ||
1804 | cc->canCreateNewThread = False; | ||
1805 | } | ||
1806 | } | ||
1807 | |||
1808 | if (me->outSize_Defined) | ||
1809 | { | ||
1810 | // next block can be zero size | ||
1811 | const UInt64 rem2 = me->outSize - me->outProcessed_Parse; | ||
1812 | if (rem2 < coder->outPreSize) | ||
1813 | { | ||
1814 | coder->parsing_Truncated = True; | ||
1815 | cc->state = MTDEC_PARSE_END; | ||
1816 | } | ||
1817 | me->outProcessed_Parse += coder->outPreSize; | ||
1818 | } | ||
1819 | } | ||
1820 | } | ||
1821 | else if (cc->srcFinished) | ||
1822 | cc->state = MTDEC_PARSE_END; | ||
1823 | else | ||
1824 | return; // SZ_OK; | ||
1825 | |||
1826 | coder->parseState = cc->state; | ||
1827 | cc->outPos = coder->outPreSize; | ||
1828 | |||
1829 | me->numStreams = coder->dec.numStartedStreams; | ||
1830 | me->numTotalBlocks = coder->dec.numTotalBlocks; | ||
1831 | me->numBlocks = coder->dec.numBlocks + 1; | ||
1832 | return; // SZ_OK; | ||
1833 | } | ||
1834 | } | ||
1835 | |||
1836 | |||
1837 | static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex) | ||
1838 | { | ||
1839 | CXzDecMt *me = (CXzDecMt *)pp; | ||
1840 | CXzDecMtThread *coder = &me->coders[coderIndex]; | ||
1841 | Byte *dest; | ||
1842 | |||
1843 | if (!coder->dec.headerParsedOk) | ||
1844 | return SZ_OK; | ||
1845 | |||
1846 | dest = coder->outBuf; | ||
1847 | |||
1848 | if (!dest || coder->outBufSize < coder->outPreSize) | ||
1849 | { | ||
1850 | if (dest) | ||
1851 | { | ||
1852 | ISzAlloc_Free(me->allocMid, dest); | ||
1853 | coder->outBuf = NULL; | ||
1854 | coder->outBufSize = 0; | ||
1855 | } | ||
1856 | { | ||
1857 | size_t outPreSize = coder->outPreSize; | ||
1858 | if (outPreSize == 0) | ||
1859 | outPreSize = 1; | ||
1860 | dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize); | ||
1861 | } | ||
1862 | if (!dest) | ||
1863 | return SZ_ERROR_MEM; | ||
1864 | coder->outBuf = dest; | ||
1865 | coder->outBufSize = coder->outPreSize; | ||
1866 | |||
1867 | if (coder->outBufSize > me->unpackBlockMaxSize) | ||
1868 | me->unpackBlockMaxSize = coder->outBufSize; | ||
1869 | } | ||
1870 | |||
1871 | // return SZ_ERROR_MEM; | ||
1872 | |||
1873 | XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize); | ||
1874 | |||
1875 | { | ||
1876 | SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize); | ||
1877 | // res = SZ_ERROR_UNSUPPORTED; // to test | ||
1878 | coder->codeRes = res; | ||
1879 | if (res != SZ_OK) | ||
1880 | { | ||
1881 | // if (res == SZ_ERROR_MEM) return res; | ||
1882 | if (me->props.ignoreErrors && res != SZ_ERROR_MEM) | ||
1883 | return SZ_OK; | ||
1884 | return res; | ||
1885 | } | ||
1886 | } | ||
1887 | |||
1888 | return SZ_OK; | ||
1889 | } | ||
1890 | |||
1891 | |||
1892 | static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex, | ||
1893 | const Byte *src, size_t srcSize, int srcFinished, | ||
1894 | // int finished, int blockFinished, | ||
1895 | UInt64 *inCodePos, UInt64 *outCodePos, int *stop) | ||
1896 | { | ||
1897 | CXzDecMt *me = (CXzDecMt *)pp; | ||
1898 | CXzDecMtThread *coder = &me->coders[coderIndex]; | ||
1899 | |||
1900 | *inCodePos = coder->inCodeSize; | ||
1901 | *outCodePos = coder->outCodeSize; | ||
1902 | *stop = True; | ||
1903 | |||
1904 | if (srcSize > coder->inPreSize - coder->inCodeSize) | ||
1905 | return SZ_ERROR_FAIL; | ||
1906 | |||
1907 | if (coder->inCodeSize < coder->inPreHeaderSize) | ||
1908 | { | ||
1909 | size_t step = coder->inPreHeaderSize - coder->inCodeSize; | ||
1910 | if (step > srcSize) | ||
1911 | step = srcSize; | ||
1912 | src += step; | ||
1913 | srcSize -= step; | ||
1914 | coder->inCodeSize += step; | ||
1915 | *inCodePos = coder->inCodeSize; | ||
1916 | if (coder->inCodeSize < coder->inPreHeaderSize) | ||
1917 | { | ||
1918 | *stop = False; | ||
1919 | return SZ_OK; | ||
1920 | } | ||
1921 | } | ||
1922 | |||
1923 | if (!coder->dec.headerParsedOk) | ||
1924 | return SZ_OK; | ||
1925 | if (!coder->outBuf) | ||
1926 | return SZ_OK; | ||
1927 | |||
1928 | if (coder->codeRes == SZ_OK) | ||
1929 | { | ||
1930 | ECoderStatus status; | ||
1931 | SRes res; | ||
1932 | size_t srcProcessed = srcSize; | ||
1933 | size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten; | ||
1934 | |||
1935 | // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur)); | ||
1936 | |||
1937 | res = XzUnpacker_Code(&coder->dec, | ||
1938 | NULL, &outSizeCur, | ||
1939 | src, &srcProcessed, srcFinished, | ||
1940 | // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY, | ||
1941 | CODER_FINISH_END, | ||
1942 | &status); | ||
1943 | |||
1944 | // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur)); | ||
1945 | |||
1946 | coder->codeRes = res; | ||
1947 | coder->status = status; | ||
1948 | coder->inCodeSize += srcProcessed; | ||
1949 | coder->outCodeSize = coder->dec.outDataWritten; | ||
1950 | *inCodePos = coder->inCodeSize; | ||
1951 | *outCodePos = coder->outCodeSize; | ||
1952 | |||
1953 | if (res == SZ_OK) | ||
1954 | { | ||
1955 | if (srcProcessed == srcSize) | ||
1956 | *stop = False; | ||
1957 | return SZ_OK; | ||
1958 | } | ||
1959 | } | ||
1960 | |||
1961 | if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM) | ||
1962 | { | ||
1963 | *inCodePos = coder->inPreSize; | ||
1964 | *outCodePos = coder->outPreSize; | ||
1965 | return SZ_OK; | ||
1966 | } | ||
1967 | return coder->codeRes; | ||
1968 | } | ||
1969 | |||
1970 | |||
1971 | #define XZDECMT_STREAM_WRITE_STEP (1 << 24) | ||
1972 | |||
1973 | static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex, | ||
1974 | BoolInt needWriteToStream, | ||
1975 | const Byte *src, size_t srcSize, BoolInt isCross, | ||
1976 | // int srcFinished, | ||
1977 | BoolInt *needContinue, | ||
1978 | BoolInt *canRecode) | ||
1979 | { | ||
1980 | CXzDecMt *me = (CXzDecMt *)pp; | ||
1981 | const CXzDecMtThread *coder = &me->coders[coderIndex]; | ||
1982 | |||
1983 | // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize)); | ||
1984 | |||
1985 | *needContinue = False; | ||
1986 | *canRecode = True; | ||
1987 | |||
1988 | if (!needWriteToStream) | ||
1989 | return SZ_OK; | ||
1990 | |||
1991 | if (!coder->dec.headerParsedOk || !coder->outBuf) | ||
1992 | { | ||
1993 | if (me->finishedDecoderIndex < 0) | ||
1994 | me->finishedDecoderIndex = (int)coderIndex; | ||
1995 | return SZ_OK; | ||
1996 | } | ||
1997 | |||
1998 | if (me->finishedDecoderIndex >= 0) | ||
1999 | return SZ_OK; | ||
2000 | |||
2001 | me->mtc.inProcessed += coder->inCodeSize; | ||
2002 | |||
2003 | *canRecode = False; | ||
2004 | |||
2005 | { | ||
2006 | SRes res; | ||
2007 | size_t size = coder->outCodeSize; | ||
2008 | Byte *data = coder->outBuf; | ||
2009 | |||
2010 | // we use in me->dec: sha, numBlocks, indexSize | ||
2011 | |||
2012 | if (!me->isBlockHeaderState_Write) | ||
2013 | { | ||
2014 | XzUnpacker_PrepareToRandomBlockDecoding(&me->dec); | ||
2015 | me->dec.decodeOnlyOneBlock = False; | ||
2016 | me->dec.numStartedStreams = coder->dec.numStartedStreams; | ||
2017 | me->dec.streamFlags = coder->streamFlags; | ||
2018 | |||
2019 | me->isBlockHeaderState_Write = True; | ||
2020 | } | ||
2021 | |||
2022 | me->dec.numTotalBlocks = coder->dec.numTotalBlocks; | ||
2023 | XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize); | ||
2024 | |||
2025 | if (coder->outPreSize != size) | ||
2026 | { | ||
2027 | if (me->props.ignoreErrors) | ||
2028 | { | ||
2029 | memset(data + size, 0, coder->outPreSize - size); | ||
2030 | size = coder->outPreSize; | ||
2031 | } | ||
2032 | // me->numBadBlocks++; | ||
2033 | if (me->mainErrorCode == SZ_OK) | ||
2034 | { | ||
2035 | if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT) | ||
2036 | me->mainErrorCode = SZ_ERROR_INPUT_EOF; | ||
2037 | else | ||
2038 | me->mainErrorCode = SZ_ERROR_DATA; | ||
2039 | } | ||
2040 | } | ||
2041 | |||
2042 | if (me->writeRes != SZ_OK) | ||
2043 | return me->writeRes; | ||
2044 | |||
2045 | res = SZ_OK; | ||
2046 | { | ||
2047 | if (me->outSize_Defined) | ||
2048 | { | ||
2049 | const UInt64 rem = me->outSize - me->outProcessed; | ||
2050 | if (size > rem) | ||
2051 | size = (SizeT)rem; | ||
2052 | } | ||
2053 | |||
2054 | for (;;) | ||
2055 | { | ||
2056 | size_t cur = size; | ||
2057 | size_t written; | ||
2058 | if (cur > XZDECMT_STREAM_WRITE_STEP) | ||
2059 | cur = XZDECMT_STREAM_WRITE_STEP; | ||
2060 | |||
2061 | written = ISeqOutStream_Write(me->outStream, data, cur); | ||
2062 | |||
2063 | // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written)); | ||
2064 | |||
2065 | me->outProcessed += written; | ||
2066 | if (written != cur) | ||
2067 | { | ||
2068 | me->writeRes = SZ_ERROR_WRITE; | ||
2069 | res = me->writeRes; | ||
2070 | break; | ||
2071 | } | ||
2072 | data += cur; | ||
2073 | size -= cur; | ||
2074 | // PRF_STR_INT("Written size =", size); | ||
2075 | if (size == 0) | ||
2076 | break; | ||
2077 | res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0); | ||
2078 | if (res != SZ_OK) | ||
2079 | break; | ||
2080 | } | ||
2081 | } | ||
2082 | |||
2083 | if (coder->codeRes != SZ_OK) | ||
2084 | if (!me->props.ignoreErrors) | ||
2085 | { | ||
2086 | me->finishedDecoderIndex = (int)coderIndex; | ||
2087 | return res; | ||
2088 | } | ||
2089 | |||
2090 | RINOK(res); | ||
2091 | |||
2092 | if (coder->inPreSize != coder->inCodeSize | ||
2093 | || coder->blockPackTotal != coder->inCodeSize) | ||
2094 | { | ||
2095 | me->finishedDecoderIndex = (int)coderIndex; | ||
2096 | return SZ_OK; | ||
2097 | } | ||
2098 | |||
2099 | if (coder->parseState != MTDEC_PARSE_END) | ||
2100 | { | ||
2101 | *needContinue = True; | ||
2102 | return SZ_OK; | ||
2103 | } | ||
2104 | } | ||
2105 | |||
2106 | // (coder->state == MTDEC_PARSE_END) means that there are no other working threads | ||
2107 | // so we can use mtc variables without lock | ||
2108 | |||
2109 | PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed); | ||
2110 | |||
2111 | me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; | ||
2112 | { | ||
2113 | CXzUnpacker *dec = &me->dec; | ||
2114 | |||
2115 | PRF_STR_INT("PostSingle", srcSize); | ||
2116 | |||
2117 | { | ||
2118 | size_t srcProcessed = srcSize; | ||
2119 | ECoderStatus status; | ||
2120 | size_t outSizeCur = 0; | ||
2121 | SRes res; | ||
2122 | |||
2123 | // dec->decodeOnlyOneBlock = False; | ||
2124 | dec->decodeToStreamSignature = True; | ||
2125 | |||
2126 | me->mainDecoderWasCalled = True; | ||
2127 | |||
2128 | if (coder->parsing_Truncated) | ||
2129 | { | ||
2130 | me->parsing_Truncated = True; | ||
2131 | return SZ_OK; | ||
2132 | } | ||
2133 | |||
2134 | /* | ||
2135 | We have processed all xz-blocks of stream, | ||
2136 | And xz unpacker is at XZ_STATE_BLOCK_HEADER state, where | ||
2137 | (src) is a pointer to xz-Index structure. | ||
2138 | We finish reading of current xz-Stream, including Zero padding after xz-Stream. | ||
2139 | We exit, if we reach extra byte (first byte of new-Stream or another data). | ||
2140 | But we don't update input stream pointer for that new extra byte. | ||
2141 | If extra byte is not correct first byte of xz-signature, | ||
2142 | we have SZ_ERROR_NO_ARCHIVE error here. | ||
2143 | */ | ||
2144 | |||
2145 | res = XzUnpacker_Code(dec, | ||
2146 | NULL, &outSizeCur, | ||
2147 | src, &srcProcessed, | ||
2148 | me->mtc.readWasFinished, // srcFinished | ||
2149 | CODER_FINISH_END, // CODER_FINISH_ANY, | ||
2150 | &status); | ||
2151 | |||
2152 | // res = SZ_ERROR_ARCHIVE; // for failure test | ||
2153 | |||
2154 | me->status = status; | ||
2155 | me->codeRes = res; | ||
2156 | |||
2157 | if (isCross) | ||
2158 | me->mtc.crossStart += srcProcessed; | ||
2159 | |||
2160 | me->mtc.inProcessed += srcProcessed; | ||
2161 | me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; | ||
2162 | |||
2163 | srcSize -= srcProcessed; | ||
2164 | src += srcProcessed; | ||
2165 | |||
2166 | if (res != SZ_OK) | ||
2167 | { | ||
2168 | return SZ_OK; | ||
2169 | // return res; | ||
2170 | } | ||
2171 | |||
2172 | if (dec->state == XZ_STATE_STREAM_HEADER) | ||
2173 | { | ||
2174 | *needContinue = True; | ||
2175 | me->isBlockHeaderState_Parse = False; | ||
2176 | me->isBlockHeaderState_Write = False; | ||
2177 | |||
2178 | if (!isCross) | ||
2179 | { | ||
2180 | Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); | ||
2181 | if (!crossBuf) | ||
2182 | return SZ_ERROR_MEM; | ||
2183 | if (srcSize != 0) | ||
2184 | memcpy(crossBuf, src, srcSize); | ||
2185 | me->mtc.crossStart = 0; | ||
2186 | me->mtc.crossEnd = srcSize; | ||
2187 | } | ||
2188 | |||
2189 | PRF_STR_INT("XZ_STATE_STREAM_HEADER crossEnd = ", (unsigned)me->mtc.crossEnd); | ||
2190 | |||
2191 | return SZ_OK; | ||
2192 | } | ||
2193 | |||
2194 | if (status != CODER_STATUS_NEEDS_MORE_INPUT || srcSize != 0) | ||
2195 | { | ||
2196 | return SZ_ERROR_FAIL; | ||
2197 | } | ||
2198 | |||
2199 | if (me->mtc.readWasFinished) | ||
2200 | { | ||
2201 | return SZ_OK; | ||
2202 | } | ||
2203 | } | ||
2204 | |||
2205 | { | ||
2206 | size_t inPos; | ||
2207 | size_t inLim; | ||
2208 | // const Byte *inData; | ||
2209 | UInt64 inProgressPrev = me->mtc.inProcessed; | ||
2210 | |||
2211 | // XzDecMt_Prepare_InBuf_ST(p); | ||
2212 | Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc); | ||
2213 | if (!crossBuf) | ||
2214 | return SZ_ERROR_MEM; | ||
2215 | |||
2216 | inPos = 0; | ||
2217 | inLim = 0; | ||
2218 | |||
2219 | // inData = crossBuf; | ||
2220 | |||
2221 | for (;;) | ||
2222 | { | ||
2223 | SizeT inProcessed; | ||
2224 | SizeT outProcessed; | ||
2225 | ECoderStatus status; | ||
2226 | SRes res; | ||
2227 | |||
2228 | if (inPos == inLim) | ||
2229 | { | ||
2230 | if (!me->mtc.readWasFinished) | ||
2231 | { | ||
2232 | inPos = 0; | ||
2233 | inLim = me->mtc.inBufSize; | ||
2234 | me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)crossBuf, &inLim); | ||
2235 | me->mtc.readProcessed += inLim; | ||
2236 | if (inLim == 0 || me->mtc.readRes != SZ_OK) | ||
2237 | me->mtc.readWasFinished = True; | ||
2238 | } | ||
2239 | } | ||
2240 | |||
2241 | inProcessed = inLim - inPos; | ||
2242 | outProcessed = 0; | ||
2243 | |||
2244 | res = XzUnpacker_Code(dec, | ||
2245 | NULL, &outProcessed, | ||
2246 | crossBuf + inPos, &inProcessed, | ||
2247 | (inProcessed == 0), // srcFinished | ||
2248 | CODER_FINISH_END, &status); | ||
2249 | |||
2250 | me->codeRes = res; | ||
2251 | me->status = status; | ||
2252 | inPos += inProcessed; | ||
2253 | me->mtc.inProcessed += inProcessed; | ||
2254 | me->mtc.mtProgress.totalInSize = me->mtc.inProcessed; | ||
2255 | |||
2256 | if (res != SZ_OK) | ||
2257 | { | ||
2258 | return SZ_OK; | ||
2259 | // return res; | ||
2260 | } | ||
2261 | |||
2262 | if (dec->state == XZ_STATE_STREAM_HEADER) | ||
2263 | { | ||
2264 | *needContinue = True; | ||
2265 | me->mtc.crossStart = inPos; | ||
2266 | me->mtc.crossEnd = inLim; | ||
2267 | me->isBlockHeaderState_Parse = False; | ||
2268 | me->isBlockHeaderState_Write = False; | ||
2269 | return SZ_OK; | ||
2270 | } | ||
2271 | |||
2272 | if (status != CODER_STATUS_NEEDS_MORE_INPUT) | ||
2273 | return SZ_ERROR_FAIL; | ||
2274 | |||
2275 | if (me->mtc.progress) | ||
2276 | { | ||
2277 | UInt64 inDelta = me->mtc.inProcessed - inProgressPrev; | ||
2278 | if (inDelta >= (1 << 22)) | ||
2279 | { | ||
2280 | RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress)); | ||
2281 | inProgressPrev = me->mtc.inProcessed; | ||
2282 | } | ||
2283 | } | ||
2284 | if (me->mtc.readWasFinished) | ||
2285 | return SZ_OK; | ||
2286 | } | ||
2287 | } | ||
2288 | } | ||
2289 | } | ||
2290 | |||
2291 | |||
2292 | #endif | ||
2293 | |||
2294 | |||
2295 | |||
2296 | void XzStatInfo_Clear(CXzStatInfo *p) | ||
2297 | { | ||
2298 | p->InSize = 0; | ||
2299 | p->OutSize = 0; | ||
2300 | |||
2301 | p->NumStreams = 0; | ||
2302 | p->NumBlocks = 0; | ||
2303 | |||
2304 | p->UnpackSize_Defined = False; | ||
2305 | |||
2306 | p->NumStreams_Defined = False; | ||
2307 | p->NumBlocks_Defined = False; | ||
2308 | |||
2309 | p->DataAfterEnd = False; | ||
2310 | p->DecodingTruncated = False; | ||
2311 | |||
2312 | p->DecodeRes = SZ_OK; | ||
2313 | p->ReadRes = SZ_OK; | ||
2314 | p->ProgressRes = SZ_OK; | ||
2315 | |||
2316 | p->CombinedRes = SZ_OK; | ||
2317 | p->CombinedRes_Type = SZ_OK; | ||
2318 | } | ||
2319 | |||
2320 | |||
2321 | |||
2322 | /* | ||
2323 | XzDecMt_Decode_ST() can return SZ_OK or the following errors | ||
2324 | - SZ_ERROR_MEM for memory allocation error | ||
2325 | - error from XzUnpacker_Code() function | ||
2326 | - SZ_ERROR_WRITE for ISeqOutStream::Write(). stat->CombinedRes_Type = SZ_ERROR_WRITE in that case | ||
2327 | - ICompressProgress::Progress() error, stat->CombinedRes_Type = SZ_ERROR_PROGRESS. | ||
2328 | But XzDecMt_Decode_ST() doesn't return ISeqInStream::Read() errors. | ||
2329 | ISeqInStream::Read() result is set to p->readRes. | ||
2330 | also it can set stat->CombinedRes_Type to SZ_ERROR_WRITE or SZ_ERROR_PROGRESS. | ||
2331 | */ | ||
2332 | |||
2333 | static SRes XzDecMt_Decode_ST(CXzDecMt *p | ||
2334 | #ifndef _7ZIP_ST | ||
2335 | , BoolInt tMode | ||
2336 | #endif | ||
2337 | , CXzStatInfo *stat) | ||
2338 | { | ||
2339 | size_t outPos; | ||
2340 | size_t inPos, inLim; | ||
2341 | const Byte *inData; | ||
2342 | UInt64 inPrev, outPrev; | ||
2343 | |||
2344 | CXzUnpacker *dec; | ||
2345 | |||
2346 | #ifndef _7ZIP_ST | ||
2347 | if (tMode) | ||
2348 | { | ||
2349 | XzDecMt_FreeOutBufs(p); | ||
2350 | tMode = MtDec_PrepareRead(&p->mtc); | ||
2351 | } | ||
2352 | #endif | ||
2353 | |||
2354 | if (!p->outBuf || p->outBufSize != p->props.outStep_ST) | ||
2355 | { | ||
2356 | ISzAlloc_Free(p->allocMid, p->outBuf); | ||
2357 | p->outBufSize = 0; | ||
2358 | p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST); | ||
2359 | if (!p->outBuf) | ||
2360 | return SZ_ERROR_MEM; | ||
2361 | p->outBufSize = p->props.outStep_ST; | ||
2362 | } | ||
2363 | |||
2364 | if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST) | ||
2365 | { | ||
2366 | ISzAlloc_Free(p->allocMid, p->inBuf); | ||
2367 | p->inBufSize = 0; | ||
2368 | p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST); | ||
2369 | if (!p->inBuf) | ||
2370 | return SZ_ERROR_MEM; | ||
2371 | p->inBufSize = p->props.inBufSize_ST; | ||
2372 | } | ||
2373 | |||
2374 | dec = &p->dec; | ||
2375 | dec->decodeToStreamSignature = False; | ||
2376 | // dec->decodeOnlyOneBlock = False; | ||
2377 | |||
2378 | XzUnpacker_SetOutBuf(dec, NULL, 0); | ||
2379 | |||
2380 | inPrev = p->inProcessed; | ||
2381 | outPrev = p->outProcessed; | ||
2382 | |||
2383 | inPos = 0; | ||
2384 | inLim = 0; | ||
2385 | inData = NULL; | ||
2386 | outPos = 0; | ||
2387 | |||
2388 | for (;;) | ||
2389 | { | ||
2390 | SizeT outSize; | ||
2391 | BoolInt finished; | ||
2392 | ECoderFinishMode finishMode; | ||
2393 | SizeT inProcessed; | ||
2394 | ECoderStatus status; | ||
2395 | SRes res; | ||
2396 | |||
2397 | SizeT outProcessed; | ||
2398 | |||
2399 | |||
2400 | |||
2401 | if (inPos == inLim) | ||
2402 | { | ||
2403 | #ifndef _7ZIP_ST | ||
2404 | if (tMode) | ||
2405 | { | ||
2406 | inData = MtDec_Read(&p->mtc, &inLim); | ||
2407 | inPos = 0; | ||
2408 | if (inData) | ||
2409 | continue; | ||
2410 | tMode = False; | ||
2411 | inLim = 0; | ||
2412 | } | ||
2413 | #endif | ||
2414 | |||
2415 | if (!p->readWasFinished) | ||
2416 | { | ||
2417 | inPos = 0; | ||
2418 | inLim = p->inBufSize; | ||
2419 | inData = p->inBuf; | ||
2420 | p->readRes = ISeqInStream_Read(p->inStream, (void *)p->inBuf, &inLim); | ||
2421 | p->readProcessed += inLim; | ||
2422 | if (inLim == 0 || p->readRes != SZ_OK) | ||
2423 | p->readWasFinished = True; | ||
2424 | } | ||
2425 | } | ||
2426 | |||
2427 | outSize = p->props.outStep_ST - outPos; | ||
2428 | |||
2429 | finishMode = CODER_FINISH_ANY; | ||
2430 | if (p->outSize_Defined) | ||
2431 | { | ||
2432 | const UInt64 rem = p->outSize - p->outProcessed; | ||
2433 | if (outSize >= rem) | ||
2434 | { | ||
2435 | outSize = (SizeT)rem; | ||
2436 | if (p->finishMode) | ||
2437 | finishMode = CODER_FINISH_END; | ||
2438 | } | ||
2439 | } | ||
2440 | |||
2441 | inProcessed = inLim - inPos; | ||
2442 | outProcessed = outSize; | ||
2443 | |||
2444 | res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed, | ||
2445 | inData + inPos, &inProcessed, | ||
2446 | (inPos == inLim), // srcFinished | ||
2447 | finishMode, &status); | ||
2448 | |||
2449 | p->codeRes = res; | ||
2450 | p->status = status; | ||
2451 | |||
2452 | inPos += inProcessed; | ||
2453 | outPos += outProcessed; | ||
2454 | p->inProcessed += inProcessed; | ||
2455 | p->outProcessed += outProcessed; | ||
2456 | |||
2457 | finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK); | ||
2458 | |||
2459 | if (finished || outProcessed >= outSize) | ||
2460 | if (outPos != 0) | ||
2461 | { | ||
2462 | const size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos); | ||
2463 | // p->outProcessed += written; // 21.01: BUG fixed | ||
2464 | if (written != outPos) | ||
2465 | { | ||
2466 | stat->CombinedRes_Type = SZ_ERROR_WRITE; | ||
2467 | return SZ_ERROR_WRITE; | ||
2468 | } | ||
2469 | outPos = 0; | ||
2470 | } | ||
2471 | |||
2472 | if (p->progress && res == SZ_OK) | ||
2473 | { | ||
2474 | if (p->inProcessed - inPrev >= (1 << 22) || | ||
2475 | p->outProcessed - outPrev >= (1 << 22)) | ||
2476 | { | ||
2477 | res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed); | ||
2478 | if (res != SZ_OK) | ||
2479 | { | ||
2480 | stat->CombinedRes_Type = SZ_ERROR_PROGRESS; | ||
2481 | stat->ProgressRes = res; | ||
2482 | return res; | ||
2483 | } | ||
2484 | inPrev = p->inProcessed; | ||
2485 | outPrev = p->outProcessed; | ||
2486 | } | ||
2487 | } | ||
2488 | |||
2489 | if (finished) | ||
2490 | { | ||
2491 | // p->codeRes is preliminary error from XzUnpacker_Code. | ||
2492 | // and it can be corrected later as final result | ||
2493 | // so we return SZ_OK here instead of (res); | ||
2494 | return SZ_OK; | ||
2495 | // return res; | ||
2496 | } | ||
2497 | } | ||
2498 | } | ||
2499 | |||
2500 | |||
2501 | |||
2502 | /* | ||
2503 | XzStatInfo_SetStat() transforms | ||
2504 | CXzUnpacker return code and status to combined CXzStatInfo results. | ||
2505 | it can convert SZ_OK to SZ_ERROR_INPUT_EOF | ||
2506 | it can convert SZ_ERROR_NO_ARCHIVE to SZ_OK and (DataAfterEnd = 1) | ||
2507 | */ | ||
2508 | |||
2509 | static void XzStatInfo_SetStat(const CXzUnpacker *dec, | ||
2510 | int finishMode, | ||
2511 | // UInt64 readProcessed, | ||
2512 | UInt64 inProcessed, | ||
2513 | SRes res, // it's result from CXzUnpacker unpacker | ||
2514 | ECoderStatus status, | ||
2515 | BoolInt decodingTruncated, | ||
2516 | CXzStatInfo *stat) | ||
2517 | { | ||
2518 | UInt64 extraSize; | ||
2519 | |||
2520 | stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0); | ||
2521 | stat->InSize = inProcessed; | ||
2522 | stat->NumStreams = dec->numStartedStreams; | ||
2523 | stat->NumBlocks = dec->numTotalBlocks; | ||
2524 | |||
2525 | stat->UnpackSize_Defined = True; | ||
2526 | stat->NumStreams_Defined = True; | ||
2527 | stat->NumBlocks_Defined = True; | ||
2528 | |||
2529 | extraSize = XzUnpacker_GetExtraSize(dec); | ||
2530 | |||
2531 | if (res == SZ_OK) | ||
2532 | { | ||
2533 | if (status == CODER_STATUS_NEEDS_MORE_INPUT) | ||
2534 | { | ||
2535 | // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams | ||
2536 | // any extra data is part of correct data | ||
2537 | extraSize = 0; | ||
2538 | // if xz stream was not finished, then we need more data | ||
2539 | if (!XzUnpacker_IsStreamWasFinished(dec)) | ||
2540 | res = SZ_ERROR_INPUT_EOF; | ||
2541 | } | ||
2542 | else | ||
2543 | { | ||
2544 | // CODER_STATUS_FINISHED_WITH_MARK is not possible for multi stream xz decoding | ||
2545 | // so he we have (status == CODER_STATUS_NOT_FINISHED) | ||
2546 | // if (status != CODER_STATUS_FINISHED_WITH_MARK) | ||
2547 | if (!decodingTruncated || finishMode) | ||
2548 | res = SZ_ERROR_DATA; | ||
2549 | } | ||
2550 | } | ||
2551 | else if (res == SZ_ERROR_NO_ARCHIVE) | ||
2552 | { | ||
2553 | /* | ||
2554 | SZ_ERROR_NO_ARCHIVE is possible for 2 states: | ||
2555 | XZ_STATE_STREAM_HEADER - if bad signature or bad CRC | ||
2556 | XZ_STATE_STREAM_PADDING - if non-zero padding data | ||
2557 | extraSize and inProcessed don't include "bad" byte | ||
2558 | */ | ||
2559 | // if (inProcessed == extraSize), there was no any good xz stream header, and we keep error | ||
2560 | if (inProcessed != extraSize) // if there were good xz streams before error | ||
2561 | { | ||
2562 | // if (extraSize != 0 || readProcessed != inProcessed) | ||
2563 | { | ||
2564 | // he we suppose that all xz streams were finsihed OK, and we have | ||
2565 | // some extra data after all streams | ||
2566 | stat->DataAfterEnd = True; | ||
2567 | res = SZ_OK; | ||
2568 | } | ||
2569 | } | ||
2570 | } | ||
2571 | |||
2572 | if (stat->DecodeRes == SZ_OK) | ||
2573 | stat->DecodeRes = res; | ||
2574 | |||
2575 | stat->InSize -= extraSize; | ||
2576 | } | ||
2577 | |||
2578 | |||
2579 | |||
2580 | SRes XzDecMt_Decode(CXzDecMtHandle pp, | ||
2581 | const CXzDecMtProps *props, | ||
2582 | const UInt64 *outDataSize, int finishMode, | ||
2583 | ISeqOutStream *outStream, | ||
2584 | // Byte *outBuf, size_t *outBufSize, | ||
2585 | ISeqInStream *inStream, | ||
2586 | // const Byte *inData, size_t inDataSize, | ||
2587 | CXzStatInfo *stat, | ||
2588 | int *isMT, | ||
2589 | ICompressProgress *progress) | ||
2590 | { | ||
2591 | CXzDecMt *p = (CXzDecMt *)pp; | ||
2592 | #ifndef _7ZIP_ST | ||
2593 | BoolInt tMode; | ||
2594 | #endif | ||
2595 | |||
2596 | XzStatInfo_Clear(stat); | ||
2597 | |||
2598 | p->props = *props; | ||
2599 | |||
2600 | p->inStream = inStream; | ||
2601 | p->outStream = outStream; | ||
2602 | p->progress = progress; | ||
2603 | // p->stat = stat; | ||
2604 | |||
2605 | p->outSize = 0; | ||
2606 | p->outSize_Defined = False; | ||
2607 | if (outDataSize) | ||
2608 | { | ||
2609 | p->outSize_Defined = True; | ||
2610 | p->outSize = *outDataSize; | ||
2611 | } | ||
2612 | |||
2613 | p->finishMode = finishMode; | ||
2614 | |||
2615 | // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test | ||
2616 | |||
2617 | p->writeRes = SZ_OK; | ||
2618 | p->outProcessed = 0; | ||
2619 | p->inProcessed = 0; | ||
2620 | p->readProcessed = 0; | ||
2621 | p->readWasFinished = False; | ||
2622 | p->readRes = SZ_OK; | ||
2623 | |||
2624 | p->codeRes = SZ_OK; | ||
2625 | p->status = CODER_STATUS_NOT_SPECIFIED; | ||
2626 | |||
2627 | XzUnpacker_Init(&p->dec); | ||
2628 | |||
2629 | *isMT = False; | ||
2630 | |||
2631 | /* | ||
2632 | p->outBuf = NULL; | ||
2633 | p->outBufSize = 0; | ||
2634 | if (!outStream) | ||
2635 | { | ||
2636 | p->outBuf = outBuf; | ||
2637 | p->outBufSize = *outBufSize; | ||
2638 | *outBufSize = 0; | ||
2639 | } | ||
2640 | */ | ||
2641 | |||
2642 | |||
2643 | #ifndef _7ZIP_ST | ||
2644 | |||
2645 | p->isBlockHeaderState_Parse = False; | ||
2646 | p->isBlockHeaderState_Write = False; | ||
2647 | // p->numBadBlocks = 0; | ||
2648 | p->mainErrorCode = SZ_OK; | ||
2649 | p->mainDecoderWasCalled = False; | ||
2650 | |||
2651 | tMode = False; | ||
2652 | |||
2653 | if (p->props.numThreads > 1) | ||
2654 | { | ||
2655 | IMtDecCallback2 vt; | ||
2656 | BoolInt needContinue; | ||
2657 | SRes res; | ||
2658 | // we just free ST buffers here | ||
2659 | // but we still keep state variables, that was set in XzUnpacker_Init() | ||
2660 | XzDecMt_FreeSt(p); | ||
2661 | |||
2662 | p->outProcessed_Parse = 0; | ||
2663 | p->parsing_Truncated = False; | ||
2664 | |||
2665 | p->numStreams = 0; | ||
2666 | p->numTotalBlocks = 0; | ||
2667 | p->numBlocks = 0; | ||
2668 | p->finishedDecoderIndex = -1; | ||
2669 | |||
2670 | if (!p->mtc_WasConstructed) | ||
2671 | { | ||
2672 | p->mtc_WasConstructed = True; | ||
2673 | MtDec_Construct(&p->mtc); | ||
2674 | } | ||
2675 | |||
2676 | p->mtc.mtCallback = &vt; | ||
2677 | p->mtc.mtCallbackObject = p; | ||
2678 | |||
2679 | p->mtc.progress = progress; | ||
2680 | p->mtc.inStream = inStream; | ||
2681 | p->mtc.alloc = &p->alignOffsetAlloc.vt; | ||
2682 | // p->mtc.inData = inData; | ||
2683 | // p->mtc.inDataSize = inDataSize; | ||
2684 | p->mtc.inBufSize = p->props.inBufSize_MT; | ||
2685 | // p->mtc.inBlockMax = p->props.inBlockMax; | ||
2686 | p->mtc.numThreadsMax = p->props.numThreads; | ||
2687 | |||
2688 | *isMT = True; | ||
2689 | |||
2690 | vt.Parse = XzDecMt_Callback_Parse; | ||
2691 | vt.PreCode = XzDecMt_Callback_PreCode; | ||
2692 | vt.Code = XzDecMt_Callback_Code; | ||
2693 | vt.Write = XzDecMt_Callback_Write; | ||
2694 | |||
2695 | |||
2696 | res = MtDec_Code(&p->mtc); | ||
2697 | |||
2698 | |||
2699 | stat->InSize = p->mtc.inProcessed; | ||
2700 | |||
2701 | p->inProcessed = p->mtc.inProcessed; | ||
2702 | p->readRes = p->mtc.readRes; | ||
2703 | p->readWasFinished = p->mtc.readWasFinished; | ||
2704 | p->readProcessed = p->mtc.readProcessed; | ||
2705 | |||
2706 | tMode = True; | ||
2707 | needContinue = False; | ||
2708 | |||
2709 | if (res == SZ_OK) | ||
2710 | { | ||
2711 | if (p->mtc.mtProgress.res != SZ_OK) | ||
2712 | { | ||
2713 | res = p->mtc.mtProgress.res; | ||
2714 | stat->ProgressRes = res; | ||
2715 | stat->CombinedRes_Type = SZ_ERROR_PROGRESS; | ||
2716 | } | ||
2717 | else | ||
2718 | needContinue = p->mtc.needContinue; | ||
2719 | } | ||
2720 | |||
2721 | if (!needContinue) | ||
2722 | { | ||
2723 | { | ||
2724 | SRes codeRes; | ||
2725 | BoolInt truncated = False; | ||
2726 | ECoderStatus status; | ||
2727 | const CXzUnpacker *dec; | ||
2728 | |||
2729 | stat->OutSize = p->outProcessed; | ||
2730 | |||
2731 | if (p->finishedDecoderIndex >= 0) | ||
2732 | { | ||
2733 | const CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex]; | ||
2734 | codeRes = coder->codeRes; | ||
2735 | dec = &coder->dec; | ||
2736 | status = coder->status; | ||
2737 | } | ||
2738 | else if (p->mainDecoderWasCalled) | ||
2739 | { | ||
2740 | codeRes = p->codeRes; | ||
2741 | dec = &p->dec; | ||
2742 | status = p->status; | ||
2743 | truncated = p->parsing_Truncated; | ||
2744 | } | ||
2745 | else | ||
2746 | return SZ_ERROR_FAIL; | ||
2747 | |||
2748 | if (p->mainErrorCode != SZ_OK) | ||
2749 | stat->DecodeRes = p->mainErrorCode; | ||
2750 | |||
2751 | XzStatInfo_SetStat(dec, p->finishMode, | ||
2752 | // p->mtc.readProcessed, | ||
2753 | p->mtc.inProcessed, | ||
2754 | codeRes, status, | ||
2755 | truncated, | ||
2756 | stat); | ||
2757 | } | ||
2758 | |||
2759 | if (res == SZ_OK) | ||
2760 | { | ||
2761 | stat->ReadRes = p->mtc.readRes; | ||
2762 | |||
2763 | if (p->writeRes != SZ_OK) | ||
2764 | { | ||
2765 | res = p->writeRes; | ||
2766 | stat->CombinedRes_Type = SZ_ERROR_WRITE; | ||
2767 | } | ||
2768 | else if (p->mtc.readRes != SZ_OK | ||
2769 | // && p->mtc.inProcessed == p->mtc.readProcessed | ||
2770 | && stat->DecodeRes == SZ_ERROR_INPUT_EOF) | ||
2771 | { | ||
2772 | res = p->mtc.readRes; | ||
2773 | stat->CombinedRes_Type = SZ_ERROR_READ; | ||
2774 | } | ||
2775 | else if (stat->DecodeRes != SZ_OK) | ||
2776 | res = stat->DecodeRes; | ||
2777 | } | ||
2778 | |||
2779 | stat->CombinedRes = res; | ||
2780 | if (stat->CombinedRes_Type == SZ_OK) | ||
2781 | stat->CombinedRes_Type = res; | ||
2782 | return res; | ||
2783 | } | ||
2784 | |||
2785 | PRF_STR("----- decoding ST -----"); | ||
2786 | } | ||
2787 | |||
2788 | #endif | ||
2789 | |||
2790 | |||
2791 | *isMT = False; | ||
2792 | |||
2793 | { | ||
2794 | SRes res = XzDecMt_Decode_ST(p | ||
2795 | #ifndef _7ZIP_ST | ||
2796 | , tMode | ||
2797 | #endif | ||
2798 | , stat | ||
2799 | ); | ||
2800 | |||
2801 | #ifndef _7ZIP_ST | ||
2802 | // we must set error code from MT decoding at first | ||
2803 | if (p->mainErrorCode != SZ_OK) | ||
2804 | stat->DecodeRes = p->mainErrorCode; | ||
2805 | #endif | ||
2806 | |||
2807 | XzStatInfo_SetStat(&p->dec, | ||
2808 | p->finishMode, | ||
2809 | // p->readProcessed, | ||
2810 | p->inProcessed, | ||
2811 | p->codeRes, p->status, | ||
2812 | False, // truncated | ||
2813 | stat); | ||
2814 | |||
2815 | stat->ReadRes = p->readRes; | ||
2816 | |||
2817 | if (res == SZ_OK) | ||
2818 | { | ||
2819 | if (p->readRes != SZ_OK | ||
2820 | // && p->inProcessed == p->readProcessed | ||
2821 | && stat->DecodeRes == SZ_ERROR_INPUT_EOF) | ||
2822 | { | ||
2823 | // we set read error as combined error, only if that error was the reason | ||
2824 | // of decoding problem | ||
2825 | res = p->readRes; | ||
2826 | stat->CombinedRes_Type = SZ_ERROR_READ; | ||
2827 | } | ||
2828 | else if (stat->DecodeRes != SZ_OK) | ||
2829 | res = stat->DecodeRes; | ||
2830 | } | ||
2831 | |||
2832 | stat->CombinedRes = res; | ||
2833 | if (stat->CombinedRes_Type == SZ_OK) | ||
2834 | stat->CombinedRes_Type = res; | ||
2835 | return res; | ||
2836 | } | ||
2837 | } | ||