1 /* XzDec.c -- Xz Decode
2 2018-04-24 : Igor Pavlov : Public domain */
16 // #define SHOW_DEBUG_INFO
18 #ifdef SHOW_DEBUG_INFO
22 #ifdef SHOW_DEBUG_INFO
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))
41 // #define USE_SUBBLOCK
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
)
58 limit
= (maxSize
> 9) ? 9 : (unsigned)maxSize
;
60 for (i
= 0; i
< limit
;)
63 *value
|= (UInt64
)(b
& 0x7F) << (7 * i
++);
65 return (b
== 0 && i
!= 1) ? 0 : i
;
70 /* ---------- BraState ---------- */
72 #define BRA_BUF_SIZE (1 << 14)
86 Byte deltaState
[DELTA_STATE_SIZE
];
88 Byte buf
[BRA_BUF_SIZE
];
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
);
101 if (p
->methodId
== XZ_ID_Delta
)
104 return SZ_ERROR_UNSUPPORTED
;
105 p
->delta
= (unsigned)props
[0] + 1;
111 UInt32 v
= GetUi32(props
);
118 return SZ_ERROR_UNSUPPORTED
;
122 return SZ_ERROR_UNSUPPORTED
;
126 return SZ_ERROR_UNSUPPORTED
;
131 else if (propSize
!= 0)
132 return SZ_ERROR_UNSUPPORTED
;
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
);
156 Delta_Encode(p
->deltaState
, p
->delta
, data
, size
);
158 Delta_Decode(p
->deltaState
, p
->delta
, data
, size
);
161 size
= x86_Convert(data
, size
, p
->ip
, &p
->x86State
, p
->encodeMode
);
169 p
->ip
+= (UInt32
)size
;
174 static SRes
BraState_Code2(void *pp
,
175 Byte
*dest
, SizeT
*destLen
,
176 const Byte
*src
, SizeT
*srcLen
, int srcWasFinished
,
177 ECoderFinishMode finishMode
,
179 ECoderStatus
*status
)
181 CBraState
*p
= ((CBraState
*)pp
);
182 SizeT destRem
= *destLen
;
183 SizeT srcRem
= *srcLen
;
184 UNUSED_VAR(finishMode
);
188 // *wasFinished = False;
189 *status
= CODER_STATUS_NOT_FINISHED
;
193 if (p
->bufPos
!= p
->bufConv
)
195 size_t size
= p
->bufConv
- p
->bufPos
;
198 memcpy(dest
, p
->buf
+ p
->bufPos
, size
);
206 p
->bufTotal
-= p
->bufPos
;
207 memmove(p
->buf
, p
->buf
+ p
->bufPos
, p
->bufTotal
);
211 size_t size
= BRA_BUF_SIZE
- p
->bufTotal
;
214 memcpy(p
->buf
+ p
->bufTotal
, src
, size
);
220 if (p
->bufTotal
== 0)
223 p
->bufConv
= BraState_Filter(pp
, p
->buf
, p
->bufTotal
);
229 p
->bufConv
= p
->bufTotal
;
233 if (p
->bufTotal
== p
->bufPos
&& srcRem
== 0 && srcWasFinished
)
235 *status
= CODER_STATUS_FINISHED_WITH_MARK
;
243 SRes
BraState_SetFromMethod(IStateCoder
*p
, UInt64 id
, int encodeMode
, ISzAllocPtr alloc
)
246 if (id
< XZ_ID_Delta
|| id
> XZ_ID_SPARC
)
247 return SZ_ERROR_UNSUPPORTED
;
251 decoder
= (CBraState
*)ISzAlloc_Alloc(alloc
, sizeof(CBraState
));
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
;
268 /* ---------- SbState ---------- */
272 static void SbState_Free(void *pp
, ISzAllocPtr alloc
)
274 CSbDec
*p
= (CSbDec
*)pp
;
276 ISzAlloc_Free(alloc
, pp
);
279 static SRes
SbState_SetProps(void *pp
, const Byte
*props
, size_t propSize
, ISzAllocPtr 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
,
295 ECoderStatus
*status
)
297 CSbDec
*p
= (CSbDec
*)pp
;
299 UNUSED_VAR(srcWasFinished
);
301 p
->destLen
= *destLen
;
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
;
315 static SRes
SbState_SetFromMethod(IStateCoder
*p
, ISzAllocPtr alloc
)
317 CSbDec
*decoder
= (CSbDec
*)p
->p
;
320 decoder
= (CSbDec
*)ISzAlloc_Alloc(alloc
, sizeof(CSbDec
));
324 p
->Free
= SbState_Free
;
325 p
->SetProps
= SbState_SetProps
;
326 p
->Init
= SbState_Init
;
327 p
->Code2
= SbState_Code2
;
330 SbDec_Construct(decoder
);
331 SbDec_SetAlloc(decoder
, alloc
);
339 /* ---------- Lzma2 ---------- */
348 static void Lzma2State_Free(void *pp
, ISzAllocPtr alloc
)
350 CLzma2Dec_Spec
*p
= (CLzma2Dec_Spec
*)pp
;
352 Lzma2Dec_FreeProbs(&p
->decoder
, alloc
);
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
)
361 return SZ_ERROR_UNSUPPORTED
;
363 CLzma2Dec_Spec
*p
= (CLzma2Dec_Spec
*)pp
;
365 return Lzma2Dec_AllocateProbs(&p
->decoder
, props
[0], alloc
);
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
,
385 ECoderStatus
*status
)
387 CLzma2Dec_Spec
*spec
= (CLzma2Dec_Spec
*)pp
;
389 /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
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
;
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
408 static SRes
Lzma2State_SetFromMethod(IStateCoder
*p
, Byte
*outBuf
, size_t outBufSize
, ISzAllocPtr alloc
)
410 CLzma2Dec_Spec
*spec
= (CLzma2Dec_Spec
*)p
->p
;
413 spec
= (CLzma2Dec_Spec
*)ISzAlloc_Alloc(alloc
, sizeof(CLzma2Dec_Spec
));
417 p
->Free
= Lzma2State_Free
;
418 p
->SetProps
= Lzma2State_SetProps
;
419 p
->Init
= Lzma2State_Init
;
420 p
->Code2
= Lzma2State_Code2
;
422 Lzma2Dec_Construct(&spec
->decoder
);
424 spec
->outBufMode
= False
;
427 spec
->outBufMode
= True
;
428 spec
->decoder
.decoder
.dic
= outBuf
;
429 spec
->decoder
.decoder
.dicBufSize
= outBufSize
;
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
;
442 spec
->decoder
.decoder
.dic
= outBuf
;
443 spec
->decoder
.decoder
.dicBufSize
= outBufSize
;
450 static void MixCoder_Construct(CMixCoder
*p
, ISzAllocPtr alloc
)
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
)
470 for (i
= 0; i
< MIXCODER_NUM_FILTERS_MAX
; i
++)
472 IStateCoder
*sc
= &p
->coders
[i
];
475 sc
->Free(sc
->p
, p
->alloc
);
481 ISzAlloc_Free(p
->alloc
, p
->buf
);
482 p
->buf
= NULL
; /* 9.31: the BUG was fixed */
486 static void MixCoder_Init(CMixCoder
*p
)
489 for (i
= 0; i
< MIXCODER_NUM_FILTERS_MAX
- 1; i
++)
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
;
502 p
->wasFinished
= False
;
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
;
514 case XZ_ID_LZMA2
: return Lzma2State_SetFromMethod(sc
, outBuf
, outBufSize
, p
->alloc
);
516 case XZ_ID_Subblock
: return SbState_SetFromMethod(sc
, p
->alloc
);
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
];
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
;
561 p
->status
= CODER_STATUS_NOT_FINISHED
;
563 // if (p->SingleBufMode)
567 SizeT destLen2
, srcLen2
;
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
,
580 wasFinished
= (p
->status
== CODER_STATUS_FINISHED_WITH_MARK
);
587 p->status = CODER_STATUS_FINISHED_WITH_MARK;
591 if (destLen2 != destLenOrig)
592 p->status = CODER_STATUS_NEEDS_MORE_INPUT;
599 p
->outWritten
+= destLen2
;
601 if (res
!= SZ_OK
|| srcWasFinished
|| wasFinished
)
602 p
->wasFinished
= True
;
604 if (p
->numCoders
== 1)
606 else if (p
->wasFinished
)
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
;
624 PRF_STR("standard mix");
626 if (p
->numCoders
!= 1)
630 p
->buf
= (Byte
*)ISzAlloc_Alloc(p
->alloc
, CODER_BUF_SIZE
* (MIXCODER_NUM_FILTERS_MAX
- 1));
635 finishMode
= CODER_FINISH_ANY
;
640 Bool processed
= False
;
641 Bool allFinished
= True
;
642 SRes resMain
= SZ_OK
;
645 p
->status
= CODER_STATUS_NOT_FINISHED
;
647 if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
651 for (i
= 0; i
< p
->numCoders
; i
++)
654 IStateCoder
*coder
= &p
->coders
[i
];
656 SizeT destLen2
, srcLen2
; // destLen2_Orig;
659 int encodingWasFinished
;
660 ECoderStatus status2
;
665 srcLen2
= srcLenOrig
- *srcLen
;
666 srcFinished2
= srcWasFinished
;
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)
679 destLen2
= destLenOrig
- *destLen
;
683 if (p
->pos
[i
] != p
->size
[i
])
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
];
698 res
= coder
->Code2(coder
->p
,
700 src2
, &srcLen2
, srcFinished2
,
702 // &encodingWasFinished,
708 if (resMain
== SZ_OK
)
712 encodingWasFinished
= (status2
== CODER_STATUS_FINISHED_WITH_MARK
);
714 if (!encodingWasFinished
)
717 if (p
->numCoders
== 1 && res
== SZ_OK
)
727 p
->pos
[(size_t)i
- 1] += srcLen2
;
729 if (i
== p
->numCoders
- 1)
731 *destLen
+= destLen2
;
736 p
->size
[i
] = destLen2
;
738 p
->finished
[i
] = encodingWasFinished
;
741 if (destLen2
!= 0 || srcLen2
!= 0)
748 p
->status
= CODER_STATUS_FINISHED_WITH_MARK
;
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;
783 const CXzFilter
*f
= &p
->filters
[numFilters
];
784 if (f
->id
!= XZ_ID_LZMA2
|| f
->propsSize
!= 1 || f
->props
[0] > 40)
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)
796 else if (f
->id
< XZ_ID_Delta
797 || f
->id
> XZ_ID_SPARC
798 || (f
->propsSize
!= 0 && f
->propsSize
!= 4))
805 SRes
XzBlock_Parse(CXzBlock
*p
, const Byte
*header
)
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
;
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
;
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
;
845 printf("\nf[%u] = %2X: ", i
, (unsigned)filter
->id
);
848 for (i
= 0; i
< size
; i
++)
849 printf(" %2X", filter
->props
[i
]);
854 if (XzBlock_HasUnsupportedFlags(p
))
855 return SZ_ERROR_UNSUPPORTED
;
857 while (pos
< headerSize
)
858 if (header
[pos
++] != 0)
859 return SZ_ERROR_ARCHIVE
;
866 static SRes
XzDecMix_Init(CMixCoder
*p
, const CXzBlock
*block
, Byte
*outBuf
, size_t outBufSize
)
869 Bool needReInit
= True
;
870 unsigned numFilters
= XzBlock_GetNumFilters(block
);
872 if (numFilters
== p
->numCoders
&& ((p
->outBuf
&& outBuf
) || (!p
->outBuf
&& !outBuf
)))
875 for (i
= 0; i
< numFilters
; i
++)
876 if (p
->ids
[i
] != block
->filters
[numFilters
- 1 - i
].id
)
883 // p->SingleBufMode = (outBuf != NULL);
885 p
->outBufSize
= outBufSize
;
887 // p->SingleBufMode = False;
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
;
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
));
917 void XzUnpacker_Init(CXzUnpacker
*p
)
919 p
->state
= XZ_STATE_STREAM_HEADER
;
921 p
->numStartedStreams
= 0;
922 p
->numFinishedStreams
= 0;
923 p
->numTotalBlocks
= 0;
925 p
->decodeOnlyOneBlock
= 0;
927 p
->parseMode
= False
;
928 p
->decodeToStreamSignature
= False
;
931 // p->outBufSize = 0;
932 p
->outDataWritten
= 0;
936 void XzUnpacker_SetOutBuf(CXzUnpacker
*p
, Byte
*outBuf
, size_t outBufSize
)
939 p
->outBufSize
= outBufSize
;
943 void XzUnpacker_Construct(CXzUnpacker
*p
, ISzAllocPtr alloc
)
945 MixCoder_Construct(&p
->decoder
, alloc
);
952 void XzUnpacker_Free(CXzUnpacker
*p
)
954 MixCoder_Free(&p
->decoder
);
958 void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker
*p
)
962 Sha256_Init(&p
->sha
);
963 p
->state
= XZ_STATE_BLOCK_HEADER
;
965 p
->decodeOnlyOneBlock
= 1;
969 static void XzUnpacker_UpdateIndex(CXzUnpacker
*p
, UInt64 packSize
, UInt64 unpackSize
)
972 unsigned num
= Xz_WriteVarInt(temp
, packSize
);
973 num
+= Xz_WriteVarInt(temp
+ num
, unpackSize
);
974 Sha256_Update(&p
->sha
, temp
, num
);
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
;
989 *status
= CODER_STATUS_NOT_SPECIFIED
;
995 if (p
->state
== XZ_STATE_BLOCK
)
997 SizeT destLen2
= destLenOrig
- *destLen
;
998 SizeT srcLen2
= srcLenOrig
- *srcLen
;
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
;
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
)
1023 finishMode2
= CODER_FINISH_END
;
1024 destLen2
= (SizeT
)rem
;
1029 if (srcLen2 == 0 && destLen2 == 0)
1031 *status = CODER_STATUS_NOT_FINISHED;
1037 res
= MixCoder_Code(&p
->decoder
,
1038 (p
->outBuf
? NULL
: dest
), &destLen2
, destFinish
,
1039 src
, &srcLen2
, srcFinished2
,
1042 *status
= p
->decoder
.status
;
1043 XzCheck_Update(&p
->check
, (p
->outBuf
? p
->outBuf
+ p
->outDataWritten
: dest
), destLen2
);
1046 p
->outDataWritten
+= destLen2
;
1049 (*srcLen
) += srcLen2
;
1051 p
->packSize
+= srcLen2
;
1052 (*destLen
) += destLen2
;
1053 p
->unpackSize
+= destLen2
;
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
;
1070 XzUnpacker_UpdateIndex(p
, XzUnpacker_GetPackSizeForIndex(p
), p
->unpackSize
);
1071 p
->state
= XZ_STATE_BLOCK_FOOTER
;
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
;
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
;
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
)
1105 p
->buf
[p
->pos
++] = *src
++;
1110 RINOK(Xz_ParseHeader(&p
->streamFlags
, p
->buf
));
1111 p
->numStartedStreams
++;
1114 Sha256_Init(&p
->sha
);
1115 p
->state
= XZ_STATE_BLOCK_HEADER
;
1121 case XZ_STATE_BLOCK_HEADER
:
1125 p
->buf
[p
->pos
++] = *src
++;
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
;
1140 p
->blockHeaderSize
= ((UInt32
)p
->buf
[0] << 2) + 4;
1144 if (p
->pos
!= p
->blockHeaderSize
)
1146 UInt32 cur
= p
->blockHeaderSize
- p
->pos
;
1148 cur
= (UInt32
)srcRem
;
1149 memcpy(p
->buf
+ p
->pos
, src
, cur
);
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
;
1163 XzCheck_Init(&p
->check
, XzFlags_GetCheckType(p
->streamFlags
));
1166 p
->headerParsedOk
= True
;
1169 RINOK(XzDecMix_Init(&p
->decoder
, &p
->block
, p
->outBuf
, p
->outBufSize
));
1174 case XZ_STATE_BLOCK_FOOTER
:
1176 if ((((unsigned)p
->packSize
+ p
->alignPos
) & 3) != 0)
1180 *status
= CODER_STATUS_NEEDS_MORE_INPUT
;
1186 return SZ_ERROR_CRC
;
1190 UInt32 checkSize
= XzFlags_GetCheckSize(p
->streamFlags
);
1191 UInt32 cur
= checkSize
- p
->pos
;
1196 *status
= CODER_STATUS_NEEDS_MORE_INPUT
;
1200 cur
= (UInt32
)srcRem
;
1201 memcpy(p
->buf
+ p
->pos
, src
, cur
);
1205 if (checkSize
!= p
->pos
)
1209 Byte digest
[XZ_CHECK_SIZE_MAX
];
1210 p
->state
= XZ_STATE_BLOCK_HEADER
;
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
;
1224 case XZ_STATE_STREAM_INDEX
:
1226 if (p
->pos
< p
->indexPreSize
)
1229 if (*src
++ != p
->buf
[p
->pos
++])
1230 return SZ_ERROR_CRC
;
1234 if (p
->indexPos
< p
->indexSize
)
1236 UInt64 cur
= p
->indexSize
- p
->indexPos
;
1238 srcRem
= (SizeT
)cur
;
1239 p
->crc
= CrcUpdate(p
->crc
, src
, srcRem
);
1240 Sha256_Update(&p
->sha
, src
, srcRem
);
1241 (*srcLen
) += srcRem
;
1243 p
->indexPos
+= srcRem
;
1245 else if ((p
->indexPos
& 3) != 0)
1248 p
->crc
= CRC_UPDATE_BYTE(p
->crc
, b
);
1253 return SZ_ERROR_CRC
;
1257 Byte digest
[SHA256_DIGEST_SIZE
];
1258 p
->state
= XZ_STATE_STREAM_INDEX_CRC
;
1261 Sha256_Final(&p
->sha
, digest
);
1262 if (memcmp(digest
, p
->shaDigest
, SHA256_DIGEST_SIZE
) != 0)
1263 return SZ_ERROR_CRC
;
1269 case XZ_STATE_STREAM_INDEX_CRC
:
1274 p
->buf
[p
->pos
++] = *src
++;
1278 p
->state
= XZ_STATE_STREAM_FOOTER
;
1280 if (CRC_GET_DIGEST(p
->crc
) != GetUi32(p
->buf
))
1281 return SZ_ERROR_CRC
;
1286 case XZ_STATE_STREAM_FOOTER
:
1288 UInt32 cur
= XZ_STREAM_FOOTER_SIZE
- p
->pos
;
1290 cur
= (UInt32
)srcRem
;
1291 memcpy(p
->buf
+ p
->pos
, src
, cur
);
1295 if (p
->pos
== XZ_STREAM_FOOTER_SIZE
)
1297 p
->state
= XZ_STATE_STREAM_PADDING
;
1298 p
->numFinishedStreams
++;
1300 if (!Xz_CheckFooter(p
->streamFlags
, p
->indexSize
, p
->buf
))
1301 return SZ_ERROR_CRC
;
1306 case XZ_STATE_STREAM_PADDING
:
1310 if (((UInt32
)p
->padSize
& 3) != 0)
1311 return SZ_ERROR_NO_ARCHIVE
;
1313 p
->state
= XZ_STATE_STREAM_HEADER
;
1324 case XZ_STATE_BLOCK
: break; /* to disable GCC warning */
1328 if (p->state == XZ_STATE_FINISHED)
1329 *status = CODER_STATUS_FINISHED_WITH_MARK;
1335 SRes
XzUnpacker_CodeFull(CXzUnpacker
*p
, Byte
*dest
, SizeT
*destLen
,
1336 const Byte
*src
, SizeT
*srcLen
,
1337 ECoderFinishMode finishMode
, ECoderStatus
*status
)
1340 XzUnpacker_SetOutBuf(p
, dest
, *destLen
);
1342 return XzUnpacker_Code(p
,
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
)
1362 if (p
->state
== XZ_STATE_STREAM_PADDING
)
1364 else if (p
->state
== XZ_STATE_STREAM_HEADER
)
1365 num
= p
->padSize
+ p
->pos
;
1394 void XzDecMtProps_Init(CXzDecMtProps
*p
)
1396 p
->inBufSize_ST
= 1 << 18;
1397 p
->outStep_ST
= 1 << 20;
1398 p
->ignoreErrors
= False
;
1402 p
->inBufSize_MT
= 1 << 18;
1403 p
->memUseMax
= sizeof(size_t) << 28;
1411 /* ---------- CXzDecMtThread ---------- */
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.
1424 ECoderStatus status
;
1427 // Bool finishedWithMark;
1428 EMtDecParseState parseState
;
1429 Bool parsing_Truncated
;
1431 CXzStreamFlags streamFlags
;
1432 // UInt64 numFinishedStreams
1434 UInt64 numTotalBlocks
;
1446 /* ---------- CXzDecMt ---------- */
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;
1462 Bool outSize_Defined
;
1465 UInt64 outProcessed
;
1467 UInt64 readProcessed
;
1468 Bool readWasFinished
;
1479 ECoderStatus status
;
1483 Bool mainDecoderWasCalled
;
1484 // int statErrorDefined;
1485 int finishedDecoderIndex
;
1487 // global values that are used in Parse stage
1488 CXzStreamFlags streamFlags
;
1489 // UInt64 numFinishedStreams
1491 UInt64 numTotalBlocks
;
1494 // UInt64 numBadBlocks;
1497 Bool isBlockHeaderState_Parse
;
1498 Bool isBlockHeaderState_Write
;
1499 UInt64 outProcessed_Parse
;
1500 Bool parsing_Truncated
;
1502 Bool mtc_WasConstructed
;
1504 CXzDecMtThread coders
[MTDEC__THREADS_MAX
];
1511 CXzDecMtHandle
XzDecMt_Create(ISzAllocPtr alloc
, ISzAllocPtr allocMid
)
1513 CXzDecMt
*p
= (CXzDecMt
*)ISzAlloc_Alloc(alloc
, sizeof(CXzDecMt
));
1517 AlignOffsetAlloc_CreateVTable(&p
->alignOffsetAlloc
);
1518 p
->alignOffsetAlloc
.baseAlloc
= alloc
;
1519 p
->alignOffsetAlloc
.numAlignBits
= 7;
1520 p
->alignOffsetAlloc
.offset
= 0;
1522 p
->allocMid
= allocMid
;
1528 p
->dec_created
= False
;
1530 p
->unpackBlockMaxSize
= 0;
1532 XzDecMtProps_Init(&p
->props
);
1535 p
->mtc_WasConstructed
= False
;
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;
1554 static void XzDecMt_FreeOutBufs(CXzDecMt
*p
)
1557 for (i
= 0; i
< MTDEC__THREADS_MAX
; i
++)
1559 CXzDecMtThread
*coder
= &p
->coders
[i
];
1562 ISzAlloc_Free(p
->allocMid
, coder
->outBuf
);
1563 coder
->outBuf
= NULL
;
1564 coder
->outBufSize
= 0;
1567 p
->unpackBlockMaxSize
= 0;
1574 static void XzDecMt_FreeSt(CXzDecMt
*p
)
1578 XzUnpacker_Free(&p
->dec
);
1579 p
->dec_created
= False
;
1584 ISzAlloc_Free(p
->allocMid
, p
->outBuf
);
1591 ISzAlloc_Free(p
->allocMid
, p
->inBuf
);
1598 void XzDecMt_Destroy(CXzDecMtHandle pp
)
1600 CXzDecMt
*p
= (CXzDecMt
*)pp
;
1606 if (p
->mtc_WasConstructed
)
1608 MtDec_Destruct(&p
->mtc
);
1609 p
->mtc_WasConstructed
= False
;
1613 for (i
= 0; i
< MTDEC__THREADS_MAX
; i
++)
1615 CXzDecMtThread
*t
= &p
->coders
[i
];
1618 // we don't need to free dict here
1619 XzUnpacker_Free(&t
->dec
);
1620 t
->dec_created
= False
;
1624 XzDecMt_FreeOutBufs(p
);
1628 ISzAlloc_Free(p
->alignOffsetAlloc
.baseAlloc
, pp
);
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
;
1643 cc
->state
= MTDEC_PARSE_CONTINUE
;
1645 cc
->canCreateNewThread
= True
;
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
);
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
;
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
,
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
;
1718 coder
->parseState
= MTDEC_PARSE_END
;
1720 if (res == SZ_ERROR_MEM)
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
;
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
;
1761 // if (coder->inPreSize <= me->props.inBlockMax)
1763 if (!cc
->srcFinished
)
1766 coder
->parseState
= MTDEC_PARSE_END
;
1769 cc
->state
= MTDEC_PARSE_OVERFLOW
;
1773 // ---------- skipMode ----------
1775 UInt64 rem
= coder
->blockPackTotal
- coder
->inPreSize
;
1776 size_t cur
= srcSize
;
1780 coder
->inPreSize
+= cur
;
1783 if (coder
->inPreSize
== coder
->blockPackTotal
)
1787 if (!cc
->srcFinished
)
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
;
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
;
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;
1837 static SRes
XzDecMt_Callback_PreCode(void *pp
, unsigned coderIndex
)
1839 CXzDecMt
*me
= (CXzDecMt
*)pp
;
1840 CXzDecMtThread
*coder
= &me
->coders
[coderIndex
];
1843 if (!coder
->dec
.headerParsedOk
)
1846 dest
= coder
->outBuf
;
1848 if (!dest
|| coder
->outBufSize
< coder
->outPreSize
)
1852 ISzAlloc_Free(me
->allocMid
, dest
);
1853 coder
->outBuf
= NULL
;
1854 coder
->outBufSize
= 0;
1857 size_t outPreSize
= coder
->outPreSize
;
1858 if (outPreSize
== 0)
1860 dest
= (Byte
*)ISzAlloc_Alloc(me
->allocMid
, outPreSize
);
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
;
1881 // if (res == SZ_ERROR_MEM) return res;
1882 if (me
->props
.ignoreErrors
&& res
!= SZ_ERROR_MEM
)
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
;
1904 if (coder
->inCodeSize
< coder
->inPreHeaderSize
)
1906 UInt64 rem
= coder
->inPreHeaderSize
- coder
->inCodeSize
;
1907 size_t step
= srcSize
;
1912 coder
->inCodeSize
+= step
;
1913 if (coder
->inCodeSize
< coder
->inPreHeaderSize
)
1920 if (!coder
->dec
.headerParsedOk
)
1925 if (coder
->codeRes
== SZ_OK
)
1927 ECoderStatus status
;
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
,
1936 src
, &srcProcessed
, srcFinished
,
1937 // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
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
;
1952 if (srcProcessed
== srcSize
)
1958 if (me
->props
.ignoreErrors
&& coder
->codeRes
!= SZ_ERROR_MEM
)
1960 *inCodePos
= coder
->inPreSize
;
1961 *outCodePos
= coder
->outPreSize
;
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
,
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
;
1985 if (!needWriteToStream
)
1988 if (!coder
->dec
.headerParsedOk
|| !coder
->outBuf
)
1990 if (me
->finishedDecoderIndex
< 0)
1991 me
->finishedDecoderIndex
= coderIndex
;
1995 if (me
->finishedDecoderIndex
>= 0)
1998 me
->mtc
.inProcessed
+= coder
->inCodeSize
;
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
;
2035 me
->mainErrorCode
= SZ_ERROR_DATA
;
2039 if (me
->writeRes
!= SZ_OK
)
2040 return me
->writeRes
;
2044 if (me
->outSize_Defined
)
2046 const UInt64 rem
= me
->outSize
- me
->outProcessed
;
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
;
2065 me
->writeRes
= SZ_ERROR_WRITE
;
2071 // PRF_STR_INT("Written size =", size);
2074 res
= MtProgress_ProgressAdd(&me
->mtc
.mtProgress
, 0, 0);
2080 if (coder
->codeRes
!= SZ_OK
)
2081 if (!me
->props
.ignoreErrors
)
2083 me
->finishedDecoderIndex
= coderIndex
;
2089 if (coder
->inPreSize
!= coder
->inCodeSize
2090 || coder
->blockPackTotal
!= coder
->inCodeSize
)
2092 me
->finishedDecoderIndex
= coderIndex
;
2096 if (coder
->parseState
!= MTDEC_PARSE_END
)
2098 *needContinue
= True
;
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;
2120 // dec->decodeOnlyOneBlock = False;
2121 dec
->decodeToStreamSignature
= True
;
2123 me
->mainDecoderWasCalled
= True
;
2125 if (coder
->parsing_Truncated
)
2127 me
->parsing_Truncated
= True
;
2131 res
= XzUnpacker_Code(dec
,
2134 me
->mtc
.readWasFinished
, // srcFinished
2135 CODER_FINISH_END
, // CODER_FINISH_ANY,
2138 me
->status
= status
;
2141 me
->mtc
.inProcessed
+= srcProcessed
;
2142 me
->mtc
.mtProgress
.totalInSize
= me
->mtc
.inProcessed
;
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
);
2158 return SZ_ERROR_MEM
;
2159 memcpy(crossBuf
, src
+ srcProcessed
, srcSize
- srcProcessed
);
2161 me
->mtc
.crossStart
= 0;
2162 me
->mtc
.crossEnd
= srcSize
- srcProcessed
;
2166 if (status
!= CODER_STATUS_NEEDS_MORE_INPUT
)
2171 if (me
->mtc
.readWasFinished
)
2181 UInt64 inProgressPrev
= me
->mtc
.inProcessed
;
2183 // XzDecMt_Prepare_InBuf_ST(p);
2184 Byte
*crossBuf
= MtDec_GetCrossBuff(&me
->mtc
);
2186 return SZ_ERROR_MEM
;
2190 // outProcessed = 0;
2198 ECoderStatus status
;
2203 if (!me
->mtc
.readWasFinished
)
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
;
2217 res
= XzUnpacker_Code(dec
,
2218 NULL
, &outProcessed
,
2219 inData
+ inPos
, &inProcessed
,
2220 (inProcessed
== 0), // srcFinished
2221 CODER_FINISH_END
, &status
);
2224 me
->status
= status
;
2225 inPos
+= inProcessed
;
2226 me
->mtc
.inProcessed
+= inProcessed
;
2227 me
->mtc
.mtProgress
.totalInSize
= me
->mtc
.inProcessed
;
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
;
2245 if (status
!= CODER_STATUS_NEEDS_MORE_INPUT
)
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
)
2269 void XzStatInfo_Clear(CXzStatInfo
*p
)
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
;
2294 p
->ProgressRes
= SZ_OK
;
2296 p
->CombinedRes
= SZ_OK
;
2297 p
->CombinedRes_Type
= SZ_OK
;
2303 static SRes
XzDecMt_Decode_ST(CXzDecMt
*p
2307 , CXzStatInfo
*stat
)
2310 size_t inPos
, inLim
;
2312 UInt64 inPrev
, outPrev
;
2319 XzDecMt_FreeOutBufs(p
);
2320 tMode
= MtDec_PrepareRead(&p
->mtc
);
2324 if (!p
->outBuf
|| p
->outBufSize
!= p
->props
.outStep_ST
)
2326 ISzAlloc_Free(p
->allocMid
, p
->outBuf
);
2328 p
->outBuf
= (Byte
*)ISzAlloc_Alloc(p
->allocMid
, p
->props
.outStep_ST
);
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
);
2338 p
->inBuf
= (Byte
*)ISzAlloc_Alloc(p
->allocMid
, p
->props
.inBufSize_ST
);
2340 return SZ_ERROR_MEM
;
2341 p
->inBufSize
= p
->props
.inBufSize_ST
;
2345 dec
->decodeToStreamSignature
= False
;
2346 // dec->decodeOnlyOneBlock = False;
2348 XzUnpacker_SetOutBuf(dec
, NULL
, 0);
2350 inPrev
= p
->inProcessed
;
2351 outPrev
= p
->outProcessed
;
2362 ECoderFinishMode finishMode
;
2364 ECoderStatus status
;
2376 inData
= MtDec_Read(&p
->mtc
, &inLim
);
2385 if (!p
->readWasFinished
)
2388 inLim
= p
->inBufSize
;
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
;
2405 outSize
= (SizeT
)rem
;
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
);
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
)
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
;
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
);
2451 stat
->CombinedRes_Type
= SZ_ERROR_PROGRESS
;
2452 stat
->ProgressRes
= res
;
2455 inPrev
= p
->inProcessed
;
2456 outPrev
= p
->outProcessed
;
2465 static SRes
XzStatInfo_SetStat(const CXzUnpacker
*dec
,
2467 UInt64 readProcessed
, UInt64 inProcessed
,
2468 SRes res
, ECoderStatus status
,
2469 Bool decodingTruncated
,
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
);
2487 if (status
== CODER_STATUS_NEEDS_MORE_INPUT
)
2489 // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
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
2514 stat
->DecodeRes
= res
;
2516 stat
->InSize
-= extraSize
;
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,
2530 ICompressProgress
*progress
)
2532 CXzDecMt
*p
= (CXzDecMt
*)pp
;
2537 XzStatInfo_Clear(stat
);
2541 p
->inStream
= inStream
;
2542 p
->outStream
= outStream
;
2543 p
->progress
= progress
;
2547 p
->outSize_Defined
= False
;
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;
2561 p
->readProcessed
= 0;
2562 p
->readWasFinished
= False
;
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
);
2583 p->outBufSize = *outBufSize;
2591 p
->isBlockHeaderState_Parse
= False
;
2592 p
->isBlockHeaderState_Write
= False
;
2593 // p->numBadBlocks = 0;
2594 p
->mainErrorCode
= SZ_OK
;
2595 p
->mainDecoderWasCalled
= False
;
2599 if (p
->props
.numThreads
> 1)
2605 p
->outProcessed_Parse
= 0;
2606 p
->parsing_Truncated
= False
;
2609 p
->numTotalBlocks
= 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
;
2633 vt
.Parse
= XzDecMt_Callback_Parse
;
2634 vt
.PreCode
= XzDecMt_Callback_PreCode
;
2635 vt
.Code
= XzDecMt_Callback_Code
;
2636 vt
.Write
= XzDecMt_Callback_Write
;
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
;
2651 needContinue
= False
;
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
;
2662 needContinue
= p
->mtc
.needContinue
;
2668 Bool truncated
= False
;
2669 ECoderStatus status
;
2672 stat
->OutSize
= p
->outProcessed
;
2674 if (p
->finishedDecoderIndex
>= 0)
2676 CXzDecMtThread
*coder
= &p
->coders
[(unsigned)p
->finishedDecoderIndex
];
2677 codeRes
= coder
->codeRes
;
2679 status
= coder
->status
;
2681 else if (p
->mainDecoderWasCalled
)
2683 codeRes
= p
->codeRes
;
2686 truncated
= p
->parsing_Truncated
;
2691 XzStatInfo_SetStat(dec
, p
->finishMode
,
2692 p
->mtc
.readProcessed
, p
->mtc
.inProcessed
,
2699 if (p
->writeRes
!= SZ_OK
)
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
;
2722 PRF_STR("----- decoding ST -----");
2732 SRes res
= XzDecMt_Decode_ST(p
2739 XzStatInfo_SetStat(&p
->dec
,
2741 p
->readProcessed
, p
->inProcessed
,
2742 p
->codeRes
, p
->status
,
2749 if (p->writeRes != SZ_OK)
2752 stat->CombinedRes_Type = SZ_ERROR_WRITE;
2756 if (p
->readRes
!= SZ_OK
&& p
->inProcessed
== p
->readProcessed
)
2759 stat
->ReadRes
= res
;
2760 stat
->CombinedRes_Type
= SZ_ERROR_READ
;
2763 else if (p
->mainErrorCode
!= SZ_OK
)
2764 res
= p
->mainErrorCode
;
2768 stat
->CombinedRes
= res
;
2769 if (stat
->CombinedRes_Type
== SZ_OK
)
2770 stat
->CombinedRes_Type
= res
;