tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Lzma2DecMt.c (24366B)


      1 /* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread
      2 2018-03-02 : Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 // #define SHOW_DEBUG_INFO
      7 
      8 #ifdef SHOW_DEBUG_INFO
      9 #include <stdio.h>
     10 #endif
     11 
     12 #ifdef SHOW_DEBUG_INFO
     13 #define PRF(x) x
     14 #else
     15 #define PRF(x)
     16 #endif
     17 
     18 #define PRF_STR(s) PRF(printf("\n" s "\n"))
     19 #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
     20 #define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2))
     21 
     22 // #define _7ZIP_ST
     23 
     24 #include "Alloc.h"
     25 
     26 #include "Lzma2Dec.h"
     27 #include "Lzma2DecMt.h"
     28 
     29 #ifndef _7ZIP_ST
     30 #include "MtDec.h"
     31 #endif
     32 
     33 
     34 #define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)
     35 
     36 void 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 
     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 typedef 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  Bool finishMode;
     98  Bool outSize_Defined;
     99  UInt64 outSize;
    100 
    101  UInt64 outProcessed;
    102  UInt64 inProcessed;
    103  Bool 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  Bool mtc_WasConstructed;
    117  CMtDec mtc;
    118  CLzma2DecMtThread coders[MTDEC__THREADS_MAX];
    119  #endif
    120 
    121 } CLzma2DecMt;
    122 
    123 
    124 
    125 CLzma2DecMtHandle 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 
    165 static 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 
    183 static 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 
    199 void 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 
    236 static 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 * ((1 << 11) + (1 << 8) + (1 << 6))) & ((1 << kNumAlignBits) - (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 = 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    Bool 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 
    415 static 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 
    455 static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex,
    456    const Byte *src, size_t srcSize, int srcFinished,
    457    // int finished, int blockFinished,
    458    UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
    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    Bool 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 
    528 static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,
    529    Bool needWriteToStream,
    530    const Byte *src, size_t srcSize,
    531    Bool *needContinue, Bool *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  Bool needContinue2 = True;
    538 
    539  PRF_STR_INT_2("Write", coderIndex, srcSize);
    540 
    541  *needContinue = False;
    542  *canRecode = True;
    543  UNUSED_VAR(src)
    544  UNUSED_VAR(srcSize)
    545 
    546  if (
    547      // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
    548         t->state == MTDEC_PARSE_OVERFLOW
    549      || t->state == MTDEC_PARSE_END)
    550    needContinue2 = False;
    551 
    552 
    553  if (!needWriteToStream)
    554    return SZ_OK;
    555 
    556  me->mtc.inProcessed += t->inCodeSize;
    557 
    558  if (t->codeRes == SZ_OK)
    559  if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
    560      || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)
    561  if (t->outPreSize != t->outCodeSize
    562      || t->inPreSize != t->inCodeSize)
    563    return SZ_ERROR_FAIL;
    564 
    565  *canRecode = False;
    566    
    567  if (me->outStream)
    568  {
    569    for (;;)
    570    {
    571      size_t cur = size;
    572      size_t written;
    573      if (cur > LZMA2DECMT_STREAM_WRITE_STEP)
    574        cur = LZMA2DECMT_STREAM_WRITE_STEP;
    575 
    576      written = ISeqOutStream_Write(me->outStream, data, cur);
    577      
    578      me->outProcessed += written;
    579      // me->mtc.writtenTotal += written;
    580      if (written != cur)
    581        return SZ_ERROR_WRITE;
    582      data += cur;
    583      size -= cur;
    584      if (size == 0)
    585      {
    586        *needContinue = needContinue2;
    587        return SZ_OK;
    588      }
    589      RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0));
    590    }
    591  }
    592  
    593  return SZ_ERROR_FAIL;
    594  /*
    595  if (size > me->outBufSize)
    596    return SZ_ERROR_OUTPUT_EOF;
    597  memcpy(me->outBuf, data, size);
    598  me->outBufSize -= size;
    599  me->outBuf += size;
    600  *needContinue = needContinue2;
    601  return SZ_OK;
    602  */
    603 }
    604 
    605 #endif
    606 
    607 
    608 static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)
    609 {
    610  if (!p->dec_created)
    611  {
    612    Lzma2Dec_Construct(&p->dec);
    613    p->dec_created = True;
    614  }
    615 
    616  RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt));
    617 
    618  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
    619  {
    620    ISzAlloc_Free(p->allocMid, p->inBuf);
    621    p->inBufSize = 0;
    622    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
    623    if (!p->inBuf)
    624      return SZ_ERROR_MEM;
    625    p->inBufSize = p->props.inBufSize_ST;
    626  }
    627 
    628  Lzma2Dec_Init(&p->dec);
    629  
    630  return SZ_OK;
    631 }
    632 
    633 
    634 static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p
    635    #ifndef _7ZIP_ST
    636    , Bool tMode
    637    #endif
    638    )
    639 {
    640  SizeT wrPos;
    641  size_t inPos, inLim;
    642  const Byte *inData;
    643  UInt64 inPrev, outPrev;
    644 
    645  CLzma2Dec *dec;
    646 
    647  #ifndef _7ZIP_ST
    648  if (tMode)
    649  {
    650    Lzma2DecMt_FreeOutBufs(p);
    651    tMode = MtDec_PrepareRead(&p->mtc);
    652  }
    653  #endif
    654 
    655  RINOK(Lzma2Dec_Prepare_ST(p));
    656 
    657  dec = &p->dec;
    658 
    659  inPrev = p->inProcessed;
    660  outPrev = p->outProcessed;
    661 
    662  inPos = 0;
    663  inLim = 0;
    664  inData = NULL;
    665  wrPos = dec->decoder.dicPos;
    666 
    667  for (;;)
    668  {
    669    SizeT dicPos;
    670    SizeT size;
    671    ELzmaFinishMode finishMode;
    672    SizeT inProcessed;
    673    ELzmaStatus status;
    674    SRes res;
    675 
    676    SizeT outProcessed;
    677    Bool outFinished;
    678    Bool needStop;
    679 
    680    if (inPos == inLim)
    681    {
    682      #ifndef _7ZIP_ST
    683      if (tMode)
    684      {
    685        inData = MtDec_Read(&p->mtc, &inLim);
    686        inPos = 0;
    687        if (inData)
    688          continue;
    689        tMode = False;
    690        inLim = 0;
    691      }
    692      #endif
    693      
    694      if (!p->readWasFinished)
    695      {
    696        inPos = 0;
    697        inLim = p->inBufSize;
    698        inData = p->inBuf;
    699        p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
    700        // p->readProcessed += inLim;
    701        // inLim -= 5; p->readWasFinished = True; // for test
    702        if (inLim == 0 || p->readRes != SZ_OK)
    703          p->readWasFinished = True;
    704      }
    705    }
    706 
    707    dicPos = dec->decoder.dicPos;
    708    {
    709      SizeT next = dec->decoder.dicBufSize;
    710      if (next - wrPos > p->props.outStep_ST)
    711        next = wrPos + p->props.outStep_ST;
    712      size = next - dicPos;
    713    }
    714 
    715    finishMode = LZMA_FINISH_ANY;
    716    if (p->outSize_Defined)
    717    {
    718      const UInt64 rem = p->outSize - p->outProcessed;
    719      if (size >= rem)
    720      {
    721        size = (SizeT)rem;
    722        if (p->finishMode)
    723          finishMode = LZMA_FINISH_END;
    724      }
    725    }
    726 
    727    inProcessed = inLim - inPos;
    728    
    729    res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);
    730 
    731    inPos += inProcessed;
    732    p->inProcessed += inProcessed;
    733    outProcessed = dec->decoder.dicPos - dicPos;
    734    p->outProcessed += outProcessed;
    735 
    736    outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);
    737 
    738    needStop = (res != SZ_OK
    739        || (inProcessed == 0 && outProcessed == 0)
    740        || status == LZMA_STATUS_FINISHED_WITH_MARK
    741        || (!p->finishMode && outFinished));
    742 
    743    if (needStop || outProcessed >= size)
    744    {
    745      SRes res2;
    746      {
    747        size_t writeSize = dec->decoder.dicPos - wrPos;
    748        size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);
    749        res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;
    750      }
    751 
    752      if (dec->decoder.dicPos == dec->decoder.dicBufSize)
    753        dec->decoder.dicPos = 0;
    754      wrPos = dec->decoder.dicPos;
    755 
    756      RINOK(res2);
    757 
    758      if (needStop)
    759      {
    760        if (res != SZ_OK)
    761          return res;
    762 
    763        if (status == LZMA_STATUS_FINISHED_WITH_MARK)
    764        {
    765          if (p->finishMode)
    766          {
    767            if (p->outSize_Defined && p->outSize != p->outProcessed)
    768              return SZ_ERROR_DATA;
    769          }
    770          return SZ_OK;
    771        }
    772 
    773        if (!p->finishMode && outFinished)
    774          return SZ_OK;
    775 
    776        if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
    777          return SZ_ERROR_INPUT_EOF;
    778        
    779        return SZ_ERROR_DATA;
    780      }
    781    }
    782    
    783    if (p->progress)
    784    {
    785      UInt64 inDelta = p->inProcessed - inPrev;
    786      UInt64 outDelta = p->outProcessed - outPrev;
    787      if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
    788      {
    789        RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed));
    790        inPrev = p->inProcessed;
    791        outPrev = p->outProcessed;
    792      }
    793    }
    794  }
    795 }
    796 
    797 
    798 
    799 SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp,
    800    Byte prop,
    801    const CLzma2DecMtProps *props,
    802    ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode,
    803    // Byte *outBuf, size_t *outBufSize,
    804    ISeqInStream *inStream,
    805    // const Byte *inData, size_t inDataSize,
    806    UInt64 *inProcessed,
    807    // UInt64 *outProcessed,
    808    int *isMT,
    809    ICompressProgress *progress)
    810 {
    811  CLzma2DecMt *p = (CLzma2DecMt *)pp;
    812  #ifndef _7ZIP_ST
    813  Bool tMode;
    814  #endif
    815 
    816  *inProcessed = 0;
    817 
    818  if (prop > 40)
    819    return SZ_ERROR_UNSUPPORTED;
    820 
    821  p->prop = prop;
    822  p->props = *props;
    823 
    824  p->inStream = inStream;
    825  p->outStream = outStream;
    826  p->progress = progress;
    827 
    828  p->outSize = 0;
    829  p->outSize_Defined = False;
    830  if (outDataSize)
    831  {
    832    p->outSize_Defined = True;
    833    p->outSize = *outDataSize;
    834  }
    835  p->finishMode = finishMode;
    836 
    837  p->outProcessed = 0;
    838  p->inProcessed = 0;
    839 
    840  p->readWasFinished = False;
    841 
    842  *isMT = False;
    843 
    844  
    845  #ifndef _7ZIP_ST
    846 
    847  tMode = False;
    848 
    849  // p->mtc.parseRes = SZ_OK;
    850 
    851  // p->mtc.numFilledThreads = 0;
    852  // p->mtc.crossStart = 0;
    853  // p->mtc.crossEnd = 0;
    854  // p->mtc.allocError_for_Read_BlockIndex = 0;
    855  // p->mtc.isAllocError = False;
    856 
    857  if (p->props.numThreads > 1)
    858  {
    859    IMtDecCallback vt;
    860 
    861    Lzma2DecMt_FreeSt(p);
    862 
    863    p->outProcessed_Parse = 0;
    864 
    865    if (!p->mtc_WasConstructed)
    866    {
    867      p->mtc_WasConstructed = True;
    868      MtDec_Construct(&p->mtc);
    869    }
    870    
    871    p->mtc.progress = progress;
    872    p->mtc.inStream = inStream;
    873 
    874    // p->outBuf = NULL;
    875    // p->outBufSize = 0;
    876    /*
    877    if (!outStream)
    878    {
    879      // p->outBuf = outBuf;
    880      // p->outBufSize = *outBufSize;
    881      // *outBufSize = 0;
    882      return SZ_ERROR_PARAM;
    883    }
    884    */
    885 
    886    // p->mtc.inBlockMax = p->props.inBlockMax;
    887    p->mtc.alloc = &p->alignOffsetAlloc.vt;
    888      // p->alignOffsetAlloc.baseAlloc;
    889    // p->mtc.inData = inData;
    890    // p->mtc.inDataSize = inDataSize;
    891    p->mtc.mtCallback = &vt;
    892    p->mtc.mtCallbackObject = p;
    893 
    894    p->mtc.inBufSize = p->props.inBufSize_MT;
    895 
    896    p->mtc.numThreadsMax = p->props.numThreads;
    897 
    898    *isMT = True;
    899 
    900    vt.Parse = Lzma2DecMt_MtCallback_Parse;
    901    vt.PreCode = Lzma2DecMt_MtCallback_PreCode;
    902    vt.Code = Lzma2DecMt_MtCallback_Code;
    903    vt.Write = Lzma2DecMt_MtCallback_Write;
    904 
    905    {
    906      Bool needContinue = False;
    907 
    908      SRes res = MtDec_Code(&p->mtc);
    909 
    910      /*
    911      if (!outStream)
    912        *outBufSize = p->outBuf - outBuf;
    913      */
    914 
    915      *inProcessed = p->mtc.inProcessed;
    916 
    917      needContinue = False;
    918 
    919      if (res == SZ_OK)
    920      {
    921        if (p->mtc.mtProgress.res != SZ_OK)
    922          res = p->mtc.mtProgress.res;
    923        else
    924          needContinue = p->mtc.needContinue;
    925      }
    926 
    927      if (!needContinue)
    928      {
    929        if (res == SZ_OK)
    930          return p->mtc.readRes;
    931        return res;
    932      }
    933 
    934      tMode = True;
    935      p->readRes = p->mtc.readRes;
    936      p->readWasFinished = p->mtc.readWasFinished;
    937      p->inProcessed = p->mtc.inProcessed;
    938      
    939      PRF_STR("----- decoding ST -----");
    940    }
    941  }
    942 
    943  #endif
    944 
    945 
    946  *isMT = False;
    947 
    948  {
    949    SRes res = Lzma2Dec_Decode_ST(p
    950        #ifndef _7ZIP_ST
    951        , tMode
    952        #endif
    953        );
    954 
    955    *inProcessed = p->inProcessed;
    956 
    957    // res = SZ_OK; // for test
    958    if (res == SZ_OK && p->readRes != SZ_OK)
    959      res = p->readRes;
    960    
    961    /*
    962    #ifndef _7ZIP_ST
    963    if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)
    964      res = p->mtc.parseRes;
    965    #endif
    966    */
    967    
    968    return res;
    969  }
    970 }
    971 
    972 
    973 /* ---------- Read from CLzma2DecMtHandle Interface ---------- */
    974 
    975 SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
    976    Byte prop,
    977    const CLzma2DecMtProps *props,
    978    const UInt64 *outDataSize, int finishMode,
    979    ISeqInStream *inStream)
    980 {
    981  CLzma2DecMt *p = (CLzma2DecMt *)pp;
    982 
    983  if (prop > 40)
    984    return SZ_ERROR_UNSUPPORTED;
    985 
    986  p->prop = prop;
    987  p->props = *props;
    988 
    989  p->inStream = inStream;
    990 
    991  p->outSize = 0;
    992  p->outSize_Defined = False;
    993  if (outDataSize)
    994  {
    995    p->outSize_Defined = True;
    996    p->outSize = *outDataSize;
    997  }
    998  p->finishMode = finishMode;
    999 
   1000  p->outProcessed = 0;
   1001  p->inProcessed = 0;
   1002 
   1003  p->inPos = 0;
   1004  p->inLim = 0;
   1005 
   1006  return Lzma2Dec_Prepare_ST(p);
   1007 }
   1008 
   1009 
   1010 SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
   1011    Byte *data, size_t *outSize,
   1012    UInt64 *inStreamProcessed)
   1013 {
   1014  CLzma2DecMt *p = (CLzma2DecMt *)pp;
   1015  ELzmaFinishMode finishMode;
   1016  SRes readRes;
   1017  size_t size = *outSize;
   1018 
   1019  *outSize = 0;
   1020  *inStreamProcessed = 0;
   1021 
   1022  finishMode = LZMA_FINISH_ANY;
   1023  if (p->outSize_Defined)
   1024  {
   1025    const UInt64 rem = p->outSize - p->outProcessed;
   1026    if (size >= rem)
   1027    {
   1028      size = (size_t)rem;
   1029      if (p->finishMode)
   1030        finishMode = LZMA_FINISH_END;
   1031    }
   1032  }
   1033 
   1034  readRes = SZ_OK;
   1035 
   1036  for (;;)
   1037  {
   1038    SizeT inCur;
   1039    SizeT outCur;
   1040    ELzmaStatus status;
   1041    SRes res;
   1042 
   1043    if (p->inPos == p->inLim && readRes == SZ_OK)
   1044    {
   1045      p->inPos = 0;
   1046      p->inLim = p->props.inBufSize_ST;
   1047      readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);
   1048    }
   1049 
   1050    inCur = p->inLim - p->inPos;
   1051    outCur = size;
   1052 
   1053    res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,
   1054        p->inBuf + p->inPos, &inCur, finishMode, &status);
   1055    
   1056    p->inPos += inCur;
   1057    p->inProcessed += inCur;
   1058    *inStreamProcessed += inCur;
   1059    p->outProcessed += outCur;
   1060    *outSize += outCur;
   1061    size -= outCur;
   1062    data += outCur;
   1063    
   1064    if (res != 0)
   1065      return res;
   1066    
   1067    /*
   1068    if (status == LZMA_STATUS_FINISHED_WITH_MARK)
   1069      return readRes;
   1070 
   1071    if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
   1072    {
   1073      if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)
   1074        return SZ_ERROR_DATA;
   1075      return readRes;
   1076    }
   1077    */
   1078 
   1079    if (inCur == 0 && outCur == 0)
   1080      return readRes;
   1081  }
   1082 }