all repos — mgba @ b2d406a411b31acce5bbf0246af32a80c22ca834

mGBA Game Boy Advance Emulator

src/third-party/lzma/XzDec.c (view raw)

   1/* XzDec.c -- Xz Decode
   22019-02-02 : 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
  54unsigned 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
  74typedef 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
  91static void BraState_Free(void *pp, ISzAllocPtr alloc)
  92{
  93  ISzAlloc_Free(alloc, pp);
  94}
  95
  96static 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
 137static 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
 149static 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
 174static 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
 243SRes 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 = (CBraState *)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
 272static void SbState_Free(void *pp, ISzAllocPtr alloc)
 273{
 274  CSbDec *p = (CSbDec *)pp;
 275  SbDec_Free(p);
 276  ISzAlloc_Free(alloc, pp);
 277}
 278
 279static 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
 287static void SbState_Init(void *pp)
 288{
 289  SbDec_Init((CSbDec *)pp);
 290}
 291
 292static 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
 315static 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
 341typedef struct
 342{
 343  CLzma2Dec decoder;
 344  BoolInt outBufMode;
 345} CLzma2Dec_Spec;
 346
 347
 348static 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
 358static 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
 371static 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
 382static 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 = (ECoderStatus)status2;
 404  return res;
 405}
 406
 407
 408static 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
 435static 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
 450static 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
 466static 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
 486static 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
 508static 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
 525static 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
 541output (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
 547static 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    BoolInt processed = False;
 641    BoolInt 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
 755SRes 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
 764static BoolInt 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
 778static BoolInt 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
 805SRes 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
 866static SRes XzDecMix_Init(CMixCoder *p, const CXzBlock *block, Byte *outBuf, size_t outBufSize)
 867{
 868  unsigned i;
 869  BoolInt 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
 917void 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
 936void XzUnpacker_SetOutBuf(CXzUnpacker *p, Byte *outBuf, size_t outBufSize)
 937{
 938  p->outBuf = outBuf;
 939  p->outBufSize = outBufSize;
 940}
 941
 942
 943void 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
 952void XzUnpacker_Free(CXzUnpacker *p)
 953{
 954  MixCoder_Free(&p->decoder);
 955}
 956
 957
 958void 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
 969static 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
 981SRes 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      BoolInt srcFinished2 = srcFinished;
1003      BoolInt 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
1335SRes 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
1349BoolInt XzUnpacker_IsBlockFinished(const CXzUnpacker *p)
1350{
1351  return (p->state == XZ_STATE_BLOCK_HEADER) && (p->pos == 0);
1352}
1353
1354BoolInt XzUnpacker_IsStreamWasFinished(const CXzUnpacker *p)
1355{
1356  return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
1357}
1358
1359UInt64 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
1394void 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
1413typedef 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  BoolInt skipMode;
1427  // BoolInt finishedWithMark;
1428  EMtDecParseState parseState;
1429  BoolInt parsing_Truncated;
1430  BoolInt atBlockHeader;
1431  CXzStreamFlags streamFlags;
1432  // UInt64 numFinishedStreams
1433  UInt64 numStreams;
1434  UInt64 numTotalBlocks;
1435  UInt64 numBlocks;
1436
1437  BoolInt dec_created;
1438  CXzUnpacker dec;
1439
1440  Byte mtPad[1 << 7];
1441} CXzDecMtThread;
1442
1443#endif
1444
1445
1446/* ---------- CXzDecMt ---------- */
1447
1448typedef 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  BoolInt finishMode;
1462  BoolInt outSize_Defined;
1463  UInt64 outSize;
1464
1465  UInt64 outProcessed;
1466  UInt64 inProcessed;
1467  UInt64 readProcessed;
1468  BoolInt readWasFinished;
1469  SRes readRes;
1470  SRes writeRes;
1471
1472  Byte *outBuf;
1473  size_t outBufSize;
1474  Byte *inBuf;
1475  size_t inBufSize;
1476
1477  CXzUnpacker dec;
1478
1479  ECoderStatus status;
1480  SRes codeRes;
1481
1482  #ifndef _7ZIP_ST
1483  BoolInt 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  BoolInt isBlockHeaderState_Parse;
1498  BoolInt isBlockHeaderState_Write;
1499  UInt64 outProcessed_Parse;
1500  BoolInt parsing_Truncated;
1501
1502  BoolInt mtc_WasConstructed;
1503  CMtDec mtc;
1504  CXzDecMtThread coders[MTDEC__THREADS_MAX];
1505  #endif
1506
1507} CXzDecMt;
1508
1509
1510
1511CXzDecMtHandle 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
1529  XzUnpacker_Construct(&p->dec, &p->alignOffsetAlloc.vt);
1530
1531  p->unpackBlockMaxSize = 0;
1532
1533  XzDecMtProps_Init(&p->props);
1534
1535  #ifndef _7ZIP_ST
1536  p->mtc_WasConstructed = False;
1537  {
1538    unsigned i;
1539    for (i = 0; i < MTDEC__THREADS_MAX; i++)
1540    {
1541      CXzDecMtThread *coder = &p->coders[i];
1542      coder->dec_created = False;
1543      coder->outBuf = NULL;
1544      coder->outBufSize = 0;
1545    }
1546  }
1547  #endif
1548
1549  return p;
1550}
1551
1552
1553#ifndef _7ZIP_ST
1554
1555static void XzDecMt_FreeOutBufs(CXzDecMt *p)
1556{
1557  unsigned i;
1558  for (i = 0; i < MTDEC__THREADS_MAX; i++)
1559  {
1560    CXzDecMtThread *coder = &p->coders[i];
1561    if (coder->outBuf)
1562    {
1563      ISzAlloc_Free(p->allocMid, coder->outBuf);
1564      coder->outBuf = NULL;
1565      coder->outBufSize = 0;
1566    }
1567  }
1568  p->unpackBlockMaxSize = 0;
1569}
1570
1571#endif
1572
1573
1574
1575static void XzDecMt_FreeSt(CXzDecMt *p)
1576{
1577  XzUnpacker_Free(&p->dec);
1578  
1579  if (p->outBuf)
1580  {
1581    ISzAlloc_Free(p->allocMid, p->outBuf);
1582    p->outBuf = NULL;
1583  }
1584  p->outBufSize = 0;
1585  
1586  if (p->inBuf)
1587  {
1588    ISzAlloc_Free(p->allocMid, p->inBuf);
1589    p->inBuf = NULL;
1590  }
1591  p->inBufSize = 0;
1592}
1593
1594
1595void XzDecMt_Destroy(CXzDecMtHandle pp)
1596{
1597  CXzDecMt *p = (CXzDecMt *)pp;
1598
1599  XzDecMt_FreeSt(p);
1600
1601  #ifndef _7ZIP_ST
1602
1603  if (p->mtc_WasConstructed)
1604  {
1605    MtDec_Destruct(&p->mtc);
1606    p->mtc_WasConstructed = False;
1607  }
1608  {
1609    unsigned i;
1610    for (i = 0; i < MTDEC__THREADS_MAX; i++)
1611    {
1612      CXzDecMtThread *t = &p->coders[i];
1613      if (t->dec_created)
1614      {
1615        // we don't need to free dict here
1616        XzUnpacker_Free(&t->dec);
1617        t->dec_created = False;
1618      }
1619    }
1620  }
1621  XzDecMt_FreeOutBufs(p);
1622
1623  #endif
1624
1625  ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
1626}
1627
1628
1629
1630#ifndef _7ZIP_ST
1631
1632static void XzDecMt_Callback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
1633{
1634  CXzDecMt *me = (CXzDecMt *)obj;
1635  CXzDecMtThread *coder = &me->coders[coderIndex];
1636  size_t srcSize = cc->srcSize;
1637
1638  cc->srcSize = 0;
1639  cc->outPos = 0;
1640  cc->state = MTDEC_PARSE_CONTINUE;
1641
1642  cc->canCreateNewThread = True;
1643
1644  if (cc->startCall)
1645  {
1646    coder->outPreSize = 0;
1647    coder->inPreSize = 0;
1648    coder->inPreHeaderSize = 0;
1649    coder->parseState = MTDEC_PARSE_CONTINUE;
1650    coder->parsing_Truncated = False;
1651    coder->skipMode = False;
1652    coder->codeRes = SZ_OK;
1653    coder->status = CODER_STATUS_NOT_SPECIFIED;
1654    coder->inCodeSize = 0;
1655    coder->outCodeSize = 0;
1656
1657    coder->numStreams = me->numStreams;
1658    coder->numTotalBlocks = me->numTotalBlocks;
1659    coder->numBlocks = me->numBlocks;
1660
1661    if (!coder->dec_created)
1662    {
1663      XzUnpacker_Construct(&coder->dec, &me->alignOffsetAlloc.vt);
1664      coder->dec_created = True;
1665    }
1666    
1667    XzUnpacker_Init(&coder->dec);
1668
1669    if (me->isBlockHeaderState_Parse)
1670    {
1671      coder->dec.streamFlags = me->streamFlags;
1672      coder->atBlockHeader = True;
1673      XzUnpacker_PrepareToRandomBlockDecoding(&coder->dec);
1674    }
1675    else
1676    {
1677      coder->atBlockHeader = False;
1678      me->isBlockHeaderState_Parse = True;
1679    }
1680
1681    coder->dec.numStartedStreams = me->numStreams;
1682    coder->dec.numTotalBlocks = me->numTotalBlocks;
1683    coder->dec.numBlocks = me->numBlocks;
1684  }
1685
1686  while (!coder->skipMode)
1687  {
1688    ECoderStatus status;
1689    SRes res;
1690    size_t srcSize2 = srcSize;
1691    size_t destSize = (size_t)0 - 1;
1692
1693    coder->dec.parseMode = True;
1694    coder->dec.headerParsedOk = False;
1695    
1696    PRF_STR_INT("Parse", srcSize2);
1697    
1698    res = XzUnpacker_Code(&coder->dec,
1699        NULL, &destSize,
1700        cc->src, &srcSize2, cc->srcFinished,
1701        CODER_FINISH_END, &status);
1702    
1703    // PRF(printf(" res = %d, srcSize2 = %d", res, (unsigned)srcSize2));
1704    
1705    coder->codeRes = res;
1706    coder->status = status;
1707    cc->srcSize += srcSize2;
1708    srcSize -= srcSize2;
1709    coder->inPreHeaderSize += srcSize2;
1710    coder->inPreSize = coder->inPreHeaderSize;
1711    
1712    if (res != SZ_OK)
1713    {
1714      cc->state =
1715      coder->parseState = MTDEC_PARSE_END;
1716      /*
1717      if (res == SZ_ERROR_MEM)
1718        return res;
1719      return SZ_OK;
1720      */
1721      return; // res;
1722    }
1723    
1724    if (coder->dec.headerParsedOk)
1725    {
1726      const CXzBlock *block = &coder->dec.block;
1727      if (XzBlock_HasUnpackSize(block)
1728          // && block->unpackSize <= me->props.outBlockMax
1729          && XzBlock_HasPackSize(block))
1730      {
1731        {
1732          if (block->unpackSize * 2 * me->mtc.numStartedThreads > me->props.memUseMax)
1733          {
1734            cc->state = MTDEC_PARSE_OVERFLOW;
1735            return; // SZ_OK;
1736          }
1737        }
1738        {
1739        UInt64 packSize = block->packSize;
1740        UInt64 packSizeAligned = packSize + ((0 - (unsigned)packSize) & 3);
1741        UInt32 checkSize = XzFlags_GetCheckSize(coder->dec.streamFlags);
1742        UInt64 blockPackSum = coder->inPreSize + packSizeAligned + checkSize;
1743        // if (blockPackSum <= me->props.inBlockMax)
1744        // unpackBlockMaxSize
1745        {
1746          coder->blockPackSize_for_Index = (size_t)(coder->dec.blockHeaderSize + packSize + checkSize);
1747          coder->blockPackTotal = (size_t)blockPackSum;
1748          coder->outPreSize = (size_t)block->unpackSize;
1749          coder->streamFlags = coder->dec.streamFlags;
1750          me->streamFlags = coder->dec.streamFlags;
1751          coder->skipMode = True;
1752          break;
1753        }
1754        }
1755      }
1756    }
1757    else
1758    // if (coder->inPreSize <= me->props.inBlockMax)
1759    {
1760      if (!cc->srcFinished)
1761        return; // SZ_OK;
1762      cc->state =
1763      coder->parseState = MTDEC_PARSE_END;
1764      return; // SZ_OK;
1765    }
1766    cc->state = MTDEC_PARSE_OVERFLOW;
1767    return; // SZ_OK;
1768  }
1769
1770  // ---------- skipMode ----------
1771  {
1772    UInt64 rem = coder->blockPackTotal - coder->inPreSize;
1773    size_t cur = srcSize;
1774    if (cur > rem)
1775      cur = (size_t)rem;
1776    cc->srcSize += cur;
1777    coder->inPreSize += cur;
1778    srcSize -= cur;
1779
1780    if (coder->inPreSize == coder->blockPackTotal)
1781    {
1782      if (srcSize == 0)
1783      {
1784        if (!cc->srcFinished)
1785          return; // SZ_OK;
1786        cc->state = MTDEC_PARSE_END;
1787      }
1788      else if ((cc->src)[cc->srcSize] == 0) // we check control byte of next block
1789        cc->state = MTDEC_PARSE_END;
1790      else
1791      {
1792        cc->state = MTDEC_PARSE_NEW;
1793
1794        {
1795          size_t blockMax = me->unpackBlockMaxSize;
1796          if (blockMax < coder->outPreSize)
1797            blockMax = coder->outPreSize;
1798          {
1799            UInt64 required = (UInt64)blockMax * (me->mtc.numStartedThreads + 1) * 2;
1800            if (me->props.memUseMax < required)
1801              cc->canCreateNewThread = False;
1802          }
1803        }
1804
1805        if (me->outSize_Defined)
1806        {
1807          // next block can be zero size
1808          const UInt64 rem2 = me->outSize - me->outProcessed_Parse;
1809          if (rem2 < coder->outPreSize)
1810          {
1811            coder->parsing_Truncated = True;
1812            cc->state = MTDEC_PARSE_END;
1813          }
1814          me->outProcessed_Parse += coder->outPreSize;
1815        }
1816      }
1817    }
1818    else if (cc->srcFinished)
1819      cc->state = MTDEC_PARSE_END;
1820    else
1821      return; // SZ_OK;
1822
1823    coder->parseState = cc->state;
1824    cc->outPos = coder->outPreSize;
1825    
1826    me->numStreams = coder->dec.numStartedStreams;
1827    me->numTotalBlocks = coder->dec.numTotalBlocks;
1828    me->numBlocks = coder->dec.numBlocks + 1;
1829    return; // SZ_OK;
1830  }
1831}
1832
1833
1834static SRes XzDecMt_Callback_PreCode(void *pp, unsigned coderIndex)
1835{
1836  CXzDecMt *me = (CXzDecMt *)pp;
1837  CXzDecMtThread *coder = &me->coders[coderIndex];
1838  Byte *dest;
1839
1840  if (!coder->dec.headerParsedOk)
1841    return SZ_OK;
1842
1843  dest = coder->outBuf;
1844
1845  if (!dest || coder->outBufSize < coder->outPreSize)
1846  {
1847    if (dest)
1848    {
1849      ISzAlloc_Free(me->allocMid, dest);
1850      coder->outBuf = NULL;
1851      coder->outBufSize = 0;
1852    }
1853    {
1854      size_t outPreSize = coder->outPreSize;
1855      if (outPreSize == 0)
1856        outPreSize = 1;
1857      dest = (Byte *)ISzAlloc_Alloc(me->allocMid, outPreSize);
1858    }
1859    if (!dest)
1860      return SZ_ERROR_MEM;
1861    coder->outBuf = dest;
1862    coder->outBufSize = coder->outPreSize;
1863
1864    if (coder->outBufSize > me->unpackBlockMaxSize)
1865      me->unpackBlockMaxSize = coder->outBufSize;
1866  }
1867
1868  // return SZ_ERROR_MEM;
1869
1870  XzUnpacker_SetOutBuf(&coder->dec, coder->outBuf, coder->outBufSize);
1871
1872  {
1873    SRes res = XzDecMix_Init(&coder->dec.decoder, &coder->dec.block, coder->outBuf, coder->outBufSize);
1874    // res = SZ_ERROR_UNSUPPORTED; // to test
1875    coder->codeRes = res;
1876    if (res != SZ_OK)
1877    {
1878      // if (res == SZ_ERROR_MEM) return res;
1879      if (me->props.ignoreErrors && res != SZ_ERROR_MEM)
1880        return S_OK;
1881      return res;
1882    }
1883  }
1884
1885  return SZ_OK;
1886}
1887
1888
1889static SRes XzDecMt_Callback_Code(void *pp, unsigned coderIndex,
1890    const Byte *src, size_t srcSize, int srcFinished,
1891    // int finished, int blockFinished,
1892    UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
1893{
1894  CXzDecMt *me = (CXzDecMt *)pp;
1895  CXzDecMtThread *coder = &me->coders[coderIndex];
1896
1897  *inCodePos = coder->inCodeSize;
1898  *outCodePos = coder->outCodeSize;
1899  *stop = True;
1900
1901  if (coder->inCodeSize < coder->inPreHeaderSize)
1902  {
1903    UInt64 rem = coder->inPreHeaderSize - coder->inCodeSize;
1904    size_t step = srcSize;
1905    if (step > rem)
1906      step = (size_t)rem;
1907    src += step;
1908    srcSize -= step;
1909    coder->inCodeSize += step;
1910    if (coder->inCodeSize < coder->inPreHeaderSize)
1911    {
1912      *stop = False;
1913      return SZ_OK;
1914    }
1915  }
1916
1917  if (!coder->dec.headerParsedOk)
1918    return SZ_OK;
1919  if (!coder->outBuf)
1920    return SZ_OK;
1921
1922  if (coder->codeRes == SZ_OK)
1923  {
1924    ECoderStatus status;
1925    SRes res;
1926    size_t srcProcessed = srcSize;
1927    size_t outSizeCur = coder->outPreSize - coder->dec.outDataWritten;
1928
1929    // PRF(printf("\nCallback_Code: Code %d %d\n", (unsigned)srcSize, (unsigned)outSizeCur));
1930
1931    res = XzUnpacker_Code(&coder->dec,
1932        NULL, &outSizeCur,
1933        src, &srcProcessed, srcFinished,
1934        // coder->finishedWithMark ? CODER_FINISH_END : CODER_FINISH_ANY,
1935        CODER_FINISH_END,
1936        &status);
1937
1938    // PRF(printf(" res = %d, srcSize2 = %d, outSizeCur = %d", res, (unsigned)srcProcessed, (unsigned)outSizeCur));
1939
1940    coder->codeRes = res;
1941    coder->status = status;
1942    coder->inCodeSize += srcProcessed;
1943    coder->outCodeSize = coder->dec.outDataWritten;
1944    *inCodePos = coder->inCodeSize;
1945    *outCodePos = coder->outCodeSize;
1946
1947    if (res == SZ_OK)
1948    {
1949      if (srcProcessed == srcSize)
1950        *stop = False;
1951      return SZ_OK;
1952    }
1953  }
1954
1955  if (me->props.ignoreErrors && coder->codeRes != SZ_ERROR_MEM)
1956  {
1957    *inCodePos = coder->inPreSize;
1958    *outCodePos = coder->outPreSize;
1959    return S_OK;
1960  }
1961  return coder->codeRes;
1962}
1963
1964
1965#define XZDECMT_STREAM_WRITE_STEP (1 << 24)
1966
1967static SRes XzDecMt_Callback_Write(void *pp, unsigned coderIndex,
1968    BoolInt needWriteToStream,
1969    const Byte *src, size_t srcSize,
1970    // int srcFinished,
1971    BoolInt *needContinue,
1972    BoolInt *canRecode)
1973{
1974  CXzDecMt *me = (CXzDecMt *)pp;
1975  const CXzDecMtThread *coder = &me->coders[coderIndex];
1976
1977  // PRF(printf("\nWrite processed = %d srcSize = %d\n", (unsigned)me->mtc.inProcessed, (unsigned)srcSize));
1978  
1979  *needContinue = False;
1980  *canRecode = True;
1981  
1982  if (!needWriteToStream)
1983    return SZ_OK;
1984
1985  if (!coder->dec.headerParsedOk || !coder->outBuf)
1986  {
1987    if (me->finishedDecoderIndex < 0)
1988      me->finishedDecoderIndex = coderIndex;
1989    return SZ_OK;
1990  }
1991
1992  if (me->finishedDecoderIndex >= 0)
1993    return SZ_OK;
1994
1995  me->mtc.inProcessed += coder->inCodeSize;
1996
1997  *canRecode = False;
1998
1999  {
2000    SRes res;
2001    size_t size = coder->outCodeSize;
2002    Byte *data = coder->outBuf;
2003    
2004    // we use in me->dec: sha, numBlocks, indexSize
2005
2006    if (!me->isBlockHeaderState_Write)
2007    {
2008      XzUnpacker_PrepareToRandomBlockDecoding(&me->dec);
2009      me->dec.decodeOnlyOneBlock = False;
2010      me->dec.numStartedStreams = coder->dec.numStartedStreams;
2011      me->dec.streamFlags = coder->streamFlags;
2012
2013      me->isBlockHeaderState_Write = True;
2014    }
2015    
2016    me->dec.numTotalBlocks = coder->dec.numTotalBlocks;
2017    XzUnpacker_UpdateIndex(&me->dec, coder->blockPackSize_for_Index, coder->outPreSize);
2018    
2019    if (coder->outPreSize != size)
2020    {
2021      if (me->props.ignoreErrors)
2022      {
2023        memset(data + size, 0, coder->outPreSize - size);
2024        size = coder->outPreSize;
2025      }
2026      // me->numBadBlocks++;
2027      if (me->mainErrorCode == SZ_OK)
2028      {
2029        if ((int)coder->status == LZMA_STATUS_NEEDS_MORE_INPUT)
2030          me->mainErrorCode = SZ_ERROR_INPUT_EOF;
2031        else
2032          me->mainErrorCode = SZ_ERROR_DATA;
2033      }
2034    }
2035    
2036    if (me->writeRes != SZ_OK)
2037      return me->writeRes;
2038
2039    res = SZ_OK;
2040    {
2041      if (me->outSize_Defined)
2042      {
2043        const UInt64 rem = me->outSize - me->outProcessed;
2044        if (size > rem)
2045          size = (SizeT)rem;
2046      }
2047
2048      for (;;)
2049      {
2050        size_t cur = size;
2051        size_t written;
2052        if (cur > XZDECMT_STREAM_WRITE_STEP)
2053          cur = XZDECMT_STREAM_WRITE_STEP;
2054
2055        written = ISeqOutStream_Write(me->outStream, data, cur);
2056
2057        // PRF(printf("\nWritten ask = %d written = %d\n", (unsigned)cur, (unsigned)written));
2058        
2059        me->outProcessed += written;
2060        if (written != cur)
2061        {
2062          me->writeRes = SZ_ERROR_WRITE;
2063          res = me->writeRes;
2064          break;
2065        }
2066        data += cur;
2067        size -= cur;
2068        // PRF_STR_INT("Written size =", size);
2069        if (size == 0)
2070          break;
2071        res = MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0);
2072        if (res != SZ_OK)
2073          break;
2074      }
2075    }
2076
2077    if (coder->codeRes != SZ_OK)
2078      if (!me->props.ignoreErrors)
2079      {
2080        me->finishedDecoderIndex = coderIndex;
2081        return res;
2082      }
2083
2084    RINOK(res);
2085
2086    if (coder->inPreSize != coder->inCodeSize
2087        || coder->blockPackTotal != coder->inCodeSize)
2088    {
2089      me->finishedDecoderIndex = coderIndex;
2090      return SZ_OK;
2091    }
2092
2093    if (coder->parseState != MTDEC_PARSE_END)
2094    {
2095      *needContinue = True;
2096      return SZ_OK;
2097    }
2098  }
2099
2100  // (coder->state == MTDEC_PARSE_END) means that there are no other working threads
2101  // so we can use mtc variables without lock
2102
2103  PRF_STR_INT("Write MTDEC_PARSE_END", me->mtc.inProcessed);
2104
2105  me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2106  {
2107    CXzUnpacker *dec = &me->dec;
2108    
2109    PRF_STR_INT("PostSingle", srcSize);
2110    
2111    {
2112      size_t srcProcessed = srcSize;
2113      ECoderStatus status;
2114      size_t outSizeCur = 0;
2115      SRes res;
2116      
2117      // dec->decodeOnlyOneBlock = False;
2118      dec->decodeToStreamSignature = True;
2119
2120      me->mainDecoderWasCalled = True;
2121
2122      if (coder->parsing_Truncated)
2123      {
2124        me->parsing_Truncated = True;
2125        return SZ_OK;
2126      }
2127      
2128      res = XzUnpacker_Code(dec,
2129          NULL, &outSizeCur,
2130          src, &srcProcessed,
2131          me->mtc.readWasFinished, // srcFinished
2132          CODER_FINISH_END, // CODER_FINISH_ANY,
2133          &status);
2134      
2135      me->status = status;
2136      me->codeRes = res;
2137
2138      me->mtc.inProcessed += srcProcessed;
2139      me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2140
2141      if (res != SZ_OK)
2142      {
2143        return S_OK;
2144        // return res;
2145      }
2146      
2147      if (dec->state == XZ_STATE_STREAM_HEADER)
2148      {
2149        *needContinue = True;
2150        me->isBlockHeaderState_Parse = False;
2151        me->isBlockHeaderState_Write = False;
2152        {
2153          Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2154          if (!crossBuf)
2155            return SZ_ERROR_MEM;
2156          memcpy(crossBuf, src + srcProcessed, srcSize - srcProcessed);
2157        }
2158        me->mtc.crossStart = 0;
2159        me->mtc.crossEnd = srcSize - srcProcessed;
2160        return SZ_OK;
2161      }
2162      
2163      if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2164      {
2165        return E_FAIL;
2166      }
2167      
2168      if (me->mtc.readWasFinished)
2169      {
2170        return SZ_OK;
2171      }
2172    }
2173    
2174    {
2175      size_t inPos;
2176      size_t inLim;
2177      const Byte *inData;
2178      UInt64 inProgressPrev = me->mtc.inProcessed;
2179      
2180      // XzDecMt_Prepare_InBuf_ST(p);
2181      Byte *crossBuf = MtDec_GetCrossBuff(&me->mtc);
2182      if (!crossBuf)
2183        return SZ_ERROR_MEM;
2184      
2185      inPos = 0;
2186      inLim = 0;
2187      // outProcessed = 0;
2188      
2189      inData = crossBuf;
2190      
2191      for (;;)
2192      {
2193        SizeT inProcessed;
2194        SizeT outProcessed;
2195        ECoderStatus status;
2196        SRes res;
2197        
2198        if (inPos == inLim)
2199        {
2200          if (!me->mtc.readWasFinished)
2201          {
2202            inPos = 0;
2203            inLim = me->mtc.inBufSize;
2204            me->mtc.readRes = ISeqInStream_Read(me->inStream, (void *)inData, &inLim);
2205            me->mtc.readProcessed += inLim;
2206            if (inLim == 0 || me->mtc.readRes != SZ_OK)
2207              me->mtc.readWasFinished = True;
2208          }
2209        }
2210        
2211        inProcessed = inLim - inPos;
2212        outProcessed = 0;
2213
2214        res = XzUnpacker_Code(dec,
2215            NULL, &outProcessed,
2216            inData + inPos, &inProcessed,
2217            (inProcessed == 0), // srcFinished
2218            CODER_FINISH_END, &status);
2219        
2220        me->codeRes = res;
2221        me->status = status;
2222        inPos += inProcessed;
2223        me->mtc.inProcessed += inProcessed;
2224        me->mtc.mtProgress.totalInSize = me->mtc.inProcessed;
2225
2226        if (res != SZ_OK)
2227        {
2228          return S_OK;
2229          // return res;
2230        }
2231
2232        if (dec->state == XZ_STATE_STREAM_HEADER)
2233        {
2234          *needContinue = True;
2235          me->mtc.crossStart = inPos;
2236          me->mtc.crossEnd = inLim;
2237          me->isBlockHeaderState_Parse = False;
2238          me->isBlockHeaderState_Write = False;
2239          return SZ_OK;
2240        }
2241        
2242        if (status != CODER_STATUS_NEEDS_MORE_INPUT)
2243          return E_FAIL;
2244        
2245        if (me->mtc.progress)
2246        {
2247          UInt64 inDelta = me->mtc.inProcessed - inProgressPrev;
2248          if (inDelta >= (1 << 22))
2249          {
2250            RINOK(MtProgress_Progress_ST(&me->mtc.mtProgress));
2251            inProgressPrev = me->mtc.inProcessed;
2252          }
2253        }
2254        if (me->mtc.readWasFinished)
2255          return SZ_OK;
2256      }
2257    }
2258  }
2259}
2260
2261
2262#endif
2263
2264
2265
2266void XzStatInfo_Clear(CXzStatInfo *p)
2267{
2268  p->InSize = 0;
2269  p->OutSize = 0;
2270  
2271  p->NumStreams = 0;
2272  p->NumBlocks = 0;
2273  
2274  p->UnpackSize_Defined = False;
2275  
2276  p->NumStreams_Defined = False;
2277  p->NumBlocks_Defined = False;
2278  
2279  // p->IsArc = False;
2280  // p->UnexpectedEnd = False;
2281  // p->Unsupported = False;
2282  // p->HeadersError = False;
2283  // p->DataError = False;
2284  // p->CrcError = False;
2285
2286  p->DataAfterEnd = False;
2287  p->DecodingTruncated = False;
2288  
2289  p->DecodeRes = SZ_OK;
2290  p->ReadRes = SZ_OK;
2291  p->ProgressRes = SZ_OK;
2292
2293  p->CombinedRes = SZ_OK;
2294  p->CombinedRes_Type = SZ_OK;
2295}
2296
2297
2298
2299
2300static SRes XzDecMt_Decode_ST(CXzDecMt *p
2301    #ifndef _7ZIP_ST
2302    , BoolInt tMode
2303    #endif
2304    , CXzStatInfo *stat)
2305{
2306  size_t outPos;
2307  size_t inPos, inLim;
2308  const Byte *inData;
2309  UInt64 inPrev, outPrev;
2310
2311  CXzUnpacker *dec;
2312
2313  #ifndef _7ZIP_ST
2314  if (tMode)
2315  {
2316    XzDecMt_FreeOutBufs(p);
2317    tMode = MtDec_PrepareRead(&p->mtc);
2318  }
2319  #endif
2320
2321  if (!p->outBuf || p->outBufSize != p->props.outStep_ST)
2322  {
2323    ISzAlloc_Free(p->allocMid, p->outBuf);
2324    p->outBufSize = 0;
2325    p->outBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.outStep_ST);
2326    if (!p->outBuf)
2327      return SZ_ERROR_MEM;
2328    p->outBufSize = p->props.outStep_ST;
2329  }
2330
2331  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
2332  {
2333    ISzAlloc_Free(p->allocMid, p->inBuf);
2334    p->inBufSize = 0;
2335    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
2336    if (!p->inBuf)
2337      return SZ_ERROR_MEM;
2338    p->inBufSize = p->props.inBufSize_ST;
2339  }
2340
2341  dec = &p->dec;
2342  dec->decodeToStreamSignature = False;
2343  // dec->decodeOnlyOneBlock = False;
2344
2345  XzUnpacker_SetOutBuf(dec, NULL, 0);
2346
2347  inPrev = p->inProcessed;
2348  outPrev = p->outProcessed;
2349
2350  inPos = 0;
2351  inLim = 0;
2352  inData = NULL;
2353  outPos = 0;
2354
2355  for (;;)
2356  {
2357    SizeT outSize;
2358    BoolInt finished;
2359    ECoderFinishMode finishMode;
2360    SizeT inProcessed;
2361    ECoderStatus status;
2362    SRes res;
2363
2364    SizeT outProcessed;
2365
2366
2367
2368    if (inPos == inLim)
2369    {
2370      #ifndef _7ZIP_ST
2371      if (tMode)
2372      {
2373        inData = MtDec_Read(&p->mtc, &inLim);
2374        inPos = 0;
2375        if (inData)
2376          continue;
2377        tMode = False;
2378        inLim = 0;
2379      }
2380      #endif
2381      
2382      if (!p->readWasFinished)
2383      {
2384        inPos = 0;
2385        inLim = p->inBufSize;
2386        inData = p->inBuf;
2387        p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
2388        p->readProcessed += inLim;
2389        if (inLim == 0 || p->readRes != SZ_OK)
2390          p->readWasFinished = True;
2391      }
2392    }
2393
2394    outSize = p->props.outStep_ST - outPos;
2395
2396    finishMode = CODER_FINISH_ANY;
2397    if (p->outSize_Defined)
2398    {
2399      const UInt64 rem = p->outSize - p->outProcessed;
2400      if (outSize >= rem)
2401      {
2402        outSize = (SizeT)rem;
2403        if (p->finishMode)
2404          finishMode = CODER_FINISH_END;
2405      }
2406    }
2407
2408    inProcessed = inLim - inPos;
2409    outProcessed = outSize;
2410
2411    res = XzUnpacker_Code(dec, p->outBuf + outPos, &outProcessed,
2412        inData + inPos, &inProcessed,
2413        (inPos == inLim), // srcFinished
2414        finishMode, &status);
2415
2416    p->codeRes = res;
2417    p->status = status;
2418
2419    inPos += inProcessed;
2420    outPos += outProcessed;
2421    p->inProcessed += inProcessed;
2422    p->outProcessed += outProcessed;
2423
2424    finished = ((inProcessed == 0 && outProcessed == 0) || res != SZ_OK);
2425
2426    if (finished || outProcessed >= outSize)
2427      if (outPos != 0)
2428      {
2429        size_t written = ISeqOutStream_Write(p->outStream, p->outBuf, outPos);
2430        p->outProcessed += written;
2431        if (written != outPos)
2432        {
2433          stat->CombinedRes_Type = SZ_ERROR_WRITE;
2434          return SZ_ERROR_WRITE;
2435        }
2436        outPos = 0;
2437      }
2438
2439    if (p->progress && res == SZ_OK)
2440    {
2441      UInt64 inDelta = p->inProcessed - inPrev;
2442      UInt64 outDelta = p->outProcessed - outPrev;
2443      if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
2444      {
2445        res = ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed);
2446        if (res != SZ_OK)
2447        {
2448          stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2449          stat->ProgressRes = res;
2450          return res;
2451        }
2452        inPrev = p->inProcessed;
2453        outPrev = p->outProcessed;
2454      }
2455    }
2456
2457    if (finished)
2458      return res;
2459  }
2460}
2461
2462static SRes XzStatInfo_SetStat(const CXzUnpacker *dec,
2463    int finishMode,
2464    UInt64 readProcessed, UInt64 inProcessed,
2465    SRes res, ECoderStatus status,
2466    BoolInt decodingTruncated,
2467    CXzStatInfo *stat)
2468{
2469  UInt64 extraSize;
2470  
2471  stat->DecodingTruncated = (Byte)(decodingTruncated ? 1 : 0);
2472  stat->InSize = inProcessed;
2473  stat->NumStreams = dec->numStartedStreams;
2474  stat->NumBlocks = dec->numTotalBlocks;
2475  
2476  stat->UnpackSize_Defined = True;
2477  stat->NumStreams_Defined = True;
2478  stat->NumBlocks_Defined = True;
2479  
2480  extraSize = XzUnpacker_GetExtraSize(dec);
2481  
2482  if (res == SZ_OK)
2483  {
2484    if (status == CODER_STATUS_NEEDS_MORE_INPUT)
2485    {
2486      // CODER_STATUS_NEEDS_MORE_INPUT is expected status for correct xz streams
2487      extraSize = 0;
2488      if (!XzUnpacker_IsStreamWasFinished(dec))
2489        res = SZ_ERROR_INPUT_EOF;
2490    }
2491    else if (!decodingTruncated || finishMode) // (status == CODER_STATUS_NOT_FINISHED)
2492      res = SZ_ERROR_DATA;
2493  }
2494  else if (res == SZ_ERROR_NO_ARCHIVE)
2495  {
2496    /*
2497    SZ_ERROR_NO_ARCHIVE is possible for 2 states:
2498      XZ_STATE_STREAM_HEADER  - if bad signature or bad CRC
2499      XZ_STATE_STREAM_PADDING - if non-zero padding data
2500    extraSize / inProcessed don't include "bad" byte
2501    */
2502    if (inProcessed != extraSize) // if good streams before error
2503      if (extraSize != 0 || readProcessed != inProcessed)
2504      {
2505        stat->DataAfterEnd = True;
2506        // there is some good xz stream before. So we set SZ_OK
2507        res = SZ_OK;
2508      }
2509  }
2510  
2511  stat->DecodeRes = res;
2512
2513  stat->InSize -= extraSize;
2514  return res;
2515}
2516
2517
2518SRes XzDecMt_Decode(CXzDecMtHandle pp,
2519    const CXzDecMtProps *props,
2520    const UInt64 *outDataSize, int finishMode,
2521    ISeqOutStream *outStream,
2522    // Byte *outBuf, size_t *outBufSize,
2523    ISeqInStream *inStream,
2524    // const Byte *inData, size_t inDataSize,
2525    CXzStatInfo *stat,
2526    int *isMT,
2527    ICompressProgress *progress)
2528{
2529  CXzDecMt *p = (CXzDecMt *)pp;
2530  #ifndef _7ZIP_ST
2531  BoolInt tMode;
2532  #endif
2533
2534  XzStatInfo_Clear(stat);
2535
2536  p->props = *props;
2537
2538  p->inStream = inStream;
2539  p->outStream = outStream;
2540  p->progress = progress;
2541  // p->stat = stat;
2542
2543  p->outSize = 0;
2544  p->outSize_Defined = False;
2545  if (outDataSize)
2546  {
2547    p->outSize_Defined = True;
2548    p->outSize = *outDataSize;
2549  }
2550
2551  p->finishMode = finishMode;
2552
2553  // p->outSize = 457; p->outSize_Defined = True; p->finishMode = False; // for test
2554
2555  p->writeRes = SZ_OK;
2556  p->outProcessed = 0;
2557  p->inProcessed = 0;
2558  p->readProcessed = 0;
2559  p->readWasFinished = False;
2560
2561  p->codeRes = 0;
2562  p->status = CODER_STATUS_NOT_SPECIFIED;
2563
2564  XzUnpacker_Init(&p->dec);
2565
2566  *isMT = False;
2567
2568    /*
2569    p->outBuf = NULL;
2570    p->outBufSize = 0;
2571    if (!outStream)
2572    {
2573      p->outBuf = outBuf;
2574      p->outBufSize = *outBufSize;
2575      *outBufSize = 0;
2576    }
2577    */
2578
2579  
2580  #ifndef _7ZIP_ST
2581
2582  p->isBlockHeaderState_Parse = False;
2583  p->isBlockHeaderState_Write = False;
2584  // p->numBadBlocks = 0;
2585  p->mainErrorCode = SZ_OK;
2586  p->mainDecoderWasCalled = False;
2587
2588  tMode = False;
2589
2590  if (p->props.numThreads > 1)
2591  {
2592    IMtDecCallback vt;
2593
2594    // we just free ST buffers here
2595    // but we still keep state variables, that was set in XzUnpacker_Init()
2596    XzDecMt_FreeSt(p);
2597
2598    p->outProcessed_Parse = 0;
2599    p->parsing_Truncated = False;
2600
2601    p->numStreams = 0;
2602    p->numTotalBlocks = 0;
2603    p->numBlocks = 0;
2604    p->finishedDecoderIndex = -1;
2605
2606    if (!p->mtc_WasConstructed)
2607    {
2608      p->mtc_WasConstructed = True;
2609      MtDec_Construct(&p->mtc);
2610    }
2611    
2612    p->mtc.mtCallback = &vt;
2613    p->mtc.mtCallbackObject = p;
2614
2615    p->mtc.progress = progress;
2616    p->mtc.inStream = inStream;
2617    p->mtc.alloc = &p->alignOffsetAlloc.vt;
2618    // p->mtc.inData = inData;
2619    // p->mtc.inDataSize = inDataSize;
2620    p->mtc.inBufSize = p->props.inBufSize_MT;
2621    // p->mtc.inBlockMax = p->props.inBlockMax;
2622    p->mtc.numThreadsMax = p->props.numThreads;
2623
2624    *isMT = True;
2625
2626    vt.Parse = XzDecMt_Callback_Parse;
2627    vt.PreCode = XzDecMt_Callback_PreCode;
2628    vt.Code = XzDecMt_Callback_Code;
2629    vt.Write = XzDecMt_Callback_Write;
2630
2631    {
2632      BoolInt needContinue;
2633      
2634      SRes res = MtDec_Code(&p->mtc);
2635
2636      stat->InSize = p->mtc.inProcessed;
2637
2638      p->inProcessed = p->mtc.inProcessed;
2639      p->readRes = p->mtc.readRes;
2640      p->readWasFinished = p->mtc.readWasFinished;
2641      p->readProcessed = p->mtc.readProcessed;
2642
2643      tMode = True;
2644      needContinue = False;
2645
2646      if (res == SZ_OK)
2647      {
2648        if (p->mtc.mtProgress.res != SZ_OK)
2649        {
2650          res = p->mtc.mtProgress.res;
2651          stat->ProgressRes = res;
2652          stat->CombinedRes_Type = SZ_ERROR_PROGRESS;
2653        }
2654        else
2655          needContinue = p->mtc.needContinue;
2656      }
2657
2658      if (!needContinue)
2659      {
2660        SRes codeRes;
2661        BoolInt truncated = False;
2662        ECoderStatus status;
2663        CXzUnpacker *dec;
2664
2665        stat->OutSize = p->outProcessed;
2666       
2667        if (p->finishedDecoderIndex >= 0)
2668        {
2669          CXzDecMtThread *coder = &p->coders[(unsigned)p->finishedDecoderIndex];
2670          codeRes = coder->codeRes;
2671          dec = &coder->dec;
2672          status = coder->status;
2673        }
2674        else if (p->mainDecoderWasCalled)
2675        {
2676          codeRes = p->codeRes;
2677          dec = &p->dec;
2678          status = p->status;
2679          truncated = p->parsing_Truncated;
2680        }
2681        else
2682          return E_FAIL;
2683
2684        XzStatInfo_SetStat(dec, p->finishMode,
2685            p->mtc.readProcessed, p->mtc.inProcessed,
2686            codeRes, status,
2687            truncated,
2688            stat);
2689
2690        if (res == SZ_OK)
2691        {
2692          if (p->writeRes != SZ_OK)
2693          {
2694            res = p->writeRes;
2695            stat->CombinedRes_Type = SZ_ERROR_WRITE;
2696          }
2697          else if (p->mtc.readRes != SZ_OK && p->mtc.inProcessed == p->mtc.readProcessed)
2698          {
2699            res = p->mtc.readRes;
2700            stat->ReadRes = res;
2701            stat->CombinedRes_Type = SZ_ERROR_READ;
2702          }
2703          else if (p->mainErrorCode != SZ_OK)
2704          {
2705            res = p->mainErrorCode;
2706          }
2707        }
2708
2709        stat->CombinedRes = res;
2710        if (stat->CombinedRes_Type == SZ_OK)
2711          stat->CombinedRes_Type = res;
2712        return res;
2713      }
2714
2715      PRF_STR("----- decoding ST -----");
2716    }
2717  }
2718
2719  #endif
2720
2721
2722  *isMT = False;
2723
2724  {
2725    SRes res = XzDecMt_Decode_ST(p
2726        #ifndef _7ZIP_ST
2727        , tMode
2728        #endif
2729        , stat
2730        );
2731
2732    XzStatInfo_SetStat(&p->dec,
2733        p->finishMode,
2734        p->readProcessed, p->inProcessed,
2735        p->codeRes, p->status,
2736        False, // truncated
2737        stat);
2738
2739    if (res == SZ_OK)
2740    {
2741      /*
2742      if (p->writeRes != SZ_OK)
2743      {
2744        res = p->writeRes;
2745        stat->CombinedRes_Type = SZ_ERROR_WRITE;
2746      }
2747      else
2748      */
2749      if (p->readRes != SZ_OK && p->inProcessed == p->readProcessed)
2750      {
2751        res = p->readRes;
2752        stat->ReadRes = res;
2753        stat->CombinedRes_Type = SZ_ERROR_READ;
2754      }
2755      #ifndef _7ZIP_ST
2756      else if (p->mainErrorCode != SZ_OK)
2757        res = p->mainErrorCode;
2758      #endif
2759    }
2760
2761    stat->CombinedRes = res;
2762    if (stat->CombinedRes_Type == SZ_OK)
2763      stat->CombinedRes_Type = res;
2764    return res;
2765  }
2766}