📄 bzip2encoder.cpp
字号:
price += lens[symbols[j]];
while (++j < i);
if (price < bestPrice)
{
m_Selectors[g] = (Byte)t;
bestPrice = price;
}
}
while(++t < numTables);
UInt32 *freqs = Freqs[m_Selectors[g++]];
int j = 0;
do
freqs[symbols[j]]++;
while (++j < i);
}
while (mtfPos < mtfArraySize);
}
int t = 0;
do
{
UInt32 *freqs = Freqs[t];
int i = 0;
do
if (freqs[i] == 0)
freqs[i] = 1;
while(++i < alphaSize);
Huffman_Generate(freqs, Codes[t], Lens[t], kMaxAlphaSize, kMaxHuffmanLenForEncoding);
}
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
{
const Byte *lens = Lens[t];
UInt32 len = lens[0];
WriteBits2(len, kNumLevelsBits);
int i = 0;
do
{
UInt32 level = lens[i];
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;
const Byte *lens = 0;
const UInt32 *codes = 0;
UInt32 mtfPos = 0;
do
{
UInt32 symbol = mtfs[mtfPos++];
if (symbol >= 0xFF)
symbol += mtfs[mtfPos++];
if (groupSize == 0)
{
groupSize = kGroupSize;
int t = m_Selectors[groupIndex++];
lens = Lens[t];
codes = Codes[t];
}
groupSize--;
m_OutStreamCurrent->WriteBits(codes[symbol], lens[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 > 0
UInt32 CThreadInfo::EncodeBlockWithHeaders(const 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(const Byte *block, UInt32 blockSize, UInt32 numPasses)
{
UInt32 numCrcs = m_NumCrcs;
bool needCompare = false;
UInt32 startBytePos = m_OutStreamCurrent->GetBytePos();
UInt32 startPos = m_OutStreamCurrent->GetPos();
Byte startCurByte = m_OutStreamCurrent->GetCurByte();
Byte endCurByte = 0;
UInt32 endPos = 0;
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;
RINOK(Create());
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.Alloc())
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;
CanProcessEvent.Set();
UInt32 t;
for (t = 0; t < NumThreads; t++)
ThreadsInfo[t].StreamWasFinishedEvent.Lock();
CanProcessEvent.Reset();
CanStartWaitingEvent.Set();
for (t = 0; t < NumThreads; t++)
ThreadsInfo[t].WaitingWasStartedEvent.Lock();
CanStartWaitingEvent.Reset();
RINOK(Result);
}
else
#endif
{
for (;;)
{
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_MT
STDMETHODIMP CEncoder::SetNumberOfThreads(UInt32 numThreads)
{
NumThreads = numThreads;
if (NumThreads < 1)
NumThreads = 1;
return S_OK;
}
#endif
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -