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

📄 cabinbuffer.cpp

📁 免费压缩软件7zip的源码
💻 CPP
字号:
// Archive/CabInBuffer.cpp

#include "StdAfx.h"

#include "../../../Common/Alloc.h"
#include "../../../Common/MyCom.h"
#include "../../../Windows/Defs.h"
#include "CabInBuffer.h"

namespace NArchive {
namespace NCab {

static const UInt32 kDataBlockHeaderSize = 8;
/*
struct CDataBlockHeader
{
  UInt32  CheckSum;	// checksum of this CFDATA entry
  UInt16  PackSize;	// number of compressed bytes in this block
  UInt16  UnPackSize;	// number of uncompressed bytes in this block
  // Byte  abReserve[];	// (optional) per-datablock reserved area
  // Byte  ab[cbData];	// compressed data bytes
};
*/

class CTempCabInBuffer
{
public:
  Byte *Buffer;
  UInt32 Size;
  UInt32 Pos;
  Byte ReadByte()
  {
    if (Pos >= Size)
      throw "overflow";
    return Buffer[Pos++];
  }
  UInt32 ReadUInt32()
  {
    UInt32 value = 0;
    for (int i = 0; i < 4; i++)
      value |= (((UInt32)ReadByte()) << (8 * i));
    return value;
  }
  UInt16 ReadUInt16()
  {
    UInt16 value = 0;
    for (int i = 0; i < 2; i++)
      value |= (((UInt16)ReadByte()) << (8 * i));
    return value;
  }
};

bool CInBuffer::Create(UInt32 bufferSize)
{
  const UInt32 kMinBlockSize = 1;
  if (bufferSize < kMinBlockSize)
    bufferSize = kMinBlockSize;
  if (m_Buffer != 0 && m_BufferSize == bufferSize)
    return true;
  Free();
  m_BufferSize = bufferSize;
  m_Buffer = (Byte *)::BigAlloc(bufferSize);
  return (m_Buffer != 0);
}

void CInBuffer::Free()
{
  BigFree(m_Buffer);
  m_Buffer = 0;
}

void CInBuffer::Init(Byte reservedSize, UInt32 numBlocks)
{
  m_ReservedSize = reservedSize;
  m_NumBlocks = numBlocks;
  m_CurrentBlockIndex = 0;
  m_ProcessedSize = 0;
  m_Pos = 0;
  m_NumReadBytesInBuffer = 0;
}

class CCheckSum
{
  UInt32 m_Value;
public:
  CCheckSum():  m_Value(0){};
  void Init() { m_Value = 0; }
  void Update(const void *data, UInt32 size);
  void UpdateUInt32(UInt32 v) { m_Value ^= v; }
  UInt32 GetResult() const { return m_Value; } 
};

void CCheckSum::Update(const void *data, UInt32 size)
{
  UInt32 checkSum = m_Value;
  const Byte *dataPointer = (const Byte  *)data;
  int numUINT32Words = size / 4; // Number of ULONGs
  
  UInt32 temp;
  while (numUINT32Words-- > 0) 
  {
    temp = *dataPointer++;
    temp |= (((UInt32)(*dataPointer++)) <<  8);
    temp |= (((UInt32)(*dataPointer++)) << 16);
    temp |= (((UInt32)(*dataPointer++)) << 24);
    checkSum ^= temp;
  }
  
  temp = 0;
  int rem = (size & 3);
  if (rem >= 3)
    temp |= (((UInt32)(*dataPointer++)) << 16);
  if (rem >= 2)
    temp |= (((UInt32)(*dataPointer++)) <<  8);
  if (rem >= 1)
    temp |= *dataPointer++;
  checkSum ^= temp;       
  m_Value = checkSum;
}

HRESULT CInBuffer::ReadBlock(UInt32 &uncompressedSize, bool &dataAreCorrect)
{
  if (m_CurrentBlockIndex >= m_NumBlocks)
    throw "there is no more data blocks";

  m_ProcessedSize += m_NumReadBytesInBuffer;

  Byte buffer[kDataBlockHeaderSize];
  UInt32 numProcessedBytes;
  RINOK(m_Stream->Read(buffer, kDataBlockHeaderSize, &numProcessedBytes));
  if (numProcessedBytes != kDataBlockHeaderSize)
    throw "bad block";
  
  CTempCabInBuffer inBuffer;
  inBuffer.Size = kDataBlockHeaderSize;
  inBuffer.Buffer = (Byte *)buffer;
  inBuffer.Pos = 0;

  UInt32 checkSum = inBuffer.ReadUInt32();	// checksum of this CFDATA entry
  UInt16 packSize = inBuffer.ReadUInt16();	// number of compressed bytes in this block
  UInt16 unPackSize = inBuffer.ReadUInt16();	// number of uncompressed bytes in this block
  
  if (m_ReservedSize != 0)
  {
    Byte reservedArea[256];
    RINOK(m_Stream->Read(reservedArea, m_ReservedSize, &numProcessedBytes));
    if (numProcessedBytes != m_ReservedSize)
      throw "bad block";
  }

  RINOK(m_Stream->Read(m_Buffer, packSize, &m_NumReadBytesInBuffer));
  if (m_NumReadBytesInBuffer != packSize)
    throw "bad block";

  // Now I don't remember why (checkSum == 0) check is disbaled
  // Cab specification: 
  //   checkSum: May be set to zero if the checksum is not supplied.
  // but seems it's stupid rule.
  if (checkSum == 0)
    dataAreCorrect = true;
  {
    CCheckSum checkSumCalc;
    checkSumCalc.Update(m_Buffer, packSize);
    checkSumCalc.UpdateUInt32(packSize | (((UInt32)unPackSize) << 16));
    dataAreCorrect = (checkSumCalc.GetResult() == checkSum);
  }

  m_Pos = 0;
  uncompressedSize = unPackSize;

  m_CurrentBlockIndex++;
  return S_OK;
}

}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -