bzip2encoder.cpp
来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 877 行 · 第 1/2 页
CPP
877 行
do huffEncoder.AddSymbol(symbols[j]); while (++j < i); } while (mtfPos < mtfArraySize); } int t = 0; do { NCompression::NHuffman::CEncoder &huffEncoder = m_HuffEncoders[t]; int i = 0; do if (huffEncoder.m_Items[i].Freq == 0) huffEncoder.m_Items[i].Freq = 1; while(++i < alphaSize); Byte levels[kMaxAlphaSize]; huffEncoder.BuildTree(levels); } while(++t < numTables); } { Byte mtfSel[kNumTablesMax]; { int t = 0; do mtfSel[t] = (Byte)t; while(++t < numTables); } UInt32 i = 0; do { Byte sel = m_Selectors[i]; int pos; for (pos = 0; mtfSel[pos] != sel; pos++) WriteBit2(true); WriteBit2(false); for (; pos > 0; pos--) mtfSel[pos] = mtfSel[pos - 1]; mtfSel[0] = sel; } while(++i < numSelectors); } { int t = 0; do { NCompression::NHuffman::CItem *items = m_HuffEncoders[t].m_Items; UInt32 len = items[0].Len; WriteBits2(len, kNumLevelsBits); int i = 0; do { UInt32 level = items[i].Len; while (len != level) { WriteBit2(true); if (len < level) { WriteBit2(false); len++; } else { WriteBit2(true); len--; } } WriteBit2(false); } while (++i < alphaSize); } while(++t < numTables); } { UInt32 groupSize = 0; UInt32 groupIndex = 0; NCompression::NHuffman::CEncoder *huffEncoder = 0; UInt32 mtfPos = 0; do { UInt32 symbol = mtfs[mtfPos++]; if (symbol >= 0xFF) symbol += mtfs[mtfPos++]; if (groupSize == 0) { groupSize = kGroupSize; huffEncoder = &m_HuffEncoders[m_Selectors[groupIndex++]]; } groupSize--; \ huffEncoder->CodeOneValue(m_OutStreamCurrent, symbol); } while (mtfPos < mtfArraySize); } if (!m_OptimizeNumTables) break; UInt32 price = m_OutStreamCurrent->GetPos() - startPos; if (price <= bestPrice) { if (nt == kNumTablesMax) break; bestPrice = price; bestNumTables = nt; } }}// blockSize > 0UInt32 CThreadInfo::EncodeBlockWithHeaders(Byte *block, UInt32 blockSize){ WriteByte2(kBlockSig0); WriteByte2(kBlockSig1); WriteByte2(kBlockSig2); WriteByte2(kBlockSig3); WriteByte2(kBlockSig4); WriteByte2(kBlockSig5); CBZip2CRC crc; int numReps = 0; Byte prevByte = block[0]; UInt32 i = 0; do { Byte b = block[i]; if (numReps == kRleModeRepSize) { for (; b > 0; b--) crc.UpdateByte(prevByte); numReps = 0; continue; } if (prevByte == b) numReps++; else { numReps = 1; prevByte = b; } crc.UpdateByte(b); } while (++i < blockSize); UInt32 crcRes = crc.GetDigest(); WriteCRC2(crcRes); EncodeBlock(block, blockSize); return crcRes;}void CThreadInfo::EncodeBlock2(Byte *block, UInt32 blockSize, UInt32 numPasses){ UInt32 numCrcs = m_NumCrcs; bool needCompare = false; UInt32 startBytePos = m_OutStreamCurrent->GetBytePos(); UInt32 startPos = m_OutStreamCurrent->GetPos(); UInt32 startCurByte = m_OutStreamCurrent->GetCurByte(); UInt32 endCurByte; UInt32 endPos; if (numPasses > 1 && blockSize >= (1 << 10)) { UInt32 blockSize0 = blockSize / 2; for (;(block[blockSize0] == block[blockSize0 - 1] || block[blockSize0 - 1] == block[blockSize0 - 2]) && blockSize0 < blockSize; blockSize0++); if (blockSize0 < blockSize) { EncodeBlock2(block, blockSize0, numPasses - 1); EncodeBlock2(block + blockSize0, blockSize - blockSize0, numPasses - 1); endPos = m_OutStreamCurrent->GetPos(); endCurByte = m_OutStreamCurrent->GetCurByte(); if ((endPos & 7) > 0) WriteBits2(0, 8 - (endPos & 7)); m_OutStreamCurrent->SetCurState((startPos & 7), startCurByte); needCompare = true; } } UInt32 startBytePos2 = m_OutStreamCurrent->GetBytePos(); UInt32 startPos2 = m_OutStreamCurrent->GetPos(); UInt32 crcVal = EncodeBlockWithHeaders(block, blockSize); UInt32 endPos2 = m_OutStreamCurrent->GetPos(); if (needCompare) { UInt32 size2 = endPos2 - startPos2; if (size2 < endPos - startPos) { UInt32 numBytes = m_OutStreamCurrent->GetBytePos() - startBytePos2; Byte *buffer = m_OutStreamCurrent->GetStream(); for (UInt32 i = 0; i < numBytes; i++) buffer[startBytePos + i] = buffer[startBytePos2 + i]; m_OutStreamCurrent->SetPos(startPos + endPos2 - startPos2); m_NumCrcs = numCrcs; m_CRCs[m_NumCrcs++] = crcVal; } else { m_OutStreamCurrent->SetPos(endPos); m_OutStreamCurrent->SetCurState((endPos & 7), endCurByte); } } else { m_NumCrcs = numCrcs; m_CRCs[m_NumCrcs++] = crcVal; }}HRESULT CThreadInfo::EncodeBlock3(UInt32 blockSize){ CMsbfEncoderTemp outStreamTemp; outStreamTemp.SetStream(m_TempArray); outStreamTemp.Init(); m_OutStreamCurrent = &outStreamTemp; m_NumCrcs = 0; EncodeBlock2(m_Block, blockSize, Encoder->NumPasses); #ifdef COMPRESS_BZIP2_MT if (Encoder->MtMode) Encoder->ThreadsInfo[m_BlockIndex].CanWriteEvent.Lock(); #endif for (UInt32 i = 0; i < m_NumCrcs; i++) Encoder->CombinedCRC.Update(m_CRCs[i]); Encoder->WriteBytes(m_TempArray, outStreamTemp.GetPos(), outStreamTemp.GetCurByte()); HRESULT res = S_OK; #ifdef COMPRESS_BZIP2_MT if (Encoder->MtMode) { UInt32 blockIndex = m_BlockIndex + 1; if (blockIndex == Encoder->NumThreads) blockIndex = 0; if (Encoder->Progress) { UInt64 unpackSize = Encoder->m_OutStream.GetProcessedSize(); res = Encoder->Progress->SetRatioInfo(&m_PackSize, &unpackSize); } Encoder->ThreadsInfo[blockIndex].CanWriteEvent.Set(); } #endif return res;}void CEncoder::WriteBytes(const Byte *data, UInt32 sizeInBits, Byte lastByte){ UInt32 bytesSize = (sizeInBits / 8); for (UInt32 i = 0; i < bytesSize; i++) m_OutStream.WriteBits(data[i], 8); WriteBits(lastByte, (sizeInBits & 7));}HRESULT CEncoder::CodeReal(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress){ #ifdef COMPRESS_BZIP2_MT Progress = progress; if (!Create()) return E_FAIL; for (UInt32 t = 0; t < NumThreads; t++) #endif { #ifdef COMPRESS_BZIP2_MT CThreadInfo &ti = ThreadsInfo[t]; ti.StreamWasFinishedEvent.Reset(); ti.WaitingWasStartedEvent.Reset(); ti.CanWriteEvent.Reset(); #else CThreadInfo &ti = ThreadsInfo; ti.Encoder = this; #endif ti.m_OptimizeNumTables = m_OptimizeNumTables; if (!ti.Create()) return E_OUTOFMEMORY; } 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(); CFlusher flusher(this); CombinedCRC.Init(); #ifdef COMPRESS_BZIP2_MT NextBlockIndex = 0; StreamWasFinished = false; CloseThreads = false; CanStartWaitingEvent.Reset(); #endif WriteByte(kArSig0); WriteByte(kArSig1); WriteByte(kArSig2); WriteByte((Byte)(kArSig3 + m_BlockSizeMult)); #ifdef COMPRESS_BZIP2_MT if (MtMode) { ThreadsInfo[0].CanWriteEvent.Set(); Result = S_OK; CS.Leave(); UInt32 t; for (t = 0; t < NumThreads; t++) ThreadsInfo[t].StreamWasFinishedEvent.Lock(); CS.Enter(); CanStartWaitingEvent.Set(); for (t = 0; t < NumThreads; t++) ThreadsInfo[t].WaitingWasStartedEvent.Lock(); CanStartWaitingEvent.Reset(); RINOK(Result); } else #endif { while (true) { CThreadInfo &ti = #ifdef COMPRESS_BZIP2_MT ThreadsInfo[0]; #else ThreadsInfo; #endif UInt32 blockSize = ReadRleBlock(ti.m_Block); if (blockSize == 0) break; RINOK(ti.EncodeBlock3(blockSize)); if (progress) { UInt64 packSize = m_InStream.GetProcessedSize(); UInt64 unpackSize = m_OutStream.GetProcessedSize(); RINOK(progress->SetRatioInfo(&packSize, &unpackSize)); } } } WriteByte(kFinSig0); WriteByte(kFinSig1); WriteByte(kFinSig2); WriteByte(kFinSig3); WriteByte(kFinSig4); WriteByte(kFinSig5); WriteCRC(CombinedCRC.GetDigest()); return S_OK;}STDMETHODIMP CEncoder::Code(ISequentialInStream *inStream, ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize, ICompressProgressInfo *progress){ try { return CodeReal(inStream, outStream, inSize, outSize, progress); } catch(const CInBufferException &e) { return e.ErrorCode; } catch(const COutBufferException &e) { return e.ErrorCode; } catch(...) { return S_FALSE; }}HRESULT CEncoder::SetCoderProperties(const PROPID *propIDs, const PROPVARIANT *properties, UInt32 numProperties){ for(UInt32 i = 0; i < numProperties; i++) { const PROPVARIANT &property = properties[i]; switch(propIDs[i]) { case NCoderPropID::kNumPasses: { if (property.vt != VT_UI4) return E_INVALIDARG; UInt32 numPasses = property.ulVal; if (numPasses == 0) numPasses = 1; if (numPasses > kNumPassesMax) numPasses = kNumPassesMax; NumPasses = numPasses; m_OptimizeNumTables = (NumPasses > 1); break; } case NCoderPropID::kDictionarySize: { if (property.vt != VT_UI4) return E_INVALIDARG; UInt32 dictionary = property.ulVal / kBlockSizeStep; if (dictionary < kBlockSizeMultMin) dictionary = kBlockSizeMultMin; else if (dictionary > kBlockSizeMultMax) dictionary = kBlockSizeMultMax; m_BlockSizeMult = dictionary; break; } case NCoderPropID::kNumThreads: { #ifdef COMPRESS_BZIP2_MT if (property.vt != VT_UI4) return E_INVALIDARG; NumThreads = property.ulVal; if (NumThreads < 1) NumThreads = 1; #endif break; } default: return E_INVALIDARG; } } return S_OK;}#ifdef COMPRESS_BZIP2_MTSTDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads){ NumThreads = numThreads; if (NumThreads < 1) NumThreads = 1; return S_OK;}#endif}}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?