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 + -
显示快捷键?