tor-browser

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

XzDec.c (67749B)


      1 /* XzDec.c -- Xz Decode
      2 2018-04-24 : Igor Pavlov : Public domain */
      3 
      4 #include "Precomp.h"
      5 
      6 // #include <stdio.h>
      7 
      8 // #define XZ_DUMP
      9 
     10 /* #define XZ_DUMP */
     11 
     12 #ifdef XZ_DUMP
     13 #include <stdio.h>
     14 #endif
     15 
     16 // #define SHOW_DEBUG_INFO
     17 
     18 #ifdef SHOW_DEBUG_INFO
     19 #include <stdio.h>
     20 #endif
     21 
     22 #ifdef SHOW_DEBUG_INFO
     23 #define PRF(x) x
     24 #else
     25 #define PRF(x)
     26 #endif
     27 
     28 #define PRF_STR(s) PRF(printf("\n" s "\n"))
     29 #define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
     30 
     31 #include <stdlib.h>
     32 #include <string.h>
     33 
     34 #include "7zCrc.h"
     35 #include "Alloc.h"
     36 #include "Bra.h"
     37 #include "CpuArch.h"
     38 #include "Delta.h"
     39 #include "Lzma2Dec.h"
     40 
     41 // #define USE_SUBBLOCK
     42 
     43 #ifdef USE_SUBBLOCK
     44 #include "Bcj3Dec.c"
     45 #include "SbDec.h"
     46 #endif
     47 
     48 #include "Xz.h"
     49 
     50 #define XZ_CHECK_SIZE_MAX 64
     51 
     52 #define CODER_BUF_SIZE ((size_t)1 << 17)
     53 
     54 unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
     55 {
     56  unsigned i, limit;
     57  *value = 0;
     58  limit = (maxSize > 9) ? 9 : (unsigned)maxSize;
     59 
     60  for (i = 0; i < limit;)
     61  {
     62    Byte b = p[i];
     63    *value |= (UInt64)(b & 0x7F) << (7 * i++);
     64    if ((b & 0x80) == 0)
     65      return (b == 0 && i != 1) ? 0 : i;
     66  }
     67  return 0;
     68 }
     69 
     70 /* ---------- BraState ---------- */
     71 
     72 #define BRA_BUF_SIZE (1 << 14)
     73 
     74 typedef struct
     75 {
     76  size_t bufPos;
     77  size_t bufConv;
     78  size_t bufTotal;
     79 
     80  int encodeMode;
     81 
     82  UInt32 methodId;
     83  UInt32 delta;
     84  UInt32 ip;
     85  UInt32 x86State;
     86  Byte deltaState[DELTA_STATE_SIZE];
     87 
     88  Byte buf[BRA_BUF_SIZE];
     89 } CBraState;
     90 
     91 static void BraState_Free(void *pp, ISzAllocPtr alloc)
     92 {
     93  ISzAlloc_Free(alloc, pp);
     94 }
     95 
     96 static SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
     97 {
     98  CBraState *p = ((CBraState *)pp);
     99  UNUSED_VAR(alloc);
    100  p->ip = 0;
    101  if (p->methodId == XZ_ID_Delta)
    102  {
    103    if (propSize != 1)
    104      return SZ_ERROR_UNSUPPORTED;
    105    p->delta = (unsigned)props[0] + 1;
    106  }
    107  else
    108  {
    109    if (propSize == 4)
    110    {
    111      UInt32 v = GetUi32(props);
    112      switch (p->methodId)
    113      {
    114        case XZ_ID_PPC:
    115        case XZ_ID_ARM:
    116        case XZ_ID_SPARC:
    117          if ((v & 3) != 0)
    118            return SZ_ERROR_UNSUPPORTED;
    119          break;
    120        case XZ_ID_ARMT:
    121          if ((v & 1) != 0)
    122            return SZ_ERROR_UNSUPPORTED;
    123          break;
    124        case XZ_ID_IA64:
    125          if ((v & 0xF) != 0)
    126            return SZ_ERROR_UNSUPPORTED;
    127          break;
    128      }
    129      p->ip = v;
    130    }
    131    else if (propSize != 0)
    132      return SZ_ERROR_UNSUPPORTED;
    133  }
    134  return SZ_OK;
    135 }
    136 
    137 static void BraState_Init(void *pp)
    138 {
    139  CBraState *p = ((CBraState *)pp);
    140  p->bufPos = p->bufConv = p->bufTotal = 0;
    141  x86_Convert_Init(p->x86State);
    142  if (p->methodId == XZ_ID_Delta)
    143    Delta_Init(p->deltaState);
    144 }
    145 
    146 
    147 #define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: size = isa ## _Convert(data, size, p->ip, p->encodeMode); break;
    148 
    149 static SizeT BraState_Filter(void *pp, Byte *data, SizeT size)
    150 {
    151  CBraState *p = ((CBraState *)pp);
    152  switch (p->methodId)
    153  {
    154    case XZ_ID_Delta:
    155      if (p->encodeMode)
    156        Delta_Encode(p->deltaState, p->delta, data, size);
    157      else
    158        Delta_Decode(p->deltaState, p->delta, data, size);
    159      break;
    160    case XZ_ID_X86:
    161      size = x86_Convert(data, size, p->ip, &p->x86State, p->encodeMode);
    162      break;
    163    CASE_BRA_CONV(PPC)
    164    CASE_BRA_CONV(IA64)
    165    CASE_BRA_CONV(ARM)
    166    CASE_BRA_CONV(ARMT)
    167    CASE_BRA_CONV(SPARC)
    168  }
    169  p->ip += (UInt32)size;
    170  return size;
    171 }
    172 
    173 
    174 static SRes BraState_Code2(void *pp,
    175    Byte *dest, SizeT *destLen,
    176    const Byte *src, SizeT *srcLen, int srcWasFinished,
    177    ECoderFinishMode finishMode,
    178    // int *wasFinished
    179    ECoderStatus *status)
    180 {
    181  CBraState *p = ((CBraState *)pp);
    182  SizeT destRem = *destLen;
    183  SizeT srcRem = *srcLen;
    184  UNUSED_VAR(finishMode);
    185 
    186  *destLen = 0;
    187  *srcLen = 0;
    188  // *wasFinished = False;
    189  *status = CODER_STATUS_NOT_FINISHED;
    190  
    191  while (destRem > 0)
    192  {
    193    if (p->bufPos != p->bufConv)
    194    {
    195      size_t size = p->bufConv - p->bufPos;
    196      if (size > destRem)
    197        size = destRem;
    198      memcpy(dest, p->buf + p->bufPos, size);
    199      p->bufPos += size;
    200      *destLen += size;
    201      dest += size;
    202      destRem -= size;
    203      continue;
    204    }
    205    
    206    p->bufTotal -= p->bufPos;
    207    memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
    208    p->bufPos = 0;
    209    p->bufConv = 0;
    210    {
    211      size_t size = BRA_BUF_SIZE - p->bufTotal;
    212      if (size > srcRem)
    213        size = srcRem;
    214      memcpy(p->buf + p->bufTotal, src, size);
    215      *srcLen += size;
    216      src += size;
    217      srcRem -= size;
    218      p->bufTotal += size;
    219    }
    220    if (p->bufTotal == 0)
    221      break;
    222    
    223    p->bufConv = BraState_Filter(pp, p->buf, p->bufTotal);
    224 
    225    if (p->bufConv == 0)
    226    {
    227      if (!srcWasFinished)
    228        break;
    229      p->bufConv = p->bufTotal;
    230    }
    231  }
    232 
    233  if (p->bufTotal == p->bufPos && srcRem == 0 && srcWasFinished)
    234  {
    235    *status = CODER_STATUS_FINISHED_WITH_MARK;
    236    // *wasFinished = 1;
    237  }
    238 
    239  return SZ_OK;
    240 }
    241 
    242 
    243 SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, int encodeMode, ISzAllocPtr alloc)
    244 {
    245  CBraState *decoder;
    246  if (id < XZ_ID_Delta || id > XZ_ID_SPARC)
    247    return SZ_ERROR_UNSUPPORTED;
    248  decoder = p->p;
    249  if (!decoder)
    250  {
    251    decoder = (CBraState *)ISzAlloc_Alloc(alloc, sizeof(CBraState));
    252    if (!decoder)
    253      return SZ_ERROR_MEM;
    254    p->p = decoder;
    255    p->Free = BraState_Free;
    256    p->SetProps = BraState_SetProps;
    257    p->Init = BraState_Init;
    258    p->Code2 = BraState_Code2;
    259    p->Filter = BraState_Filter;
    260  }
    261  decoder->methodId = (UInt32)id;
    262  decoder->encodeMode = encodeMode;
    263  return SZ_OK;
    264 }
    265 
    266 
    267 
    268 /* ---------- SbState ---------- */
    269 
    270 #ifdef USE_SUBBLOCK
    271 
    272 static void SbState_Free(void *pp, ISzAllocPtr alloc)
    273 {
    274  CSbDec *p = (CSbDec *)pp;
    275  SbDec_Free(p);
    276  ISzAlloc_Free(alloc, pp);
    277 }
    278 
    279 static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
    280 {
    281  UNUSED_VAR(pp);
    282  UNUSED_VAR(props);
    283  UNUSED_VAR(alloc);
    284  return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
    285 }
    286 
    287 static void SbState_Init(void *pp)
    288 {
    289  SbDec_Init((CSbDec *)pp);
    290 }
    291 
    292 static SRes SbState_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    293    int srcWasFinished, ECoderFinishMode finishMode,
    294    // int *wasFinished
    295    ECoderStatus *status)
    296 {
    297  CSbDec *p = (CSbDec *)pp;
    298  SRes res;
    299  UNUSED_VAR(srcWasFinished);
    300  p->dest = dest;
    301  p->destLen = *destLen;
    302  p->src = src;
    303  p->srcLen = *srcLen;
    304  p->finish = finishMode; /* change it */
    305  res = SbDec_Decode((CSbDec *)pp);
    306  *destLen -= p->destLen;
    307  *srcLen -= p->srcLen;
    308  // *wasFinished = (*destLen == 0 && *srcLen == 0); /* change it */
    309  *status = (*destLen == 0 && *srcLen == 0) ?
    310      CODER_STATUS_FINISHED_WITH_MARK :
    311      CODER_STATUS_NOT_FINISHED;
    312  return res;
    313 }
    314 
    315 static SRes SbState_SetFromMethod(IStateCoder *p, ISzAllocPtr alloc)
    316 {
    317  CSbDec *decoder = (CSbDec *)p->p;
    318  if (!decoder)
    319  {
    320    decoder = (CSbDec *)ISzAlloc_Alloc(alloc, sizeof(CSbDec));
    321    if (!decoder)
    322      return SZ_ERROR_MEM;
    323    p->p = decoder;
    324    p->Free = SbState_Free;
    325    p->SetProps = SbState_SetProps;
    326    p->Init = SbState_Init;
    327    p->Code2 = SbState_Code2;
    328    p->Filter = NULL;
    329  }
    330  SbDec_Construct(decoder);
    331  SbDec_SetAlloc(decoder, alloc);
    332  return SZ_OK;
    333 }
    334 
    335 #endif
    336 
    337 
    338 
    339 /* ---------- Lzma2 ---------- */
    340 
    341 typedef struct
    342 {
    343  CLzma2Dec decoder;
    344  Bool outBufMode;
    345 } CLzma2Dec_Spec;
    346 
    347 
    348 static void Lzma2State_Free(void *pp, ISzAllocPtr alloc)
    349 {
    350  CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
    351  if (p->outBufMode)
    352    Lzma2Dec_FreeProbs(&p->decoder, alloc);
    353  else
    354    Lzma2Dec_Free(&p->decoder, alloc);
    355  ISzAlloc_Free(alloc, pp);
    356 }
    357 
    358 static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAllocPtr alloc)
    359 {
    360  if (propSize != 1)
    361    return SZ_ERROR_UNSUPPORTED;
    362  {
    363    CLzma2Dec_Spec *p = (CLzma2Dec_Spec *)pp;
    364    if (p->outBufMode)
    365      return Lzma2Dec_AllocateProbs(&p->decoder, props[0], alloc);
    366    else
    367      return Lzma2Dec_Allocate(&p->decoder, props[0], alloc);
    368  }
    369 }
    370 
    371 static void Lzma2State_Init(void *pp)
    372 {
    373  Lzma2Dec_Init(&((CLzma2Dec_Spec *)pp)->decoder);
    374 }
    375 
    376 
    377 /*
    378  if (outBufMode), then (dest) is not used. Use NULL.
    379         Data is unpacked to (spec->decoder.decoder.dic) output buffer.
    380 */
    381 
    382 static SRes Lzma2State_Code2(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
    383    int srcWasFinished, ECoderFinishMode finishMode,
    384    // int *wasFinished,
    385    ECoderStatus *status)
    386 {
    387  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)pp;
    388  ELzmaStatus status2;
    389  /* ELzmaFinishMode fm = (finishMode == LZMA_FINISH_ANY) ? LZMA_FINISH_ANY : LZMA_FINISH_END; */
    390  SRes res;
    391  UNUSED_VAR(srcWasFinished);
    392  if (spec->outBufMode)
    393  {
    394    SizeT dicPos = spec->decoder.decoder.dicPos;
    395    SizeT dicLimit = dicPos + *destLen;
    396    res = Lzma2Dec_DecodeToDic(&spec->decoder, dicLimit, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
    397    *destLen = spec->decoder.decoder.dicPos - dicPos;
    398  }
    399  else
    400    res = Lzma2Dec_DecodeToBuf(&spec->decoder, dest, destLen, src, srcLen, (ELzmaFinishMode)finishMode, &status2);
    401  // *wasFinished = (status2 == LZMA_STATUS_FINISHED_WITH_MARK);
    402  // ECoderStatus values are identical to ELzmaStatus values of LZMA2 decoder
    403  *status = status2;
    404  return res;
    405 }
    406 
    407 
    408 static SRes Lzma2State_SetFromMethod(IStateCoder *p, Byte *outBuf, size_t outBufSize, ISzAllocPtr alloc)
    409 {
    410  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
    411  if (!spec)
    412  {
    413    spec = (CLzma2Dec_Spec *)ISzAlloc_Alloc(alloc, sizeof(CLzma2Dec_Spec));
    414    if (!spec)
    415      return SZ_ERROR_MEM;
    416    p->p = spec;
    417    p->Free = Lzma2State_Free;
    418    p->SetProps = Lzma2State_SetProps;
    419    p->Init = Lzma2State_Init;
    420    p->Code2 = Lzma2State_Code2;
    421    p->Filter = NULL;
    422    Lzma2Dec_Construct(&spec->decoder);
    423  }
    424  spec->outBufMode = False;
    425  if (outBuf)
    426  {
    427    spec->outBufMode = True;
    428    spec->decoder.decoder.dic = outBuf;
    429    spec->decoder.decoder.dicBufSize = outBufSize;
    430  }
    431  return SZ_OK;
    432 }
    433 
    434 
    435 static SRes Lzma2State_ResetOutBuf(IStateCoder *p, Byte *outBuf, size_t outBufSize)
    436 {
    437  CLzma2Dec_Spec *spec = (CLzma2Dec_Spec *)p->p;
    438  if ((spec->outBufMode && !outBuf) || (!spec->outBufMode && outBuf))
    439    return SZ_ERROR_FAIL;
    440  if (outBuf)
    441  {
    442    spec->decoder.decoder.dic = outBuf;
    443    spec->decoder.decoder.dicBufSize = outBufSize;
    444  }
    445  return SZ_OK;
    446 }
    447 
    448 
    449 
    450 static void MixCoder_Construct(CMixCoder *p, ISzAllocPtr alloc)
    451 {
    452  unsigned i;
    453  p->alloc = alloc;
    454  p->buf = NULL;
    455  p->numCoders = 0;
    456  
    457  p->outBufSize = 0;
    458  p->outBuf = NULL;
    459  // p->SingleBufMode = False;
    460 
    461  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
    462    p->coders[i].p = NULL;
    463 }
    464 
    465 
    466 static void MixCoder_Free(CMixCoder *p)
    467 {
    468  unsigned i;
    469  p->numCoders = 0;
    470  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
    471  {
    472    IStateCoder *sc = &p->coders[i];
    473    if (sc->p)
    474    {
    475      sc->Free(sc->p, p->alloc);
    476      sc->p = NULL;
    477    }
    478  }
    479  if (p->buf)
    480  {
    481    ISzAlloc_Free(p->alloc, p->buf);
    482    p->buf = NULL; /* 9.31: the BUG was fixed */
    483  }
    484 }
    485 
    486 static void MixCoder_Init(CMixCoder *p)
    487 {
    488  unsigned i;
    489  for (i = 0; i < MIXCODER_NUM_FILTERS_MAX - 1; i++)
    490  {
    491    p->size[i] = 0;
    492    p->pos[i] = 0;
    493    p->finished[i] = 0;
    494  }
    495  for (i = 0; i < p->numCoders; i++)
    496  {
    497    IStateCoder *coder = &p->coders[i];
    498    coder->Init(coder->p);
    499    p->results[i] = SZ_OK;
    500  }
    501  p->outWritten = 0;
    502  p->wasFinished = False;
    503  p->res = SZ_OK;
    504  p->status = CODER_STATUS_NOT_SPECIFIED;
    505 }
    506 
    507 
    508 static SRes MixCoder_SetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
    509 {
    510  IStateCoder *sc = &p->coders[coderIndex];
    511  p->ids[coderIndex] = methodId;
    512  switch (methodId)
    513  {
    514    case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, outBuf, outBufSize, p->alloc);
    515    #ifdef USE_SUBBLOCK
    516    case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
    517    #endif
    518  }
    519  if (coderIndex == 0)
    520    return SZ_ERROR_UNSUPPORTED;
    521  return BraState_SetFromMethod(sc, methodId, 0, p->alloc);
    522 }
    523 
    524 
    525 static SRes MixCoder_ResetFromMethod(CMixCoder *p, unsigned coderIndex, UInt64 methodId, Byte *outBuf, size_t outBufSize)
    526 {
    527  IStateCoder *sc = &p->coders[coderIndex];
    528  switch (methodId)
    529  {
    530    case XZ_ID_LZMA2: return Lzma2State_ResetOutBuf(sc, outBuf, outBufSize);
    531  }
    532  return SZ_ERROR_UNSUPPORTED;
    533 }
    534 
    535 
    536 
    537 /*
    538 if (destFinish) - then unpack data block is finished at (*destLen) position,
    539                   and we can return data that were not processed by filter
    540 
    541 output (status) can be :
    542  CODER_STATUS_NOT_FINISHED
    543  CODER_STATUS_FINISHED_WITH_MARK
    544  CODER_STATUS_NEEDS_MORE_INPUT - not implemented still
    545 */
    546 
    547 static SRes MixCoder_Code(CMixCoder *p,
    548    Byte *dest, SizeT *destLen, int destFinish,
    549    const Byte *src, SizeT *srcLen, int srcWasFinished,
    550    ECoderFinishMode finishMode)
    551 {
    552  SizeT destLenOrig = *destLen;
    553  SizeT srcLenOrig = *srcLen;
    554 
    555  *destLen = 0;
    556  *srcLen = 0;
    557 
    558  if (p->wasFinished)
    559    return p->res;
    560  
    561  p->status = CODER_STATUS_NOT_FINISHED;
    562 
    563  // if (p->SingleBufMode)
    564  if (p->outBuf)
    565  {
    566    SRes res;
    567    SizeT destLen2, srcLen2;
    568    int wasFinished;
    569    
    570    PRF_STR("------- MixCoder Single ----------");
    571      
    572    srcLen2 = srcLenOrig;
    573    destLen2 = destLenOrig;
    574    
    575    {
    576      IStateCoder *coder = &p->coders[0];
    577      res = coder->Code2(coder->p, NULL, &destLen2, src, &srcLen2, srcWasFinished, finishMode,
    578          // &wasFinished,
    579          &p->status);
    580      wasFinished = (p->status == CODER_STATUS_FINISHED_WITH_MARK);
    581    }
    582    
    583    p->res = res;
    584    
    585    /*
    586    if (wasFinished)
    587      p->status = CODER_STATUS_FINISHED_WITH_MARK;
    588    else
    589    {
    590      if (res == SZ_OK)
    591        if (destLen2 != destLenOrig)
    592          p->status = CODER_STATUS_NEEDS_MORE_INPUT;
    593    }
    594    */
    595 
    596    
    597    *srcLen = srcLen2;
    598    src += srcLen2;
    599    p->outWritten += destLen2;
    600    
    601    if (res != SZ_OK || srcWasFinished || wasFinished)
    602      p->wasFinished = True;
    603    
    604    if (p->numCoders == 1)
    605      *destLen = destLen2;
    606    else if (p->wasFinished)
    607    {
    608      unsigned i;
    609      size_t processed = p->outWritten;
    610      
    611      for (i = 1; i < p->numCoders; i++)
    612      {
    613        IStateCoder *coder = &p->coders[i];
    614        processed = coder->Filter(coder->p, p->outBuf, processed);
    615        if (wasFinished || (destFinish && p->outWritten == destLenOrig))
    616          processed = p->outWritten;
    617        PRF_STR_INT("filter", i);
    618      }
    619      *destLen = processed;
    620    }
    621    return res;
    622  }
    623 
    624  PRF_STR("standard mix");
    625 
    626  if (p->numCoders != 1)
    627  {
    628    if (!p->buf)
    629    {
    630      p->buf = (Byte *)ISzAlloc_Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
    631      if (!p->buf)
    632        return SZ_ERROR_MEM;
    633    }
    634    
    635    finishMode = CODER_FINISH_ANY;
    636  }
    637 
    638  for (;;)
    639  {
    640    Bool processed = False;
    641    Bool allFinished = True;
    642    SRes resMain = SZ_OK;
    643    unsigned i;
    644 
    645    p->status = CODER_STATUS_NOT_FINISHED;
    646    /*
    647    if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
    648      break;
    649    */
    650 
    651    for (i = 0; i < p->numCoders; i++)
    652    {
    653      SRes res;
    654      IStateCoder *coder = &p->coders[i];
    655      Byte *dest2;
    656      SizeT destLen2, srcLen2; // destLen2_Orig;
    657      const Byte *src2;
    658      int srcFinished2;
    659      int encodingWasFinished;
    660      ECoderStatus status2;
    661      
    662      if (i == 0)
    663      {
    664        src2 = src;
    665        srcLen2 = srcLenOrig - *srcLen;
    666        srcFinished2 = srcWasFinished;
    667      }
    668      else
    669      {
    670        size_t k = i - 1;
    671        src2 = p->buf + (CODER_BUF_SIZE * k) + p->pos[k];
    672        srcLen2 = p->size[k] - p->pos[k];
    673        srcFinished2 = p->finished[k];
    674      }
    675      
    676      if (i == p->numCoders - 1)
    677      {
    678        dest2 = dest;
    679        destLen2 = destLenOrig - *destLen;
    680      }
    681      else
    682      {
    683        if (p->pos[i] != p->size[i])
    684          continue;
    685        dest2 = p->buf + (CODER_BUF_SIZE * i);
    686        destLen2 = CODER_BUF_SIZE;
    687      }
    688      
    689      // destLen2_Orig = destLen2;
    690      
    691      if (p->results[i] != SZ_OK)
    692      {
    693        if (resMain == SZ_OK)
    694          resMain = p->results[i];
    695        continue;
    696      }
    697 
    698      res = coder->Code2(coder->p,
    699          dest2, &destLen2,
    700          src2, &srcLen2, srcFinished2,
    701          finishMode,
    702          // &encodingWasFinished,
    703          &status2);
    704 
    705      if (res != SZ_OK)
    706      {
    707        p->results[i] = res;
    708        if (resMain == SZ_OK)
    709          resMain = res;
    710      }
    711 
    712      encodingWasFinished = (status2 == CODER_STATUS_FINISHED_WITH_MARK);
    713      
    714      if (!encodingWasFinished)
    715      {
    716        allFinished = False;
    717        if (p->numCoders == 1 && res == SZ_OK)
    718          p->status = status2;
    719      }
    720 
    721      if (i == 0)
    722      {
    723        *srcLen += srcLen2;
    724        src += srcLen2;
    725      }
    726      else
    727        p->pos[(size_t)i - 1] += srcLen2;
    728 
    729      if (i == p->numCoders - 1)
    730      {
    731        *destLen += destLen2;
    732        dest += destLen2;
    733      }
    734      else
    735      {
    736        p->size[i] = destLen2;
    737        p->pos[i] = 0;
    738        p->finished[i] = encodingWasFinished;
    739      }
    740      
    741      if (destLen2 != 0 || srcLen2 != 0)
    742        processed = True;
    743    }
    744    
    745    if (!processed)
    746    {
    747      if (allFinished)
    748        p->status = CODER_STATUS_FINISHED_WITH_MARK;
    749      return resMain;
    750    }
    751  }
    752 }
    753 
    754 
    755 SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
    756 {
    757  *p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
    758  if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
    759      GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
    760    return SZ_ERROR_NO_ARCHIVE;
    761  return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
    762 }
    763 
    764 static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
    765 {
    766  return indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2)
    767      && GetUi32(buf) == CrcCalc(buf + 4, 6)
    768      && flags == GetBe16(buf + 8)
    769      && buf[10] == XZ_FOOTER_SIG_0
    770      && buf[11] == XZ_FOOTER_SIG_1;
    771 }
    772 
    773 #define READ_VARINT_AND_CHECK(buf, pos, size, res) \
    774  { unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
    775  if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
    776 
    777 
    778 static Bool XzBlock_AreSupportedFilters(const CXzBlock *p)
    779 {
    780  unsigned numFilters = XzBlock_GetNumFilters(p) - 1;
    781  unsigned i;
    782  {
    783    const CXzFilter *f = &p->filters[numFilters];
    784    if (f->id != XZ_ID_LZMA2 || f->propsSize != 1 || f->props[0] > 40)
    785      return False;
    786  }
    787 
    788  for (i = 0; i < numFilters; i++)
    789  {
    790    const CXzFilter *f = &p->filters[i];
    791    if (f->id == XZ_ID_Delta)
    792    {
    793      if (f->propsSize != 1)
    794        return False;
    795    }
    796    else if (f->id < XZ_ID_Delta
    797        || f->id > XZ_ID_SPARC
    798        || (f->propsSize != 0 && f->propsSize != 4))
    799      return False;
    800  }
    801  return True;
    802 }
    803 
    804 
    805 SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
    806 {
    807  unsigned pos;
    808  unsigned numFilters, i;
    809  unsigned headerSize = (unsigned)header[0] << 2;
    810 
    811  /* (headerSize != 0) : another code checks */
    812 
    813  if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
    814    return SZ_ERROR_ARCHIVE;
    815 
    816  pos = 1;
    817  p->flags = header[pos++];
    818 
    819  p->packSize = (UInt64)(Int64)-1;
    820  if (XzBlock_HasPackSize(p))
    821  {
    822    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
    823    if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
    824      return SZ_ERROR_ARCHIVE;
    825  }
    826 
    827  p->unpackSize = (UInt64)(Int64)-1;
    828  if (XzBlock_HasUnpackSize(p))
    829    READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
    830 
    831  numFilters = XzBlock_GetNumFilters(p);
    832  for (i = 0; i < numFilters; i++)
    833  {
    834    CXzFilter *filter = p->filters + i;
    835    UInt64 size;
    836    READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
    837    READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
    838    if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
    839      return SZ_ERROR_ARCHIVE;
    840    filter->propsSize = (UInt32)size;
    841    memcpy(filter->props, header + pos, (size_t)size);
    842    pos += (unsigned)size;
    843 
    844    #ifdef XZ_DUMP
    845    printf("\nf[%u] = %2X: ", i, (unsigned)filter->id);
    846    {
    847      unsigned i;
    848      for (i = 0; i < size; i++)
    849        printf(" %2X", filter->props[i]);
    850    }
    851    #endif
    852  }
    853 
    854  if (XzBlock_HasUnsupportedFlags(p))
    855    return SZ_ERROR_UNSUPPORTED;
    856 
    857  while (pos < headerSize)
    858    if (header[pos++] != 0)
    859      return SZ_ERROR_ARCHIVE;
    860  return SZ_OK;
    861 }
    862 
    863 
    864 
    865 
    866 static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
    867 {
    868  unsigned i;
    869  Bool needReInit = True;
    870  unsigned numFilters = XzBlock_GetNumFilters(block);
    871 
    872  if (numFilters == p->numCoders && ((p->outBuf && outBuf) || (!p->outBuf && !outBuf)))
    873  {
    874    needReInit = False;
    875    for (i = 0; i < numFilters; i++)
    876      if (p->ids[i] != block->filters[numFilters - 1 - i].id)
    877      {
    878        needReInit = True;
    879        break;
    880      }
    881  }
    882 
    883  // p->SingleBufMode = (outBuf != NULL);
    884  p->outBuf = outBuf;
    885  p->outBufSize = outBufSize;
    886 
    887  // p->SingleBufMode = False;
    888  // outBuf = NULL;
    889  
    890  if (needReInit)
    891  {
    892    MixCoder_Free(p);
    893    for (i = 0; i < numFilters; i++)
    894    {
    895      RINOK(MixCoder_SetFromMethod(p, i, block->filters[numFilters - 1 - i].id, outBuf, outBufSize));
    896    }
    897    p->numCoders = numFilters;
    898  }
    899  else
    900  {
    901    RINOK(MixCoder_ResetFromMethod(p, 0, block->filters[numFilters - 1].id, outBuf, outBufSize));
    902  }
    903 
    904  for (i = 0; i < numFilters; i++)
    905  {
    906    const CXzFilter *f = &block->filters[numFilters - 1 - i];
    907    IStateCoder *sc = &p->coders[i];
    908    RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
    909  }
    910  
    911  MixCoder_Init(p);
    912  return SZ_OK;
    913 }
    914 
    915 
    916 
    917 void XzUnpacker_Init(CXzUnpacker *p)
    918 {
    919  p->state = XZ_STATE_STREAM_HEADER;
    920  p->pos = 0;
    921  p->numStartedStreams = 0;
    922  p->numFinishedStreams = 0;
    923  p->numTotalBlocks = 0;
    924  p->padSize = 0;
    925  p->decodeOnlyOneBlock = 0;
    926 
    927  p->parseMode = False;
    928  p->decodeToStreamSignature = False;
    929 
    930  // p->outBuf = NULL;
    931  // p->outBufSize = 0;
    932  p->outDataWritten = 0;
    933 }
    934 
    935 
    936 void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
    937 {
    938  p->outBuf = outBuf;
    939  p->outBufSize = outBufSize;
    940 }
    941 
    942 
    943 void XzUnpacker_Construct(CXzUnpacker *p, ISzAllocPtr alloc)
    944 {
    945  MixCoder_Construct(&p->decoder, alloc);
    946  p->outBuf = NULL;
    947  p->outBufSize = 0;
    948  XzUnpacker_Init(p);
    949 }
    950 
    951 
    952 void XzUnpacker_Free(CXzUnpacker *p)
    953 {
    954  MixCoder_Free(&p->decoder);
    955 }
    956 
    957 
    958 void XzUnpacker_PrepareToRandomBlockDecoding(CXzUnpacker *p)
    959 {
    960  p->indexSize = 0;
    961  p->numBlocks = 0;
    962  Sha256_Init(&p->sha);
    963  p->state = XZ_STATE_BLOCK_HEADER;
    964  p->pos = 0;
    965  p->decodeOnlyOneBlock = 1;
    966 }
    967 
    968 
    969 static void XzUnpacker_UpdateIndex(CXzUnpacker *p, UInt64 packSize, UInt64 unpackSize)
    970 {
    971  Byte temp[32];
    972  unsigned num = Xz_WriteVarInt(temp, packSize);
    973  num += Xz_WriteVarInt(temp + num, unpackSize);
    974  Sha256_Update(&p->sha, temp, num);
    975  p->indexSize += num;
    976  p->numBlocks++;
    977 }
    978 
    979 
    980 
    981 SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
    982    const Byte *src, SizeT *srcLen, int srcFinished,
    983    ECoderFinishMode finishMode, ECoderStatus *status)
    984 {
    985  SizeT destLenOrig = *destLen;
    986  SizeT srcLenOrig = *srcLen;
    987  *destLen = 0;
    988  *srcLen = 0;
    989  *status = CODER_STATUS_NOT_SPECIFIED;
    990 
    991  for (;;)
    992  {
    993    SizeT srcRem;
    994 
    995    if (p->state == XZ_STATE_BLOCK)
    996    {
    997      SizeT destLen2 = destLenOrig - *destLen;
    998      SizeT srcLen2 = srcLenOrig - *srcLen;
    999      SRes res;
   1000 
   1001      ECoderFinishMode finishMode2 = finishMode;
   1002      Bool srcFinished2 = srcFinished;
   1003      Bool destFinish = False;
   1004 
   1005      if (p->block.packSize != (UInt64)(Int64)-1)
   1006      {
   1007        UInt64 rem = p->block.packSize - p->packSize;
   1008        if (srcLen2 >= rem)
   1009        {
   1010          srcFinished2 = True;
   1011          srcLen2 = (SizeT)rem;
   1012        }
   1013        if (rem == 0 && p->block.unpackSize == p->unpackSize)
   1014          return SZ_ERROR_DATA;
   1015      }
   1016 
   1017      if (p->block.unpackSize != (UInt64)(Int64)-1)
   1018      {
   1019        UInt64 rem = p->block.unpackSize - p->unpackSize;
   1020        if (destLen2 >= rem)
   1021        {
   1022          destFinish = True;
   1023          finishMode2 = CODER_FINISH_END;
   1024          destLen2 = (SizeT)rem;
   1025        }
   1026      }
   1027 
   1028      /*
   1029      if (srcLen2 == 0 && destLen2 == 0)
   1030      {
   1031        *status = CODER_STATUS_NOT_FINISHED;
   1032        return SZ_OK;
   1033      }
   1034      */
   1035      
   1036      {
   1037        res = MixCoder_Code(&p->decoder,
   1038            (p->outBuf ? NULL : dest), &destLen2, destFinish,
   1039            src, &srcLen2, srcFinished2,
   1040            finishMode2);
   1041        
   1042        *status = p->decoder.status;
   1043        XzCheck_Update(&p->check, (p->outBuf ? p->outBuf + p->outDataWritten : dest), destLen2);
   1044        if (!p->outBuf)
   1045          dest += destLen2;
   1046        p->outDataWritten += destLen2;
   1047      }
   1048      
   1049      (*srcLen) += srcLen2;
   1050      src += srcLen2;
   1051      p->packSize += srcLen2;
   1052      (*destLen) += destLen2;
   1053      p->unpackSize += destLen2;
   1054 
   1055      RINOK(res);
   1056 
   1057      if (*status != CODER_STATUS_FINISHED_WITH_MARK)
   1058      {
   1059        if (p->block.packSize == p->packSize
   1060            && *status == CODER_STATUS_NEEDS_MORE_INPUT)
   1061        {
   1062          PRF_STR("CODER_STATUS_NEEDS_MORE_INPUT");
   1063          *status = CODER_STATUS_NOT_SPECIFIED;
   1064          return SZ_ERROR_DATA;
   1065        }
   1066        
   1067        return SZ_OK;
   1068      }
   1069      {
   1070        XzUnpacker_UpdateIndex(p, XzUnpacker_GetPackSizeForIndex(p), p->unpackSize);
   1071        p->state = XZ_STATE_BLOCK_FOOTER;
   1072        p->pos = 0;
   1073        p->alignPos = 0;
   1074        *status = CODER_STATUS_NOT_SPECIFIED;
   1075 
   1076        if ((p->block.packSize != (UInt64)(Int64)-1 && p->block.packSize != p->packSize)
   1077           || (p->block.unpackSize != (UInt64)(Int64)-1 && p->block.unpackSize != p->unpackSize))
   1078        {
   1079          PRF_STR("ERROR: block.size mismatch");
   1080          return SZ_ERROR_DATA;
   1081        }
   1082      }
   1083      // continue;
   1084    }
   1085 
   1086    srcRem = srcLenOrig - *srcLen;
   1087 
   1088    // XZ_STATE_BLOCK_FOOTER can transit to XZ_STATE_BLOCK_HEADER without input bytes
   1089    if (srcRem == 0 && p->state != XZ_STATE_BLOCK_FOOTER)
   1090    {
   1091      *status = CODER_STATUS_NEEDS_MORE_INPUT;
   1092      return SZ_OK;
   1093    }
   1094 
   1095    switch (p->state)
   1096    {
   1097      case XZ_STATE_STREAM_HEADER:
   1098      {
   1099        if (p->pos < XZ_STREAM_HEADER_SIZE)
   1100        {
   1101          if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
   1102            return SZ_ERROR_NO_ARCHIVE;
   1103          if (p->decodeToStreamSignature)
   1104            return SZ_OK;
   1105          p->buf[p->pos++] = *src++;
   1106          (*srcLen)++;
   1107        }
   1108        else
   1109        {
   1110          RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
   1111          p->numStartedStreams++;
   1112          p->indexSize = 0;
   1113          p->numBlocks = 0;
   1114          Sha256_Init(&p->sha);
   1115          p->state = XZ_STATE_BLOCK_HEADER;
   1116          p->pos = 0;
   1117        }
   1118        break;
   1119      }
   1120 
   1121      case XZ_STATE_BLOCK_HEADER:
   1122      {
   1123        if (p->pos == 0)
   1124        {
   1125          p->buf[p->pos++] = *src++;
   1126          (*srcLen)++;
   1127          if (p->buf[0] == 0)
   1128          {
   1129            if (p->decodeOnlyOneBlock)
   1130              return SZ_ERROR_DATA;
   1131            p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
   1132            p->indexPos = p->indexPreSize;
   1133            p->indexSize += p->indexPreSize;
   1134            Sha256_Final(&p->sha, p->shaDigest);
   1135            Sha256_Init(&p->sha);
   1136            p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
   1137            p->state = XZ_STATE_STREAM_INDEX;
   1138            break;
   1139          }
   1140          p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
   1141          break;
   1142        }
   1143        
   1144        if (p->pos != p->blockHeaderSize)
   1145        {
   1146          UInt32 cur = p->blockHeaderSize - p->pos;
   1147          if (cur > srcRem)
   1148            cur = (UInt32)srcRem;
   1149          memcpy(p->buf + p->pos, src, cur);
   1150          p->pos += cur;
   1151          (*srcLen) += cur;
   1152          src += cur;
   1153        }
   1154        else
   1155        {
   1156          RINOK(XzBlock_Parse(&p->block, p->buf));
   1157          if (!XzBlock_AreSupportedFilters(&p->block))
   1158            return SZ_ERROR_UNSUPPORTED;
   1159          p->numTotalBlocks++;
   1160          p->state = XZ_STATE_BLOCK;
   1161          p->packSize = 0;
   1162          p->unpackSize = 0;
   1163          XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
   1164          if (p->parseMode)
   1165          {
   1166            p->headerParsedOk = True;
   1167            return SZ_OK;
   1168          }
   1169          RINOK(XzDecMix_Init(&p->decoder, &p->block, p->outBuf, p->outBufSize));
   1170        }
   1171        break;
   1172      }
   1173 
   1174      case XZ_STATE_BLOCK_FOOTER:
   1175      {
   1176        if ((((unsigned)p->packSize + p->alignPos) & 3) != 0)
   1177        {
   1178          if (srcRem == 0)
   1179          {
   1180            *status = CODER_STATUS_NEEDS_MORE_INPUT;
   1181            return SZ_OK;
   1182          }
   1183          (*srcLen)++;
   1184          p->alignPos++;
   1185          if (*src++ != 0)
   1186            return SZ_ERROR_CRC;
   1187        }
   1188        else
   1189        {
   1190          UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
   1191          UInt32 cur = checkSize - p->pos;
   1192          if (cur != 0)
   1193          {
   1194            if (srcRem == 0)
   1195            {
   1196              *status = CODER_STATUS_NEEDS_MORE_INPUT;
   1197              return SZ_OK;
   1198            }
   1199            if (cur > srcRem)
   1200              cur = (UInt32)srcRem;
   1201            memcpy(p->buf + p->pos, src, cur);
   1202            p->pos += cur;
   1203            (*srcLen) += cur;
   1204            src += cur;
   1205            if (checkSize != p->pos)
   1206              break;
   1207          }
   1208          {
   1209            Byte digest[XZ_CHECK_SIZE_MAX];
   1210            p->state = XZ_STATE_BLOCK_HEADER;
   1211            p->pos = 0;
   1212            if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
   1213              return SZ_ERROR_CRC;
   1214            if (p->decodeOnlyOneBlock)
   1215            {
   1216              *status = CODER_STATUS_FINISHED_WITH_MARK;
   1217              return SZ_OK;
   1218            }
   1219          }
   1220        }
   1221        break;
   1222      }
   1223 
   1224      case XZ_STATE_STREAM_INDEX:
   1225      {
   1226        if (p->pos < p->indexPreSize)
   1227        {
   1228          (*srcLen)++;
   1229          if (*src++ != p->buf[p->pos++])
   1230            return SZ_ERROR_CRC;
   1231        }
   1232        else
   1233        {
   1234          if (p->indexPos < p->indexSize)
   1235          {
   1236            UInt64 cur = p->indexSize - p->indexPos;
   1237            if (srcRem > cur)
   1238              srcRem = (SizeT)cur;
   1239            p->crc = CrcUpdate(p->crc, src, srcRem);
   1240            Sha256_Update(&p->sha, src, srcRem);
   1241            (*srcLen) += srcRem;
   1242            src += srcRem;
   1243            p->indexPos += srcRem;
   1244          }
   1245          else if ((p->indexPos & 3) != 0)
   1246          {
   1247            Byte b = *src++;
   1248            p->crc = CRC_UPDATE_BYTE(p->crc, b);
   1249            (*srcLen)++;
   1250            p->indexPos++;
   1251            p->indexSize++;
   1252            if (b != 0)
   1253              return SZ_ERROR_CRC;
   1254          }
   1255          else
   1256          {
   1257            Byte digest[SHA256_DIGEST_SIZE];
   1258            p->state = XZ_STATE_STREAM_INDEX_CRC;
   1259            p->indexSize += 4;
   1260            p->pos = 0;
   1261            Sha256_Final(&p->sha, digest);
   1262            if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
   1263              return SZ_ERROR_CRC;
   1264          }
   1265        }
   1266        break;
   1267      }
   1268 
   1269      case XZ_STATE_STREAM_INDEX_CRC:
   1270      {
   1271        if (p->pos < 4)
   1272        {
   1273          (*srcLen)++;
   1274          p->buf[p->pos++] = *src++;
   1275        }
   1276        else
   1277        {
   1278          p->state = XZ_STATE_STREAM_FOOTER;
   1279          p->pos = 0;
   1280          if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
   1281            return SZ_ERROR_CRC;
   1282        }
   1283        break;
   1284      }
   1285 
   1286      case XZ_STATE_STREAM_FOOTER:
   1287      {
   1288        UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
   1289        if (cur > srcRem)
   1290          cur = (UInt32)srcRem;
   1291        memcpy(p->buf + p->pos, src, cur);
   1292        p->pos += cur;
   1293        (*srcLen) += cur;
   1294        src += cur;
   1295        if (p->pos == XZ_STREAM_FOOTER_SIZE)
   1296        {
   1297          p->state = XZ_STATE_STREAM_PADDING;
   1298          p->numFinishedStreams++;
   1299          p->padSize = 0;
   1300          if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
   1301            return SZ_ERROR_CRC;
   1302        }
   1303        break;
   1304      }
   1305 
   1306      case XZ_STATE_STREAM_PADDING:
   1307      {
   1308        if (*src != 0)
   1309        {
   1310          if (((UInt32)p->padSize & 3) != 0)
   1311            return SZ_ERROR_NO_ARCHIVE;
   1312          p->pos = 0;
   1313          p->state = XZ_STATE_STREAM_HEADER;
   1314        }
   1315        else
   1316        {
   1317          (*srcLen)++;
   1318          src++;
   1319          p->padSize++;
   1320        }
   1321        break;
   1322      }
   1323      
   1324      case XZ_STATE_BLOCK: break; /* to disable GCC warning */
   1325    }
   1326  }
   1327  /*
   1328  if (p->state == XZ_STATE_FINISHED)
   1329    *status = CODER_STATUS_FINISHED_WITH_MARK;
   1330  return SZ_OK;
   1331  */
   1332 }
   1333 
   1334 
   1335 SRes XzUnpacker_CodeFull(CXzUnpacker *p, Byte *dest, SizeT *destLen,
   1336    const Byte *src, SizeT *srcLen,
   1337    ECoderFinishMode finishMode, ECoderStatus *status)
   1338 {
   1339  XzUnpacker_Init(p);
   1340  XzUnpacker_SetOutBuf(p, dest, *destLen);
   1341 
   1342  return XzUnpacker_Code(p,
   1343      NULL, destLen,
   1344      src, srcLen, True,
   1345      finishMode, status);
   1346 }
   1347 
   1348 
   1349 Bool XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
   1350 {
   1351  return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
   1352 }
   1353 
   1354 Bool XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
   1355 {
   1356  return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
   1357 }
   1358 
   1359 UInt64 XzUnpacker_GetExtraSize(const CXzUnpacker *p)
   1360 {
   1361  UInt64 num = 0;
   1362  if (p->state == XZ_STATE_STREAM_PADDING)
   1363    num = p->padSize;
   1364  else if (p->state == XZ_STATE_STREAM_HEADER)
   1365    num = p->padSize + p->pos;
   1366  return num;
   1367 }
   1368 
   1369 
   1370 
   1371 
   1372 
   1373 
   1374 
   1375 
   1376 
   1377 
   1378 
   1379 
   1380 
   1381 
   1382 
   1383 
   1384 
   1385 
   1386 
   1387 
   1388 
   1389 #ifndef _7ZIP_ST
   1390 #include "MtDec.h"
   1391 #endif
   1392 
   1393 
   1394 void XzDecMtProps_Init(CXzDecMtProps *p)
   1395 {
   1396  p->inBufSize_ST = 1 << 18;
   1397  p->outStep_ST = 1 << 20;
   1398  p->ignoreErrors = False;
   1399 
   1400  #ifndef _7ZIP_ST
   1401  p->numThreads = 1;
   1402  p->inBufSize_MT = 1 << 18;
   1403  p->memUseMax = sizeof(size_t) << 28;
   1404  #endif
   1405 }
   1406 
   1407 
   1408 
   1409 #ifndef _7ZIP_ST
   1410 
   1411 /* ---------- CXzDecMtThread ---------- */
   1412 
   1413 typedef struct
   1414 {
   1415  Byte *outBuf;
   1416  size_t outBufSize;
   1417  size_t outPreSize;
   1418  size_t inPreSize;
   1419  size_t inPreHeaderSize;
   1420  size_t blockPackSize_for_Index;  // including block header and checksum.
   1421  size_t blockPackTotal;  // including stream header, block header and checksum.
   1422  size_t inCodeSize;
   1423  size_t outCodeSize;
   1424  ECoderStatus status;
   1425  SRes codeRes;
   1426  Bool skipMode;
   1427  // Bool finishedWithMark;
   1428  EMtDecParseState parseState;
   1429  Bool parsing_Truncated;
   1430  Bool atBlockHeader;
   1431  CXzStreamFlags streamFlags;
   1432  // UInt64 numFinishedStreams
   1433  UInt64 numStreams;
   1434  UInt64 numTotalBlocks;
   1435  UInt64 numBlocks;
   1436 
   1437  Bool dec_created;
   1438  CXzUnpacker dec;
   1439 
   1440  Byte mtPad[1 << 7];
   1441 } CXzDecMtThread;
   1442 
   1443 #endif
   1444 
   1445 
   1446 /* ---------- CXzDecMt ---------- */
   1447 
   1448 typedef struct
   1449 {
   1450  CAlignOffsetAlloc alignOffsetAlloc;
   1451  ISzAllocPtr allocMid;
   1452 
   1453  CXzDecMtProps props;
   1454  size_t unpackBlockMaxSize;
   1455  
   1456  ISeqInStream *inStream;
   1457  ISeqOutStream *outStream;
   1458  ICompressProgress *progress;
   1459  // CXzStatInfo *stat;
   1460 
   1461  Bool finishMode;
   1462  Bool outSize_Defined;
   1463  UInt64 outSize;
   1464 
   1465  UInt64 outProcessed;
   1466  UInt64 inProcessed;
   1467  UInt64 readProcessed;
   1468  Bool readWasFinished;
   1469  SRes readRes;
   1470  SRes writeRes;
   1471 
   1472  Byte *outBuf;
   1473  size_t outBufSize;
   1474  Byte *inBuf;
   1475  size_t inBufSize;
   1476  Bool dec_created;
   1477  CXzUnpacker dec;
   1478 
   1479  ECoderStatus status;
   1480  SRes codeRes;
   1481 
   1482  #ifndef _7ZIP_ST
   1483  Bool mainDecoderWasCalled;
   1484  // int statErrorDefined;
   1485  int finishedDecoderIndex;
   1486 
   1487  // global values that are used in Parse stage
   1488  CXzStreamFlags streamFlags;
   1489  // UInt64 numFinishedStreams
   1490  UInt64 numStreams;
   1491  UInt64 numTotalBlocks;
   1492  UInt64 numBlocks;
   1493 
   1494  // UInt64 numBadBlocks;
   1495  SRes mainErrorCode;
   1496 
   1497  Bool isBlockHeaderState_Parse;
   1498  Bool isBlockHeaderState_Write;
   1499  UInt64 outProcessed_Parse;
   1500  Bool parsing_Truncated;
   1501 
   1502  Bool mtc_WasConstructed;
   1503  CMtDec mtc;
   1504  CXzDecMtThread coders[MTDEC__THREADS_MAX];
   1505  #endif
   1506 
   1507 } CXzDecMt;
   1508 
   1509 
   1510 
   1511 CXzDecMtHandle XzDecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
   1512 {
   1513  CXzDecMt *p = (CXzDecMt *)ISzAlloc_Alloc(alloc, sizeof(CXzDecMt));
   1514  if (!p)
   1515    return NULL;
   1516  
   1517  AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
   1518  p->alignOffsetAlloc.baseAlloc = alloc;
   1519  p->alignOffsetAlloc.numAlignBits = 7;
   1520  p->alignOffsetAlloc.offset = 0;
   1521 
   1522  p->allocMid = allocMid;
   1523 
   1524  p->outBuf = NULL;
   1525  p->outBufSize = 0;
   1526  p->inBuf = NULL;
   1527  p->inBufSize = 0;
   1528  p->dec_created = False;
   1529 
   1530  p->unpackBlockMaxSize = 0;
   1531 
   1532  XzDecMtProps_Init(&p->props);
   1533 
   1534  #ifndef _7ZIP_ST
   1535  p->mtc_WasConstructed = False;
   1536  {
   1537    unsigned i;
   1538    for (i = 0; i < MTDEC__THREADS_MAX; i++)
   1539    {
   1540      CXzDecMtThread *coder = &p->coders[i];
   1541      coder->dec_created = False;
   1542      coder->outBuf = NULL;
   1543      coder->outBufSize = 0;
   1544    }
   1545  }
   1546  #endif
   1547 
   1548  return p;
   1549 }
   1550 
   1551 
   1552 #ifndef _7ZIP_ST
   1553 
   1554 static void XzDecMt_FreeOutBufs(CXzDecMt *p)
   1555 {
   1556  unsigned i;
   1557  for (i = 0; i < MTDEC__THREADS_MAX; i++)
   1558  {
   1559    CXzDecMtThread *coder = &p->coders[i];
   1560    if (coder->outBuf)
   1561    {
   1562      ISzAlloc_Free(p->allocMid, coder->outBuf);
   1563      coder->outBuf = NULL;
   1564      coder->outBufSize = 0;
   1565    }
   1566  }
   1567  p->unpackBlockMaxSize = 0;
   1568 }
   1569 
   1570 #endif
   1571 
   1572 
   1573 
   1574 static void XzDecMt_FreeSt(CXzDecMt *p)
   1575 {
   1576  if (p->dec_created)
   1577  {
   1578    XzUnpacker_Free(&p->dec);
   1579    p->dec_created = False;
   1580  }
   1581  
   1582  if (p->outBuf)
   1583  {
   1584    ISzAlloc_Free(p->allocMid, p->outBuf);
   1585    p->outBuf = NULL;
   1586  }
   1587  p->outBufSize = 0;
   1588  
   1589  if (p->inBuf)
   1590  {
   1591    ISzAlloc_Free(p->allocMid, p->inBuf);
   1592    p->inBuf = NULL;
   1593  }
   1594  p->inBufSize = 0;
   1595 }
   1596 
   1597 
   1598 void XzDecMt_Destroy(CXzDecMtHandle pp)
   1599 {
   1600  CXzDecMt *p = (CXzDecMt *)pp;
   1601 
   1602  XzDecMt_FreeSt(p);
   1603 
   1604  #ifndef _7ZIP_ST
   1605 
   1606  if (p->mtc_WasConstructed)
   1607  {
   1608    MtDec_Destruct(&p->mtc);
   1609    p->mtc_WasConstructed = False;
   1610  }
   1611  {
   1612    unsigned i;
   1613    for (i = 0; i < MTDEC__THREADS_MAX; i++)
   1614    {
   1615      CXzDecMtThread *t = &p->coders[i];
   1616      if (t->dec_created)
   1617      {
   1618        // we don't need to free dict here
   1619        XzUnpacker_Free(&t->dec);
   1620        t->dec_created = False;
   1621      }
   1622    }
   1623  }
   1624  XzDecMt_FreeOutBufs(p);
   1625 
   1626  #endif
   1627 
   1628  ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
   1629 }
   1630 
   1631 
   1632 
   1633 #ifndef _7ZIP_ST
   1634 
   1635 static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
   1636 {
   1637  CXzDecMt *me = (CXzDecMt *)obj;
   1638  CXzDecMtThread *coder = &me->coders[coderIndex];
   1639  size_t srcSize = cc->srcSize;
   1640 
   1641  cc->srcSize = 0;
   1642  cc->outPos = 0;
   1643  cc->state = MTDEC_PARSE_CONTINUE;
   1644 
   1645  cc->canCreateNewThread = True;
   1646 
   1647  if (cc->startCall)
   1648  {
   1649    coder->outPreSize = 0;
   1650    coder->inPreSize = 0;
   1651    coder->inPreHeaderSize = 0;
   1652    coder->parseState = MTDEC_PARSE_CONTINUE;
   1653    coder->parsing_Truncated = False;
   1654    coder->skipMode = False;
   1655    coder->codeRes = SZ_OK;
   1656    coder->status = CODER_STATUS_NOT_SPECIFIED;
   1657    coder->inCodeSize = 0;
   1658    coder->outCodeSize = 0;
   1659 
   1660    coder->numStreams = me->numStreams;
   1661    coder->numTotalBlocks = me->numTotalBlocks;
   1662    coder->numBlocks = me->numBlocks;
   1663 
   1664    if (!coder->dec_created)
   1665    {
   1666      XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
   1667      coder->dec_created = True;
   1668    }
   1669    
   1670    XzUnpacker_Init(&coder->dec);
   1671 
   1672    if (me->isBlockHeaderState_Parse)
   1673    {
   1674      coder->dec.streamFlags = me->streamFlags;
   1675      coder->atBlockHeader = True;
   1676      XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
   1677    }
   1678    else
   1679    {
   1680      coder->atBlockHeader = False;
   1681      me->isBlockHeaderState_Parse = True;
   1682    }
   1683 
   1684    coder->dec.numStartedStreams = me->numStreams;
   1685    coder->dec.numTotalBlocks = me->numTotalBlocks;
   1686    coder->dec.numBlocks = me->numBlocks;
   1687  }
   1688 
   1689  while (!coder->skipMode)
   1690  {
   1691    ECoderStatus status;
   1692    SRes res;
   1693    size_t srcSize2 = srcSize;
   1694    size_t destSize = (size_t)0 - 1;
   1695 
   1696    coder->dec.parseMode = True;
   1697    coder->dec.headerParsedOk = False;
   1698    
   1699    PRF_STR_INT("Parse", srcSize2);
   1700    
   1701    res = XzUnpacker_Code(&coder->dec,
   1702        NULL, &destSize,
   1703        cc->src, &srcSize2, cc->srcFinished,
   1704        CODER_FINISH_END, &status);
   1705    
   1706    // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
   1707    
   1708    coder->codeRes = res;
   1709    coder->status = status;
   1710    cc->srcSize += srcSize2;
   1711    srcSize -= srcSize2;
   1712    coder->inPreHeaderSize += srcSize2;
   1713    coder->inPreSize = coder->inPreHeaderSize;
   1714    
   1715    if (res != SZ_OK)
   1716    {
   1717      cc->state =
   1718      coder->parseState = MTDEC_PARSE_END;
   1719      /*
   1720      if (res == SZ_ERROR_MEM)
   1721        return res;
   1722      return SZ_OK;
   1723      */
   1724      return; // res;
   1725    }
   1726    
   1727    if (coder->dec.headerParsedOk)
   1728    {
   1729      const CXzBlock *block = &coder->dec.block;
   1730      if (XzBlock_HasUnpackSize(block)
   1731          // && block->unpackSize <= me->props.outBlockMax
   1732          && XzBlock_HasPackSize(block))
   1733      {
   1734        {
   1735          if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
   1736          {
   1737            cc->state = MTDEC_PARSE_OVERFLOW;
   1738            return; // SZ_OK;
   1739          }
   1740        }
   1741        {
   1742        UInt64 packSize = block->packSize;
   1743        UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
   1744        UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
   1745        UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
   1746        // if (blockPackSum <= me->props.inBlockMax)
   1747        // unpackBlockMaxSize
   1748        {
   1749          coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
   1750          coder->blockPackTotal = (size_t)blockPackSum;
   1751          coder->outPreSize = (size_t)block->unpackSize;
   1752          coder->streamFlags = coder->dec.streamFlags;
   1753          me->streamFlags = coder->dec.streamFlags;
   1754          coder->skipMode = True;
   1755          break;
   1756        }
   1757        }
   1758      }
   1759    }
   1760    else
   1761    // if (coder->inPreSize <= me->props.inBlockMax)
   1762    {
   1763      if (!cc->srcFinished)
   1764        return; // SZ_OK;
   1765      cc->state =
   1766      coder->parseState = MTDEC_PARSE_END;
   1767      return; // SZ_OK;
   1768    }
   1769    cc->state = MTDEC_PARSE_OVERFLOW;
   1770    return; // SZ_OK;
   1771  }
   1772 
   1773  // ---------- skipMode ----------
   1774  {
   1775    UInt64 rem = coder->blockPackTotal - coder->inPreSize;
   1776    size_t cur = srcSize;
   1777    if (cur > rem)
   1778      cur = (size_t)rem;
   1779    cc->srcSize += cur;
   1780    coder->inPreSize += cur;
   1781    srcSize -= cur;
   1782 
   1783    if (coder->inPreSize == coder->blockPackTotal)
   1784    {
   1785      if (srcSize == 0)
   1786      {
   1787        if (!cc->srcFinished)
   1788          return; // SZ_OK;
   1789        cc->state = MTDEC_PARSE_END;
   1790      }
   1791      else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
   1792        cc->state = MTDEC_PARSE_END;
   1793      else
   1794      {
   1795        cc->state = MTDEC_PARSE_NEW;
   1796 
   1797        {
   1798          size_t blockMax = me->unpackBlockMaxSize;
   1799          if (blockMax < coder->outPreSize)
   1800            blockMax = coder->outPreSize;
   1801          {
   1802            UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
   1803            if (me->props.memUseMax < required)
   1804              cc->canCreateNewThread = False;
   1805          }
   1806        }
   1807 
   1808        if (me->outSize_Defined)
   1809        {
   1810          // next block can be zero size
   1811          const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
   1812          if (rem2 < coder->outPreSize)
   1813          {
   1814            coder->parsing_Truncated = True;
   1815            cc->state = MTDEC_PARSE_END;
   1816          }
   1817          me->outProcessed_Parse += coder->outPreSize;
   1818        }
   1819      }
   1820    }
   1821    else if (cc->srcFinished)
   1822      cc->state = MTDEC_PARSE_END;
   1823    else
   1824      return; // SZ_OK;
   1825 
   1826    coder->parseState = cc->state;
   1827    cc->outPos = coder->outPreSize;
   1828    
   1829    me->numStreams = coder->dec.numStartedStreams;
   1830    me->numTotalBlocks = coder->dec.numTotalBlocks;
   1831    me->numBlocks = coder->dec.numBlocks + 1;
   1832    return; // SZ_OK;
   1833  }
   1834 }
   1835 
   1836 
   1837 static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
   1838 {
   1839  CXzDecMt *me = (CXzDecMt *)pp;
   1840  CXzDecMtThread *coder = &me->coders[coderIndex];
   1841  Byte *dest;
   1842 
   1843  if (!coder->dec.headerParsedOk)
   1844    return SZ_OK;
   1845 
   1846  dest = coder->outBuf;
   1847 
   1848  if (!dest || coder->outBufSize < coder->outPreSize)
   1849  {
   1850    if (dest)
   1851    {
   1852      ISzAlloc_Free(me->allocMid, dest);
   1853      coder->outBuf = NULL;
   1854      coder->outBufSize = 0;
   1855    }
   1856    {
   1857      size_t outPreSize = coder->outPreSize;
   1858      if (outPreSize == 0)
   1859        outPreSize = 1;
   1860      dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
   1861    }
   1862    if (!dest)
   1863      return SZ_ERROR_MEM;
   1864    coder->outBuf = dest;
   1865    coder->outBufSize = coder->outPreSize;
   1866 
   1867    if (coder->outBufSize > me->unpackBlockMaxSize)
   1868      me->unpackBlockMaxSize = coder->outBufSize;
   1869  }
   1870 
   1871  // return SZ_ERROR_MEM;
   1872 
   1873  XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
   1874 
   1875  {
   1876    SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
   1877    // res = SZ_ERROR_UNSUPPORTED; // to test
   1878    coder->codeRes = res;
   1879    if (res != SZ_OK)
   1880    {
   1881      // if (res == SZ_ERROR_MEM) return res;
   1882      if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
   1883        return S_OK;
   1884      return res;
   1885    }
   1886  }
   1887 
   1888  return SZ_OK;
   1889 }
   1890 
   1891 
   1892 static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
   1893    const Byte *src, size_t srcSize, int srcFinished,
   1894    // int finished, int blockFinished,
   1895    UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
   1896 {
   1897  CXzDecMt *me = (CXzDecMt *)pp;
   1898  CXzDecMtThread *coder = &me->coders[coderIndex];
   1899 
   1900  *inCodePos = coder->inCodeSize;
   1901  *outCodePos = coder->outCodeSize;
   1902  *stop = True;
   1903 
   1904  if (coder->inCodeSize < coder->inPreHeaderSize)
   1905  {
   1906    UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;
   1907    size_t step = srcSize;
   1908    if (step > rem)
   1909      step = (size_t)rem;
   1910    src += step;
   1911    srcSize -= step;
   1912    coder->inCodeSize += step;
   1913    if (coder->inCodeSize < coder->inPreHeaderSize)
   1914    {
   1915      *stop = False;
   1916      return SZ_OK;
   1917    }
   1918  }
   1919 
   1920  if (!coder->dec.headerParsedOk)
   1921    return SZ_OK;
   1922  if (!coder->outBuf)
   1923    return SZ_OK;
   1924 
   1925  if (coder->codeRes == SZ_OK)
   1926  {
   1927    ECoderStatus status;
   1928    SRes res;
   1929    size_t srcProcessed = srcSize;
   1930    size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
   1931 
   1932    // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
   1933 
   1934    res = XzUnpacker_Code(&coder->dec,
   1935        NULL, &outSizeCur,
   1936        src, &srcProcessed, srcFinished,
   1937        // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
   1938        CODER_FINISH_END,
   1939        &status);
   1940 
   1941    // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
   1942 
   1943    coder->codeRes = res;
   1944    coder->status = status;
   1945    coder->inCodeSize += srcProcessed;
   1946    coder->outCodeSize = coder->dec.outDataWritten;
   1947    *inCodePos = coder->inCodeSize;
   1948    *outCodePos = coder->outCodeSize;
   1949 
   1950    if (res == SZ_OK)
   1951    {
   1952      if (srcProcessed == srcSize)
   1953        *stop = False;
   1954      return SZ_OK;
   1955    }
   1956  }
   1957 
   1958  if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
   1959  {
   1960    *inCodePos = coder->inPreSize;
   1961    *outCodePos = coder->outPreSize;
   1962    return S_OK;
   1963  }
   1964  return coder->codeRes;
   1965 }
   1966 
   1967 
   1968 #define XZDECMT_STREAM_WRITE_STEP (1 << 24)
   1969 
   1970 static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
   1971    Bool needWriteToStream,
   1972    const Byte *src, size_t srcSize,
   1973    // int srcFinished,
   1974    Bool *needContinue,
   1975    Bool *canRecode)
   1976 {
   1977  CXzDecMt *me = (CXzDecMt *)pp;
   1978  const CXzDecMtThread *coder = &me->coders[coderIndex];
   1979 
   1980  // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
   1981  
   1982  *needContinue = False;
   1983  *canRecode = True;
   1984  
   1985  if (!needWriteToStream)
   1986    return SZ_OK;
   1987 
   1988  if (!coder->dec.headerParsedOk || !coder->outBuf)
   1989  {
   1990    if (me->finishedDecoderIndex < 0)
   1991      me->finishedDecoderIndex = coderIndex;
   1992    return SZ_OK;
   1993  }
   1994 
   1995  if (me->finishedDecoderIndex >= 0)
   1996    return SZ_OK;
   1997 
   1998  me->mtc.inProcessed += coder->inCodeSize;
   1999 
   2000  *canRecode = False;
   2001 
   2002  {
   2003    SRes res;
   2004    size_t size = coder->outCodeSize;
   2005    Byte *data = coder->outBuf;
   2006    
   2007    // we use in me->dec: sha, numBlocks, indexSize
   2008 
   2009    if (!me->isBlockHeaderState_Write)
   2010    {
   2011      XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
   2012      me->dec.decodeOnlyOneBlock = False;
   2013      me->dec.numStartedStreams = coder->dec.numStartedStreams;
   2014      me->dec.streamFlags = coder->streamFlags;
   2015 
   2016      me->isBlockHeaderState_Write = True;
   2017    }
   2018    
   2019    me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
   2020    XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
   2021    
   2022    if (coder->outPreSize != size)
   2023    {
   2024      if (me->props.ignoreErrors)
   2025      {
   2026        memset(data + size, 0, coder->outPreSize - size);
   2027        size = coder->outPreSize;
   2028      }
   2029      // me->numBadBlocks++;
   2030      if (me->mainErrorCode == SZ_OK)
   2031      {
   2032        if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
   2033          me->mainErrorCode = SZ_ERROR_INPUT_EOF;
   2034        else
   2035          me->mainErrorCode = SZ_ERROR_DATA;
   2036      }
   2037    }
   2038    
   2039    if (me->writeRes != SZ_OK)
   2040      return me->writeRes;
   2041 
   2042    res = SZ_OK;
   2043    {
   2044      if (me->outSize_Defined)
   2045      {
   2046        const UInt64 rem = me->outSize - me->outProcessed;
   2047        if (size > rem)
   2048          size = (SizeT)rem;
   2049      }
   2050 
   2051      for (;;)
   2052      {
   2053        size_t cur = size;
   2054        size_t written;
   2055        if (cur > XZDECMT_STREAM_WRITE_STEP)
   2056          cur = XZDECMT_STREAM_WRITE_STEP;
   2057 
   2058        written = ISeqOutStream_Write(me->outStream, data, cur);
   2059 
   2060        // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
   2061        
   2062        me->outProcessed += written;
   2063        if (written != cur)
   2064        {
   2065          me->writeRes = SZ_ERROR_WRITE;
   2066          res = me->writeRes;
   2067          break;
   2068        }
   2069        data += cur;
   2070        size -= cur;
   2071        // PRF_STR_INT("Written size =", size);
   2072        if (size == 0)
   2073          break;
   2074        res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
   2075        if (res != SZ_OK)
   2076          break;
   2077      }
   2078    }
   2079 
   2080    if (coder->codeRes != SZ_OK)
   2081      if (!me->props.ignoreErrors)
   2082      {
   2083        me->finishedDecoderIndex = coderIndex;
   2084        return res;
   2085      }
   2086 
   2087    RINOK(res);
   2088 
   2089    if (coder->inPreSize != coder->inCodeSize
   2090        || coder->blockPackTotal != coder->inCodeSize)
   2091    {
   2092      me->finishedDecoderIndex = coderIndex;
   2093      return SZ_OK;
   2094    }
   2095 
   2096    if (coder->parseState != MTDEC_PARSE_END)
   2097    {
   2098      *needContinue = True;
   2099      return SZ_OK;
   2100    }
   2101  }
   2102 
   2103  // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
   2104  // so we can use mtc variables without lock
   2105 
   2106  PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
   2107 
   2108  me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
   2109  {
   2110    CXzUnpacker *dec = &me->dec;
   2111    
   2112    PRF_STR_INT("PostSingle", srcSize);
   2113    
   2114    {
   2115      size_t srcProcessed = srcSize;
   2116      ECoderStatus status;
   2117      size_t outSizeCur = 0;
   2118      SRes res;
   2119      
   2120      // dec->decodeOnlyOneBlock = False;
   2121      dec->decodeToStreamSignature = True;
   2122 
   2123      me->mainDecoderWasCalled = True;
   2124 
   2125      if (coder->parsing_Truncated)
   2126      {
   2127        me->parsing_Truncated = True;
   2128        return SZ_OK;
   2129      }
   2130      
   2131      res = XzUnpacker_Code(dec,
   2132          NULL, &outSizeCur,
   2133          src, &srcProcessed,
   2134          me->mtc.readWasFinished, // srcFinished
   2135          CODER_FINISH_END, // CODER_FINISH_ANY,
   2136          &status);
   2137      
   2138      me->status = status;
   2139      me->codeRes = res;
   2140 
   2141      me->mtc.inProcessed += srcProcessed;
   2142      me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
   2143 
   2144      if (res != SZ_OK)
   2145      {
   2146        return S_OK;
   2147        // return res;
   2148      }
   2149      
   2150      if (dec->state == XZ_STATE_STREAM_HEADER)
   2151      {
   2152        *needContinue = True;
   2153        me->isBlockHeaderState_Parse = False;
   2154        me->isBlockHeaderState_Write = False;
   2155        {
   2156          Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
   2157          if (!crossBuf)
   2158            return SZ_ERROR_MEM;
   2159          memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);
   2160        }
   2161        me->mtc.crossStart = 0;
   2162        me->mtc.crossEnd = srcSize - srcProcessed;
   2163        return SZ_OK;
   2164      }
   2165      
   2166      if (status != CODER_STATUS_NEEDS_MORE_INPUT)
   2167      {
   2168        return E_FAIL;
   2169      }
   2170      
   2171      if (me->mtc.readWasFinished)
   2172      {
   2173        return SZ_OK;
   2174      }
   2175    }
   2176    
   2177    {
   2178      size_t inPos;
   2179      size_t inLim;
   2180      const Byte *inData;
   2181      UInt64 inProgressPrev = me->mtc.inProcessed;
   2182      
   2183      // XzDecMt_Prepare_InBuf_ST(p);
   2184      Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
   2185      if (!crossBuf)
   2186        return SZ_ERROR_MEM;
   2187      
   2188      inPos = 0;
   2189      inLim = 0;
   2190      // outProcessed = 0;
   2191      
   2192      inData = crossBuf;
   2193      
   2194      for (;;)
   2195      {
   2196        SizeT inProcessed;
   2197        SizeT outProcessed;
   2198        ECoderStatus status;
   2199        SRes res;
   2200        
   2201        if (inPos == inLim)
   2202        {
   2203          if (!me->mtc.readWasFinished)
   2204          {
   2205            inPos = 0;
   2206            inLim = me->mtc.inBufSize;
   2207            me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim);
   2208            me->mtc.readProcessed += inLim;
   2209            if (inLim == 0 || me->mtc.readRes != SZ_OK)
   2210              me->mtc.readWasFinished = True;
   2211          }
   2212        }
   2213        
   2214        inProcessed = inLim - inPos;
   2215        outProcessed = 0;
   2216 
   2217        res = XzUnpacker_Code(dec,
   2218            NULL, &outProcessed,
   2219            inData + inPos, &inProcessed,
   2220            (inProcessed == 0), // srcFinished
   2221            CODER_FINISH_END, &status);
   2222        
   2223        me->codeRes = res;
   2224        me->status = status;
   2225        inPos += inProcessed;
   2226        me->mtc.inProcessed += inProcessed;
   2227        me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
   2228 
   2229        if (res != SZ_OK)
   2230        {
   2231          return S_OK;
   2232          // return res;
   2233        }
   2234 
   2235        if (dec->state == XZ_STATE_STREAM_HEADER)
   2236        {
   2237          *needContinue = True;
   2238          me->mtc.crossStart = inPos;
   2239          me->mtc.crossEnd = inLim;
   2240          me->isBlockHeaderState_Parse = False;
   2241          me->isBlockHeaderState_Write = False;
   2242          return SZ_OK;
   2243        }
   2244        
   2245        if (status != CODER_STATUS_NEEDS_MORE_INPUT)
   2246          return E_FAIL;
   2247        
   2248        if (me->mtc.progress)
   2249        {
   2250          UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
   2251          if (inDelta >= (1 << 22))
   2252          {
   2253            RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
   2254            inProgressPrev = me->mtc.inProcessed;
   2255          }
   2256        }
   2257        if (me->mtc.readWasFinished)
   2258          return SZ_OK;
   2259      }
   2260    }
   2261  }
   2262 }
   2263 
   2264 
   2265 #endif
   2266 
   2267 
   2268 
   2269 void XzStatInfo_Clear(CXzStatInfo *p)
   2270 {
   2271  p->InSize = 0;
   2272  p->OutSize = 0;
   2273  
   2274  p->NumStreams = 0;
   2275  p->NumBlocks = 0;
   2276  
   2277  p->UnpackSize_Defined = False;
   2278  
   2279  p->NumStreams_Defined = False;
   2280  p->NumBlocks_Defined = False;
   2281  
   2282  // p->IsArc = False;
   2283  // p->UnexpectedEnd = False;
   2284  // p->Unsupported = False;
   2285  // p->HeadersError = False;
   2286  // p->DataError = False;
   2287  // p->CrcError = False;
   2288 
   2289  p->DataAfterEnd = False;
   2290  p->DecodingTruncated = False;
   2291  
   2292  p->DecodeRes = SZ_OK;
   2293  p->ReadRes = SZ_OK;
   2294  p->ProgressRes = SZ_OK;
   2295 
   2296  p->CombinedRes = SZ_OK;
   2297  p->CombinedRes_Type = SZ_OK;
   2298 }
   2299 
   2300 
   2301 
   2302 
   2303 static SRes XzDecMt_Decode_ST(CXzDecMt *p
   2304    #ifndef _7ZIP_ST
   2305    , Bool tMode
   2306    #endif
   2307    , CXzStatInfo *stat)
   2308 {
   2309  size_t outPos;
   2310  size_t inPos, inLim;
   2311  const Byte *inData;
   2312  UInt64 inPrev, outPrev;
   2313 
   2314  CXzUnpacker *dec;
   2315 
   2316  #ifndef _7ZIP_ST
   2317  if (tMode)
   2318  {
   2319    XzDecMt_FreeOutBufs(p);
   2320    tMode = MtDec_PrepareRead(&p->mtc);
   2321  }
   2322  #endif
   2323 
   2324  if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
   2325  {
   2326    ISzAlloc_Free(p->allocMid, p->outBuf);
   2327    p->outBufSize = 0;
   2328    p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
   2329    if (!p->outBuf)
   2330      return SZ_ERROR_MEM;
   2331    p->outBufSize = p->props.outStep_ST;
   2332  }
   2333 
   2334  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
   2335  {
   2336    ISzAlloc_Free(p->allocMid, p->inBuf);
   2337    p->inBufSize = 0;
   2338    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
   2339    if (!p->inBuf)
   2340      return SZ_ERROR_MEM;
   2341    p->inBufSize = p->props.inBufSize_ST;
   2342  }
   2343 
   2344  dec = &p->dec;
   2345  dec->decodeToStreamSignature = False;
   2346  // dec->decodeOnlyOneBlock = False;
   2347 
   2348  XzUnpacker_SetOutBuf(dec, NULL, 0);
   2349 
   2350  inPrev = p->inProcessed;
   2351  outPrev = p->outProcessed;
   2352 
   2353  inPos = 0;
   2354  inLim = 0;
   2355  inData = NULL;
   2356  outPos = 0;
   2357 
   2358  for (;;)
   2359  {
   2360    SizeT outSize;
   2361    Bool finished;
   2362    ECoderFinishMode finishMode;
   2363    SizeT inProcessed;
   2364    ECoderStatus status;
   2365    SRes res;
   2366 
   2367    SizeT outProcessed;
   2368 
   2369 
   2370 
   2371    if (inPos == inLim)
   2372    {
   2373      #ifndef _7ZIP_ST
   2374      if (tMode)
   2375      {
   2376        inData = MtDec_Read(&p->mtc, &inLim);
   2377        inPos = 0;
   2378        if (inData)
   2379          continue;
   2380        tMode = False;
   2381        inLim = 0;
   2382      }
   2383      #endif
   2384      
   2385      if (!p->readWasFinished)
   2386      {
   2387        inPos = 0;
   2388        inLim = p->inBufSize;
   2389        inData = p->inBuf;
   2390        p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
   2391        p->readProcessed += inLim;
   2392        if (inLim == 0 || p->readRes != SZ_OK)
   2393          p->readWasFinished = True;
   2394      }
   2395    }
   2396 
   2397    outSize = p->props.outStep_ST - outPos;
   2398 
   2399    finishMode = CODER_FINISH_ANY;
   2400    if (p->outSize_Defined)
   2401    {
   2402      const UInt64 rem = p->outSize - p->outProcessed;
   2403      if (outSize >= rem)
   2404      {
   2405        outSize = (SizeT)rem;
   2406        if (p->finishMode)
   2407          finishMode = CODER_FINISH_END;
   2408      }
   2409    }
   2410 
   2411    inProcessed = inLim - inPos;
   2412    outProcessed = outSize;
   2413 
   2414    res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
   2415        inData + inPos, &inProcessed,
   2416        (inPos == inLim), // srcFinished
   2417        finishMode, &status);
   2418 
   2419    p->codeRes = res;
   2420    p->status = status;
   2421 
   2422    inPos += inProcessed;
   2423    outPos += outProcessed;
   2424    p->inProcessed += inProcessed;
   2425    p->outProcessed += outProcessed;
   2426 
   2427    finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
   2428 
   2429    if (finished || outProcessed >= outSize)
   2430      if (outPos != 0)
   2431      {
   2432        size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
   2433        p->outProcessed += written;
   2434        if (written != outPos)
   2435        {
   2436          stat->CombinedRes_Type = SZ_ERROR_WRITE;
   2437          return SZ_ERROR_WRITE;
   2438        }
   2439        outPos = 0;
   2440      }
   2441 
   2442    if (p->progress && res == SZ_OK)
   2443    {
   2444      UInt64 inDelta = p->inProcessed - inPrev;
   2445      UInt64 outDelta = p->outProcessed - outPrev;
   2446      if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
   2447      {
   2448        res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
   2449        if (res != SZ_OK)
   2450        {
   2451          stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
   2452          stat->ProgressRes = res;
   2453          return res;
   2454        }
   2455        inPrev = p->inProcessed;
   2456        outPrev = p->outProcessed;
   2457      }
   2458    }
   2459 
   2460    if (finished)
   2461      return res;
   2462  }
   2463 }
   2464 
   2465 static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,
   2466    int finishMode,
   2467    UInt64 readProcessed, UInt64 inProcessed,
   2468    SRes res, ECoderStatus status,
   2469    Bool decodingTruncated,
   2470    CXzStatInfo *stat)
   2471 {
   2472  UInt64 extraSize;
   2473  
   2474  stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
   2475  stat->InSize = inProcessed;
   2476  stat->NumStreams = dec->numStartedStreams;
   2477  stat->NumBlocks = dec->numTotalBlocks;
   2478  
   2479  stat->UnpackSize_Defined = True;
   2480  stat->NumStreams_Defined = True;
   2481  stat->NumBlocks_Defined = True;
   2482  
   2483  extraSize = XzUnpacker_GetExtraSize(dec);
   2484  
   2485  if (res == SZ_OK)
   2486  {
   2487    if (status == CODER_STATUS_NEEDS_MORE_INPUT)
   2488    {
   2489      // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
   2490      extraSize = 0;
   2491      if (!XzUnpacker_IsStreamWasFinished(dec))
   2492        res = SZ_ERROR_INPUT_EOF;
   2493    }
   2494    else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
   2495      res = SZ_ERROR_DATA;
   2496  }
   2497  else if (res == SZ_ERROR_NO_ARCHIVE)
   2498  {
   2499    /*
   2500    SZ_ERROR_NO_ARCHIVE is possible for 2 states:
   2501      XZ_STATE_STREAM_HEADER  - if bad signature or bad CRC
   2502      XZ_STATE_STREAM_PADDING - if non-zero padding data
   2503    extraSize / inProcessed don't include "bad" byte
   2504    */
   2505    if (inProcessed != extraSize) // if good streams before error
   2506      if (extraSize != 0 || readProcessed != inProcessed)
   2507      {
   2508        stat->DataAfterEnd = True;
   2509        // there is some good xz stream before. So we set SZ_OK
   2510        res = SZ_OK;
   2511      }
   2512  }
   2513  
   2514  stat->DecodeRes = res;
   2515 
   2516  stat->InSize -= extraSize;
   2517  return res;
   2518 }
   2519 
   2520 
   2521 SRes XzDecMt_Decode(CXzDecMtHandle pp,
   2522    const CXzDecMtProps *props,
   2523    const UInt64 *outDataSize, int finishMode,
   2524    ISeqOutStream *outStream,
   2525    // Byte *outBuf, size_t *outBufSize,
   2526    ISeqInStream *inStream,
   2527    // const Byte *inData, size_t inDataSize,
   2528    CXzStatInfo *stat,
   2529    int *isMT,
   2530    ICompressProgress *progress)
   2531 {
   2532  CXzDecMt *p = (CXzDecMt *)pp;
   2533  #ifndef _7ZIP_ST
   2534  Bool tMode;
   2535  #endif
   2536 
   2537  XzStatInfo_Clear(stat);
   2538 
   2539  p->props = *props;
   2540 
   2541  p->inStream = inStream;
   2542  p->outStream = outStream;
   2543  p->progress = progress;
   2544  // p->stat = stat;
   2545 
   2546  p->outSize = 0;
   2547  p->outSize_Defined = False;
   2548  if (outDataSize)
   2549  {
   2550    p->outSize_Defined = True;
   2551    p->outSize = *outDataSize;
   2552  }
   2553 
   2554  p->finishMode = finishMode;
   2555 
   2556  // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
   2557 
   2558  p->writeRes = SZ_OK;
   2559  p->outProcessed = 0;
   2560  p->inProcessed = 0;
   2561  p->readProcessed = 0;
   2562  p->readWasFinished = False;
   2563 
   2564  p->codeRes = 0;
   2565  p->status = CODER_STATUS_NOT_SPECIFIED;
   2566 
   2567  if (!p->dec_created)
   2568  {
   2569    XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
   2570    p->dec_created = True;
   2571  }
   2572  XzUnpacker_Init(&p->dec);
   2573  
   2574 
   2575  *isMT = False;
   2576 
   2577    /*
   2578    p->outBuf = NULL;
   2579    p->outBufSize = 0;
   2580    if (!outStream)
   2581    {
   2582      p->outBuf = outBuf;
   2583      p->outBufSize = *outBufSize;
   2584      *outBufSize = 0;
   2585    }
   2586    */
   2587 
   2588  
   2589  #ifndef _7ZIP_ST
   2590 
   2591  p->isBlockHeaderState_Parse = False;
   2592  p->isBlockHeaderState_Write = False;
   2593  // p->numBadBlocks = 0;
   2594  p->mainErrorCode = SZ_OK;
   2595  p->mainDecoderWasCalled = False;
   2596 
   2597  tMode = False;
   2598 
   2599  if (p->props.numThreads > 1)
   2600  {
   2601    IMtDecCallback vt;
   2602 
   2603    XzDecMt_FreeSt(p);
   2604 
   2605    p->outProcessed_Parse = 0;
   2606    p->parsing_Truncated = False;
   2607 
   2608    p->numStreams = 0;
   2609    p->numTotalBlocks = 0;
   2610    p->numBlocks = 0;
   2611    p->finishedDecoderIndex = -1;
   2612 
   2613    if (!p->mtc_WasConstructed)
   2614    {
   2615      p->mtc_WasConstructed = True;
   2616      MtDec_Construct(&p->mtc);
   2617    }
   2618    
   2619    p->mtc.mtCallback = &vt;
   2620    p->mtc.mtCallbackObject = p;
   2621 
   2622    p->mtc.progress = progress;
   2623    p->mtc.inStream = inStream;
   2624    p->mtc.alloc = &p->alignOffsetAlloc.vt;
   2625    // p->mtc.inData = inData;
   2626    // p->mtc.inDataSize = inDataSize;
   2627    p->mtc.inBufSize = p->props.inBufSize_MT;
   2628    // p->mtc.inBlockMax = p->props.inBlockMax;
   2629    p->mtc.numThreadsMax = p->props.numThreads;
   2630 
   2631    *isMT = True;
   2632 
   2633    vt.Parse = XzDecMt_Callback_Parse;
   2634    vt.PreCode = XzDecMt_Callback_PreCode;
   2635    vt.Code = XzDecMt_Callback_Code;
   2636    vt.Write = XzDecMt_Callback_Write;
   2637 
   2638    {
   2639      Bool needContinue;
   2640      
   2641      SRes res = MtDec_Code(&p->mtc);
   2642 
   2643      stat->InSize = p->mtc.inProcessed;
   2644 
   2645      p->inProcessed = p->mtc.inProcessed;
   2646      p->readRes = p->mtc.readRes;
   2647      p->readWasFinished = p->mtc.readWasFinished;
   2648      p->readProcessed = p->mtc.readProcessed;
   2649 
   2650      tMode = True;
   2651      needContinue = False;
   2652 
   2653      if (res == SZ_OK)
   2654      {
   2655        if (p->mtc.mtProgress.res != SZ_OK)
   2656        {
   2657          res = p->mtc.mtProgress.res;
   2658          stat->ProgressRes = res;
   2659          stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
   2660        }
   2661        else
   2662          needContinue = p->mtc.needContinue;
   2663      }
   2664 
   2665      if (!needContinue)
   2666      {
   2667        SRes codeRes;
   2668        Bool truncated = False;
   2669        ECoderStatus status;
   2670        CXzUnpacker *dec;
   2671 
   2672        stat->OutSize = p->outProcessed;
   2673       
   2674        if (p->finishedDecoderIndex >= 0)
   2675        {
   2676          CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
   2677          codeRes = coder->codeRes;
   2678          dec = &coder->dec;
   2679          status = coder->status;
   2680        }
   2681        else if (p->mainDecoderWasCalled)
   2682        {
   2683          codeRes = p->codeRes;
   2684          dec = &p->dec;
   2685          status = p->status;
   2686          truncated = p->parsing_Truncated;
   2687        }
   2688        else
   2689          return E_FAIL;
   2690 
   2691        XzStatInfo_SetStat(dec, p->finishMode,
   2692            p->mtc.readProcessed, p->mtc.inProcessed,
   2693            codeRes, status,
   2694            truncated,
   2695            stat);
   2696 
   2697        if (res == SZ_OK)
   2698        {
   2699          if (p->writeRes != SZ_OK)
   2700          {
   2701            res = p->writeRes;
   2702            stat->CombinedRes_Type = SZ_ERROR_WRITE;
   2703          }
   2704          else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)
   2705          {
   2706            res = p->mtc.readRes;
   2707            stat->ReadRes = res;
   2708            stat->CombinedRes_Type = SZ_ERROR_READ;
   2709          }
   2710          else if (p->mainErrorCode != SZ_OK)
   2711          {
   2712            res = p->mainErrorCode;
   2713          }
   2714        }
   2715 
   2716        stat->CombinedRes = res;
   2717        if (stat->CombinedRes_Type == SZ_OK)
   2718          stat->CombinedRes_Type = res;
   2719        return res;
   2720      }
   2721 
   2722      PRF_STR("----- decoding ST -----");
   2723    }
   2724  }
   2725 
   2726  #endif
   2727 
   2728 
   2729  *isMT = False;
   2730 
   2731  {
   2732    SRes res = XzDecMt_Decode_ST(p
   2733        #ifndef _7ZIP_ST
   2734        , tMode
   2735        #endif
   2736        , stat
   2737        );
   2738 
   2739    XzStatInfo_SetStat(&p->dec,
   2740        p->finishMode,
   2741        p->readProcessed, p->inProcessed,
   2742        p->codeRes, p->status,
   2743        False, // truncated
   2744        stat);
   2745 
   2746    if (res == SZ_OK)
   2747    {
   2748      /*
   2749      if (p->writeRes != SZ_OK)
   2750      {
   2751        res = p->writeRes;
   2752        stat->CombinedRes_Type = SZ_ERROR_WRITE;
   2753      }
   2754      else
   2755      */
   2756      if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)
   2757      {
   2758        res = p->readRes;
   2759        stat->ReadRes = res;
   2760        stat->CombinedRes_Type = SZ_ERROR_READ;
   2761      }
   2762      #ifndef _7ZIP_ST
   2763      else if (p->mainErrorCode != SZ_OK)
   2764        res = p->mainErrorCode;
   2765      #endif
   2766    }
   2767 
   2768    stat->CombinedRes = res;
   2769    if (stat->CombinedRes_Type == SZ_OK)
   2770      stat->CombinedRes_Type = res;
   2771    return res;
   2772  }
   2773 }