all repos — mgba @ b2d406a411b31acce5bbf0246af32a80c22ca834

mGBA Game Boy Advance Emulator

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

   1/* Lzma2DecMt.c -- LZMA2 Decoder Multi-thread
   22019-02-02 : Igor Pavlov : Public domain */
   3
   4#include "Precomp.h"
   5
   6// #define SHOW_DEBUG_INFO
   7
   8#ifdef SHOW_DEBUG_INFO
   9#include <stdio.h>
  10#endif
  11
  12#ifdef SHOW_DEBUG_INFO
  13#define PRF(x) x
  14#else
  15#define PRF(x)
  16#endif
  17
  18#define PRF_STR(s) PRF(printf("\n" s "\n"))
  19#define PRF_STR_INT(s, d) PRF(printf("\n" s " %d\n", (unsigned)d))
  20#define PRF_STR_INT_2(s, d1, d2) PRF(printf("\n" s " %d %d\n", (unsigned)d1, (unsigned)d2))
  21
  22// #define _7ZIP_ST
  23
  24#include "Alloc.h"
  25
  26#include "Lzma2Dec.h"
  27#include "Lzma2DecMt.h"
  28
  29#ifndef _7ZIP_ST
  30#include "MtDec.h"
  31#endif
  32
  33
  34#define LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT (1 << 28)
  35
  36void Lzma2DecMtProps_Init(CLzma2DecMtProps *p)
  37{
  38  p->inBufSize_ST = 1 << 20;
  39  p->outStep_ST = 1 << 20;
  40
  41  #ifndef _7ZIP_ST
  42  p->numThreads = 1;
  43  p->inBufSize_MT = 1 << 18;
  44  p->outBlockMax = LZMA2DECMT_OUT_BLOCK_MAX_DEFAULT;
  45  p->inBlockMax = p->outBlockMax + p->outBlockMax / 16;
  46  #endif
  47}
  48
  49
  50
  51#ifndef _7ZIP_ST
  52
  53/* ---------- CLzma2DecMtThread ---------- */
  54
  55typedef struct
  56{
  57  CLzma2Dec dec;
  58  Byte dec_created;
  59  Byte needInit;
  60  
  61  Byte *outBuf;
  62  size_t outBufSize;
  63
  64  EMtDecParseState state;
  65  ELzma2ParseStatus parseStatus;
  66
  67  size_t inPreSize;
  68  size_t outPreSize;
  69
  70  size_t inCodeSize;
  71  size_t outCodeSize;
  72  SRes codeRes;
  73
  74  CAlignOffsetAlloc alloc;
  75
  76  Byte mtPad[1 << 7];
  77} CLzma2DecMtThread;
  78
  79#endif
  80
  81
  82/* ---------- CLzma2DecMt ---------- */
  83
  84typedef struct
  85{
  86  // ISzAllocPtr alloc;
  87  ISzAllocPtr allocMid;
  88
  89  CAlignOffsetAlloc alignOffsetAlloc;
  90  CLzma2DecMtProps props;
  91  Byte prop;
  92  
  93  ISeqInStream *inStream;
  94  ISeqOutStream *outStream;
  95  ICompressProgress *progress;
  96
  97  BoolInt finishMode;
  98  BoolInt outSize_Defined;
  99  UInt64 outSize;
 100
 101  UInt64 outProcessed;
 102  UInt64 inProcessed;
 103  BoolInt readWasFinished;
 104  SRes readRes;
 105
 106  Byte *inBuf;
 107  size_t inBufSize;
 108  Byte dec_created;
 109  CLzma2Dec dec;
 110
 111  size_t inPos;
 112  size_t inLim;
 113
 114  #ifndef _7ZIP_ST
 115  UInt64 outProcessed_Parse;
 116  BoolInt mtc_WasConstructed;
 117  CMtDec mtc;
 118  CLzma2DecMtThread coders[MTDEC__THREADS_MAX];
 119  #endif
 120
 121} CLzma2DecMt;
 122
 123
 124
 125CLzma2DecMtHandle Lzma2DecMt_Create(ISzAllocPtr alloc, ISzAllocPtr allocMid)
 126{
 127  CLzma2DecMt *p = (CLzma2DecMt *)ISzAlloc_Alloc(alloc, sizeof(CLzma2DecMt));
 128  if (!p)
 129    return NULL;
 130  
 131  // p->alloc = alloc;
 132  p->allocMid = allocMid;
 133
 134  AlignOffsetAlloc_CreateVTable(&p->alignOffsetAlloc);
 135  p->alignOffsetAlloc.numAlignBits = 7;
 136  p->alignOffsetAlloc.offset = 0;
 137  p->alignOffsetAlloc.baseAlloc = alloc;
 138
 139  p->inBuf = NULL;
 140  p->inBufSize = 0;
 141  p->dec_created = False;
 142
 143  // Lzma2DecMtProps_Init(&p->props);
 144
 145  #ifndef _7ZIP_ST
 146  p->mtc_WasConstructed = False;
 147  {
 148    unsigned i;
 149    for (i = 0; i < MTDEC__THREADS_MAX; i++)
 150    {
 151      CLzma2DecMtThread *t = &p->coders[i];
 152      t->dec_created = False;
 153      t->outBuf = NULL;
 154      t->outBufSize = 0;
 155    }
 156  }
 157  #endif
 158
 159  return p;
 160}
 161
 162
 163#ifndef _7ZIP_ST
 164
 165static void Lzma2DecMt_FreeOutBufs(CLzma2DecMt *p)
 166{
 167  unsigned i;
 168  for (i = 0; i < MTDEC__THREADS_MAX; i++)
 169  {
 170    CLzma2DecMtThread *t = &p->coders[i];
 171    if (t->outBuf)
 172    {
 173      ISzAlloc_Free(p->allocMid, t->outBuf);
 174      t->outBuf = NULL;
 175      t->outBufSize = 0;
 176    }
 177  }
 178}
 179
 180#endif
 181
 182
 183static void Lzma2DecMt_FreeSt(CLzma2DecMt *p)
 184{
 185  if (p->dec_created)
 186  {
 187    Lzma2Dec_Free(&p->dec, &p->alignOffsetAlloc.vt);
 188    p->dec_created = False;
 189  }
 190  if (p->inBuf)
 191  {
 192    ISzAlloc_Free(p->allocMid, p->inBuf);
 193    p->inBuf = NULL;
 194  }
 195  p->inBufSize = 0;
 196}
 197
 198
 199void Lzma2DecMt_Destroy(CLzma2DecMtHandle pp)
 200{
 201  CLzma2DecMt *p = (CLzma2DecMt *)pp;
 202
 203  Lzma2DecMt_FreeSt(p);
 204
 205  #ifndef _7ZIP_ST
 206
 207  if (p->mtc_WasConstructed)
 208  {
 209    MtDec_Destruct(&p->mtc);
 210    p->mtc_WasConstructed = False;
 211  }
 212  {
 213    unsigned i;
 214    for (i = 0; i < MTDEC__THREADS_MAX; i++)
 215    {
 216      CLzma2DecMtThread *t = &p->coders[i];
 217      if (t->dec_created)
 218      {
 219        // we don't need to free dict here
 220        Lzma2Dec_FreeProbs(&t->dec, &t->alloc.vt); // p->alloc !!!
 221        t->dec_created = False;
 222      }
 223    }
 224  }
 225  Lzma2DecMt_FreeOutBufs(p);
 226
 227  #endif
 228
 229  ISzAlloc_Free(p->alignOffsetAlloc.baseAlloc, pp);
 230}
 231
 232
 233
 234#ifndef _7ZIP_ST
 235
 236static void Lzma2DecMt_MtCallback_Parse(void *obj, unsigned coderIndex, CMtDecCallbackInfo *cc)
 237{
 238  CLzma2DecMt *me = (CLzma2DecMt *)obj;
 239  CLzma2DecMtThread *t = &me->coders[coderIndex];
 240
 241  PRF_STR_INT_2("Parse", coderIndex, cc->srcSize);
 242
 243  cc->state = MTDEC_PARSE_CONTINUE;
 244
 245  if (cc->startCall)
 246  {
 247    if (!t->dec_created)
 248    {
 249      Lzma2Dec_Construct(&t->dec);
 250      t->dec_created = True;
 251      AlignOffsetAlloc_CreateVTable(&t->alloc);
 252      {
 253        /* (1 << 12) is expected size of one way in data cache.
 254           We optimize alignment for cache line size of 128 bytes and smaller */
 255        const unsigned kNumAlignBits = 12;
 256        const unsigned kNumCacheLineBits = 7; /* <= kNumAlignBits */
 257        t->alloc.numAlignBits = kNumAlignBits;
 258        t->alloc.offset = ((UInt32)coderIndex * ((1 << 11) + (1 << 8) + (1 << 6))) & ((1 << kNumAlignBits) - (1 << kNumCacheLineBits));
 259        t->alloc.baseAlloc = me->alignOffsetAlloc.baseAlloc;
 260      }
 261    }
 262    Lzma2Dec_Init(&t->dec);
 263    
 264    t->inPreSize = 0;
 265    t->outPreSize = 0;
 266    // t->blockWasFinished = False;
 267    // t->finishedWithMark = False;
 268    t->parseStatus = (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
 269    t->state = MTDEC_PARSE_CONTINUE;
 270
 271    t->inCodeSize = 0;
 272    t->outCodeSize = 0;
 273    t->codeRes = SZ_OK;
 274
 275    // (cc->srcSize == 0) is allowed
 276  }
 277
 278  {
 279    ELzma2ParseStatus status;
 280    BoolInt overflow;
 281    UInt32 unpackRem = 0;
 282    
 283    int checkFinishBlock = True;
 284    size_t limit = me->props.outBlockMax;
 285    if (me->outSize_Defined)
 286    {
 287      UInt64 rem = me->outSize - me->outProcessed_Parse;
 288      if (limit >= rem)
 289      {
 290        limit = (size_t)rem;
 291        if (!me->finishMode)
 292          checkFinishBlock = False;
 293      }
 294    }
 295
 296    // checkFinishBlock = False, if we want to decode partial data
 297    // that must be finished at position <= outBlockMax.
 298
 299    {
 300      const SizeT srcOrig = cc->srcSize;
 301      SizeT srcSize_Point = 0;
 302      SizeT dicPos_Point = 0;
 303      
 304      cc->srcSize = 0;
 305      overflow = False;
 306
 307      for (;;)
 308      {
 309        SizeT srcCur = srcOrig - cc->srcSize;
 310        
 311        status = Lzma2Dec_Parse(&t->dec,
 312            limit - t->dec.decoder.dicPos,
 313            cc->src + cc->srcSize, &srcCur,
 314            checkFinishBlock);
 315
 316        cc->srcSize += srcCur;
 317
 318        if (status == LZMA2_PARSE_STATUS_NEW_CHUNK)
 319        {
 320          if (t->dec.unpackSize > me->props.outBlockMax - t->dec.decoder.dicPos)
 321          {
 322            overflow = True;
 323            break;
 324          }
 325          continue;
 326        }
 327        
 328        if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
 329        {
 330          if (t->dec.decoder.dicPos == 0)
 331            continue;
 332          // we decode small blocks in one thread
 333          if (t->dec.decoder.dicPos >= (1 << 14))
 334            break;
 335          dicPos_Point = t->dec.decoder.dicPos;
 336          srcSize_Point = cc->srcSize;
 337          continue;
 338        }
 339
 340        if ((int)status == LZMA_STATUS_NOT_FINISHED && checkFinishBlock
 341            // && limit == t->dec.decoder.dicPos
 342            // && limit == me->props.outBlockMax
 343            )
 344        {
 345          overflow = True;
 346          break;
 347        }
 348        
 349        unpackRem = Lzma2Dec_GetUnpackExtra(&t->dec);
 350        break;
 351      }
 352
 353      if (dicPos_Point != 0
 354          && (int)status != LZMA2_PARSE_STATUS_NEW_BLOCK
 355          && (int)status != LZMA_STATUS_FINISHED_WITH_MARK
 356          && (int)status != LZMA_STATUS_NOT_SPECIFIED)
 357      {
 358        // we revert to latest newBlock state
 359        status = LZMA2_PARSE_STATUS_NEW_BLOCK;
 360        unpackRem = 0;
 361        t->dec.decoder.dicPos = dicPos_Point;
 362        cc->srcSize = srcSize_Point;
 363        overflow = False;
 364      }
 365    }
 366
 367    t->inPreSize += cc->srcSize;
 368    t->parseStatus = status;
 369
 370    if (overflow)
 371      cc->state = MTDEC_PARSE_OVERFLOW;
 372    else
 373    {
 374      size_t dicPos = t->dec.decoder.dicPos;
 375
 376      if ((int)status != LZMA_STATUS_NEEDS_MORE_INPUT)
 377      {
 378        if (status == LZMA2_PARSE_STATUS_NEW_BLOCK)
 379        {
 380          cc->state = MTDEC_PARSE_NEW;
 381          cc->srcSize--; // we don't need control byte of next block
 382          t->inPreSize--;
 383        }
 384        else
 385        {
 386          cc->state = MTDEC_PARSE_END;
 387          if ((int)status != LZMA_STATUS_FINISHED_WITH_MARK)
 388          {
 389            // (status == LZMA_STATUS_NOT_SPECIFIED)
 390            // (status == LZMA_STATUS_NOT_FINISHED)
 391            if (unpackRem != 0)
 392            {
 393              /* we also reserve space for max possible number of output bytes of current LZMA chunk */
 394              SizeT rem = limit - dicPos;
 395              if (rem > unpackRem)
 396                rem = unpackRem;
 397              dicPos += rem;
 398            }
 399          }
 400        }
 401    
 402        me->outProcessed_Parse += dicPos;
 403      }
 404      
 405      cc->outPos = dicPos;
 406      t->outPreSize = (size_t)dicPos;
 407    }
 408
 409    t->state = cc->state;
 410    return;
 411  }
 412}
 413
 414
 415static SRes Lzma2DecMt_MtCallback_PreCode(void *pp, unsigned coderIndex)
 416{
 417  CLzma2DecMt *me = (CLzma2DecMt *)pp;
 418  CLzma2DecMtThread *t = &me->coders[coderIndex];
 419  Byte *dest = t->outBuf;
 420
 421  if (t->inPreSize == 0)
 422  {
 423    t->codeRes = SZ_ERROR_DATA;
 424    return t->codeRes;
 425  }
 426
 427  if (!dest || t->outBufSize < t->outPreSize)
 428  {
 429    if (dest)
 430    {
 431      ISzAlloc_Free(me->allocMid, dest);
 432      t->outBuf = NULL;
 433      t->outBufSize = 0;
 434    }
 435
 436    dest = (Byte *)ISzAlloc_Alloc(me->allocMid, t->outPreSize
 437        // + (1 << 28)
 438        );
 439    // Sleep(200);
 440    if (!dest)
 441      return SZ_ERROR_MEM;
 442    t->outBuf = dest;
 443    t->outBufSize = t->outPreSize;
 444  }
 445
 446  t->dec.decoder.dic = dest;
 447  t->dec.decoder.dicBufSize = t->outPreSize;
 448
 449  t->needInit = True;
 450
 451  return Lzma2Dec_AllocateProbs(&t->dec, me->prop, &t->alloc.vt); // alloc.vt
 452}
 453
 454
 455static SRes Lzma2DecMt_MtCallback_Code(void *pp, unsigned coderIndex,
 456    const Byte *src, size_t srcSize, int srcFinished,
 457    // int finished, int blockFinished,
 458    UInt64 *inCodePos, UInt64 *outCodePos, int *stop)
 459{
 460  CLzma2DecMt *me = (CLzma2DecMt *)pp;
 461  CLzma2DecMtThread *t = &me->coders[coderIndex];
 462
 463  UNUSED_VAR(srcFinished)
 464
 465  PRF_STR_INT_2("Code", coderIndex, srcSize);
 466
 467  *inCodePos = t->inCodeSize;
 468  *outCodePos = 0;
 469  *stop = True;
 470
 471  if (t->needInit)
 472  {
 473    Lzma2Dec_Init(&t->dec);
 474    t->needInit = False;
 475  }
 476
 477  {
 478    ELzmaStatus status;
 479    size_t srcProcessed = srcSize;
 480    BoolInt blockWasFinished =
 481        ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
 482        || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK);
 483    
 484    SRes res = Lzma2Dec_DecodeToDic(&t->dec,
 485        t->outPreSize,
 486        src, &srcProcessed,
 487        blockWasFinished ? LZMA_FINISH_END : LZMA_FINISH_ANY,
 488        &status);
 489
 490    t->codeRes = res;
 491
 492    t->inCodeSize += srcProcessed;
 493    *inCodePos = t->inCodeSize;
 494    t->outCodeSize = t->dec.decoder.dicPos;
 495    *outCodePos = t->dec.decoder.dicPos;
 496
 497    if (res != SZ_OK)
 498      return res;
 499
 500    if (srcProcessed == srcSize)
 501      *stop = False;
 502
 503    if (blockWasFinished)
 504    {
 505      if (srcSize != srcProcessed)
 506        return SZ_ERROR_FAIL;
 507      
 508      if (t->inPreSize == t->inCodeSize)
 509      {
 510        if (t->outPreSize != t->outCodeSize)
 511          return SZ_ERROR_FAIL;
 512        *stop = True;
 513      }
 514    }
 515    else
 516    {
 517      if (t->outPreSize == t->outCodeSize)
 518        *stop = True;
 519    }
 520
 521    return SZ_OK;
 522  }
 523}
 524
 525
 526#define LZMA2DECMT_STREAM_WRITE_STEP (1 << 24)
 527
 528static SRes Lzma2DecMt_MtCallback_Write(void *pp, unsigned coderIndex,
 529    BoolInt needWriteToStream,
 530    const Byte *src, size_t srcSize,
 531    BoolInt *needContinue, BoolInt *canRecode)
 532{
 533  CLzma2DecMt *me = (CLzma2DecMt *)pp;
 534  const CLzma2DecMtThread *t = &me->coders[coderIndex];
 535  size_t size = t->outCodeSize;
 536  const Byte *data = t->outBuf;
 537  BoolInt needContinue2 = True;
 538
 539  PRF_STR_INT_2("Write", coderIndex, srcSize);
 540
 541  *needContinue = False;
 542  *canRecode = True;
 543  UNUSED_VAR(src)
 544  UNUSED_VAR(srcSize)
 545
 546  if (
 547      // t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
 548         t->state == MTDEC_PARSE_OVERFLOW
 549      || t->state == MTDEC_PARSE_END)
 550    needContinue2 = False;
 551
 552
 553  if (!needWriteToStream)
 554    return SZ_OK;
 555
 556  me->mtc.inProcessed += t->inCodeSize;
 557
 558  if (t->codeRes == SZ_OK)
 559  if ((int)t->parseStatus == LZMA_STATUS_FINISHED_WITH_MARK
 560      || t->parseStatus == LZMA2_PARSE_STATUS_NEW_BLOCK)
 561  if (t->outPreSize != t->outCodeSize
 562      || t->inPreSize != t->inCodeSize)
 563    return SZ_ERROR_FAIL;
 564
 565  *canRecode = False;
 566    
 567  if (me->outStream)
 568  {
 569    for (;;)
 570    {
 571      size_t cur = size;
 572      size_t written;
 573      if (cur > LZMA2DECMT_STREAM_WRITE_STEP)
 574        cur = LZMA2DECMT_STREAM_WRITE_STEP;
 575
 576      written = ISeqOutStream_Write(me->outStream, data, cur);
 577      
 578      me->outProcessed += written;
 579      // me->mtc.writtenTotal += written;
 580      if (written != cur)
 581        return SZ_ERROR_WRITE;
 582      data += cur;
 583      size -= cur;
 584      if (size == 0)
 585      {
 586        *needContinue = needContinue2;
 587        return SZ_OK;
 588      }
 589      RINOK(MtProgress_ProgressAdd(&me->mtc.mtProgress, 0, 0));
 590    }
 591  }
 592  
 593  return SZ_ERROR_FAIL;
 594  /*
 595  if (size > me->outBufSize)
 596    return SZ_ERROR_OUTPUT_EOF;
 597  memcpy(me->outBuf, data, size);
 598  me->outBufSize -= size;
 599  me->outBuf += size;
 600  *needContinue = needContinue2;
 601  return SZ_OK;
 602  */
 603}
 604
 605#endif
 606
 607
 608static SRes Lzma2Dec_Prepare_ST(CLzma2DecMt *p)
 609{
 610  if (!p->dec_created)
 611  {
 612    Lzma2Dec_Construct(&p->dec);
 613    p->dec_created = True;
 614  }
 615
 616  RINOK(Lzma2Dec_Allocate(&p->dec, p->prop, &p->alignOffsetAlloc.vt));
 617
 618  if (!p->inBuf || p->inBufSize != p->props.inBufSize_ST)
 619  {
 620    ISzAlloc_Free(p->allocMid, p->inBuf);
 621    p->inBufSize = 0;
 622    p->inBuf = (Byte *)ISzAlloc_Alloc(p->allocMid, p->props.inBufSize_ST);
 623    if (!p->inBuf)
 624      return SZ_ERROR_MEM;
 625    p->inBufSize = p->props.inBufSize_ST;
 626  }
 627
 628  Lzma2Dec_Init(&p->dec);
 629  
 630  return SZ_OK;
 631}
 632
 633
 634static SRes Lzma2Dec_Decode_ST(CLzma2DecMt *p
 635    #ifndef _7ZIP_ST
 636    , BoolInt tMode
 637    #endif
 638    )
 639{
 640  SizeT wrPos;
 641  size_t inPos, inLim;
 642  const Byte *inData;
 643  UInt64 inPrev, outPrev;
 644
 645  CLzma2Dec *dec;
 646
 647  #ifndef _7ZIP_ST
 648  if (tMode)
 649  {
 650    Lzma2DecMt_FreeOutBufs(p);
 651    tMode = MtDec_PrepareRead(&p->mtc);
 652  }
 653  #endif
 654
 655  RINOK(Lzma2Dec_Prepare_ST(p));
 656
 657  dec = &p->dec;
 658
 659  inPrev = p->inProcessed;
 660  outPrev = p->outProcessed;
 661
 662  inPos = 0;
 663  inLim = 0;
 664  inData = NULL;
 665  wrPos = dec->decoder.dicPos;
 666
 667  for (;;)
 668  {
 669    SizeT dicPos;
 670    SizeT size;
 671    ELzmaFinishMode finishMode;
 672    SizeT inProcessed;
 673    ELzmaStatus status;
 674    SRes res;
 675
 676    SizeT outProcessed;
 677    BoolInt outFinished;
 678    BoolInt needStop;
 679
 680    if (inPos == inLim)
 681    {
 682      #ifndef _7ZIP_ST
 683      if (tMode)
 684      {
 685        inData = MtDec_Read(&p->mtc, &inLim);
 686        inPos = 0;
 687        if (inData)
 688          continue;
 689        tMode = False;
 690        inLim = 0;
 691      }
 692      #endif
 693      
 694      if (!p->readWasFinished)
 695      {
 696        inPos = 0;
 697        inLim = p->inBufSize;
 698        inData = p->inBuf;
 699        p->readRes = ISeqInStream_Read(p->inStream, (void *)inData, &inLim);
 700        // p->readProcessed += inLim;
 701        // inLim -= 5; p->readWasFinished = True; // for test
 702        if (inLim == 0 || p->readRes != SZ_OK)
 703          p->readWasFinished = True;
 704      }
 705    }
 706
 707    dicPos = dec->decoder.dicPos;
 708    {
 709      SizeT next = dec->decoder.dicBufSize;
 710      if (next - wrPos > p->props.outStep_ST)
 711        next = wrPos + p->props.outStep_ST;
 712      size = next - dicPos;
 713    }
 714
 715    finishMode = LZMA_FINISH_ANY;
 716    if (p->outSize_Defined)
 717    {
 718      const UInt64 rem = p->outSize - p->outProcessed;
 719      if (size >= rem)
 720      {
 721        size = (SizeT)rem;
 722        if (p->finishMode)
 723          finishMode = LZMA_FINISH_END;
 724      }
 725    }
 726
 727    inProcessed = inLim - inPos;
 728    
 729    res = Lzma2Dec_DecodeToDic(dec, dicPos + size, inData + inPos, &inProcessed, finishMode, &status);
 730
 731    inPos += inProcessed;
 732    p->inProcessed += inProcessed;
 733    outProcessed = dec->decoder.dicPos - dicPos;
 734    p->outProcessed += outProcessed;
 735
 736    outFinished = (p->outSize_Defined && p->outSize <= p->outProcessed);
 737
 738    needStop = (res != SZ_OK
 739        || (inProcessed == 0 && outProcessed == 0)
 740        || status == LZMA_STATUS_FINISHED_WITH_MARK
 741        || (!p->finishMode && outFinished));
 742
 743    if (needStop || outProcessed >= size)
 744    {
 745      SRes res2;
 746      {
 747        size_t writeSize = dec->decoder.dicPos - wrPos;
 748        size_t written = ISeqOutStream_Write(p->outStream, dec->decoder.dic + wrPos, writeSize);
 749        res2 = (written == writeSize) ? SZ_OK : SZ_ERROR_WRITE;
 750      }
 751
 752      if (dec->decoder.dicPos == dec->decoder.dicBufSize)
 753        dec->decoder.dicPos = 0;
 754      wrPos = dec->decoder.dicPos;
 755
 756      RINOK(res2);
 757
 758      if (needStop)
 759      {
 760        if (res != SZ_OK)
 761          return res;
 762
 763        if (status == LZMA_STATUS_FINISHED_WITH_MARK)
 764        {
 765          if (p->finishMode)
 766          {
 767            if (p->outSize_Defined && p->outSize != p->outProcessed)
 768              return SZ_ERROR_DATA;
 769          }
 770          return SZ_OK;
 771        }
 772
 773        if (!p->finishMode && outFinished)
 774          return SZ_OK;
 775
 776        if (status == LZMA_STATUS_NEEDS_MORE_INPUT)
 777          return SZ_ERROR_INPUT_EOF;
 778        
 779        return SZ_ERROR_DATA;
 780      }
 781    }
 782    
 783    if (p->progress)
 784    {
 785      UInt64 inDelta = p->inProcessed - inPrev;
 786      UInt64 outDelta = p->outProcessed - outPrev;
 787      if (inDelta >= (1 << 22) || outDelta >= (1 << 22))
 788      {
 789        RINOK(ICompressProgress_Progress(p->progress, p->inProcessed, p->outProcessed));
 790        inPrev = p->inProcessed;
 791        outPrev = p->outProcessed;
 792      }
 793    }
 794  }
 795}
 796
 797
 798
 799SRes Lzma2DecMt_Decode(CLzma2DecMtHandle pp,
 800    Byte prop,
 801    const CLzma2DecMtProps *props,
 802    ISeqOutStream *outStream, const UInt64 *outDataSize, int finishMode,
 803    // Byte *outBuf, size_t *outBufSize,
 804    ISeqInStream *inStream,
 805    // const Byte *inData, size_t inDataSize,
 806    UInt64 *inProcessed,
 807    // UInt64 *outProcessed,
 808    int *isMT,
 809    ICompressProgress *progress)
 810{
 811  CLzma2DecMt *p = (CLzma2DecMt *)pp;
 812  #ifndef _7ZIP_ST
 813  BoolInt tMode;
 814  #endif
 815
 816  *inProcessed = 0;
 817
 818  if (prop > 40)
 819    return SZ_ERROR_UNSUPPORTED;
 820
 821  p->prop = prop;
 822  p->props = *props;
 823
 824  p->inStream = inStream;
 825  p->outStream = outStream;
 826  p->progress = progress;
 827
 828  p->outSize = 0;
 829  p->outSize_Defined = False;
 830  if (outDataSize)
 831  {
 832    p->outSize_Defined = True;
 833    p->outSize = *outDataSize;
 834  }
 835  p->finishMode = finishMode;
 836
 837  p->outProcessed = 0;
 838  p->inProcessed = 0;
 839
 840  p->readWasFinished = False;
 841
 842  *isMT = False;
 843
 844  
 845  #ifndef _7ZIP_ST
 846
 847  tMode = False;
 848
 849  // p->mtc.parseRes = SZ_OK;
 850
 851  // p->mtc.numFilledThreads = 0;
 852  // p->mtc.crossStart = 0;
 853  // p->mtc.crossEnd = 0;
 854  // p->mtc.allocError_for_Read_BlockIndex = 0;
 855  // p->mtc.isAllocError = False;
 856
 857  if (p->props.numThreads > 1)
 858  {
 859    IMtDecCallback vt;
 860
 861    Lzma2DecMt_FreeSt(p);
 862
 863    p->outProcessed_Parse = 0;
 864
 865    if (!p->mtc_WasConstructed)
 866    {
 867      p->mtc_WasConstructed = True;
 868      MtDec_Construct(&p->mtc);
 869    }
 870    
 871    p->mtc.progress = progress;
 872    p->mtc.inStream = inStream;
 873
 874    // p->outBuf = NULL;
 875    // p->outBufSize = 0;
 876    /*
 877    if (!outStream)
 878    {
 879      // p->outBuf = outBuf;
 880      // p->outBufSize = *outBufSize;
 881      // *outBufSize = 0;
 882      return SZ_ERROR_PARAM;
 883    }
 884    */
 885
 886    // p->mtc.inBlockMax = p->props.inBlockMax;
 887    p->mtc.alloc = &p->alignOffsetAlloc.vt;
 888      // p->alignOffsetAlloc.baseAlloc;
 889    // p->mtc.inData = inData;
 890    // p->mtc.inDataSize = inDataSize;
 891    p->mtc.mtCallback = &vt;
 892    p->mtc.mtCallbackObject = p;
 893
 894    p->mtc.inBufSize = p->props.inBufSize_MT;
 895
 896    p->mtc.numThreadsMax = p->props.numThreads;
 897
 898    *isMT = True;
 899
 900    vt.Parse = Lzma2DecMt_MtCallback_Parse;
 901    vt.PreCode = Lzma2DecMt_MtCallback_PreCode;
 902    vt.Code = Lzma2DecMt_MtCallback_Code;
 903    vt.Write = Lzma2DecMt_MtCallback_Write;
 904
 905    {
 906      BoolInt needContinue = False;
 907
 908      SRes res = MtDec_Code(&p->mtc);
 909
 910      /*
 911      if (!outStream)
 912        *outBufSize = p->outBuf - outBuf;
 913      */
 914
 915      *inProcessed = p->mtc.inProcessed;
 916
 917      needContinue = False;
 918
 919      if (res == SZ_OK)
 920      {
 921        if (p->mtc.mtProgress.res != SZ_OK)
 922          res = p->mtc.mtProgress.res;
 923        else
 924          needContinue = p->mtc.needContinue;
 925      }
 926
 927      if (!needContinue)
 928      {
 929        if (res == SZ_OK)
 930          return p->mtc.readRes;
 931        return res;
 932      }
 933
 934      tMode = True;
 935      p->readRes = p->mtc.readRes;
 936      p->readWasFinished = p->mtc.readWasFinished;
 937      p->inProcessed = p->mtc.inProcessed;
 938      
 939      PRF_STR("----- decoding ST -----");
 940    }
 941  }
 942
 943  #endif
 944
 945
 946  *isMT = False;
 947
 948  {
 949    SRes res = Lzma2Dec_Decode_ST(p
 950        #ifndef _7ZIP_ST
 951        , tMode
 952        #endif
 953        );
 954
 955    *inProcessed = p->inProcessed;
 956
 957    // res = SZ_OK; // for test
 958    if (res == SZ_OK && p->readRes != SZ_OK)
 959      res = p->readRes;
 960    
 961    /*
 962    #ifndef _7ZIP_ST
 963    if (res == SZ_OK && tMode && p->mtc.parseRes != SZ_OK)
 964      res = p->mtc.parseRes;
 965    #endif
 966    */
 967    
 968    return res;
 969  }
 970}
 971
 972
 973/* ---------- Read from CLzma2DecMtHandle Interface ---------- */
 974
 975SRes Lzma2DecMt_Init(CLzma2DecMtHandle pp,
 976    Byte prop,
 977    const CLzma2DecMtProps *props,
 978    const UInt64 *outDataSize, int finishMode,
 979    ISeqInStream *inStream)
 980{
 981  CLzma2DecMt *p = (CLzma2DecMt *)pp;
 982
 983  if (prop > 40)
 984    return SZ_ERROR_UNSUPPORTED;
 985
 986  p->prop = prop;
 987  p->props = *props;
 988
 989  p->inStream = inStream;
 990
 991  p->outSize = 0;
 992  p->outSize_Defined = False;
 993  if (outDataSize)
 994  {
 995    p->outSize_Defined = True;
 996    p->outSize = *outDataSize;
 997  }
 998  p->finishMode = finishMode;
 999
1000  p->outProcessed = 0;
1001  p->inProcessed = 0;
1002
1003  p->inPos = 0;
1004  p->inLim = 0;
1005
1006  return Lzma2Dec_Prepare_ST(p);
1007}
1008
1009
1010SRes Lzma2DecMt_Read(CLzma2DecMtHandle pp,
1011    Byte *data, size_t *outSize,
1012    UInt64 *inStreamProcessed)
1013{
1014  CLzma2DecMt *p = (CLzma2DecMt *)pp;
1015  ELzmaFinishMode finishMode;
1016  SRes readRes;
1017  size_t size = *outSize;
1018
1019  *outSize = 0;
1020  *inStreamProcessed = 0;
1021
1022  finishMode = LZMA_FINISH_ANY;
1023  if (p->outSize_Defined)
1024  {
1025    const UInt64 rem = p->outSize - p->outProcessed;
1026    if (size >= rem)
1027    {
1028      size = (size_t)rem;
1029      if (p->finishMode)
1030        finishMode = LZMA_FINISH_END;
1031    }
1032  }
1033
1034  readRes = SZ_OK;
1035
1036  for (;;)
1037  {
1038    SizeT inCur;
1039    SizeT outCur;
1040    ELzmaStatus status;
1041    SRes res;
1042
1043    if (p->inPos == p->inLim && readRes == SZ_OK)
1044    {
1045      p->inPos = 0;
1046      p->inLim = p->props.inBufSize_ST;
1047      readRes = ISeqInStream_Read(p->inStream, p->inBuf, &p->inLim);
1048    }
1049
1050    inCur = p->inLim - p->inPos;
1051    outCur = size;
1052
1053    res = Lzma2Dec_DecodeToBuf(&p->dec, data, &outCur,
1054        p->inBuf + p->inPos, &inCur, finishMode, &status);
1055    
1056    p->inPos += inCur;
1057    p->inProcessed += inCur;
1058    *inStreamProcessed += inCur;
1059    p->outProcessed += outCur;
1060    *outSize += outCur;
1061    size -= outCur;
1062    data += outCur;
1063    
1064    if (res != 0)
1065      return res;
1066    
1067    /*
1068    if (status == LZMA_STATUS_FINISHED_WITH_MARK)
1069      return readRes;
1070
1071    if (size == 0 && status != LZMA_STATUS_NEEDS_MORE_INPUT)
1072    {
1073      if (p->finishMode && p->outSize_Defined && p->outProcessed >= p->outSize)
1074        return SZ_ERROR_DATA;
1075      return readRes;
1076    }
1077    */
1078
1079    if (inCur == 0 && outCur == 0)
1080      return readRes;
1081  }
1082}