xref: /third_party/lzma/C/Lzma2DecMt.c (revision 370b324c)
1/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread
22023-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
36void 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
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
84struct 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
124CLzma2DecMtHandle 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
164static 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
182static 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
200void 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
237static 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
416static 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
456static 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
529static 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
611static 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
637static 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
802SRes 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
984SRes 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
1019SRes 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