xref: /aosp_15_r20/external/lzma/C/Lzma2DecMt.c (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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