diff options
Diffstat (limited to 'CPP/7zip/Compress/BZip2Decoder.cpp')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/Compress/BZip2Decoder.cpp | 318 |
1 files changed, 184 insertions, 134 deletions
diff --git a/CPP/7zip/Compress/BZip2Decoder.cpp b/CPP/7zip/Compress/BZip2Decoder.cpp index cb1f981a..3798421e 100755..100644 --- a/CPP/7zip/Compress/BZip2Decoder.cpp +++ b/CPP/7zip/Compress/BZip2Decoder.cpp @@ -85,41 +85,21 @@ void CState::Free() Counters = 0; } -UInt32 CDecoder::ReadBits(unsigned numBits) { return m_InStream.ReadBits(numBits); } -Byte CDecoder::ReadByte() {return (Byte)ReadBits(8); } -bool CDecoder::ReadBit() { return ReadBits(1) != 0; } +Byte CDecoder::ReadByte() { return (Byte)Base.ReadBits(8); } -UInt32 CDecoder::ReadCrc() -{ - UInt32 crc = 0; - for (int i = 0; i < 4; i++) - { - crc <<= 8; - crc |= ReadByte(); - } - return crc; -} +UInt32 CBase::ReadBits(unsigned numBits) { return BitDecoder.ReadBits(numBits); } +unsigned CBase::ReadBit() { return (unsigned)BitDecoder.ReadBits(1); } -static UInt32 NO_INLINE ReadBits(NBitm::CDecoder<CInBuffer> *m_InStream, unsigned num) +HRESULT CBase::ReadBlock(UInt32 *charCounters, UInt32 blockSizeMax, CBlockProps *props) { - return m_InStream->ReadBits(num); -} - -static UInt32 NO_INLINE ReadBit(NBitm::CDecoder<CInBuffer> *m_InStream) -{ - return m_InStream->ReadBits(1); -} + NumBlocks++; -static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, - UInt32 *CharCounters, UInt32 blockSizeMax, Byte *m_Selectors, CHuffmanDecoder *m_HuffmanDecoders, - UInt32 *blockSizeRes, UInt32 *origPtrRes, bool *randRes) -{ - if (randRes) - *randRes = ReadBit(m_InStream) ? true : false; - *origPtrRes = ReadBits(m_InStream, kNumOrigBits); + if (props->randMode) + props->randMode = ReadBit() ? true : false; + props->origPtr = ReadBits(kNumOrigBits); // in original code it compares OrigPtr to (UInt32)(10 + blockSizeMax)) : why ? - if (*origPtrRes >= blockSizeMax) + if (props->origPtr >= blockSizeMax) return S_FALSE; CMtf8Decoder mtf; @@ -130,11 +110,11 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, Byte inUse16[16]; int i; for (i = 0; i < 16; i++) - inUse16[i] = (Byte)ReadBit(m_InStream); + inUse16[i] = (Byte)ReadBit(); for (i = 0; i < 256; i++) if (inUse16[i >> 4]) { - if (ReadBit(m_InStream)) + if (ReadBit()) mtf.Add(numInUse++, (Byte)i); } if (numInUse == 0) @@ -143,11 +123,11 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, } int alphaSize = numInUse + 2; - int numTables = ReadBits(m_InStream, kNumTablesBits); + int numTables = ReadBits(kNumTablesBits); if (numTables < kNumTablesMin || numTables > kNumTablesMax) return S_FALSE; - UInt32 numSelectors = ReadBits(m_InStream, kNumSelectorsBits); + UInt32 numSelectors = ReadBits(kNumSelectorsBits); if (numSelectors < 1 || numSelectors > kNumSelectorsMax) return S_FALSE; @@ -156,12 +136,12 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, int t = 0; do mtfPos[t] = (Byte)t; - while(++t < numTables); + while (++t < numTables); UInt32 i = 0; do { int j = 0; - while (ReadBit(m_InStream)) + while (ReadBit()) if (++j >= numTables) return S_FALSE; Byte tmp = mtfPos[j]; @@ -169,14 +149,14 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, mtfPos[j] = mtfPos[j - 1]; m_Selectors[i] = mtfPos[0] = tmp; } - while(++i < numSelectors); + while (++i < numSelectors); } int t = 0; do { Byte lens[kMaxAlphaSize]; - int len = (int)ReadBits(m_InStream, kNumLevelsBits); + int len = (int)ReadBits(kNumLevelsBits); int i; for (i = 0; i < alphaSize; i++) { @@ -184,22 +164,22 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, { if (len < 1 || len > kMaxHuffmanLen) return S_FALSE; - if (!ReadBit(m_InStream)) + if (!ReadBit()) break; - len += 1 - (int)(ReadBit(m_InStream) << 1); + len += 1 - (int)(ReadBit() << 1); } lens[i] = (Byte)len; } for (; i < kMaxAlphaSize; i++) lens[i] = 0; - if(!m_HuffmanDecoders[t].SetCodeLengths(lens)) + if (!m_HuffmanDecoders[t].SetCodeLengths(lens)) return S_FALSE; } - while(++t < numTables); + while (++t < numTables); { for (int i = 0; i < 256; i++) - CharCounters[i] = 0; + charCounters[i] = 0; } UInt32 blockSize = 0; @@ -221,7 +201,10 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, } groupSize--; - UInt32 nextSym = huffmanDecoder->DecodeSymbol(m_InStream); + if (BitDecoder.ExtraBitsWereRead_Fast()) + break; + + UInt32 nextSym = huffmanDecoder->DecodeSymbol(&BitDecoder); if (nextSym < 2) { @@ -233,10 +216,10 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, if (runCounter != 0) { UInt32 b = (UInt32)mtf.GetHead(); - CharCounters[b] += runCounter; + charCounters[b] += runCounter; do - CharCounters[256 + blockSize++] = b; - while(--runCounter != 0); + charCounters[256 + blockSize++] = b; + while (--runCounter != 0); runPower = 0; } if (nextSym <= (UInt32)numInUse) @@ -244,17 +227,20 @@ static HRESULT NO_INLINE ReadBlock(NBitm::CDecoder<CInBuffer> *m_InStream, UInt32 b = (UInt32)mtf.GetAndMove((int)nextSym - 1); if (blockSize >= blockSizeMax) return S_FALSE; - CharCounters[b]++; - CharCounters[256 + blockSize++] = b; + charCounters[b]++; + charCounters[256 + blockSize++] = b; } else if (nextSym == (UInt32)numInUse + 1) break; else return S_FALSE; } + + if (BitDecoder.ExtraBitsWereRead()) + return S_FALSE; } - *blockSizeRes = blockSize; - return (*origPtrRes < blockSize) ? S_OK : S_FALSE; + props->blockSize = blockSize; + return (props->origPtr < props->blockSize) ? S_OK : S_FALSE; } static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) @@ -273,7 +259,7 @@ static void NO_INLINE DecodeBlock1(UInt32 *charCounters, UInt32 blockSize) UInt32 i = 0; do tt[charCounters[tt[i] & 0xFF]++] |= (i << 8); - while(++i < blockSize); + while (++i < blockSize); } static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 OrigPtr, COutBuffer &m_OutStream) @@ -363,7 +349,7 @@ static UInt32 NO_INLINE DecodeBlock2(const UInt32 *tt, UInt32 blockSize, UInt32 } */ } - while(--blockSize != 0); + while (--blockSize != 0); return crc.GetDigest(); } @@ -412,10 +398,17 @@ static UInt32 NO_INLINE DecodeBlock2Rand(const UInt32 *tt, UInt32 blockSize, UIn crc.UpdateByte(b); m_OutStream.WriteByte((Byte)b); } - while(--blockSize != 0); + while (--blockSize != 0); return crc.GetDigest(); } +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); +} CDecoder::CDecoder() { @@ -434,7 +427,7 @@ CDecoder::~CDecoder() Free(); } -#define RINOK_THREAD(x) { WRes __result_ = (x); if(__result_ != 0) return __result_; } +#define RINOK_THREAD(x) { WRes __result_ = (x); if (__result_ != 0) return __result_; } HRESULT CDecoder::Create() { @@ -489,37 +482,71 @@ void CDecoder::Free() #endif -HRESULT CDecoder::ReadSignatures(bool &wasFinished, UInt32 &crc) +bool IsEndSig(const Byte *p) throw() { - wasFinished = false; - Byte s[6]; - for (int i = 0; i < 6; i++) + return + p[0] == kFinSig0 && + p[1] == kFinSig1 && + p[2] == kFinSig2 && + p[3] == kFinSig3 && + p[4] == kFinSig4 && + p[5] == kFinSig5; +} + +bool IsBlockSig(const Byte *p) throw() +{ + return + p[0] == kBlockSig0 && + p[1] == kBlockSig1 && + p[2] == kBlockSig2 && + p[3] == kBlockSig3 && + p[4] == kBlockSig4 && + p[5] == kBlockSig5; +} + +HRESULT CDecoder::ReadSignature(UInt32 &crc) +{ + BzWasFinished = false; + crc = 0; + + Byte s[10]; + int i; + for (i = 0; i < 10; i++) s[i] = ReadByte(); - crc = ReadCrc(); - if (s[0] == kFinSig0) + + if (Base.BitDecoder.ExtraBitsWereRead()) + return S_FALSE; + + UInt32 v = 0; + for (i = 0; i < 4; i++) { - 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; + v <<= 8; + v |= s[6 + i]; } - if (s[0] != kBlockSig0 || - s[1] != kBlockSig1 || - s[2] != kBlockSig2 || - s[3] != kBlockSig3 || - s[4] != kBlockSig4 || - s[5] != kBlockSig5) + + crc = v; + + if (IsBlockSig(s)) + { + IsBz = true; + CombinedCrc.Update(crc); + return S_OK; + } + + if (!IsEndSig(s)) return S_FALSE; - CombinedCrc.Update(crc); + + IsBz = true; + BzWasFinished = true; + if (crc != CombinedCrc.GetDigest()) + { + CrcError = true; + return S_FALSE; + } return S_OK; } -HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) +HRESULT CDecoder::DecodeFile(ICompressProgressInfo *progress) { Progress = progress; #ifndef _7ZIP_ST @@ -541,18 +568,27 @@ HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) return E_OUTOFMEMORY; #endif - isBZ = false; - Byte s[6]; + IsBz = false; + + /* + if (Base.BitDecoder.ExtraBitsWereRead()) + return E_FAIL; + */ + + Byte s[4]; int i; for (i = 0; i < 4; i++) s[i] = ReadByte(); + if (Base.BitDecoder.ExtraBitsWereRead()) + return S_FALSE; + if (s[0] != kArSig0 || s[1] != kArSig1 || s[2] != kArSig2 || s[3] <= kArSig3 || s[3] > kArSig3 + kBlockSizeMultMax) - return S_OK; - isBZ = true; + return S_FALSE; + UInt32 dicSize = (UInt32)(s[3] - kArSig3) * kBlockSizeStep; CombinedCrc.Init(); @@ -584,58 +620,59 @@ HRESULT CDecoder::DecodeFile(bool &isBZ, ICompressProgressInfo *progress) CState &state = m_States[0]; for (;;) { - RINOK(SetRatioProgress(m_InStream.GetProcessedSize())); - bool wasFinished; + RINOK(SetRatioProgress(Base.BitDecoder.GetProcessedSize())); UInt32 crc; - RINOK(ReadSignatures(wasFinished, crc)); - if (wasFinished) + RINOK(ReadSignature(crc)); + if (BzWasFinished) 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) + CBlockProps props; + props.randMode = true; + RINOK(Base.ReadBlock(state.Counters, dicSize, &props)); + DecodeBlock1(state.Counters, props.blockSize); + if (DecodeBlock(props, state.Counters + 256, m_OutStream) != crc) + { + CrcError = true; return S_FALSE; + } } } - return SetRatioProgress(m_InStream.GetProcessedSize()); + return SetRatioProgress(Base.BitDecoder.GetProcessedSize()); } HRESULT CDecoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, - bool &isBZ, ICompressProgressInfo *progress) + ICompressProgressInfo *progress) { - isBZ = false; + IsBz = false; + BzWasFinished = false; + CrcError = false; + try { - if (!m_InStream.Create(kBufferSize)) + if (!Base.BitDecoder.Create(kBufferSize)) return E_OUTOFMEMORY; if (!m_OutStream.Create(kBufferSize)) return E_OUTOFMEMORY; if (inStream) - m_InStream.SetStream(inStream); + Base.BitDecoder.SetStream(inStream); - CDecoderFlusher flusher(this, inStream != NULL); + CDecoderFlusher flusher(this); if (_needInStreamInit) { - m_InStream.Init(); + Base.BitDecoder.Init(); _needInStreamInit = false; } - _inStart = m_InStream.GetProcessedSize(); + _inStart = Base.BitDecoder.GetProcessedSize(); - m_InStream.AlignToByte(); + Base.BitDecoder.AlignToByte(); m_OutStream.SetStream(outStream); m_OutStream.Init(); - RINOK(DecodeFile(isBZ, progress)); + RINOK(DecodeFile(progress)); flusher.NeedFlush = false; return Flush(); @@ -649,18 +686,26 @@ STDMETHODIMP CDecoder::Code(ISequentialInStream *inStream, ISequentialOutStream const UInt64 * /* inSize */, const UInt64 * /* outSize */, ICompressProgressInfo *progress) { _needInStreamInit = true; - bool isBZ; - RINOK(CodeReal(inStream, outStream, isBZ, progress)); - return isBZ ? S_OK : S_FALSE; + return CodeReal(inStream, outStream, progress); } -HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, bool &isBZ, ICompressProgressInfo *progress) +HRESULT CDecoder::CodeResume(ISequentialOutStream *outStream, ICompressProgressInfo *progress) { - return CodeReal(NULL, outStream, isBZ, progress); + return CodeReal(NULL, outStream, progress); } -STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; } -STDMETHODIMP CDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; } +STDMETHODIMP CDecoder::SetInStream(ISequentialInStream *inStream) +{ + Base.InStreamRef = inStream; + Base.BitDecoder.SetStream(inStream); + return S_OK; +} + +STDMETHODIMP CDecoder::ReleaseInStream() +{ + Base.InStreamRef.Release(); + return S_OK; +} #ifndef _7ZIP_ST @@ -709,36 +754,33 @@ void CState::ThreadFunc() Decoder->NextBlockIndex = nextBlockIndex; UInt32 crc; UInt64 packSize = 0; - UInt32 blockSize = 0, origPtr = 0; - bool randMode = false; + CBlockProps props; try { - bool wasFinished; - res = Decoder->ReadSignatures(wasFinished, crc); + res = Decoder->ReadSignature(crc); if (res != S_OK) { Decoder->Result1 = res; FinishStream(); continue; } - if (wasFinished) + if (Decoder->BzWasFinished) { Decoder->Result1 = res; FinishStream(); continue; } - res = ReadBlock(&Decoder->m_InStream, Counters, Decoder->BlockSizeMax, - Decoder->m_Selectors, Decoder->m_HuffmanDecoders, - &blockSize, &origPtr, &randMode); + props.randMode = true; + res = Decoder->Base.ReadBlock(Counters, Decoder->BlockSizeMax, &props); if (res != S_OK) { Decoder->Result1 = res; FinishStream(); continue; } - packSize = Decoder->m_InStream.GetProcessedSize(); + packSize = Decoder->Base.BitDecoder.GetProcessedSize(); } catch(const CInBufferException &e) { res = e.ErrorCode; if (res != S_OK) res = E_FAIL; } catch(...) { res = E_FAIL; } @@ -751,7 +793,7 @@ void CState::ThreadFunc() Decoder->CS.Leave(); - DecodeBlock1(Counters, blockSize); + DecodeBlock1(Counters, props.blockSize); bool needFinish = true; try @@ -760,9 +802,7 @@ void CState::ThreadFunc() 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 (DecodeBlock(props, Counters + 256, Decoder->m_OutStream) == crc) res = Decoder->SetRatioProgress(packSize); else res = S_FALSE; @@ -818,8 +858,17 @@ enum NSIS_STATE_ERROR }; -STDMETHODIMP CNsisDecoder::SetInStream(ISequentialInStream *inStream) { m_InStream.SetStream(inStream); return S_OK; } -STDMETHODIMP CNsisDecoder::ReleaseInStream() { m_InStream.ReleaseStream(); return S_OK; } +STDMETHODIMP CNsisDecoder::SetInStream(ISequentialInStream *inStream) +{ + Base.InStreamRef = inStream; + Base.BitDecoder.SetStream(inStream); + return S_OK; +} +STDMETHODIMP CNsisDecoder::ReleaseInStream() +{ + Base.InStreamRef.Release(); + return S_OK; +} STDMETHODIMP CNsisDecoder::SetOutStreamSize(const UInt64 * /* outSize */) { @@ -843,17 +892,17 @@ STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) if (_nsisState == NSIS_STATE_INIT) { - if (!m_InStream.Create(kBufferSize)) + if (!Base.BitDecoder.Create(kBufferSize)) return E_OUTOFMEMORY; if (!state.Alloc()) return E_OUTOFMEMORY; - m_InStream.Init(); + Base.BitDecoder.Init(); _nsisState = NSIS_STATE_NEW_BLOCK; } if (_nsisState == NSIS_STATE_NEW_BLOCK) { - Byte b = (Byte)m_InStream.ReadBits(8); + Byte b = (Byte)Base.ReadBits(8); if (b == kFinSig0) { _nsisState = NSIS_STATE_FINISHED; @@ -864,12 +913,13 @@ STDMETHODIMP CNsisDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) _nsisState = NSIS_STATE_ERROR; return S_FALSE; } - UInt32 origPtr; - RINOK(ReadBlock(&m_InStream, state.Counters, 9 * kBlockSizeStep, - m_Selectors, m_HuffmanDecoders, &_blockSize, &origPtr, NULL)); - DecodeBlock1(state.Counters, _blockSize); + CBlockProps props; + props.randMode = false; + RINOK(Base.ReadBlock(state.Counters, 9 * kBlockSizeStep, &props)); + _blockSize = props.blockSize; + DecodeBlock1(state.Counters, props.blockSize); const UInt32 *tt = state.Counters + 256; - _tPos = tt[tt[origPtr] >> 8]; + _tPos = tt[tt[props.origPtr] >> 8]; _prevByte = (unsigned)(_tPos & 0xFF); _numReps = 0; _repRem = 0; |