Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / 3rdparty / seven_zip / Lzma2DecMt.c
blob988643d952b7488816e38cf60eca6e14c5d7a717
1 /* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread
2 2019-02-02 : Igor Pavlov : Public domain */
4 #include "Precomp.h"
6 // #define SHOW_DEBUG_INFO
8 #ifdef SHOW_DEBUG_INFO
9 #include <stdio.h>
10 #endif
12 #ifdef SHOW_DEBUG_INFO
13 #define PRF(x) x
14 #else
15 #define PRF(x)
16 #endif
18 #define PRF_STR(s) PRF(printf("\n" s "\n"))
19 #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
20 #define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2))
22 // #define _7ZIP_ST
24 #include "Alloc.h"
26 #include "Lzma2Dec.h"
27 #include "Lzma2DecMt.h"
29 #ifndef _7ZIP_ST
30 #include "MtDec.h"
31 #endif
34 #define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)
36 void Lzma2DecMtProps_Init(CLzma2DecMtProps *p)
38 p->inBufSize_ST = 1 << 20;
39 p->outStep_ST = 1 << 20;
41 #ifndef _7ZIP_ST
42 p->numThreads = 1;
43 p->inBufSize_MT = 1 << 18;
44 p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT;
45 p->inBlockMax = p->outBlockMax + p->outBlockMax / 16;
46 #endif
51 #ifndef _7ZIP_ST
53 /* ---------- CLzma2DecMtThread ---------- */
55 typedef struct
57 CLzma2Dec dec;
58 Byte dec_created;
59 Byte needInit;
61 Byte *outBuf;
62 size_t outBufSize;
64 EMtDecParseState state;
65 ELzma2ParseStatus parseStatus;
67 size_t inPreSize;
68 size_t outPreSize;
70 size_t inCodeSize;
71 size_t outCodeSize;
72 SRes codeRes;
74 CAlignOffsetAlloc alloc;
76 Byte mtPad[1 << 7];
77 } CLzma2DecMtThread;
79 #endif
82 /* ---------- CLzma2DecMt ---------- */
84 typedef struct
86 // ISzAllocPtr alloc;
87 ISzAllocPtr allocMid;
89 CAlignOffsetAlloc alignOffsetAlloc;
90 CLzma2DecMtProps props;
91 Byte prop;
93 ISeqInStream *inStream;
94 ISeqOutStream *outStream;
95 ICompressProgress *progress;
97 BoolInt finishMode;
98 BoolInt outSize_Defined;
99 UInt64 outSize;
101 UInt64 outProcessed;
102 UInt64 inProcessed;
103 BoolInt readWasFinished;
104 SRes readRes;
106 Byte *inBuf;
107 size_t inBufSize;
108 Byte dec_created;
109 CLzma2Dec dec;
111 size_t inPos;
112 size_t inLim;
114 #ifndef _7ZIP_ST
115 UInt64 outProcessed_Parse;
116 BoolInt mtc_WasConstructed;
117 CMtDec mtc;
118 CLzma2DecMtThread coders[MTDEC__THREADS_MAX];
119 #endif
121 } CLzma2DecMt;
125 CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
127 CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt));
128 if (!p)
129 return NULL;
131 // p->alloc = alloc;
132 p->allocMid = allocMid;
134 AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
135 p->alignOffsetAlloc.numAlignBits = 7;
136 p->alignOffsetAlloc.offset = 0;
137 p->alignOffsetAlloc.baseAlloc = alloc;
139 p->inBuf = NULL;
140 p->inBufSize = 0;
141 p->dec_created = False;
143 // Lzma2DecMtProps_Init(&p->props);
145 #ifndef _7ZIP_ST
146 p->mtc_WasConstructed = False;
148 unsigned i;
149 for (i = 0; i < MTDEC__THREADS_MAX; i++)
151 CLzma2DecMtThread *t = &p->coders[i];
152 t->dec_created = False;
153 t->outBuf = NULL;
154 t->outBufSize = 0;
157 #endif
159 return p;
163 #ifndef _7ZIP_ST
165 static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p)
167 unsigned i;
168 for (i = 0; i < MTDEC__THREADS_MAX; i++)
170 CLzma2DecMtThread *t = &p->coders[i];
171 if (t->outBuf)
173 ISzAlloc_Free(p->allocMid, t->outBuf);
174 t->outBuf = NULL;
175 t->outBufSize = 0;
180 #endif
183 static void Lzma2DecMt_FreeSt(CLzma2DecMt *p)
185 if (p->dec_created)
187 Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt);
188 p->dec_created = False;
190 if (p->inBuf)
192 ISzAlloc_Free(p->allocMid, p->inBuf);
193 p->inBuf = NULL;
195 p->inBufSize = 0;
199 void Lzma2DecMt_Destroy(CLzma2DecMtHandle pp)
201 CLzma2DecMt *p = (CLzma2DecMt *)pp;
203 Lzma2DecMt_FreeSt(p);
205 #ifndef _7ZIP_ST
207 if (p->mtc_WasConstructed)
209 MtDec_Destruct(&p->mtc);
210 p->mtc_WasConstructed = False;
213 unsigned i;
214 for (i = 0; i < MTDEC__THREADS_MAX; i++)
216 CLzma2DecMtThread *t = &p->coders[i];
217 if (t->dec_created)
219 // we don't need to free dict here
220 Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!!
221 t->dec_created = False;
225 Lzma2DecMt_FreeOutBufs(p);
227 #endif
229 ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
234 #ifndef _7ZIP_ST
236 static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
238 CLzma2DecMt *me = (CLzma2DecMt *)obj;
239 CLzma2DecMtThread *t = &me->coders[coderIndex];
241 PRF_STR_INT_2("Parse", coderIndex, cc->srcSize);
243 cc->state = MTDEC_PARSE_CONTINUE;
245 if (cc->startCall)
247 if (!t->dec_created)
249 Lzma2Dec_Construct(&t->dec);
250 t->dec_created = True;
251 AlignOffsetAlloc_CreateVTable(&t->alloc);
253 /* (1 << 12) is expected size of one way in data cache.
254 We optimize alignment for cache line size of 128 bytes and smaller */
255 const unsigned kNumAlignBits = 12;
256 const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */
257 t->alloc.numAlignBits = kNumAlignBits;
258 t->alloc.offset = ((UInt32)coderIndex * ((1 << 11) + (1 << 8) + (1 << 6))) & ((1 << kNumAlignBits) - (1 << kNumCacheLineBits));
259 t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc;
262 Lzma2Dec_Init(&t->dec);
264 t->inPreSize = 0;
265 t->outPreSize = 0;
266 // t->blockWasFinished = False;
267 // t->finishedWithMark = False;
268 t->parseStatus = (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
269 t->state = MTDEC_PARSE_CONTINUE;
271 t->inCodeSize = 0;
272 t->outCodeSize = 0;
273 t->codeRes = SZ_OK;
275 // (cc->srcSize == 0) is allowed
279 ELzma2ParseStatus status;
280 BoolInt overflow;
281 UInt32 unpackRem = 0;
283 int checkFinishBlock = True;
284 size_t limit = me->props.outBlockMax;
285 if (me->outSize_Defined)
287 UInt64 rem = me->outSize - me->outProcessed_Parse;
288 if (limit >= rem)
290 limit = (size_t)rem;
291 if (!me->finishMode)
292 checkFinishBlock = False;
296 // checkFinishBlock = False, if we want to decode partial data
297 // that must be finished at position <= outBlockMax.
300 const SizeT srcOrig = cc->srcSize;
301 SizeT srcSize_Point = 0;
302 SizeT dicPos_Point = 0;
304 cc->srcSize = 0;
305 overflow = False;
307 for (;;)
309 SizeT srcCur = srcOrig - cc->srcSize;
311 status = Lzma2Dec_Parse(&t->dec,
312 limit - t->dec.decoder.dicPos,
313 cc->src + cc->srcSize, &srcCur,
314 checkFinishBlock);
316 cc->srcSize += srcCur;
318 if (status == LZMA2_PARSE_STATUS_NEW_CHUNK)
320 if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos)
322 overflow = True;
323 break;
325 continue;
328 if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
330 if (t->dec.decoder.dicPos == 0)
331 continue;
332 // we decode small blocks in one thread
333 if (t->dec.decoder.dicPos >= (1 << 14))
334 break;
335 dicPos_Point = t->dec.decoder.dicPos;
336 srcSize_Point = cc->srcSize;
337 continue;
340 if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock
341 // && limit == t->dec.decoder.dicPos
342 // && limit == me->props.outBlockMax
345 overflow = True;
346 break;
349 unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec);
350 break;
353 if (dicPos_Point != 0
354 && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK
355 && (int)status != LZMA_STATUS_FINISHED_WITH_MARK
356 && (int)status != LZMA_STATUS_NOT_SPECIFIED)
358 // we revert to latest newBlock state
359 status = LZMA2_PARSE_STATUS_NEW_BLOCK;
360 unpackRem = 0;
361 t->dec.decoder.dicPos = dicPos_Point;
362 cc->srcSize = srcSize_Point;
363 overflow = False;
367 t->inPreSize += cc->srcSize;
368 t->parseStatus = status;
370 if (overflow)
371 cc->state = MTDEC_PARSE_OVERFLOW;
372 else
374 size_t dicPos = t->dec.decoder.dicPos;
376 if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT)
378 if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
380 cc->state = MTDEC_PARSE_NEW;
381 cc->srcSize--; // we don't need control byte of next block
382 t->inPreSize--;
384 else
386 cc->state = MTDEC_PARSE_END;
387 if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK)
389 // (status == LZMA_STATUS_NOT_SPECIFIED)
390 // (status == LZMA_STATUS_NOT_FINISHED)
391 if (unpackRem != 0)
393 /* we also reserve space for max possible number of output bytes of current LZMA chunk */
394 SizeT rem = limit - dicPos;
395 if (rem > unpackRem)
396 rem = unpackRem;
397 dicPos += rem;
402 me->outProcessed_Parse += dicPos;
405 cc->outPos = dicPos;
406 t->outPreSize = (size_t)dicPos;
409 t->state = cc->state;
410 return;
415 static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex)
417 CLzma2DecMt *me = (CLzma2DecMt *)pp;
418 CLzma2DecMtThread *t = &me->coders[coderIndex];
419 Byte *dest = t->outBuf;
421 if (t->inPreSize == 0)
423 t->codeRes = SZ_ERROR_DATA;
424 return t->codeRes;
427 if (!dest || t->outBufSize < t->outPreSize)
429 if (dest)
431 ISzAlloc_Free(me->allocMid, dest);
432 t->outBuf = NULL;
433 t->outBufSize = 0;
436 dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize
437 // + (1 << 28)
439 // Sleep(200);
440 if (!dest)
441 return SZ_ERROR_MEM;
442 t->outBuf = dest;
443 t->outBufSize = t->outPreSize;
446 t->dec.decoder.dic = dest;
447 t->dec.decoder.dicBufSize = t->outPreSize;
449 t->needInit = True;
451 return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt
455 static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex,
456 const Byte *src, size_t srcSize, int srcFinished,
457 // int finished, int blockFinished,
458 UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
460 CLzma2DecMt *me = (CLzma2DecMt *)pp;
461 CLzma2DecMtThread *t = &me->coders[coderIndex];
463 UNUSED_VAR(srcFinished)
465 PRF_STR_INT_2("Code", coderIndex, srcSize);
467 *inCodePos = t->inCodeSize;
468 *outCodePos = 0;
469 *stop = True;
471 if (t->needInit)
473 Lzma2Dec_Init(&t->dec);
474 t->needInit = False;
478 ELzmaStatus status;
479 size_t srcProcessed = srcSize;
480 BoolInt blockWasFinished =
481 ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
482 || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK);
484 SRes res = Lzma2Dec_DecodeToDic(&t->dec,
485 t->outPreSize,
486 src, &srcProcessed,
487 blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY,
488 &status);
490 t->codeRes = res;
492 t->inCodeSize += srcProcessed;
493 *inCodePos = t->inCodeSize;
494 t->outCodeSize = t->dec.decoder.dicPos;
495 *outCodePos = t->dec.decoder.dicPos;
497 if (res != SZ_OK)
498 return res;
500 if (srcProcessed == srcSize)
501 *stop = False;
503 if (blockWasFinished)
505 if (srcSize != srcProcessed)
506 return SZ_ERROR_FAIL;
508 if (t->inPreSize == t->inCodeSize)
510 if (t->outPreSize != t->outCodeSize)
511 return SZ_ERROR_FAIL;
512 *stop = True;
515 else
517 if (t->outPreSize == t->outCodeSize)
518 *stop = True;
521 return SZ_OK;
526 #define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24)
528 static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,
529 BoolInt needWriteToStream,
530 const Byte *src, size_t srcSize,
531 BoolInt *needContinue, BoolInt *canRecode)
533 CLzma2DecMt *me = (CLzma2DecMt *)pp;
534 const CLzma2DecMtThread *t = &me->coders[coderIndex];
535 size_t size = t->outCodeSize;
536 const Byte *data = t->outBuf;
537 BoolInt needContinue2 = True;
539 PRF_STR_INT_2("Write", coderIndex, srcSize);
541 *needContinue = False;
542 *canRecode = True;
543 UNUSED_VAR(src)
544 UNUSED_VAR(srcSize)
546 if (
547 // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
548 t->state == MTDEC_PARSE_OVERFLOW
549 || t->state == MTDEC_PARSE_END)
550 needContinue2 = False;
553 if (!needWriteToStream)
554 return SZ_OK;
556 me->mtc.inProcessed += t->inCodeSize;
558 if (t->codeRes == SZ_OK)
559 if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
560 || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)
561 if (t->outPreSize != t->outCodeSize
562 || t->inPreSize != t->inCodeSize)
563 return SZ_ERROR_FAIL;
565 *canRecode = False;
567 if (me->outStream)
569 for (;;)
571 size_t cur = size;
572 size_t written;
573 if (cur > LZMA2DECMT_STREAM_WRITE_STEP)
574 cur = LZMA2DECMT_STREAM_WRITE_STEP;
576 written = ISeqOutStream_Write(me->outStream, data, cur);
578 me->outProcessed += written;
579 // me->mtc.writtenTotal += written;
580 if (written != cur)
581 return SZ_ERROR_WRITE;
582 data += cur;
583 size -= cur;
584 if (size == 0)
586 *needContinue = needContinue2;
587 return SZ_OK;
589 RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0));
593 return SZ_ERROR_FAIL;
595 if (size > me->outBufSize)
596 return SZ_ERROR_OUTPUT_EOF;
597 memcpy(me->outBuf, data, size);
598 me->outBufSize -= size;
599 me->outBuf += size;
600 *needContinue = needContinue2;
601 return SZ_OK;
605 #endif
608 static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)
610 if (!p->dec_created)
612 Lzma2Dec_Construct(&p->dec);
613 p->dec_created = True;
616 RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt));
618 if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
620 ISzAlloc_Free(p->allocMid, p->inBuf);
621 p->inBufSize = 0;
622 p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
623 if (!p->inBuf)
624 return SZ_ERROR_MEM;
625 p->inBufSize = p->props.inBufSize_ST;
628 Lzma2Dec_Init(&p->dec);
630 return SZ_OK;
634 static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p
635 #ifndef _7ZIP_ST
636 , BoolInt tMode
637 #endif
640 SizeT wrPos;
641 size_t inPos, inLim;
642 const Byte *inData;
643 UInt64 inPrev, outPrev;
645 CLzma2Dec *dec;
647 #ifndef _7ZIP_ST
648 if (tMode)
650 Lzma2DecMt_FreeOutBufs(p);
651 tMode = MtDec_PrepareRead(&p->mtc);
653 #endif
655 RINOK(Lzma2Dec_Prepare_ST(p));
657 dec = &p->dec;
659 inPrev = p->inProcessed;
660 outPrev = p->outProcessed;
662 inPos = 0;
663 inLim = 0;
664 inData = NULL;
665 wrPos = dec->decoder.dicPos;
667 for (;;)
669 SizeT dicPos;
670 SizeT size;
671 ELzmaFinishMode finishMode;
672 SizeT inProcessed;
673 ELzmaStatus status;
674 SRes res;
676 SizeT outProcessed;
677 BoolInt outFinished;
678 BoolInt needStop;
680 if (inPos == inLim)
682 #ifndef _7ZIP_ST
683 if (tMode)
685 inData = MtDec_Read(&p->mtc, &inLim);
686 inPos = 0;
687 if (inData)
688 continue;
689 tMode = False;
690 inLim = 0;
692 #endif
694 if (!p->readWasFinished)
696 inPos = 0;
697 inLim = p->inBufSize;
698 inData = p->inBuf;
699 p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
700 // p->readProcessed += inLim;
701 // inLim -= 5; p->readWasFinished = True; // for test
702 if (inLim == 0 || p->readRes != SZ_OK)
703 p->readWasFinished = True;
707 dicPos = dec->decoder.dicPos;
709 SizeT next = dec->decoder.dicBufSize;
710 if (next - wrPos > p->props.outStep_ST)
711 next = wrPos + p->props.outStep_ST;
712 size = next - dicPos;
715 finishMode = LZMA_FINISH_ANY;
716 if (p->outSize_Defined)
718 const UInt64 rem = p->outSize - p->outProcessed;
719 if (size >= rem)
721 size = (SizeT)rem;
722 if (p->finishMode)
723 finishMode = LZMA_FINISH_END;
727 inProcessed = inLim - inPos;
729 res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);
731 inPos += inProcessed;
732 p->inProcessed += inProcessed;
733 outProcessed = dec->decoder.dicPos - dicPos;
734 p->outProcessed += outProcessed;
736 outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);
738 needStop = (res != SZ_OK
739 || (inProcessed == 0 && outProcessed == 0)
740 || status == LZMA_STATUS_FINISHED_WITH_MARK
741 || (!p->finishMode && outFinished));
743 if (needStop || outProcessed >= size)
745 SRes res2;
747 size_t writeSize = dec->decoder.dicPos - wrPos;
748 size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);
749 res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;
752 if (dec->decoder.dicPos == dec->decoder.dicBufSize)
753 dec->decoder.dicPos = 0;
754 wrPos = dec->decoder.dicPos;
756 RINOK(res2);
758 if (needStop)
760 if (res != SZ_OK)
761 return res;
763 if (status == LZMA_STATUS_FINISHED_WITH_MARK)
765 if (p->finishMode)
767 if (p->outSize_Defined && p->outSize != p->outProcessed)
768 return SZ_ERROR_DATA;
770 return SZ_OK;
773 if (!p->finishMode && outFinished)
774 return SZ_OK;
776 if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
777 return SZ_ERROR_INPUT_EOF;
779 return SZ_ERROR_DATA;
783 if (p->progress)
785 UInt64 inDelta = p->inProcessed - inPrev;
786 UInt64 outDelta = p->outProcessed - outPrev;
787 if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
789 RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed));
790 inPrev = p->inProcessed;
791 outPrev = p->outProcessed;
799 SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp,
800 Byte prop,
801 const CLzma2DecMtProps *props,
802 ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode,
803 // Byte *outBuf, size_t *outBufSize,
804 ISeqInStream *inStream,
805 // const Byte *inData, size_t inDataSize,
806 UInt64 *inProcessed,
807 // UInt64 *outProcessed,
808 int *isMT,
809 ICompressProgress *progress)
811 CLzma2DecMt *p = (CLzma2DecMt *)pp;
812 #ifndef _7ZIP_ST
813 BoolInt tMode;
814 #endif
816 *inProcessed = 0;
818 if (prop > 40)
819 return SZ_ERROR_UNSUPPORTED;
821 p->prop = prop;
822 p->props = *props;
824 p->inStream = inStream;
825 p->outStream = outStream;
826 p->progress = progress;
828 p->outSize = 0;
829 p->outSize_Defined = False;
830 if (outDataSize)
832 p->outSize_Defined = True;
833 p->outSize = *outDataSize;
835 p->finishMode = finishMode;
837 p->outProcessed = 0;
838 p->inProcessed = 0;
840 p->readWasFinished = False;
842 *isMT = False;
845 #ifndef _7ZIP_ST
847 tMode = False;
849 // p->mtc.parseRes = SZ_OK;
851 // p->mtc.numFilledThreads = 0;
852 // p->mtc.crossStart = 0;
853 // p->mtc.crossEnd = 0;
854 // p->mtc.allocError_for_Read_BlockIndex = 0;
855 // p->mtc.isAllocError = False;
857 if (p->props.numThreads > 1)
859 IMtDecCallback vt;
861 Lzma2DecMt_FreeSt(p);
863 p->outProcessed_Parse = 0;
865 if (!p->mtc_WasConstructed)
867 p->mtc_WasConstructed = True;
868 MtDec_Construct(&p->mtc);
871 p->mtc.progress = progress;
872 p->mtc.inStream = inStream;
874 // p->outBuf = NULL;
875 // p->outBufSize = 0;
877 if (!outStream)
879 // p->outBuf = outBuf;
880 // p->outBufSize = *outBufSize;
881 // *outBufSize = 0;
882 return SZ_ERROR_PARAM;
886 // p->mtc.inBlockMax = p->props.inBlockMax;
887 p->mtc.alloc = &p->alignOffsetAlloc.vt;
888 // p->alignOffsetAlloc.baseAlloc;
889 // p->mtc.inData = inData;
890 // p->mtc.inDataSize = inDataSize;
891 p->mtc.mtCallback = &vt;
892 p->mtc.mtCallbackObject = p;
894 p->mtc.inBufSize = p->props.inBufSize_MT;
896 p->mtc.numThreadsMax = p->props.numThreads;
898 *isMT = True;
900 vt.Parse = Lzma2DecMt_MtCallback_Parse;
901 vt.PreCode = Lzma2DecMt_MtCallback_PreCode;
902 vt.Code = Lzma2DecMt_MtCallback_Code;
903 vt.Write = Lzma2DecMt_MtCallback_Write;
906 BoolInt needContinue = False;
908 SRes res = MtDec_Code(&p->mtc);
911 if (!outStream)
912 *outBufSize = p->outBuf - outBuf;
915 *inProcessed = p->mtc.inProcessed;
917 needContinue = False;
919 if (res == SZ_OK)
921 if (p->mtc.mtProgress.res != SZ_OK)
922 res = p->mtc.mtProgress.res;
923 else
924 needContinue = p->mtc.needContinue;
927 if (!needContinue)
929 if (res == SZ_OK)
930 return p->mtc.readRes;
931 return res;
934 tMode = True;
935 p->readRes = p->mtc.readRes;
936 p->readWasFinished = p->mtc.readWasFinished;
937 p->inProcessed = p->mtc.inProcessed;
939 PRF_STR("----- decoding ST -----");
943 #endif
946 *isMT = False;
949 SRes res = Lzma2Dec_Decode_ST(p
950 #ifndef _7ZIP_ST
951 , tMode
952 #endif
955 *inProcessed = p->inProcessed;
957 // res = SZ_OK; // for test
958 if (res == SZ_OK && p->readRes != SZ_OK)
959 res = p->readRes;
962 #ifndef _7ZIP_ST
963 if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)
964 res = p->mtc.parseRes;
965 #endif
968 return res;
973 /* ---------- Read from CLzma2DecMtHandle Interface ---------- */
975 SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
976 Byte prop,
977 const CLzma2DecMtProps *props,
978 const UInt64 *outDataSize, int finishMode,
979 ISeqInStream *inStream)
981 CLzma2DecMt *p = (CLzma2DecMt *)pp;
983 if (prop > 40)
984 return SZ_ERROR_UNSUPPORTED;
986 p->prop = prop;
987 p->props = *props;
989 p->inStream = inStream;
991 p->outSize = 0;
992 p->outSize_Defined = False;
993 if (outDataSize)
995 p->outSize_Defined = True;
996 p->outSize = *outDataSize;
998 p->finishMode = finishMode;
1000 p->outProcessed = 0;
1001 p->inProcessed = 0;
1003 p->inPos = 0;
1004 p->inLim = 0;
1006 return Lzma2Dec_Prepare_ST(p);
1010 SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
1011 Byte *data, size_t *outSize,
1012 UInt64 *inStreamProcessed)
1014 CLzma2DecMt *p = (CLzma2DecMt *)pp;
1015 ELzmaFinishMode finishMode;
1016 SRes readRes;
1017 size_t size = *outSize;
1019 *outSize = 0;
1020 *inStreamProcessed = 0;
1022 finishMode = LZMA_FINISH_ANY;
1023 if (p->outSize_Defined)
1025 const UInt64 rem = p->outSize - p->outProcessed;
1026 if (size >= rem)
1028 size = (size_t)rem;
1029 if (p->finishMode)
1030 finishMode = LZMA_FINISH_END;
1034 readRes = SZ_OK;
1036 for (;;)
1038 SizeT inCur;
1039 SizeT outCur;
1040 ELzmaStatus status;
1041 SRes res;
1043 if (p->inPos == p->inLim && readRes == SZ_OK)
1045 p->inPos = 0;
1046 p->inLim = p->props.inBufSize_ST;
1047 readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);
1050 inCur = p->inLim - p->inPos;
1051 outCur = size;
1053 res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,
1054 p->inBuf + p->inPos, &inCur, finishMode, &status);
1056 p->inPos += inCur;
1057 p->inProcessed += inCur;
1058 *inStreamProcessed += inCur;
1059 p->outProcessed += outCur;
1060 *outSize += outCur;
1061 size -= outCur;
1062 data += outCur;
1064 if (res != 0)
1065 return res;
1068 if (status == LZMA_STATUS_FINISHED_WITH_MARK)
1069 return readRes;
1071 if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
1073 if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)
1074 return SZ_ERROR_DATA;
1075 return readRes;
1079 if (inCur == 0 && outCur == 0)
1080 return readRes;