arjin.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 284 行

CPP
284
字号
// Archive/arj/InEngine.cpp#include "StdAfx.h"#include "Common/StringConvert.h"#include "Common/Buffer.h"#include "Common/CRC.h"#include "../../Common/StreamUtils.h"#include "ArjIn.h"namespace NArchive {namespace NArj { HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize){  UInt32 realProcessedSize;  HRESULT result = ReadStream(_stream, data, size, &realProcessedSize);  if(processedSize != NULL)    *processedSize = realProcessedSize;  IncreasePositionValue(realProcessedSize);  return result;}static inline UInt16 GetUInt16FromMemLE(const Byte *p){  return p[0] | (((UInt32)p[1]) << 8);}static inline UInt32 GetUInt32FromMemLE(const Byte *p){  return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);}inline bool TestMarkerCandidate(const void *testBytes, UInt32 maxSize){  if (maxSize < 2 + 2 + 4)    return false;  const Byte *block = ((const Byte *)(testBytes));  if (block[0] != NSignature::kSig0 || block[1] != NSignature::kSig1)    return false;  UInt32 blockSize = GetUInt16FromMemLE(block + 2);  if (maxSize < 2 + 2 + blockSize + 4)    return false;  block += 4;  if (blockSize == 0 || blockSize > 2600)    return false;  UInt32 crcFromFile = GetUInt32FromMemLE(block + blockSize);  return (CCRC::VerifyDigest(crcFromFile, block, blockSize));}bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit){  // _archiveInfo.StartPosition = 0;  _position = _streamStartPosition;  if(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL) != S_OK)    return false;  const int kMarkerSizeMax = 2 + 2 + kMaxBlockSize + 4;  CByteBuffer byteBuffer;  static const UInt32 kSearchMarkerBufferSize = 0x10000;  byteBuffer.SetCapacity(kSearchMarkerBufferSize);  Byte *buffer = byteBuffer;  UInt32 processedSize;   ReadBytes(buffer, kMarkerSizeMax, &processedSize);  if (processedSize == 0)    return false;  if (TestMarkerCandidate(buffer, processedSize))  {    _position = _streamStartPosition;    if(_stream->Seek(_position, STREAM_SEEK_SET, NULL) != S_OK)      return false;    return true;  }  UInt32 numBytesPrev = processedSize - 1;  memmove(buffer, buffer + 1, numBytesPrev);  UInt64 curTestPos = _streamStartPosition + 1;  while(true)  {    if (searchHeaderSizeLimit != NULL)      if (curTestPos - _streamStartPosition > *searchHeaderSizeLimit)        return false;    UInt32 numReadBytes = kSearchMarkerBufferSize - numBytesPrev;    ReadBytes(buffer + numBytesPrev, numReadBytes, &processedSize);    UInt32 numBytesInBuffer = numBytesPrev + processedSize;    if (numBytesInBuffer < 1)      return false;    UInt32 numTests = numBytesInBuffer;    for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)    {       if (TestMarkerCandidate(buffer + pos, numBytesInBuffer - pos))      {        // _archiveInfo.StartPosition = curTestPos;        _position = curTestPos;        if(_stream->Seek(_position, STREAM_SEEK_SET, NULL) != S_OK)          return false;        return true;      }    }    numBytesPrev = numBytesInBuffer - numTests;    memmove(buffer, buffer + numTests, numBytesPrev);  }}void CInArchive::IncreasePositionValue(UInt64 addValue){  _position += addValue;}void CInArchive::IncreaseRealPosition(UInt64 addValue){  if(_stream->Seek(addValue, STREAM_SEEK_CUR, &_position) != S_OK)    throw CInArchiveException(CInArchiveException::kSeekStreamError);}bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size){  UInt32 realProcessedSize;  if(ReadBytes(data, size, &realProcessedSize) != S_OK)    throw CInArchiveException(CInArchiveException::kReadStreamError);  return (realProcessedSize == size);}void CInArchive::SafeReadBytes(void *data, UInt32 size){  if(!ReadBytesAndTestSize(data, size))    throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);}Byte CInArchive::SafeReadByte(){  Byte b;  SafeReadBytes(&b, 1);  return b;}UInt16 CInArchive::SafeReadUInt16(){  UInt16 value = 0;  for (int i = 0; i < 2; i++)  {    Byte b = SafeReadByte();    value |= (UInt16(b) << (8 * i));  }  return value;}UInt32 CInArchive::SafeReadUInt32(){  UInt32 value = 0;  for (int i = 0; i < 4; i++)  {    Byte b = SafeReadByte();    value |= (UInt32(b) << (8 * i));  }  return value;}bool CInArchive::ReadBlock(){  _blockPos = 0;  _blockSize = SafeReadUInt16();  if (_blockSize == 0 || _blockSize > kMaxBlockSize)    return false;  SafeReadBytes(_block, _blockSize);  UInt32 crcFromFile = SafeReadUInt32();  if (!CCRC::VerifyDigest(crcFromFile, _block, _blockSize))    throw CInArchiveException(CInArchiveException::kCRCError);  return true;}bool CInArchive::ReadBlock2(){  Byte id[2];  ReadBytesAndTestSize(id, 2);  if (id[0] != NSignature::kSig0 || id[1] != NSignature::kSig1)    throw CInArchiveException(CInArchiveException::kIncorrectArchive);  return ReadBlock();}bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit){  _stream = inStream;  if(_stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition) != S_OK)    return false;  _position = _streamStartPosition;  if (!FindAndReadMarker(searchHeaderSizeLimit))    return false;  if (!ReadBlock2())    return false;  while(true)    if (!ReadBlock())      break;  return true;}void CInArchive::Close(){  _stream.Release();}void CInArchive::ThrowIncorrectArchiveException(){  throw CInArchiveException(CInArchiveException::kIncorrectArchive);}Byte CInArchive::ReadByte(){  if (_blockPos >= _blockSize)    ThrowIncorrectArchiveException();  return _block[_blockPos++];}UInt16 CInArchive::ReadUInt16(){  UInt16 value = 0;  for (int i = 0; i < 2; i++)  {    Byte b = ReadByte();    value |= (UInt16(b) << (8 * i));  }  return value;}UInt32 CInArchive::ReadUInt32(){  UInt32 value = 0;  for (int i = 0; i < 4; i++)  {    Byte b = ReadByte();    value |= (UInt32(b) << (8 * i));  }  return value;}HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item){  filled  = false;  if (!ReadBlock2())    return S_OK;  Byte firstHeaderSize = ReadByte();  item.Version = ReadByte();  item.ExtractVersion = ReadByte();  item.HostOS = ReadByte();  item.Flags = ReadByte();  item.Method = ReadByte();  item.FileType = ReadByte();  ReadByte(); // Reserved  item.ModifiedTime = ReadUInt32();  item.PackSize = ReadUInt32();  item.Size = ReadUInt32();  item.FileCRC = ReadUInt32();  ReadUInt16(); // FilespecPositionInFilename  item.FileAccessMode = ReadUInt16();  ReadByte(); // FirstChapter  ReadByte(); // LastChapter  /*  UInt32 extraData;  if ((header.Flags & NFileHeader::NFlags::kExtFile) != 0)    extraData = GetUInt32FromMemLE(_block + pos);  */  _blockPos = firstHeaderSize;  for (; _blockPos < _blockSize;)    item.Name += (char)ReadByte();  while(true)    if (!ReadBlock())      break;  item.DataPosition = _position;  filled  = true;  return S_OK;}  }}

⌨️ 快捷键说明

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