⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bzip2encoder.cpp

📁 seven zip源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
              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 + -