示例#1
0
static UInt32 NO_INLINE DecodeBlock(const CBlockProps &props, UInt32 *tt, COutBuffer &m_OutStream)
{
  if (props.randMode)
    return DecodeBlock2Rand(tt, props.blockSize, props.origPtr, m_OutStream);
  else
    return DecodeBlock2    (tt, props.blockSize, props.origPtr, m_OutStream);
}
示例#2
0
void CState::ThreadFunc()
{
  for (;;)
  {
    Decoder->CanProcessEvent.Lock();
    Decoder->CS.Enter();
    if (Decoder->CloseThreads)
    {
      Decoder->CS.Leave();
      return;
    }
    if (Decoder->StreamWasFinished1)
    {
      FinishStream();
      continue;
    }
    HRESULT res = S_OK;

    UInt32 blockIndex = Decoder->NextBlockIndex;
    UInt32 nextBlockIndex = blockIndex + 1;
    if (nextBlockIndex == Decoder->NumThreads)
      nextBlockIndex = 0;
    Decoder->NextBlockIndex = nextBlockIndex;
    UInt32 crc;
    UInt64 packSize;
    UInt32 blockSize = 0, origPtr = 0;
    bool randMode = false;

    try
    {
      bool wasFinished;
      res = Decoder->ReadSignatures(wasFinished, crc);
      if (res != S_OK)
      {
        Decoder->Result1 = res;
        FinishStream();
        continue;
      }
      if (wasFinished)
      {
        Decoder->Result1 = res;
        FinishStream();
        continue;
      }

      res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax,
          Decoder->m_Selectors, Decoder->m_HuffmanDecoders,
          &blockSize, &origPtr, &randMode);
      if (res != S_OK)
      {
        Decoder->Result1 = res;
        FinishStream();
        continue;
      }
      packSize = Decoder->m_InStream.GetProcessedSize();
    }
    catch(const CInBufferException &e) { res = e.ErrorCode;  if (res != S_OK) res = E_FAIL; }
    catch(...) { res = E_FAIL; }
    if (res != S_OK)
    {
      Decoder->Result1 = res;
      FinishStream();
      continue;
    }

    Decoder->CS.Leave();

    DecodeBlock1(Counters, blockSize);

    bool needFinish = true;
    try
    {
      Decoder->m_States[blockIndex].CanWriteEvent.Lock();
      needFinish = Decoder->StreamWasFinished2;
      if (!needFinish)
      {
        if ((randMode ?
          DecodeBlock2Rand(Counters + 256, blockSize, origPtr, Decoder->m_OutStream) :
          DecodeBlock2(Counters + 256, blockSize, origPtr, Decoder->m_OutStream)) == crc)
        {
          if (Decoder->Progress)
          {
            UInt64 unpackSize = Decoder->m_OutStream.GetProcessedSize();
            res = Decoder->Progress->SetRatioInfo(&packSize, &unpackSize);
          }
        }
        else
          res = S_FALSE;
      }
    }
    catch(const COutBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; }
    catch(...) { res = E_FAIL; }
    if (res != S_OK)
    {
      Decoder->Result2 = res;
      Decoder->StreamWasFinished2 = true;
    }
    Decoder->m_States[nextBlockIndex].CanWriteEvent.Set();
    if (res != S_OK || needFinish)
    {
      StreamWasFinishedEvent.Set();
      Decoder->CanStartWaitingEvent.Lock();
      WaitingWasStartedEvent.Set();
    }
  }
}
示例#3
0
HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress)
{
  #ifdef COMPRESS_BZIP2_MT
  Progress = progress;
  RINOK(Create());
  for (UInt32 t = 0; t < NumThreads; t++)
  {
    CState &s = m_States[t];
    if (!s.Alloc())
      return E_OUTOFMEMORY;
    if (MtMode)
    {
      RINOK(s.StreamWasFinishedEvent.Reset());
      RINOK(s.WaitingWasStartedEvent.Reset());
      RINOK(s.CanWriteEvent.Reset());
    }
  }
  #else
  if (!m_States[0].Alloc())
    return E_OUTOFMEMORY;
  #endif

  isBZ = false;
  Byte s[6];
  int i;
  for (i = 0; i < 4; i++)
    s[i] = ReadByte();
  if (s[0] != kArSig0 ||
      s[1] != kArSig1 ||
      s[2] != kArSig2 ||
      s[3] <= kArSig3 ||
      s[3] > kArSig3 + kBlockSizeMultMax)
    return S_OK;
  isBZ = true;
  UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep;

  CombinedCrc.Init();
  #ifdef COMPRESS_BZIP2_MT
  if (MtMode)
  {
    NextBlockIndex = 0;
    StreamWasFinished1 = StreamWasFinished2 = false;
    CloseThreads = false;
    CanStartWaitingEvent.Reset();
    m_States[0].CanWriteEvent.Set();
    BlockSizeMax = dicSize;
    Result1 = Result2 = S_OK;
    CanProcessEvent.Set();
    UInt32 t;
    for (t = 0; t < NumThreads; t++)
      m_States[t].StreamWasFinishedEvent.Lock();
    CanProcessEvent.Reset();
    CanStartWaitingEvent.Set();
    for (t = 0; t < NumThreads; t++)
      m_States[t].WaitingWasStartedEvent.Lock();
    CanStartWaitingEvent.Reset();
    RINOK(Result2);
    RINOK(Result1);
  }
  else
  #endif
  {
    CState &state = m_States[0];
    for (;;)
    {
      if (progress)
      {
        UInt64 packSize = m_InStream.GetProcessedSize();
        UInt64 unpackSize = m_OutStream.GetProcessedSize();
        RINOK(progress->SetRatioInfo(&packSize, &unpackSize));
      }
      bool wasFinished;
      UInt32 crc;
      RINOK(ReadSignatures(wasFinished, crc));
      if (wasFinished)
        return S_OK;

      UInt32 blockSize, origPtr;
      bool randMode;
      RINOK(ReadBlock(&m_InStream, state.Counters, dicSize,
        m_Selectors, m_HuffmanDecoders,
        &blockSize, &origPtr, &randMode));
      DecodeBlock1(state.Counters, blockSize);
      if ((randMode ?
          DecodeBlock2Rand(state.Counters + 256, blockSize, origPtr, m_OutStream) :
          DecodeBlock2(state.Counters + 256, blockSize, origPtr, m_OutStream)) != crc)
        return S_FALSE;
    }
  }
  return S_OK;
}