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