aboutsummaryrefslogtreecommitdiff
path: root/C/Lzma2DecMt.c
diff options
context:
space:
mode:
Diffstat (limited to 'C/Lzma2DecMt.c')
-rw-r--r--C/Lzma2DecMt.c1090
1 files changed, 1090 insertions, 0 deletions
diff --git a/C/Lzma2DecMt.c b/C/Lzma2DecMt.c
new file mode 100644
index 0000000..9f1dc52
--- /dev/null
+++ b/C/Lzma2DecMt.c
@@ -0,0 +1,1090 @@
1/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread
22021-04-01 : Igor Pavlov : Public domain */
3
4#include "Precomp.h"
5
6// #define SHOW_DEBUG_INFO
7
8// #define _7ZIP_ST
9
10#ifdef SHOW_DEBUG_INFO
11#include <stdio.h>
12#endif
13
14#ifndef _7ZIP_ST
15#ifdef SHOW_DEBUG_INFO
16#define PRF(x) x
17#else
18#define PRF(x)
19#endif
20#define PRF_STR(s) PRF(printf("\n" s "\n"))
21#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2))
22#endif
23
24#include "Alloc.h"
25
26#include "Lzma2Dec.h"
27#include "Lzma2DecMt.h"
28
29#ifndef _7ZIP_ST
30#include "MtDec.h"
31
32#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)
33#endif
34
35
36void Lzma2DecMtProps_Init(CLzma2DecMtProps *p)
37{
38 p->inBufSize_ST = 1 << 20;
39 p->outStep_ST = 1 << 20;
40
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
47}
48
49
50
51#ifndef _7ZIP_ST
52
53/* ---------- CLzma2DecMtThread ---------- */
54
55typedef struct
56{
57 CLzma2Dec dec;
58 Byte dec_created;
59 Byte needInit;
60
61 Byte *outBuf;
62 size_t outBufSize;
63
64 EMtDecParseState state;
65 ELzma2ParseStatus parseStatus;
66
67 size_t inPreSize;
68 size_t outPreSize;
69
70 size_t inCodeSize;
71 size_t outCodeSize;
72 SRes codeRes;
73
74 CAlignOffsetAlloc alloc;
75
76 Byte mtPad[1 << 7];
77} CLzma2DecMtThread;
78
79#endif
80
81
82/* ---------- CLzma2DecMt ---------- */
83
84typedef struct
85{
86 // ISzAllocPtr alloc;
87 ISzAllocPtr allocMid;
88
89 CAlignOffsetAlloc alignOffsetAlloc;
90 CLzma2DecMtProps props;
91 Byte prop;
92
93 ISeqInStream *inStream;
94 ISeqOutStream *outStream;
95 ICompressProgress *progress;
96
97 BoolInt finishMode;
98 BoolInt outSize_Defined;
99 UInt64 outSize;
100
101 UInt64 outProcessed;
102 UInt64 inProcessed;
103 BoolInt readWasFinished;
104 SRes readRes;
105
106 Byte *inBuf;
107 size_t inBufSize;
108 Byte dec_created;
109 CLzma2Dec dec;
110
111 size_t inPos;
112 size_t inLim;
113
114 #ifndef _7ZIP_ST
115 UInt64 outProcessed_Parse;
116 BoolInt mtc_WasConstructed;
117 CMtDec mtc;
118 CLzma2DecMtThread coders[MTDEC__THREADS_MAX];
119 #endif
120
121} CLzma2DecMt;
122
123
124
125CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
126{
127 CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt));
128 if (!p)
129 return NULL;
130
131 // p->alloc = alloc;
132 p->allocMid = allocMid;
133
134 AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
135 p->alignOffsetAlloc.numAlignBits = 7;
136 p->alignOffsetAlloc.offset = 0;
137 p->alignOffsetAlloc.baseAlloc = alloc;
138
139 p->inBuf = NULL;
140 p->inBufSize = 0;
141 p->dec_created = False;
142
143 // Lzma2DecMtProps_Init(&p->props);
144
145 #ifndef _7ZIP_ST
146 p->mtc_WasConstructed = False;
147 {
148 unsigned i;
149 for (i = 0; i < MTDEC__THREADS_MAX; i++)
150 {
151 CLzma2DecMtThread *t = &p->coders[i];
152 t->dec_created = False;
153 t->outBuf = NULL;
154 t->outBufSize = 0;
155 }
156 }
157 #endif
158
159 return p;
160}
161
162
163#ifndef _7ZIP_ST
164
165static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p)
166{
167 unsigned i;
168 for (i = 0; i < MTDEC__THREADS_MAX; i++)
169 {
170 CLzma2DecMtThread *t = &p->coders[i];
171 if (t->outBuf)
172 {
173 ISzAlloc_Free(p->allocMid, t->outBuf);
174 t->outBuf = NULL;
175 t->outBufSize = 0;
176 }
177 }
178}
179
180#endif
181
182
183static void Lzma2DecMt_FreeSt(CLzma2DecMt *p)
184{
185 if (p->dec_created)
186 {
187 Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt);
188 p->dec_created = False;
189 }
190 if (p->inBuf)
191 {
192 ISzAlloc_Free(p->allocMid, p->inBuf);
193 p->inBuf = NULL;
194 }
195 p->inBufSize = 0;
196}
197
198
199void Lzma2DecMt_Destroy(CLzma2DecMtHandle pp)
200{
201 CLzma2DecMt *p = (CLzma2DecMt *)pp;
202
203 Lzma2DecMt_FreeSt(p);
204
205 #ifndef _7ZIP_ST
206
207 if (p->mtc_WasConstructed)
208 {
209 MtDec_Destruct(&p->mtc);
210 p->mtc_WasConstructed = False;
211 }
212 {
213 unsigned i;
214 for (i = 0; i < MTDEC__THREADS_MAX; i++)
215 {
216 CLzma2DecMtThread *t = &p->coders[i];
217 if (t->dec_created)
218 {
219 // we don't need to free dict here
220 Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!!
221 t->dec_created = False;
222 }
223 }
224 }
225 Lzma2DecMt_FreeOutBufs(p);
226
227 #endif
228
229 ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
230}
231
232
233
234#ifndef _7ZIP_ST
235
236static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
237{
238 CLzma2DecMt *me = (CLzma2DecMt *)obj;
239 CLzma2DecMtThread *t = &me->coders[coderIndex];
240
241 PRF_STR_INT_2("Parse", coderIndex, cc->srcSize);
242
243 cc->state = MTDEC_PARSE_CONTINUE;
244
245 if (cc->startCall)
246 {
247 if (!t->dec_created)
248 {
249 Lzma2Dec_Construct(&t->dec);
250 t->dec_created = True;
251 AlignOffsetAlloc_CreateVTable(&t->alloc);
252 {
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 * (((unsigned)1 << 11) + (1 << 8) + (1 << 6))) & (((unsigned)1 << kNumAlignBits) - ((unsigned)1 << kNumCacheLineBits));
259 t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc;
260 }
261 }
262 Lzma2Dec_Init(&t->dec);
263
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;
270
271 t->inCodeSize = 0;
272 t->outCodeSize = 0;
273 t->codeRes = SZ_OK;
274
275 // (cc->srcSize == 0) is allowed
276 }
277
278 {
279 ELzma2ParseStatus status;
280 BoolInt overflow;
281 UInt32 unpackRem = 0;
282
283 int checkFinishBlock = True;
284 size_t limit = me->props.outBlockMax;
285 if (me->outSize_Defined)
286 {
287 UInt64 rem = me->outSize - me->outProcessed_Parse;
288 if (limit >= rem)
289 {
290 limit = (size_t)rem;
291 if (!me->finishMode)
292 checkFinishBlock = False;
293 }
294 }
295
296 // checkFinishBlock = False, if we want to decode partial data
297 // that must be finished at position <= outBlockMax.
298
299 {
300 const SizeT srcOrig = cc->srcSize;
301 SizeT srcSize_Point = 0;
302 SizeT dicPos_Point = 0;
303
304 cc->srcSize = 0;
305 overflow = False;
306
307 for (;;)
308 {
309 SizeT srcCur = srcOrig - cc->srcSize;
310
311 status = Lzma2Dec_Parse(&t->dec,
312 limit - t->dec.decoder.dicPos,
313 cc->src + cc->srcSize, &srcCur,
314 checkFinishBlock);
315
316 cc->srcSize += srcCur;
317
318 if (status == LZMA2_PARSE_STATUS_NEW_CHUNK)
319 {
320 if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos)
321 {
322 overflow = True;
323 break;
324 }
325 continue;
326 }
327
328 if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
329 {
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;
338 }
339
340 if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock
341 // && limit == t->dec.decoder.dicPos
342 // && limit == me->props.outBlockMax
343 )
344 {
345 overflow = True;
346 break;
347 }
348
349 unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec);
350 break;
351 }
352
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)
357 {
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;
364 }
365 }
366
367 t->inPreSize += cc->srcSize;
368 t->parseStatus = status;
369
370 if (overflow)
371 cc->state = MTDEC_PARSE_OVERFLOW;
372 else
373 {
374 size_t dicPos = t->dec.decoder.dicPos;
375
376 if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT)
377 {
378 if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
379 {
380 cc->state = MTDEC_PARSE_NEW;
381 cc->srcSize--; // we don't need control byte of next block
382 t->inPreSize--;
383 }
384 else
385 {
386 cc->state = MTDEC_PARSE_END;
387 if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK)
388 {
389 // (status == LZMA_STATUS_NOT_SPECIFIED)
390 // (status == LZMA_STATUS_NOT_FINISHED)
391 if (unpackRem != 0)
392 {
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;
398 }
399 }
400 }
401
402 me->outProcessed_Parse += dicPos;
403 }
404
405 cc->outPos = dicPos;
406 t->outPreSize = (size_t)dicPos;
407 }
408
409 t->state = cc->state;
410 return;
411 }
412}
413
414
415static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex)
416{
417 CLzma2DecMt *me = (CLzma2DecMt *)pp;
418 CLzma2DecMtThread *t = &me->coders[coderIndex];
419 Byte *dest = t->outBuf;
420
421 if (t->inPreSize == 0)
422 {
423 t->codeRes = SZ_ERROR_DATA;
424 return t->codeRes;
425 }
426
427 if (!dest || t->outBufSize < t->outPreSize)
428 {
429 if (dest)
430 {
431 ISzAlloc_Free(me->allocMid, dest);
432 t->outBuf = NULL;
433 t->outBufSize = 0;
434 }
435
436 dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize
437 // + (1 << 28)
438 );
439 // Sleep(200);
440 if (!dest)
441 return SZ_ERROR_MEM;
442 t->outBuf = dest;
443 t->outBufSize = t->outPreSize;
444 }
445
446 t->dec.decoder.dic = dest;
447 t->dec.decoder.dicBufSize = t->outPreSize;
448
449 t->needInit = True;
450
451 return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt
452}
453
454
455static 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)
459{
460 CLzma2DecMt *me = (CLzma2DecMt *)pp;
461 CLzma2DecMtThread *t = &me->coders[coderIndex];
462
463 UNUSED_VAR(srcFinished)
464
465 PRF_STR_INT_2("Code", coderIndex, srcSize);
466
467 *inCodePos = t->inCodeSize;
468 *outCodePos = 0;
469 *stop = True;
470
471 if (t->needInit)
472 {
473 Lzma2Dec_Init(&t->dec);
474 t->needInit = False;
475 }
476
477 {
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);
483
484 SRes res = Lzma2Dec_DecodeToDic(&t->dec,
485 t->outPreSize,
486 src, &srcProcessed,
487 blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY,
488 &status);
489
490 t->codeRes = res;
491
492 t->inCodeSize += srcProcessed;
493 *inCodePos = t->inCodeSize;
494 t->outCodeSize = t->dec.decoder.dicPos;
495 *outCodePos = t->dec.decoder.dicPos;
496
497 if (res != SZ_OK)
498 return res;
499
500 if (srcProcessed == srcSize)
501 *stop = False;
502
503 if (blockWasFinished)
504 {
505 if (srcSize != srcProcessed)
506 return SZ_ERROR_FAIL;
507
508 if (t->inPreSize == t->inCodeSize)
509 {
510 if (t->outPreSize != t->outCodeSize)
511 return SZ_ERROR_FAIL;
512 *stop = True;
513 }
514 }
515 else
516 {
517 if (t->outPreSize == t->outCodeSize)
518 *stop = True;
519 }
520
521 return SZ_OK;
522 }
523}
524
525
526#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24)
527
528static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,
529 BoolInt needWriteToStream,
530 const Byte *src, size_t srcSize, BoolInt isCross,
531 BoolInt *needContinue, BoolInt *canRecode)
532{
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;
538
539 UNUSED_VAR(src)
540 UNUSED_VAR(srcSize)
541 UNUSED_VAR(isCross)
542
543 PRF_STR_INT_2("Write", coderIndex, srcSize);
544
545 *needContinue = False;
546 *canRecode = True;
547
548 if (
549 // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
550 t->state == MTDEC_PARSE_OVERFLOW
551 || t->state == MTDEC_PARSE_END)
552 needContinue2 = False;
553
554
555 if (!needWriteToStream)
556 return SZ_OK;
557
558 me->mtc.inProcessed += t->inCodeSize;
559
560 if (t->codeRes == SZ_OK)
561 if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
562 || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)
563 if (t->outPreSize != t->outCodeSize
564 || t->inPreSize != t->inCodeSize)
565 return SZ_ERROR_FAIL;
566
567 *canRecode = False;
568
569 if (me->outStream)
570 {
571 for (;;)
572 {
573 size_t cur = size;
574 size_t written;
575 if (cur > LZMA2DECMT_STREAM_WRITE_STEP)
576 cur = LZMA2DECMT_STREAM_WRITE_STEP;
577
578 written = ISeqOutStream_Write(me->outStream, data, cur);
579
580 me->outProcessed += written;
581 // me->mtc.writtenTotal += written;
582 if (written != cur)
583 return SZ_ERROR_WRITE;
584 data += cur;
585 size -= cur;
586 if (size == 0)
587 {
588 *needContinue = needContinue2;
589 return SZ_OK;
590 }
591 RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0));
592 }
593 }
594
595 return SZ_ERROR_FAIL;
596 /*
597 if (size > me->outBufSize)
598 return SZ_ERROR_OUTPUT_EOF;
599 memcpy(me->outBuf, data, size);
600 me->outBufSize -= size;
601 me->outBuf += size;
602 *needContinue = needContinue2;
603 return SZ_OK;
604 */
605}
606
607#endif
608
609
610static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)
611{
612 if (!p->dec_created)
613 {
614 Lzma2Dec_Construct(&p->dec);
615 p->dec_created = True;
616 }
617
618 RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt));
619
620 if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
621 {
622 ISzAlloc_Free(p->allocMid, p->inBuf);
623 p->inBufSize = 0;
624 p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
625 if (!p->inBuf)
626 return SZ_ERROR_MEM;
627 p->inBufSize = p->props.inBufSize_ST;
628 }
629
630 Lzma2Dec_Init(&p->dec);
631
632 return SZ_OK;
633}
634
635
636static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p
637 #ifndef _7ZIP_ST
638 , BoolInt tMode
639 #endif
640 )
641{
642 SizeT wrPos;
643 size_t inPos, inLim;
644 const Byte *inData;
645 UInt64 inPrev, outPrev;
646
647 CLzma2Dec *dec;
648
649 #ifndef _7ZIP_ST
650 if (tMode)
651 {
652 Lzma2DecMt_FreeOutBufs(p);
653 tMode = MtDec_PrepareRead(&p->mtc);
654 }
655 #endif
656
657 RINOK(Lzma2Dec_Prepare_ST(p));
658
659 dec = &p->dec;
660
661 inPrev = p->inProcessed;
662 outPrev = p->outProcessed;
663
664 inPos = 0;
665 inLim = 0;
666 inData = NULL;
667 wrPos = dec->decoder.dicPos;
668
669 for (;;)
670 {
671 SizeT dicPos;
672 SizeT size;
673 ELzmaFinishMode finishMode;
674 SizeT inProcessed;
675 ELzmaStatus status;
676 SRes res;
677
678 SizeT outProcessed;
679 BoolInt outFinished;
680 BoolInt needStop;
681
682 if (inPos == inLim)
683 {
684 #ifndef _7ZIP_ST
685 if (tMode)
686 {
687 inData = MtDec_Read(&p->mtc, &inLim);
688 inPos = 0;
689 if (inData)
690 continue;
691 tMode = False;
692 inLim = 0;
693 }
694 #endif
695
696 if (!p->readWasFinished)
697 {
698 inPos = 0;
699 inLim = p->inBufSize;
700 inData = p->inBuf;
701 p->readRes = ISeqInStream_Read(p->inStream, (void *)(p->inBuf), &inLim);
702 // p->readProcessed += inLim;
703 // inLim -= 5; p->readWasFinished = True; // for test
704 if (inLim == 0 || p->readRes != SZ_OK)
705 p->readWasFinished = True;
706 }
707 }
708
709 dicPos = dec->decoder.dicPos;
710 {
711 SizeT next = dec->decoder.dicBufSize;
712 if (next - wrPos > p->props.outStep_ST)
713 next = wrPos + p->props.outStep_ST;
714 size = next - dicPos;
715 }
716
717 finishMode = LZMA_FINISH_ANY;
718 if (p->outSize_Defined)
719 {
720 const UInt64 rem = p->outSize - p->outProcessed;
721 if (size >= rem)
722 {
723 size = (SizeT)rem;
724 if (p->finishMode)
725 finishMode = LZMA_FINISH_END;
726 }
727 }
728
729 inProcessed = inLim - inPos;
730
731 res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);
732
733 inPos += inProcessed;
734 p->inProcessed += inProcessed;
735 outProcessed = dec->decoder.dicPos - dicPos;
736 p->outProcessed += outProcessed;
737
738 outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);
739
740 needStop = (res != SZ_OK
741 || (inProcessed == 0 && outProcessed == 0)
742 || status == LZMA_STATUS_FINISHED_WITH_MARK
743 || (!p->finishMode && outFinished));
744
745 if (needStop || outProcessed >= size)
746 {
747 SRes res2;
748 {
749 size_t writeSize = dec->decoder.dicPos - wrPos;
750 size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);
751 res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;
752 }
753
754 if (dec->decoder.dicPos == dec->decoder.dicBufSize)
755 dec->decoder.dicPos = 0;
756 wrPos = dec->decoder.dicPos;
757
758 RINOK(res2);
759
760 if (needStop)
761 {
762 if (res != SZ_OK)
763 return res;
764
765 if (status == LZMA_STATUS_FINISHED_WITH_MARK)
766 {
767 if (p->finishMode)
768 {
769 if (p->outSize_Defined && p->outSize != p->outProcessed)
770 return SZ_ERROR_DATA;
771 }
772 return SZ_OK;
773 }
774
775 if (!p->finishMode && outFinished)
776 return SZ_OK;
777
778 if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
779 return SZ_ERROR_INPUT_EOF;
780
781 return SZ_ERROR_DATA;
782 }
783 }
784
785 if (p->progress)
786 {
787 UInt64 inDelta = p->inProcessed - inPrev;
788 UInt64 outDelta = p->outProcessed - outPrev;
789 if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
790 {
791 RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed));
792 inPrev = p->inProcessed;
793 outPrev = p->outProcessed;
794 }
795 }
796 }
797}
798
799
800
801SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp,
802 Byte prop,
803 const CLzma2DecMtProps *props,
804 ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode,
805 // Byte *outBuf, size_t *outBufSize,
806 ISeqInStream *inStream,
807 // const Byte *inData, size_t inDataSize,
808 UInt64 *inProcessed,
809 // UInt64 *outProcessed,
810 int *isMT,
811 ICompressProgress *progress)
812{
813 CLzma2DecMt *p = (CLzma2DecMt *)pp;
814 #ifndef _7ZIP_ST
815 BoolInt tMode;
816 #endif
817
818 *inProcessed = 0;
819
820 if (prop > 40)
821 return SZ_ERROR_UNSUPPORTED;
822
823 p->prop = prop;
824 p->props = *props;
825
826 p->inStream = inStream;
827 p->outStream = outStream;
828 p->progress = progress;
829
830 p->outSize = 0;
831 p->outSize_Defined = False;
832 if (outDataSize)
833 {
834 p->outSize_Defined = True;
835 p->outSize = *outDataSize;
836 }
837 p->finishMode = finishMode;
838
839 p->outProcessed = 0;
840 p->inProcessed = 0;
841
842 p->readWasFinished = False;
843 p->readRes = SZ_OK;
844
845 *isMT = False;
846
847
848 #ifndef _7ZIP_ST
849
850 tMode = False;
851
852 // p->mtc.parseRes = SZ_OK;
853
854 // p->mtc.numFilledThreads = 0;
855 // p->mtc.crossStart = 0;
856 // p->mtc.crossEnd = 0;
857 // p->mtc.allocError_for_Read_BlockIndex = 0;
858 // p->mtc.isAllocError = False;
859
860 if (p->props.numThreads > 1)
861 {
862 IMtDecCallback2 vt;
863
864 Lzma2DecMt_FreeSt(p);
865
866 p->outProcessed_Parse = 0;
867
868 if (!p->mtc_WasConstructed)
869 {
870 p->mtc_WasConstructed = True;
871 MtDec_Construct(&p->mtc);
872 }
873
874 p->mtc.progress = progress;
875 p->mtc.inStream = inStream;
876
877 // p->outBuf = NULL;
878 // p->outBufSize = 0;
879 /*
880 if (!outStream)
881 {
882 // p->outBuf = outBuf;
883 // p->outBufSize = *outBufSize;
884 // *outBufSize = 0;
885 return SZ_ERROR_PARAM;
886 }
887 */
888
889 // p->mtc.inBlockMax = p->props.inBlockMax;
890 p->mtc.alloc = &p->alignOffsetAlloc.vt;
891 // p->alignOffsetAlloc.baseAlloc;
892 // p->mtc.inData = inData;
893 // p->mtc.inDataSize = inDataSize;
894 p->mtc.mtCallback = &vt;
895 p->mtc.mtCallbackObject = p;
896
897 p->mtc.inBufSize = p->props.inBufSize_MT;
898
899 p->mtc.numThreadsMax = p->props.numThreads;
900
901 *isMT = True;
902
903 vt.Parse = Lzma2DecMt_MtCallback_Parse;
904 vt.PreCode = Lzma2DecMt_MtCallback_PreCode;
905 vt.Code = Lzma2DecMt_MtCallback_Code;
906 vt.Write = Lzma2DecMt_MtCallback_Write;
907
908 {
909 BoolInt needContinue = False;
910
911 SRes res = MtDec_Code(&p->mtc);
912
913 /*
914 if (!outStream)
915 *outBufSize = p->outBuf - outBuf;
916 */
917
918 *inProcessed = p->mtc.inProcessed;
919
920 needContinue = False;
921
922 if (res == SZ_OK)
923 {
924 if (p->mtc.mtProgress.res != SZ_OK)
925 res = p->mtc.mtProgress.res;
926 else
927 needContinue = p->mtc.needContinue;
928 }
929
930 if (!needContinue)
931 {
932 if (res == SZ_OK)
933 return p->mtc.readRes;
934 return res;
935 }
936
937 tMode = True;
938 p->readRes = p->mtc.readRes;
939 p->readWasFinished = p->mtc.readWasFinished;
940 p->inProcessed = p->mtc.inProcessed;
941
942 PRF_STR("----- decoding ST -----");
943 }
944 }
945
946 #endif
947
948
949 *isMT = False;
950
951 {
952 SRes res = Lzma2Dec_Decode_ST(p
953 #ifndef _7ZIP_ST
954 , tMode
955 #endif
956 );
957
958 *inProcessed = p->inProcessed;
959
960 // res = SZ_OK; // for test
961 if (res == SZ_ERROR_INPUT_EOF)
962 {
963 if (p->readRes != SZ_OK)
964 res = p->readRes;
965 }
966 else if (res == SZ_OK && p->readRes != SZ_OK)
967 res = p->readRes;
968
969 /*
970 #ifndef _7ZIP_ST
971 if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)
972 res = p->mtc.parseRes;
973 #endif
974 */
975
976 return res;
977 }
978}
979
980
981/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
982
983SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
984 Byte prop,
985 const CLzma2DecMtProps *props,
986 const UInt64 *outDataSize, int finishMode,
987 ISeqInStream *inStream)
988{
989 CLzma2DecMt *p = (CLzma2DecMt *)pp;
990
991 if (prop > 40)
992 return SZ_ERROR_UNSUPPORTED;
993
994 p->prop = prop;
995 p->props = *props;
996
997 p->inStream = inStream;
998
999 p->outSize = 0;
1000 p->outSize_Defined = False;
1001 if (outDataSize)
1002 {
1003 p->outSize_Defined = True;
1004 p->outSize = *outDataSize;
1005 }
1006 p->finishMode = finishMode;
1007
1008 p->outProcessed = 0;
1009 p->inProcessed = 0;
1010
1011 p->inPos = 0;
1012 p->inLim = 0;
1013
1014 return Lzma2Dec_Prepare_ST(p);
1015}
1016
1017
1018SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
1019 Byte *data, size_t *outSize,
1020 UInt64 *inStreamProcessed)
1021{
1022 CLzma2DecMt *p = (CLzma2DecMt *)pp;
1023 ELzmaFinishMode finishMode;
1024 SRes readRes;
1025 size_t size = *outSize;
1026
1027 *outSize = 0;
1028 *inStreamProcessed = 0;
1029
1030 finishMode = LZMA_FINISH_ANY;
1031 if (p->outSize_Defined)
1032 {
1033 const UInt64 rem = p->outSize - p->outProcessed;
1034 if (size >= rem)
1035 {
1036 size = (size_t)rem;
1037 if (p->finishMode)
1038 finishMode = LZMA_FINISH_END;
1039 }
1040 }
1041
1042 readRes = SZ_OK;
1043
1044 for (;;)
1045 {
1046 SizeT inCur;
1047 SizeT outCur;
1048 ELzmaStatus status;
1049 SRes res;
1050
1051 if (p->inPos == p->inLim && readRes == SZ_OK)
1052 {
1053 p->inPos = 0;
1054 p->inLim = p->props.inBufSize_ST;
1055 readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);
1056 }
1057
1058 inCur = p->inLim - p->inPos;
1059 outCur = size;
1060
1061 res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,
1062 p->inBuf + p->inPos, &inCur, finishMode, &status);
1063
1064 p->inPos += inCur;
1065 p->inProcessed += inCur;
1066 *inStreamProcessed += inCur;
1067 p->outProcessed += outCur;
1068 *outSize += outCur;
1069 size -= outCur;
1070 data += outCur;
1071
1072 if (res != 0)
1073 return res;
1074
1075 /*
1076 if (status == LZMA_STATUS_FINISHED_WITH_MARK)
1077 return readRes;
1078
1079 if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
1080 {
1081 if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)
1082 return SZ_ERROR_DATA;
1083 return readRes;
1084 }
1085 */
1086
1087 if (inCur == 0 && outCur == 0)
1088 return readRes;
1089 }
1090}