Bug 1941128 - Turn off network.dns.native_https_query on Mac again
[gecko.git] / other-licenses / 7zstub / src / C / XzDec.c
blobebf198336c1e039b6fc604e8b13e5a67fffac585
1 /* XzDec.c -- Xz Decode
2 2018-04-24 : Igor Pavlov : Public domain */
4 #include "Precomp.h"
6 // #include <stdio.h>
8 // #define XZ_DUMP
10 /* #define XZ_DUMP */
12 #ifdef XZ_DUMP
13 #include <stdio.h>
14 #endif
16 // #define SHOW_DEBUG_INFO
18 #ifdef SHOW_DEBUG_INFO
19 #include <stdio.h>
20 #endif
22 #ifdef SHOW_DEBUG_INFO
23 #define PRF(x) x
24 #else
25 #define PRF(x)
26 #endif
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))
31 #include <stdlib.h>
32 #include <string.h>
34 #include "7zCrc.h"
35 #include "Alloc.h"
36 #include "Bra.h"
37 #include "CpuArch.h"
38 #include "Delta.h"
39 #include "Lzma2Dec.h"
41 // #define USE_SUBBLOCK
43 #ifdef USE_SUBBLOCK
44 #include "Bcj3Dec.c"
45 #include "SbDec.h"
46 #endif
48 #include "Xz.h"
50 #define XZ_CHECK_SIZE_MAX 64
52 #define CODER_BUF_SIZE ((size_t)1 << 17)
54 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
56 unsigned i, limit;
57 *value = 0;
58 limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
60 for (i = 0; i < limit;)
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;
67 return 0;
70 /* ---------- BraState ---------- */
72 #define BRA_BUF_SIZE (1 << 14)
74 typedef struct
76 size_t bufPos;
77 size_t bufConv;
78 size_t bufTotal;
80 int encodeMode;
82 UInt32 methodId;
83 UInt32 delta;
84 UInt32 ip;
85 UInt32 x86State;
86 Byte deltaState[DELTA_STATE_SIZE];
88 Byte buf[BRA_BUF_SIZE];
89 } CBraState;
91 static void BraState_Free(void *pp, ISzAllocPtr alloc)
93 ISzAlloc_Free(alloc, pp);
96 static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
98 CBraState *p = ((CBraState *)pp);
99 UNUSED_VAR(alloc);
100 p->ip = 0;
101 if (p->methodId == XZ_ID_Delta)
103 if (propSize != 1)
104 return SZ_ERROR_UNSUPPORTED;
105 p->delta = (unsigned)props[0] + 1;
107 else
109 if (propSize == 4)
111 UInt32 v = GetUi32(props);
112 switch (p->methodId)
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;
129 p->ip = v;
131 else if (propSize != 0)
132 return SZ_ERROR_UNSUPPORTED;
134 return SZ_OK;
137 static void BraState_Init(void *pp)
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);
147 #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break;
149 static SizeT BraState_Filter(void *pp, Byte *data, SizeT size)
151 CBraState *p = ((CBraState *)pp);
152 switch (p->methodId)
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)
169 p->ip += (UInt32)size;
170 return size;
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)
181 CBraState *p = ((CBraState *)pp);
182 SizeT destRem = *destLen;
183 SizeT srcRem = *srcLen;
184 UNUSED_VAR(finishMode);
186 *destLen = 0;
187 *srcLen = 0;
188 // *wasFinished = False;
189 *status = CODER_STATUS_NOT_FINISHED;
191 while (destRem > 0)
193 if (p->bufPos != p->bufConv)
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;
206 p->bufTotal -= p->bufPos;
207 memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
208 p->bufPos = 0;
209 p->bufConv = 0;
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;
220 if (p->bufTotal == 0)
221 break;
223 p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal);
225 if (p->bufConv == 0)
227 if (!srcWasFinished)
228 break;
229 p->bufConv = p->bufTotal;
233 if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
235 *status = CODER_STATUS_FINISHED_WITH_MARK;
236 // *wasFinished = 1;
239 return SZ_OK;
243 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
245 CBraState *decoder;
246 if (id < XZ_ID_Delta || id > XZ_ID_SPARC)
247 return SZ_ERROR_UNSUPPORTED;
248 decoder = p->p;
249 if (!decoder)
251 decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));
252 if (!decoder)
253 return SZ_ERROR_MEM;
254 p->p = decoder;
255 p->Free = BraState_Free;
256 p->SetProps = BraState_SetProps;
257 p->Init = BraState_Init;
258 p->Code2 = BraState_Code2;
259 p->Filter = BraState_Filter;
261 decoder->methodId = (UInt32)id;
262 decoder->encodeMode = encodeMode;
263 return SZ_OK;
268 /* ---------- SbState ---------- */
270 #ifdef USE_SUBBLOCK
272 static void SbState_Free(void *pp, ISzAllocPtr alloc)
274 CSbDec *p = (CSbDec *)pp;
275 SbDec_Free(p);
276 ISzAlloc_Free(alloc, pp);
279 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
281 UNUSED_VAR(pp);
282 UNUSED_VAR(props);
283 UNUSED_VAR(alloc);
284 return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
287 static void SbState_Init(void *pp)
289 SbDec_Init((CSbDec *)pp);
292 static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
293 int srcWasFinished, ECoderFinishMode finishMode,
294 // int *wasFinished
295 ECoderStatus *status)
297 CSbDec *p = (CSbDec *)pp;
298 SRes res;
299 UNUSED_VAR(srcWasFinished);
300 p->dest = dest;
301 p->destLen = *destLen;
302 p->src = src;
303 p->srcLen = *srcLen;
304 p->finish = finishMode; /* change it */
305 res = SbDec_Decode((CSbDec *)pp);
306 *destLen -= p->destLen;
307 *srcLen -= p->srcLen;
308 // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
309 *status = (*destLen == 0 && *srcLen == 0) ?
310 CODER_STATUS_FINISHED_WITH_MARK :
311 CODER_STATUS_NOT_FINISHED;
312 return res;
315 static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
317 CSbDec *decoder = (CSbDec *)p->p;
318 if (!decoder)
320 decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
321 if (!decoder)
322 return SZ_ERROR_MEM;
323 p->p = decoder;
324 p->Free = SbState_Free;
325 p->SetProps = SbState_SetProps;
326 p->Init = SbState_Init;
327 p->Code2 = SbState_Code2;
328 p->Filter = NULL;
330 SbDec_Construct(decoder);
331 SbDec_SetAlloc(decoder, alloc);
332 return SZ_OK;
335 #endif
339 /* ---------- Lzma2 ---------- */
341 typedef struct
343 CLzma2Dec decoder;
344 Bool outBufMode;
345 } CLzma2Dec_Spec;
348 static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
350 CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
351 if (p->outBufMode)
352 Lzma2Dec_FreeProbs(&p->decoder, alloc);
353 else
354 Lzma2Dec_Free(&p->decoder, alloc);
355 ISzAlloc_Free(alloc, pp);
358 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
360 if (propSize != 1)
361 return SZ_ERROR_UNSUPPORTED;
363 CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
364 if (p->outBufMode)
365 return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
366 else
367 return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
371 static void Lzma2State_Init(void *pp)
373 Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
378 if (outBufMode), then (dest) is not used. Use NULL.
379 Data is unpacked to (spec->decoder.decoder.dic) output buffer.
382 static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
383 int srcWasFinished, ECoderFinishMode finishMode,
384 // int *wasFinished,
385 ECoderStatus *status)
387 CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
388 ELzmaStatus status2;
389 /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
390 SRes res;
391 UNUSED_VAR(srcWasFinished);
392 if (spec->outBufMode)
394 SizeT dicPos = spec->decoder.decoder.dicPos;
395 SizeT dicLimit = dicPos + *destLen;
396 res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
397 *destLen = spec->decoder.decoder.dicPos - dicPos;
399 else
400 res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
401 // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
402 // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
403 *status = status2;
404 return res;
408 static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
410 CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
411 if (!spec)
413 spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
414 if (!spec)
415 return SZ_ERROR_MEM;
416 p->p = spec;
417 p->Free = Lzma2State_Free;
418 p->SetProps = Lzma2State_SetProps;
419 p->Init = Lzma2State_Init;
420 p->Code2 = Lzma2State_Code2;
421 p->Filter = NULL;
422 Lzma2Dec_Construct(&spec->decoder);
424 spec->outBufMode = False;
425 if (outBuf)
427 spec->outBufMode = True;
428 spec->decoder.decoder.dic = outBuf;
429 spec->decoder.decoder.dicBufSize = outBufSize;
431 return SZ_OK;
435 static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
437 CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
438 if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
439 return SZ_ERROR_FAIL;
440 if (outBuf)
442 spec->decoder.decoder.dic = outBuf;
443 spec->decoder.decoder.dicBufSize = outBufSize;
445 return SZ_OK;
450 static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
452 unsigned i;
453 p->alloc = alloc;
454 p->buf = NULL;
455 p->numCoders = 0;
457 p->outBufSize = 0;
458 p->outBuf = NULL;
459 // p->SingleBufMode = False;
461 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
462 p->coders[i].p = NULL;
466 static void MixCoder_Free(CMixCoder *p)
468 unsigned i;
469 p->numCoders = 0;
470 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
472 IStateCoder *sc = &p->coders[i];
473 if (sc->p)
475 sc->Free(sc->p, p->alloc);
476 sc->p = NULL;
479 if (p->buf)
481 ISzAlloc_Free(p->alloc, p->buf);
482 p->buf = NULL; /* 9.31: the BUG was fixed */
486 static void MixCoder_Init(CMixCoder *p)
488 unsigned i;
489 for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
491 p->size[i] = 0;
492 p->pos[i] = 0;
493 p->finished[i] = 0;
495 for (i = 0; i < p->numCoders; i++)
497 IStateCoder *coder = &p->coders[i];
498 coder->Init(coder->p);
499 p->results[i] = SZ_OK;
501 p->outWritten = 0;
502 p->wasFinished = False;
503 p->res = SZ_OK;
504 p->status = CODER_STATUS_NOT_SPECIFIED;
508 static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
510 IStateCoder *sc = &p->coders[coderIndex];
511 p->ids[coderIndex] = methodId;
512 switch (methodId)
514 case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
515 #ifdef USE_SUBBLOCK
516 case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
517 #endif
519 if (coderIndex == 0)
520 return SZ_ERROR_UNSUPPORTED;
521 return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
525 static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
527 IStateCoder *sc = &p->coders[coderIndex];
528 switch (methodId)
530 case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
532 return SZ_ERROR_UNSUPPORTED;
538 if (destFinish) - then unpack data block is finished at (*destLen) position,
539 and we can return data that were not processed by filter
541 output (status) can be :
542 CODER_STATUS_NOT_FINISHED
543 CODER_STATUS_FINISHED_WITH_MARK
544 CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
547 static SRes MixCoder_Code(CMixCoder *p,
548 Byte *dest, SizeT *destLen, int destFinish,
549 const Byte *src, SizeT *srcLen, int srcWasFinished,
550 ECoderFinishMode finishMode)
552 SizeT destLenOrig = *destLen;
553 SizeT srcLenOrig = *srcLen;
555 *destLen = 0;
556 *srcLen = 0;
558 if (p->wasFinished)
559 return p->res;
561 p->status = CODER_STATUS_NOT_FINISHED;
563 // if (p->SingleBufMode)
564 if (p->outBuf)
566 SRes res;
567 SizeT destLen2, srcLen2;
568 int wasFinished;
570 PRF_STR("------- MixCoder Single ----------");
572 srcLen2 = srcLenOrig;
573 destLen2 = destLenOrig;
576 IStateCoder *coder = &p->coders[0];
577 res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
578 // &wasFinished,
579 &p->status);
580 wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
583 p->res = res;
586 if (wasFinished)
587 p->status = CODER_STATUS_FINISHED_WITH_MARK;
588 else
590 if (res == SZ_OK)
591 if (destLen2 != destLenOrig)
592 p->status = CODER_STATUS_NEEDS_MORE_INPUT;
597 *srcLen = srcLen2;
598 src += srcLen2;
599 p->outWritten += destLen2;
601 if (res != SZ_OK || srcWasFinished || wasFinished)
602 p->wasFinished = True;
604 if (p->numCoders == 1)
605 *destLen = destLen2;
606 else if (p->wasFinished)
608 unsigned i;
609 size_t processed = p->outWritten;
611 for (i = 1; i < p->numCoders; i++)
613 IStateCoder *coder = &p->coders[i];
614 processed = coder->Filter(coder->p, p->outBuf, processed);
615 if (wasFinished || (destFinish && p->outWritten == destLenOrig))
616 processed = p->outWritten;
617 PRF_STR_INT("filter", i);
619 *destLen = processed;
621 return res;
624 PRF_STR("standard mix");
626 if (p->numCoders != 1)
628 if (!p->buf)
630 p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
631 if (!p->buf)
632 return SZ_ERROR_MEM;
635 finishMode = CODER_FINISH_ANY;
638 for (;;)
640 Bool processed = False;
641 Bool allFinished = True;
642 SRes resMain = SZ_OK;
643 unsigned i;
645 p->status = CODER_STATUS_NOT_FINISHED;
647 if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
648 break;
651 for (i = 0; i < p->numCoders; i++)
653 SRes res;
654 IStateCoder *coder = &p->coders[i];
655 Byte *dest2;
656 SizeT destLen2, srcLen2; // destLen2_Orig;
657 const Byte *src2;
658 int srcFinished2;
659 int encodingWasFinished;
660 ECoderStatus status2;
662 if (i == 0)
664 src2 = src;
665 srcLen2 = srcLenOrig - *srcLen;
666 srcFinished2 = srcWasFinished;
668 else
670 size_t k = i - 1;
671 src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
672 srcLen2 = p->size[k] - p->pos[k];
673 srcFinished2 = p->finished[k];
676 if (i == p->numCoders - 1)
678 dest2 = dest;
679 destLen2 = destLenOrig - *destLen;
681 else
683 if (p->pos[i] != p->size[i])
684 continue;
685 dest2 = p->buf + (CODER_BUF_SIZE * i);
686 destLen2 = CODER_BUF_SIZE;
689 // destLen2_Orig = destLen2;
691 if (p->results[i] != SZ_OK)
693 if (resMain == SZ_OK)
694 resMain = p->results[i];
695 continue;
698 res = coder->Code2(coder->p,
699 dest2, &destLen2,
700 src2, &srcLen2, srcFinished2,
701 finishMode,
702 // &encodingWasFinished,
703 &status2);
705 if (res != SZ_OK)
707 p->results[i] = res;
708 if (resMain == SZ_OK)
709 resMain = res;
712 encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
714 if (!encodingWasFinished)
716 allFinished = False;
717 if (p->numCoders == 1 && res == SZ_OK)
718 p->status = status2;
721 if (i == 0)
723 *srcLen += srcLen2;
724 src += srcLen2;
726 else
727 p->pos[(size_t)i - 1] += srcLen2;
729 if (i == p->numCoders - 1)
731 *destLen += destLen2;
732 dest += destLen2;
734 else
736 p->size[i] = destLen2;
737 p->pos[i] = 0;
738 p->finished[i] = encodingWasFinished;
741 if (destLen2 != 0 || srcLen2 != 0)
742 processed = True;
745 if (!processed)
747 if (allFinished)
748 p->status = CODER_STATUS_FINISHED_WITH_MARK;
749 return resMain;
755 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
757 *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
758 if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
759 GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
760 return SZ_ERROR_NO_ARCHIVE;
761 return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
764 static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
766 return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
767 && GetUi32(buf) == CrcCalc(buf + 4, 6)
768 && flags == GetBe16(buf + 8)
769 && buf[10] == XZ_FOOTER_SIG_0
770 && buf[11] == XZ_FOOTER_SIG_1;
773 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
774 { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
775 if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
778 static Bool XzBlock_AreSupportedFilters(const CXzBlock *p)
780 unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
781 unsigned i;
783 const CXzFilter *f = &p->filters[numFilters];
784 if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
785 return False;
788 for (i = 0; i < numFilters; i++)
790 const CXzFilter *f = &p->filters[i];
791 if (f->id == XZ_ID_Delta)
793 if (f->propsSize != 1)
794 return False;
796 else if (f->id < XZ_ID_Delta
797 || f->id > XZ_ID_SPARC
798 || (f->propsSize != 0 && f->propsSize != 4))
799 return False;
801 return True;
805 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
807 unsigned pos;
808 unsigned numFilters, i;
809 unsigned headerSize = (unsigned)header[0] << 2;
811 /* (headerSize != 0) : another code checks */
813 if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
814 return SZ_ERROR_ARCHIVE;
816 pos = 1;
817 p->flags = header[pos++];
819 p->packSize = (UInt64)(Int64)-1;
820 if (XzBlock_HasPackSize(p))
822 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
823 if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
824 return SZ_ERROR_ARCHIVE;
827 p->unpackSize = (UInt64)(Int64)-1;
828 if (XzBlock_HasUnpackSize(p))
829 READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
831 numFilters = XzBlock_GetNumFilters(p);
832 for (i = 0; i < numFilters; i++)
834 CXzFilter *filter = p->filters + i;
835 UInt64 size;
836 READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
837 READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
838 if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
839 return SZ_ERROR_ARCHIVE;
840 filter->propsSize = (UInt32)size;
841 memcpy(filter->props, header + pos, (size_t)size);
842 pos += (unsigned)size;
844 #ifdef XZ_DUMP
845 printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
847 unsigned i;
848 for (i = 0; i < size; i++)
849 printf(" %2X", filter->props[i]);
851 #endif
854 if (XzBlock_HasUnsupportedFlags(p))
855 return SZ_ERROR_UNSUPPORTED;
857 while (pos < headerSize)
858 if (header[pos++] != 0)
859 return SZ_ERROR_ARCHIVE;
860 return SZ_OK;
866 static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
868 unsigned i;
869 Bool needReInit = True;
870 unsigned numFilters = XzBlock_GetNumFilters(block);
872 if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
874 needReInit = False;
875 for (i = 0; i < numFilters; i++)
876 if (p->ids[i] != block->filters[numFilters - 1 - i].id)
878 needReInit = True;
879 break;
883 // p->SingleBufMode = (outBuf != NULL);
884 p->outBuf = outBuf;
885 p->outBufSize = outBufSize;
887 // p->SingleBufMode = False;
888 // outBuf = NULL;
890 if (needReInit)
892 MixCoder_Free(p);
893 for (i = 0; i < numFilters; i++)
895 RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));
897 p->numCoders = numFilters;
899 else
901 RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize));
904 for (i = 0; i < numFilters; i++)
906 const CXzFilter *f = &block->filters[numFilters - 1 - i];
907 IStateCoder *sc = &p->coders[i];
908 RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
911 MixCoder_Init(p);
912 return SZ_OK;
917 void XzUnpacker_Init(CXzUnpacker *p)
919 p->state = XZ_STATE_STREAM_HEADER;
920 p->pos = 0;
921 p->numStartedStreams = 0;
922 p->numFinishedStreams = 0;
923 p->numTotalBlocks = 0;
924 p->padSize = 0;
925 p->decodeOnlyOneBlock = 0;
927 p->parseMode = False;
928 p->decodeToStreamSignature = False;
930 // p->outBuf = NULL;
931 // p->outBufSize = 0;
932 p->outDataWritten = 0;
936 void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
938 p->outBuf = outBuf;
939 p->outBufSize = outBufSize;
943 void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
945 MixCoder_Construct(&p->decoder, alloc);
946 p->outBuf = NULL;
947 p->outBufSize = 0;
948 XzUnpacker_Init(p);
952 void XzUnpacker_Free(CXzUnpacker *p)
954 MixCoder_Free(&p->decoder);
958 void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
960 p->indexSize = 0;
961 p->numBlocks = 0;
962 Sha256_Init(&p->sha);
963 p->state = XZ_STATE_BLOCK_HEADER;
964 p->pos = 0;
965 p->decodeOnlyOneBlock = 1;
969 static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
971 Byte temp[32];
972 unsigned num = Xz_WriteVarInt(temp, packSize);
973 num += Xz_WriteVarInt(temp + num, unpackSize);
974 Sha256_Update(&p->sha, temp, num);
975 p->indexSize += num;
976 p->numBlocks++;
981 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
982 const Byte *src, SizeT *srcLen, int srcFinished,
983 ECoderFinishMode finishMode, ECoderStatus *status)
985 SizeT destLenOrig = *destLen;
986 SizeT srcLenOrig = *srcLen;
987 *destLen = 0;
988 *srcLen = 0;
989 *status = CODER_STATUS_NOT_SPECIFIED;
991 for (;;)
993 SizeT srcRem;
995 if (p->state == XZ_STATE_BLOCK)
997 SizeT destLen2 = destLenOrig - *destLen;
998 SizeT srcLen2 = srcLenOrig - *srcLen;
999 SRes res;
1001 ECoderFinishMode finishMode2 = finishMode;
1002 Bool srcFinished2 = srcFinished;
1003 Bool destFinish = False;
1005 if (p->block.packSize != (UInt64)(Int64)-1)
1007 UInt64 rem = p->block.packSize - p->packSize;
1008 if (srcLen2 >= rem)
1010 srcFinished2 = True;
1011 srcLen2 = (SizeT)rem;
1013 if (rem == 0 && p->block.unpackSize == p->unpackSize)
1014 return SZ_ERROR_DATA;
1017 if (p->block.unpackSize != (UInt64)(Int64)-1)
1019 UInt64 rem = p->block.unpackSize - p->unpackSize;
1020 if (destLen2 >= rem)
1022 destFinish = True;
1023 finishMode2 = CODER_FINISH_END;
1024 destLen2 = (SizeT)rem;
1029 if (srcLen2 == 0 && destLen2 == 0)
1031 *status = CODER_STATUS_NOT_FINISHED;
1032 return SZ_OK;
1037 res = MixCoder_Code(&p->decoder,
1038 (p->outBuf ? NULL : dest), &destLen2, destFinish,
1039 src, &srcLen2, srcFinished2,
1040 finishMode2);
1042 *status = p->decoder.status;
1043 XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
1044 if (!p->outBuf)
1045 dest += destLen2;
1046 p->outDataWritten += destLen2;
1049 (*srcLen) += srcLen2;
1050 src += srcLen2;
1051 p->packSize += srcLen2;
1052 (*destLen) += destLen2;
1053 p->unpackSize += destLen2;
1055 RINOK(res);
1057 if (*status != CODER_STATUS_FINISHED_WITH_MARK)
1059 if (p->block.packSize == p->packSize
1060 && *status == CODER_STATUS_NEEDS_MORE_INPUT)
1062 PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT");
1063 *status = CODER_STATUS_NOT_SPECIFIED;
1064 return SZ_ERROR_DATA;
1067 return SZ_OK;
1070 XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
1071 p->state = XZ_STATE_BLOCK_FOOTER;
1072 p->pos = 0;
1073 p->alignPos = 0;
1074 *status = CODER_STATUS_NOT_SPECIFIED;
1076 if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
1077 || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
1079 PRF_STR("ERROR: block.size mismatch");
1080 return SZ_ERROR_DATA;
1083 // continue;
1086 srcRem = srcLenOrig - *srcLen;
1088 // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
1089 if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
1091 *status = CODER_STATUS_NEEDS_MORE_INPUT;
1092 return SZ_OK;
1095 switch (p->state)
1097 case XZ_STATE_STREAM_HEADER:
1099 if (p->pos < XZ_STREAM_HEADER_SIZE)
1101 if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
1102 return SZ_ERROR_NO_ARCHIVE;
1103 if (p->decodeToStreamSignature)
1104 return SZ_OK;
1105 p->buf[p->pos++] = *src++;
1106 (*srcLen)++;
1108 else
1110 RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
1111 p->numStartedStreams++;
1112 p->indexSize = 0;
1113 p->numBlocks = 0;
1114 Sha256_Init(&p->sha);
1115 p->state = XZ_STATE_BLOCK_HEADER;
1116 p->pos = 0;
1118 break;
1121 case XZ_STATE_BLOCK_HEADER:
1123 if (p->pos == 0)
1125 p->buf[p->pos++] = *src++;
1126 (*srcLen)++;
1127 if (p->buf[0] == 0)
1129 if (p->decodeOnlyOneBlock)
1130 return SZ_ERROR_DATA;
1131 p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
1132 p->indexPos = p->indexPreSize;
1133 p->indexSize += p->indexPreSize;
1134 Sha256_Final(&p->sha, p->shaDigest);
1135 Sha256_Init(&p->sha);
1136 p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
1137 p->state = XZ_STATE_STREAM_INDEX;
1138 break;
1140 p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
1141 break;
1144 if (p->pos != p->blockHeaderSize)
1146 UInt32 cur = p->blockHeaderSize - p->pos;
1147 if (cur > srcRem)
1148 cur = (UInt32)srcRem;
1149 memcpy(p->buf + p->pos, src, cur);
1150 p->pos += cur;
1151 (*srcLen) += cur;
1152 src += cur;
1154 else
1156 RINOK(XzBlock_Parse(&p->block, p->buf));
1157 if (!XzBlock_AreSupportedFilters(&p->block))
1158 return SZ_ERROR_UNSUPPORTED;
1159 p->numTotalBlocks++;
1160 p->state = XZ_STATE_BLOCK;
1161 p->packSize = 0;
1162 p->unpackSize = 0;
1163 XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
1164 if (p->parseMode)
1166 p->headerParsedOk = True;
1167 return SZ_OK;
1169 RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));
1171 break;
1174 case XZ_STATE_BLOCK_FOOTER:
1176 if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
1178 if (srcRem == 0)
1180 *status = CODER_STATUS_NEEDS_MORE_INPUT;
1181 return SZ_OK;
1183 (*srcLen)++;
1184 p->alignPos++;
1185 if (*src++ != 0)
1186 return SZ_ERROR_CRC;
1188 else
1190 UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
1191 UInt32 cur = checkSize - p->pos;
1192 if (cur != 0)
1194 if (srcRem == 0)
1196 *status = CODER_STATUS_NEEDS_MORE_INPUT;
1197 return SZ_OK;
1199 if (cur > srcRem)
1200 cur = (UInt32)srcRem;
1201 memcpy(p->buf + p->pos, src, cur);
1202 p->pos += cur;
1203 (*srcLen) += cur;
1204 src += cur;
1205 if (checkSize != p->pos)
1206 break;
1209 Byte digest[XZ_CHECK_SIZE_MAX];
1210 p->state = XZ_STATE_BLOCK_HEADER;
1211 p->pos = 0;
1212 if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
1213 return SZ_ERROR_CRC;
1214 if (p->decodeOnlyOneBlock)
1216 *status = CODER_STATUS_FINISHED_WITH_MARK;
1217 return SZ_OK;
1221 break;
1224 case XZ_STATE_STREAM_INDEX:
1226 if (p->pos < p->indexPreSize)
1228 (*srcLen)++;
1229 if (*src++ != p->buf[p->pos++])
1230 return SZ_ERROR_CRC;
1232 else
1234 if (p->indexPos < p->indexSize)
1236 UInt64 cur = p->indexSize - p->indexPos;
1237 if (srcRem > cur)
1238 srcRem = (SizeT)cur;
1239 p->crc = CrcUpdate(p->crc, src, srcRem);
1240 Sha256_Update(&p->sha, src, srcRem);
1241 (*srcLen) += srcRem;
1242 src += srcRem;
1243 p->indexPos += srcRem;
1245 else if ((p->indexPos & 3) != 0)
1247 Byte b = *src++;
1248 p->crc = CRC_UPDATE_BYTE(p->crc, b);
1249 (*srcLen)++;
1250 p->indexPos++;
1251 p->indexSize++;
1252 if (b != 0)
1253 return SZ_ERROR_CRC;
1255 else
1257 Byte digest[SHA256_DIGEST_SIZE];
1258 p->state = XZ_STATE_STREAM_INDEX_CRC;
1259 p->indexSize += 4;
1260 p->pos = 0;
1261 Sha256_Final(&p->sha, digest);
1262 if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
1263 return SZ_ERROR_CRC;
1266 break;
1269 case XZ_STATE_STREAM_INDEX_CRC:
1271 if (p->pos < 4)
1273 (*srcLen)++;
1274 p->buf[p->pos++] = *src++;
1276 else
1278 p->state = XZ_STATE_STREAM_FOOTER;
1279 p->pos = 0;
1280 if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
1281 return SZ_ERROR_CRC;
1283 break;
1286 case XZ_STATE_STREAM_FOOTER:
1288 UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
1289 if (cur > srcRem)
1290 cur = (UInt32)srcRem;
1291 memcpy(p->buf + p->pos, src, cur);
1292 p->pos += cur;
1293 (*srcLen) += cur;
1294 src += cur;
1295 if (p->pos == XZ_STREAM_FOOTER_SIZE)
1297 p->state = XZ_STATE_STREAM_PADDING;
1298 p->numFinishedStreams++;
1299 p->padSize = 0;
1300 if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
1301 return SZ_ERROR_CRC;
1303 break;
1306 case XZ_STATE_STREAM_PADDING:
1308 if (*src != 0)
1310 if (((UInt32)p->padSize & 3) != 0)
1311 return SZ_ERROR_NO_ARCHIVE;
1312 p->pos = 0;
1313 p->state = XZ_STATE_STREAM_HEADER;
1315 else
1317 (*srcLen)++;
1318 src++;
1319 p->padSize++;
1321 break;
1324 case XZ_STATE_BLOCK: break; /* to disable GCC warning */
1328 if (p->state == XZ_STATE_FINISHED)
1329 *status = CODER_STATUS_FINISHED_WITH_MARK;
1330 return SZ_OK;
1335 SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
1336 const Byte *src, SizeT *srcLen,
1337 ECoderFinishMode finishMode, ECoderStatus *status)
1339 XzUnpacker_Init(p);
1340 XzUnpacker_SetOutBuf(p, dest, *destLen);
1342 return XzUnpacker_Code(p,
1343 NULL, destLen,
1344 src, srcLen, True,
1345 finishMode, status);
1349 Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1351 return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1354 Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1356 return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1359 UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
1361 UInt64 num = 0;
1362 if (p->state == XZ_STATE_STREAM_PADDING)
1363 num = p->padSize;
1364 else if (p->state == XZ_STATE_STREAM_HEADER)
1365 num = p->padSize + p->pos;
1366 return num;
1389 #ifndef _7ZIP_ST
1390 #include "MtDec.h"
1391 #endif
1394 void XzDecMtProps_Init(CXzDecMtProps *p)
1396 p->inBufSize_ST = 1 << 18;
1397 p->outStep_ST = 1 << 20;
1398 p->ignoreErrors = False;
1400 #ifndef _7ZIP_ST
1401 p->numThreads = 1;
1402 p->inBufSize_MT = 1 << 18;
1403 p->memUseMax = sizeof(size_t) << 28;
1404 #endif
1409 #ifndef _7ZIP_ST
1411 /* ---------- CXzDecMtThread ---------- */
1413 typedef struct
1415 Byte *outBuf;
1416 size_t outBufSize;
1417 size_t outPreSize;
1418 size_t inPreSize;
1419 size_t inPreHeaderSize;
1420 size_t blockPackSize_for_Index; // including block header and checksum.
1421 size_t blockPackTotal; // including stream header, block header and checksum.
1422 size_t inCodeSize;
1423 size_t outCodeSize;
1424 ECoderStatus status;
1425 SRes codeRes;
1426 Bool skipMode;
1427 // Bool finishedWithMark;
1428 EMtDecParseState parseState;
1429 Bool parsing_Truncated;
1430 Bool atBlockHeader;
1431 CXzStreamFlags streamFlags;
1432 // UInt64 numFinishedStreams
1433 UInt64 numStreams;
1434 UInt64 numTotalBlocks;
1435 UInt64 numBlocks;
1437 Bool dec_created;
1438 CXzUnpacker dec;
1440 Byte mtPad[1 << 7];
1441 } CXzDecMtThread;
1443 #endif
1446 /* ---------- CXzDecMt ---------- */
1448 typedef struct
1450 CAlignOffsetAlloc alignOffsetAlloc;
1451 ISzAllocPtr allocMid;
1453 CXzDecMtProps props;
1454 size_t unpackBlockMaxSize;
1456 ISeqInStream *inStream;
1457 ISeqOutStream *outStream;
1458 ICompressProgress *progress;
1459 // CXzStatInfo *stat;
1461 Bool finishMode;
1462 Bool outSize_Defined;
1463 UInt64 outSize;
1465 UInt64 outProcessed;
1466 UInt64 inProcessed;
1467 UInt64 readProcessed;
1468 Bool readWasFinished;
1469 SRes readRes;
1470 SRes writeRes;
1472 Byte *outBuf;
1473 size_t outBufSize;
1474 Byte *inBuf;
1475 size_t inBufSize;
1476 Bool dec_created;
1477 CXzUnpacker dec;
1479 ECoderStatus status;
1480 SRes codeRes;
1482 #ifndef _7ZIP_ST
1483 Bool mainDecoderWasCalled;
1484 // int statErrorDefined;
1485 int finishedDecoderIndex;
1487 // global values that are used in Parse stage
1488 CXzStreamFlags streamFlags;
1489 // UInt64 numFinishedStreams
1490 UInt64 numStreams;
1491 UInt64 numTotalBlocks;
1492 UInt64 numBlocks;
1494 // UInt64 numBadBlocks;
1495 SRes mainErrorCode;
1497 Bool isBlockHeaderState_Parse;
1498 Bool isBlockHeaderState_Write;
1499 UInt64 outProcessed_Parse;
1500 Bool parsing_Truncated;
1502 Bool mtc_WasConstructed;
1503 CMtDec mtc;
1504 CXzDecMtThread coders[MTDEC__THREADS_MAX];
1505 #endif
1507 } CXzDecMt;
1511 CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
1513 CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
1514 if (!p)
1515 return NULL;
1517 AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
1518 p->alignOffsetAlloc.baseAlloc = alloc;
1519 p->alignOffsetAlloc.numAlignBits = 7;
1520 p->alignOffsetAlloc.offset = 0;
1522 p->allocMid = allocMid;
1524 p->outBuf = NULL;
1525 p->outBufSize = 0;
1526 p->inBuf = NULL;
1527 p->inBufSize = 0;
1528 p->dec_created = False;
1530 p->unpackBlockMaxSize = 0;
1532 XzDecMtProps_Init(&p->props);
1534 #ifndef _7ZIP_ST
1535 p->mtc_WasConstructed = False;
1537 unsigned i;
1538 for (i = 0; i < MTDEC__THREADS_MAX; i++)
1540 CXzDecMtThread *coder = &p->coders[i];
1541 coder->dec_created = False;
1542 coder->outBuf = NULL;
1543 coder->outBufSize = 0;
1546 #endif
1548 return p;
1552 #ifndef _7ZIP_ST
1554 static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1556 unsigned i;
1557 for (i = 0; i < MTDEC__THREADS_MAX; i++)
1559 CXzDecMtThread *coder = &p->coders[i];
1560 if (coder->outBuf)
1562 ISzAlloc_Free(p->allocMid, coder->outBuf);
1563 coder->outBuf = NULL;
1564 coder->outBufSize = 0;
1567 p->unpackBlockMaxSize = 0;
1570 #endif
1574 static void XzDecMt_FreeSt(CXzDecMt *p)
1576 if (p->dec_created)
1578 XzUnpacker_Free(&p->dec);
1579 p->dec_created = False;
1582 if (p->outBuf)
1584 ISzAlloc_Free(p->allocMid, p->outBuf);
1585 p->outBuf = NULL;
1587 p->outBufSize = 0;
1589 if (p->inBuf)
1591 ISzAlloc_Free(p->allocMid, p->inBuf);
1592 p->inBuf = NULL;
1594 p->inBufSize = 0;
1598 void XzDecMt_Destroy(CXzDecMtHandle pp)
1600 CXzDecMt *p = (CXzDecMt *)pp;
1602 XzDecMt_FreeSt(p);
1604 #ifndef _7ZIP_ST
1606 if (p->mtc_WasConstructed)
1608 MtDec_Destruct(&p->mtc);
1609 p->mtc_WasConstructed = False;
1612 unsigned i;
1613 for (i = 0; i < MTDEC__THREADS_MAX; i++)
1615 CXzDecMtThread *t = &p->coders[i];
1616 if (t->dec_created)
1618 // we don't need to free dict here
1619 XzUnpacker_Free(&t->dec);
1620 t->dec_created = False;
1624 XzDecMt_FreeOutBufs(p);
1626 #endif
1628 ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
1633 #ifndef _7ZIP_ST
1635 static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
1637 CXzDecMt *me = (CXzDecMt *)obj;
1638 CXzDecMtThread *coder = &me->coders[coderIndex];
1639 size_t srcSize = cc->srcSize;
1641 cc->srcSize = 0;
1642 cc->outPos = 0;
1643 cc->state = MTDEC_PARSE_CONTINUE;
1645 cc->canCreateNewThread = True;
1647 if (cc->startCall)
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;
1660 coder->numStreams = me->numStreams;
1661 coder->numTotalBlocks = me->numTotalBlocks;
1662 coder->numBlocks = me->numBlocks;
1664 if (!coder->dec_created)
1666 XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
1667 coder->dec_created = True;
1670 XzUnpacker_Init(&coder->dec);
1672 if (me->isBlockHeaderState_Parse)
1674 coder->dec.streamFlags = me->streamFlags;
1675 coder->atBlockHeader = True;
1676 XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
1678 else
1680 coder->atBlockHeader = False;
1681 me->isBlockHeaderState_Parse = True;
1684 coder->dec.numStartedStreams = me->numStreams;
1685 coder->dec.numTotalBlocks = me->numTotalBlocks;
1686 coder->dec.numBlocks = me->numBlocks;
1689 while (!coder->skipMode)
1691 ECoderStatus status;
1692 SRes res;
1693 size_t srcSize2 = srcSize;
1694 size_t destSize = (size_t)0 - 1;
1696 coder->dec.parseMode = True;
1697 coder->dec.headerParsedOk = False;
1699 PRF_STR_INT("Parse", srcSize2);
1701 res = XzUnpacker_Code(&coder->dec,
1702 NULL, &destSize,
1703 cc->src, &srcSize2, cc->srcFinished,
1704 CODER_FINISH_END, &status);
1706 // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
1708 coder->codeRes = res;
1709 coder->status = status;
1710 cc->srcSize += srcSize2;
1711 srcSize -= srcSize2;
1712 coder->inPreHeaderSize += srcSize2;
1713 coder->inPreSize = coder->inPreHeaderSize;
1715 if (res != SZ_OK)
1717 cc->state =
1718 coder->parseState = MTDEC_PARSE_END;
1720 if (res == SZ_ERROR_MEM)
1721 return res;
1722 return SZ_OK;
1724 return; // res;
1727 if (coder->dec.headerParsedOk)
1729 const CXzBlock *block = &coder->dec.block;
1730 if (XzBlock_HasUnpackSize(block)
1731 // && block->unpackSize <= me->props.outBlockMax
1732 && XzBlock_HasPackSize(block))
1735 if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
1737 cc->state = MTDEC_PARSE_OVERFLOW;
1738 return; // SZ_OK;
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
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;
1760 else
1761 // if (coder->inPreSize <= me->props.inBlockMax)
1763 if (!cc->srcFinished)
1764 return; // SZ_OK;
1765 cc->state =
1766 coder->parseState = MTDEC_PARSE_END;
1767 return; // SZ_OK;
1769 cc->state = MTDEC_PARSE_OVERFLOW;
1770 return; // SZ_OK;
1773 // ---------- skipMode ----------
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;
1783 if (coder->inPreSize == coder->blockPackTotal)
1785 if (srcSize == 0)
1787 if (!cc->srcFinished)
1788 return; // SZ_OK;
1789 cc->state = MTDEC_PARSE_END;
1791 else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
1792 cc->state = MTDEC_PARSE_END;
1793 else
1795 cc->state = MTDEC_PARSE_NEW;
1798 size_t blockMax = me->unpackBlockMaxSize;
1799 if (blockMax < coder->outPreSize)
1800 blockMax = coder->outPreSize;
1802 UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
1803 if (me->props.memUseMax < required)
1804 cc->canCreateNewThread = False;
1808 if (me->outSize_Defined)
1810 // next block can be zero size
1811 const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
1812 if (rem2 < coder->outPreSize)
1814 coder->parsing_Truncated = True;
1815 cc->state = MTDEC_PARSE_END;
1817 me->outProcessed_Parse += coder->outPreSize;
1821 else if (cc->srcFinished)
1822 cc->state = MTDEC_PARSE_END;
1823 else
1824 return; // SZ_OK;
1826 coder->parseState = cc->state;
1827 cc->outPos = coder->outPreSize;
1829 me->numStreams = coder->dec.numStartedStreams;
1830 me->numTotalBlocks = coder->dec.numTotalBlocks;
1831 me->numBlocks = coder->dec.numBlocks + 1;
1832 return; // SZ_OK;
1837 static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
1839 CXzDecMt *me = (CXzDecMt *)pp;
1840 CXzDecMtThread *coder = &me->coders[coderIndex];
1841 Byte *dest;
1843 if (!coder->dec.headerParsedOk)
1844 return SZ_OK;
1846 dest = coder->outBuf;
1848 if (!dest || coder->outBufSize < coder->outPreSize)
1850 if (dest)
1852 ISzAlloc_Free(me->allocMid, dest);
1853 coder->outBuf = NULL;
1854 coder->outBufSize = 0;
1857 size_t outPreSize = coder->outPreSize;
1858 if (outPreSize == 0)
1859 outPreSize = 1;
1860 dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
1862 if (!dest)
1863 return SZ_ERROR_MEM;
1864 coder->outBuf = dest;
1865 coder->outBufSize = coder->outPreSize;
1867 if (coder->outBufSize > me->unpackBlockMaxSize)
1868 me->unpackBlockMaxSize = coder->outBufSize;
1871 // return SZ_ERROR_MEM;
1873 XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
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)
1881 // if (res == SZ_ERROR_MEM) return res;
1882 if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
1883 return S_OK;
1884 return res;
1888 return SZ_OK;
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)
1897 CXzDecMt *me = (CXzDecMt *)pp;
1898 CXzDecMtThread *coder = &me->coders[coderIndex];
1900 *inCodePos = coder->inCodeSize;
1901 *outCodePos = coder->outCodeSize;
1902 *stop = True;
1904 if (coder->inCodeSize < coder->inPreHeaderSize)
1906 UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;
1907 size_t step = srcSize;
1908 if (step > rem)
1909 step = (size_t)rem;
1910 src += step;
1911 srcSize -= step;
1912 coder->inCodeSize += step;
1913 if (coder->inCodeSize < coder->inPreHeaderSize)
1915 *stop = False;
1916 return SZ_OK;
1920 if (!coder->dec.headerParsedOk)
1921 return SZ_OK;
1922 if (!coder->outBuf)
1923 return SZ_OK;
1925 if (coder->codeRes == SZ_OK)
1927 ECoderStatus status;
1928 SRes res;
1929 size_t srcProcessed = srcSize;
1930 size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1932 // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1934 res = XzUnpacker_Code(&coder->dec,
1935 NULL, &outSizeCur,
1936 src, &srcProcessed, srcFinished,
1937 // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1938 CODER_FINISH_END,
1939 &status);
1941 // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1943 coder->codeRes = res;
1944 coder->status = status;
1945 coder->inCodeSize += srcProcessed;
1946 coder->outCodeSize = coder->dec.outDataWritten;
1947 *inCodePos = coder->inCodeSize;
1948 *outCodePos = coder->outCodeSize;
1950 if (res == SZ_OK)
1952 if (srcProcessed == srcSize)
1953 *stop = False;
1954 return SZ_OK;
1958 if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1960 *inCodePos = coder->inPreSize;
1961 *outCodePos = coder->outPreSize;
1962 return S_OK;
1964 return coder->codeRes;
1968 #define XZDECMT_STREAM_WRITE_STEP (1 << 24)
1970 static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
1971 Bool needWriteToStream,
1972 const Byte *src, size_t srcSize,
1973 // int srcFinished,
1974 Bool *needContinue,
1975 Bool *canRecode)
1977 CXzDecMt *me = (CXzDecMt *)pp;
1978 const CXzDecMtThread *coder = &me->coders[coderIndex];
1980 // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
1982 *needContinue = False;
1983 *canRecode = True;
1985 if (!needWriteToStream)
1986 return SZ_OK;
1988 if (!coder->dec.headerParsedOk || !coder->outBuf)
1990 if (me->finishedDecoderIndex < 0)
1991 me->finishedDecoderIndex = coderIndex;
1992 return SZ_OK;
1995 if (me->finishedDecoderIndex >= 0)
1996 return SZ_OK;
1998 me->mtc.inProcessed += coder->inCodeSize;
2000 *canRecode = False;
2003 SRes res;
2004 size_t size = coder->outCodeSize;
2005 Byte *data = coder->outBuf;
2007 // we use in me->dec: sha, numBlocks, indexSize
2009 if (!me->isBlockHeaderState_Write)
2011 XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2012 me->dec.decodeOnlyOneBlock = False;
2013 me->dec.numStartedStreams = coder->dec.numStartedStreams;
2014 me->dec.streamFlags = coder->streamFlags;
2016 me->isBlockHeaderState_Write = True;
2019 me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2020 XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2022 if (coder->outPreSize != size)
2024 if (me->props.ignoreErrors)
2026 memset(data + size, 0, coder->outPreSize - size);
2027 size = coder->outPreSize;
2029 // me->numBadBlocks++;
2030 if (me->mainErrorCode == SZ_OK)
2032 if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2033 me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2034 else
2035 me->mainErrorCode = SZ_ERROR_DATA;
2039 if (me->writeRes != SZ_OK)
2040 return me->writeRes;
2042 res = SZ_OK;
2044 if (me->outSize_Defined)
2046 const UInt64 rem = me->outSize - me->outProcessed;
2047 if (size > rem)
2048 size = (SizeT)rem;
2051 for (;;)
2053 size_t cur = size;
2054 size_t written;
2055 if (cur > XZDECMT_STREAM_WRITE_STEP)
2056 cur = XZDECMT_STREAM_WRITE_STEP;
2058 written = ISeqOutStream_Write(me->outStream, data, cur);
2060 // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2062 me->outProcessed += written;
2063 if (written != cur)
2065 me->writeRes = SZ_ERROR_WRITE;
2066 res = me->writeRes;
2067 break;
2069 data += cur;
2070 size -= cur;
2071 // PRF_STR_INT("Written size =", size);
2072 if (size == 0)
2073 break;
2074 res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2075 if (res != SZ_OK)
2076 break;
2080 if (coder->codeRes != SZ_OK)
2081 if (!me->props.ignoreErrors)
2083 me->finishedDecoderIndex = coderIndex;
2084 return res;
2087 RINOK(res);
2089 if (coder->inPreSize != coder->inCodeSize
2090 || coder->blockPackTotal != coder->inCodeSize)
2092 me->finishedDecoderIndex = coderIndex;
2093 return SZ_OK;
2096 if (coder->parseState != MTDEC_PARSE_END)
2098 *needContinue = True;
2099 return SZ_OK;
2103 // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2104 // so we can use mtc variables without lock
2106 PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
2108 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2110 CXzUnpacker *dec = &me->dec;
2112 PRF_STR_INT("PostSingle", srcSize);
2115 size_t srcProcessed = srcSize;
2116 ECoderStatus status;
2117 size_t outSizeCur = 0;
2118 SRes res;
2120 // dec->decodeOnlyOneBlock = False;
2121 dec->decodeToStreamSignature = True;
2123 me->mainDecoderWasCalled = True;
2125 if (coder->parsing_Truncated)
2127 me->parsing_Truncated = True;
2128 return SZ_OK;
2131 res = XzUnpacker_Code(dec,
2132 NULL, &outSizeCur,
2133 src, &srcProcessed,
2134 me->mtc.readWasFinished, // srcFinished
2135 CODER_FINISH_END, // CODER_FINISH_ANY,
2136 &status);
2138 me->status = status;
2139 me->codeRes = res;
2141 me->mtc.inProcessed += srcProcessed;
2142 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2144 if (res != SZ_OK)
2146 return S_OK;
2147 // return res;
2150 if (dec->state == XZ_STATE_STREAM_HEADER)
2152 *needContinue = True;
2153 me->isBlockHeaderState_Parse = False;
2154 me->isBlockHeaderState_Write = False;
2156 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2157 if (!crossBuf)
2158 return SZ_ERROR_MEM;
2159 memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);
2161 me->mtc.crossStart = 0;
2162 me->mtc.crossEnd = srcSize - srcProcessed;
2163 return SZ_OK;
2166 if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2168 return E_FAIL;
2171 if (me->mtc.readWasFinished)
2173 return SZ_OK;
2178 size_t inPos;
2179 size_t inLim;
2180 const Byte *inData;
2181 UInt64 inProgressPrev = me->mtc.inProcessed;
2183 // XzDecMt_Prepare_InBuf_ST(p);
2184 Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2185 if (!crossBuf)
2186 return SZ_ERROR_MEM;
2188 inPos = 0;
2189 inLim = 0;
2190 // outProcessed = 0;
2192 inData = crossBuf;
2194 for (;;)
2196 SizeT inProcessed;
2197 SizeT outProcessed;
2198 ECoderStatus status;
2199 SRes res;
2201 if (inPos == inLim)
2203 if (!me->mtc.readWasFinished)
2205 inPos = 0;
2206 inLim = me->mtc.inBufSize;
2207 me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim);
2208 me->mtc.readProcessed += inLim;
2209 if (inLim == 0 || me->mtc.readRes != SZ_OK)
2210 me->mtc.readWasFinished = True;
2214 inProcessed = inLim - inPos;
2215 outProcessed = 0;
2217 res = XzUnpacker_Code(dec,
2218 NULL, &outProcessed,
2219 inData + inPos, &inProcessed,
2220 (inProcessed == 0), // srcFinished
2221 CODER_FINISH_END, &status);
2223 me->codeRes = res;
2224 me->status = status;
2225 inPos += inProcessed;
2226 me->mtc.inProcessed += inProcessed;
2227 me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2229 if (res != SZ_OK)
2231 return S_OK;
2232 // return res;
2235 if (dec->state == XZ_STATE_STREAM_HEADER)
2237 *needContinue = True;
2238 me->mtc.crossStart = inPos;
2239 me->mtc.crossEnd = inLim;
2240 me->isBlockHeaderState_Parse = False;
2241 me->isBlockHeaderState_Write = False;
2242 return SZ_OK;
2245 if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2246 return E_FAIL;
2248 if (me->mtc.progress)
2250 UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2251 if (inDelta >= (1 << 22))
2253 RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
2254 inProgressPrev = me->mtc.inProcessed;
2257 if (me->mtc.readWasFinished)
2258 return SZ_OK;
2265 #endif
2269 void XzStatInfo_Clear(CXzStatInfo *p)
2271 p->InSize = 0;
2272 p->OutSize = 0;
2274 p->NumStreams = 0;
2275 p->NumBlocks = 0;
2277 p->UnpackSize_Defined = False;
2279 p->NumStreams_Defined = False;
2280 p->NumBlocks_Defined = False;
2282 // p->IsArc = False;
2283 // p->UnexpectedEnd = False;
2284 // p->Unsupported = False;
2285 // p->HeadersError = False;
2286 // p->DataError = False;
2287 // p->CrcError = False;
2289 p->DataAfterEnd = False;
2290 p->DecodingTruncated = False;
2292 p->DecodeRes = SZ_OK;
2293 p->ReadRes = SZ_OK;
2294 p->ProgressRes = SZ_OK;
2296 p->CombinedRes = SZ_OK;
2297 p->CombinedRes_Type = SZ_OK;
2303 static SRes XzDecMt_Decode_ST(CXzDecMt *p
2304 #ifndef _7ZIP_ST
2305 , Bool tMode
2306 #endif
2307 , CXzStatInfo *stat)
2309 size_t outPos;
2310 size_t inPos, inLim;
2311 const Byte *inData;
2312 UInt64 inPrev, outPrev;
2314 CXzUnpacker *dec;
2316 #ifndef _7ZIP_ST
2317 if (tMode)
2319 XzDecMt_FreeOutBufs(p);
2320 tMode = MtDec_PrepareRead(&p->mtc);
2322 #endif
2324 if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2326 ISzAlloc_Free(p->allocMid, p->outBuf);
2327 p->outBufSize = 0;
2328 p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2329 if (!p->outBuf)
2330 return SZ_ERROR_MEM;
2331 p->outBufSize = p->props.outStep_ST;
2334 if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2336 ISzAlloc_Free(p->allocMid, p->inBuf);
2337 p->inBufSize = 0;
2338 p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2339 if (!p->inBuf)
2340 return SZ_ERROR_MEM;
2341 p->inBufSize = p->props.inBufSize_ST;
2344 dec = &p->dec;
2345 dec->decodeToStreamSignature = False;
2346 // dec->decodeOnlyOneBlock = False;
2348 XzUnpacker_SetOutBuf(dec, NULL, 0);
2350 inPrev = p->inProcessed;
2351 outPrev = p->outProcessed;
2353 inPos = 0;
2354 inLim = 0;
2355 inData = NULL;
2356 outPos = 0;
2358 for (;;)
2360 SizeT outSize;
2361 Bool finished;
2362 ECoderFinishMode finishMode;
2363 SizeT inProcessed;
2364 ECoderStatus status;
2365 SRes res;
2367 SizeT outProcessed;
2371 if (inPos == inLim)
2373 #ifndef _7ZIP_ST
2374 if (tMode)
2376 inData = MtDec_Read(&p->mtc, &inLim);
2377 inPos = 0;
2378 if (inData)
2379 continue;
2380 tMode = False;
2381 inLim = 0;
2383 #endif
2385 if (!p->readWasFinished)
2387 inPos = 0;
2388 inLim = p->inBufSize;
2389 inData = p->inBuf;
2390 p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
2391 p->readProcessed += inLim;
2392 if (inLim == 0 || p->readRes != SZ_OK)
2393 p->readWasFinished = True;
2397 outSize = p->props.outStep_ST - outPos;
2399 finishMode = CODER_FINISH_ANY;
2400 if (p->outSize_Defined)
2402 const UInt64 rem = p->outSize - p->outProcessed;
2403 if (outSize >= rem)
2405 outSize = (SizeT)rem;
2406 if (p->finishMode)
2407 finishMode = CODER_FINISH_END;
2411 inProcessed = inLim - inPos;
2412 outProcessed = outSize;
2414 res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2415 inData + inPos, &inProcessed,
2416 (inPos == inLim), // srcFinished
2417 finishMode, &status);
2419 p->codeRes = res;
2420 p->status = status;
2422 inPos += inProcessed;
2423 outPos += outProcessed;
2424 p->inProcessed += inProcessed;
2425 p->outProcessed += outProcessed;
2427 finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2429 if (finished || outProcessed >= outSize)
2430 if (outPos != 0)
2432 size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2433 p->outProcessed += written;
2434 if (written != outPos)
2436 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2437 return SZ_ERROR_WRITE;
2439 outPos = 0;
2442 if (p->progress && res == SZ_OK)
2444 UInt64 inDelta = p->inProcessed - inPrev;
2445 UInt64 outDelta = p->outProcessed - outPrev;
2446 if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
2448 res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2449 if (res != SZ_OK)
2451 stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2452 stat->ProgressRes = res;
2453 return res;
2455 inPrev = p->inProcessed;
2456 outPrev = p->outProcessed;
2460 if (finished)
2461 return res;
2465 static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,
2466 int finishMode,
2467 UInt64 readProcessed, UInt64 inProcessed,
2468 SRes res, ECoderStatus status,
2469 Bool decodingTruncated,
2470 CXzStatInfo *stat)
2472 UInt64 extraSize;
2474 stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2475 stat->InSize = inProcessed;
2476 stat->NumStreams = dec->numStartedStreams;
2477 stat->NumBlocks = dec->numTotalBlocks;
2479 stat->UnpackSize_Defined = True;
2480 stat->NumStreams_Defined = True;
2481 stat->NumBlocks_Defined = True;
2483 extraSize = XzUnpacker_GetExtraSize(dec);
2485 if (res == SZ_OK)
2487 if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2489 // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2490 extraSize = 0;
2491 if (!XzUnpacker_IsStreamWasFinished(dec))
2492 res = SZ_ERROR_INPUT_EOF;
2494 else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
2495 res = SZ_ERROR_DATA;
2497 else if (res == SZ_ERROR_NO_ARCHIVE)
2500 SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2501 XZ_STATE_STREAM_HEADER - if bad signature or bad CRC
2502 XZ_STATE_STREAM_PADDING - if non-zero padding data
2503 extraSize / inProcessed don't include "bad" byte
2505 if (inProcessed != extraSize) // if good streams before error
2506 if (extraSize != 0 || readProcessed != inProcessed)
2508 stat->DataAfterEnd = True;
2509 // there is some good xz stream before. So we set SZ_OK
2510 res = SZ_OK;
2514 stat->DecodeRes = res;
2516 stat->InSize -= extraSize;
2517 return res;
2521 SRes XzDecMt_Decode(CXzDecMtHandle pp,
2522 const CXzDecMtProps *props,
2523 const UInt64 *outDataSize, int finishMode,
2524 ISeqOutStream *outStream,
2525 // Byte *outBuf, size_t *outBufSize,
2526 ISeqInStream *inStream,
2527 // const Byte *inData, size_t inDataSize,
2528 CXzStatInfo *stat,
2529 int *isMT,
2530 ICompressProgress *progress)
2532 CXzDecMt *p = (CXzDecMt *)pp;
2533 #ifndef _7ZIP_ST
2534 Bool tMode;
2535 #endif
2537 XzStatInfo_Clear(stat);
2539 p->props = *props;
2541 p->inStream = inStream;
2542 p->outStream = outStream;
2543 p->progress = progress;
2544 // p->stat = stat;
2546 p->outSize = 0;
2547 p->outSize_Defined = False;
2548 if (outDataSize)
2550 p->outSize_Defined = True;
2551 p->outSize = *outDataSize;
2554 p->finishMode = finishMode;
2556 // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2558 p->writeRes = SZ_OK;
2559 p->outProcessed = 0;
2560 p->inProcessed = 0;
2561 p->readProcessed = 0;
2562 p->readWasFinished = False;
2564 p->codeRes = 0;
2565 p->status = CODER_STATUS_NOT_SPECIFIED;
2567 if (!p->dec_created)
2569 XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
2570 p->dec_created = True;
2572 XzUnpacker_Init(&p->dec);
2575 *isMT = False;
2578 p->outBuf = NULL;
2579 p->outBufSize = 0;
2580 if (!outStream)
2582 p->outBuf = outBuf;
2583 p->outBufSize = *outBufSize;
2584 *outBufSize = 0;
2589 #ifndef _7ZIP_ST
2591 p->isBlockHeaderState_Parse = False;
2592 p->isBlockHeaderState_Write = False;
2593 // p->numBadBlocks = 0;
2594 p->mainErrorCode = SZ_OK;
2595 p->mainDecoderWasCalled = False;
2597 tMode = False;
2599 if (p->props.numThreads > 1)
2601 IMtDecCallback vt;
2603 XzDecMt_FreeSt(p);
2605 p->outProcessed_Parse = 0;
2606 p->parsing_Truncated = False;
2608 p->numStreams = 0;
2609 p->numTotalBlocks = 0;
2610 p->numBlocks = 0;
2611 p->finishedDecoderIndex = -1;
2613 if (!p->mtc_WasConstructed)
2615 p->mtc_WasConstructed = True;
2616 MtDec_Construct(&p->mtc);
2619 p->mtc.mtCallback = &vt;
2620 p->mtc.mtCallbackObject = p;
2622 p->mtc.progress = progress;
2623 p->mtc.inStream = inStream;
2624 p->mtc.alloc = &p->alignOffsetAlloc.vt;
2625 // p->mtc.inData = inData;
2626 // p->mtc.inDataSize = inDataSize;
2627 p->mtc.inBufSize = p->props.inBufSize_MT;
2628 // p->mtc.inBlockMax = p->props.inBlockMax;
2629 p->mtc.numThreadsMax = p->props.numThreads;
2631 *isMT = True;
2633 vt.Parse = XzDecMt_Callback_Parse;
2634 vt.PreCode = XzDecMt_Callback_PreCode;
2635 vt.Code = XzDecMt_Callback_Code;
2636 vt.Write = XzDecMt_Callback_Write;
2639 Bool needContinue;
2641 SRes res = MtDec_Code(&p->mtc);
2643 stat->InSize = p->mtc.inProcessed;
2645 p->inProcessed = p->mtc.inProcessed;
2646 p->readRes = p->mtc.readRes;
2647 p->readWasFinished = p->mtc.readWasFinished;
2648 p->readProcessed = p->mtc.readProcessed;
2650 tMode = True;
2651 needContinue = False;
2653 if (res == SZ_OK)
2655 if (p->mtc.mtProgress.res != SZ_OK)
2657 res = p->mtc.mtProgress.res;
2658 stat->ProgressRes = res;
2659 stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2661 else
2662 needContinue = p->mtc.needContinue;
2665 if (!needContinue)
2667 SRes codeRes;
2668 Bool truncated = False;
2669 ECoderStatus status;
2670 CXzUnpacker *dec;
2672 stat->OutSize = p->outProcessed;
2674 if (p->finishedDecoderIndex >= 0)
2676 CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2677 codeRes = coder->codeRes;
2678 dec = &coder->dec;
2679 status = coder->status;
2681 else if (p->mainDecoderWasCalled)
2683 codeRes = p->codeRes;
2684 dec = &p->dec;
2685 status = p->status;
2686 truncated = p->parsing_Truncated;
2688 else
2689 return E_FAIL;
2691 XzStatInfo_SetStat(dec, p->finishMode,
2692 p->mtc.readProcessed, p->mtc.inProcessed,
2693 codeRes, status,
2694 truncated,
2695 stat);
2697 if (res == SZ_OK)
2699 if (p->writeRes != SZ_OK)
2701 res = p->writeRes;
2702 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2704 else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)
2706 res = p->mtc.readRes;
2707 stat->ReadRes = res;
2708 stat->CombinedRes_Type = SZ_ERROR_READ;
2710 else if (p->mainErrorCode != SZ_OK)
2712 res = p->mainErrorCode;
2716 stat->CombinedRes = res;
2717 if (stat->CombinedRes_Type == SZ_OK)
2718 stat->CombinedRes_Type = res;
2719 return res;
2722 PRF_STR("----- decoding ST -----");
2726 #endif
2729 *isMT = False;
2732 SRes res = XzDecMt_Decode_ST(p
2733 #ifndef _7ZIP_ST
2734 , tMode
2735 #endif
2736 , stat
2739 XzStatInfo_SetStat(&p->dec,
2740 p->finishMode,
2741 p->readProcessed, p->inProcessed,
2742 p->codeRes, p->status,
2743 False, // truncated
2744 stat);
2746 if (res == SZ_OK)
2749 if (p->writeRes != SZ_OK)
2751 res = p->writeRes;
2752 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2754 else
2756 if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)
2758 res = p->readRes;
2759 stat->ReadRes = res;
2760 stat->CombinedRes_Type = SZ_ERROR_READ;
2762 #ifndef _7ZIP_ST
2763 else if (p->mainErrorCode != SZ_OK)
2764 res = p->mainErrorCode;
2765 #endif
2768 stat->CombinedRes = res;
2769 if (stat->CombinedRes_Type == SZ_OK)
2770 stat->CombinedRes_Type = res;
2771 return res;