bzip2decoder.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 649 行 · 第 1/2 页

CPP
649
字号
      }       if (nextSym <= (UInt32)numInUse)       {        Byte b = mtf.GetAndMove((int)nextSym - 1);        if (blockSize >= blockSizeMax)           return S_FALSE;        state.CharCounters[b]++;        state.tt[blockSize++] = (UInt32)b;      }      else if (nextSym == (UInt32)numInUse + 1)         break;      else         return S_FALSE;    }  }  if (state.OrigPtr >= blockSize)    return S_FALSE;  state.BlockSize = blockSize;  return S_OK;}void CState::DecodeBlock1(){  UInt32 *charCounters = this->CharCounters;  {    UInt32 sum = 0;    for (UInt32 i = 0; i < 256; i++)     {      sum += charCounters[i];      charCounters[i] = sum - charCounters[i];    }  }    // Compute the T^(-1) vector  UInt32 blockSize = this->BlockSize;  UInt32 i = 0;  do    tt[charCounters[tt[i] & 0xFF]++] |= (i << 8);  while(++i < blockSize);}UInt32 CState::DecodeBlock2(COutBuffer &m_OutStream){  UInt32 blockSize = this->BlockSize;  CBZip2CRC crc;    UInt32 randIndex = 1;  UInt32 randToGo = kRandNums[0] - 2;    int numReps = 0;  // it's for speed optimization: prefetch & prevByte_init;  UInt32 tPos = tt[tt[OrigPtr] >> 8];  Byte prevByte = (Byte)(tPos & 0xFF);    do  {    Byte b = (Byte)(tPos & 0xFF);    tPos = tt[tPos >> 8];        if (BlockRandomised)     {      if (randToGo == 0)       {        b ^= 1;        randToGo = kRandNums[randIndex++];        randIndex &= 0x1FF;      }      randToGo--;    }        if (numReps == kRleModeRepSize)    {      for (; b > 0; b--)      {        crc.UpdateByte(prevByte);        m_OutStream.WriteByte(prevByte);      }      numReps = 0;      continue;    }    if (prevByte == b)      numReps++;    else    {      numReps = 1;      prevByte = b;    }    crc.UpdateByte(b);    m_OutStream.WriteByte(b);  }  while(--blockSize != 0);  return crc.GetDigest();}#ifdef COMPRESS_BZIP2_MTCDecoder::CDecoder():  m_States(0){  m_NumThreadsPrev = 0;  NumThreads = 1;  CS.Enter();}CDecoder::~CDecoder(){  Free();}bool CDecoder::Create(){  try   {     if (m_States != 0 && m_NumThreadsPrev == NumThreads)      return true;    Free();    MtMode = (NumThreads > 1);    m_NumThreadsPrev = NumThreads;    m_States = new CState[NumThreads];    if (m_States == 0)      return false;    #ifdef COMPRESS_BZIP2_MT    for (UInt32 t = 0; t < NumThreads; t++)    {      CState &ti = m_States[t];      ti.Decoder = this;      if (MtMode)        if (!ti.Thread.Create(MFThread, &ti))        {          NumThreads = t;          Free();          return false;         }    }    #endif  }  catch(...) { return false; }  return true;}void CDecoder::Free(){  if (!m_States)    return;  CloseThreads = true;  CS.Leave();  for (UInt32 t = 0; t < NumThreads; t++)  {    CState &s = m_States[t];    if (MtMode)      s.Thread.Wait();    s.Free();  }  delete []m_States;  m_States = 0;}#endifHRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc){  wasFinished = false;  Byte s[6];  for (int i = 0; i < 6; i++)    s[i] = ReadByte();  crc = ReadCRC();  if (s[0] == kFinSig0)  {    if (s[1] != kFinSig1 ||         s[2] != kFinSig2 ||         s[3] != kFinSig3 ||         s[4] != kFinSig4 ||         s[5] != kFinSig5)      return S_FALSE;        wasFinished = true;    return (crc == CombinedCRC.GetDigest()) ? S_OK : S_FALSE;  }  if (s[0] != kBlockSig0 ||       s[1] != kBlockSig1 ||       s[2] != kBlockSig2 ||       s[3] != kBlockSig3 ||       s[4] != kBlockSig4 ||       s[5] != kBlockSig5)    return S_FALSE;  CombinedCRC.Update(crc);  return S_OK;}HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress){  #ifdef COMPRESS_BZIP2_MT  Progress = progress;  if (!Create())    return E_FAIL;  for (UInt32 t = 0; t < NumThreads; t++)  {    CState &s = m_States[t];    if (!s.Alloc())      return E_OUTOFMEMORY;    s.StreamWasFinishedEvent.Reset();    s.WaitingWasStartedEvent.Reset();    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;    StreamWasFinished = false;    CloseThreads = false;    CanStartWaitingEvent.Reset();    m_States[0].CanWriteEvent.Set();    BlockSizeMax = dicSize;    Result = S_OK;    CS.Leave();    UInt32 t;    for (t = 0; t < NumThreads; t++)      m_States[t].StreamWasFinishedEvent.Lock();    CS.Enter();    CanStartWaitingEvent.Set();    for (t = 0; t < NumThreads; t++)      m_States[t].WaitingWasStartedEvent.Lock();    CanStartWaitingEvent.Reset();    RINOK(Result);  }  else  #endif  {    CState &state = m_States[0];    while (true)    {      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;      RINOK(ReadBlock(dicSize, state));      state.DecodeBlock1();      if (state.DecodeBlock2(m_OutStream) != crc)        return S_FALSE;    }  }  return S_OK;}HRESULT CDecoder::CodeReal(ISequentialInStream *inStream,    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress){  if (!m_InStream.Create(kBufferSize))    return E_OUTOFMEMORY;  if (!m_OutStream.Create(kBufferSize))    return E_OUTOFMEMORY;  m_InStream.SetStream(inStream);  m_InStream.Init();  m_OutStream.SetStream(outStream);  m_OutStream.Init();  CDecoderFlusher flusher(this);  bool isBZ;  RINOK(DecodeFile(isBZ, progress));  return isBZ ? S_OK: S_FALSE;}STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream,    ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,    ICompressProgressInfo *progress){  try { return CodeReal(inStream, outStream, inSize, outSize, progress); }  catch(...) { return S_FALSE; }}STDMETHODIMP CDecoder::GetInStreamProcessedSize(UInt64 *value){  if (value == NULL)    return E_INVALIDARG;  *value = m_InStream.GetProcessedSize();  return S_OK;}#ifdef COMPRESS_BZIP2_MTSTDMETHODIMP CDecoder::SetNumberOfThreads(UInt32 numThreads){  NumThreads = numThreads;  if (NumThreads < 1)    NumThreads = 1;  if (NumThreads > kNumThreadsMax)    NumThreads = kNumThreadsMax;  return S_OK;}#endif}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?