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

📄 cabin.cpp

📁 由7-zip提供的压缩、解压缩程序
💻 CPP
字号:
// Archive/CabIn.cpp#include "StdAfx.h"#include "Common/StringConvert.h"#include "Common/MyCom.h"#include "CabIn.h"#include "Windows/Defs.h"#include "../../Common/StreamUtils.h"namespace NArchive{namespace NCab{static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size){  UInt32 realProcessedSize;  RINOK(ReadStream(inStream, data, size, &realProcessedSize));  if(realProcessedSize != size)    return S_FALSE;  return S_OK;}static HRESULT SafeRead(IInStream *inStream, void *data, UInt32 size){  UInt32 realProcessedSize;  RINOK(ReadStream(inStream, data, size, &realProcessedSize));  if(realProcessedSize != size)    throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);  return S_OK;}static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 size){  UInt32 realProcessedSize;  inBuffer.ReadBytes(data, size, realProcessedSize);  if(realProcessedSize != size)    throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);}Byte CInArchive::ReadByte(){  Byte b;  if (!inBuffer.ReadByte(b))    throw CInArchiveException(CInArchiveException::kUnsupported);  return b;}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;}AString CInArchive::SafeReadName(){  AString name;  while(true)  {    Byte b = ReadByte();    if (b == 0)      return name;    name += (char)b;  }}void CInArchive::ReadOtherArchive(COtherArchive &oa){  oa.FileName = SafeReadName();  oa.DiskName = SafeReadName();}void CInArchive::Skeep(size_t size){  while (size-- != 0)    ReadByte();}HRESULT CInArchive::Open2(IInStream *inStream,     const UInt64 *searchHeaderSizeLimit,    CDatabase &database){  database.Clear();  RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &database.StartPosition));  {    if (!inBuffer.Create(1 << 17))      return E_OUTOFMEMORY;    inBuffer.SetStream(inStream);    inBuffer.Init();    UInt64 value = 0;    const int kSignatureSize = 8;    UInt64 kSignature64 = NHeader::NArchive::kSignature;    while(true)    {      Byte b;      if (!inBuffer.ReadByte(b))        return S_FALSE;      value >>= 8;      value |= ((UInt64)b) << ((kSignatureSize - 1) * 8);      if (inBuffer.GetProcessedSize() >= kSignatureSize)      {        if (value == kSignature64)          break;        if (searchHeaderSizeLimit != NULL)          if (inBuffer.GetProcessedSize() > (*searchHeaderSizeLimit))            return S_FALSE;      }    }    database.StartPosition += inBuffer.GetProcessedSize() - kSignatureSize;  }  CInArchiveInfo &archiveInfo = database.ArchiveInfo;  archiveInfo.Size = ReadUInt32();	// size of this cabinet file in bytes  if (ReadUInt32() != 0)    return S_FALSE;  archiveInfo.FileHeadersOffset = ReadUInt32();	// offset of the first CFFILE entry  if (ReadUInt32() != 0)    return S_FALSE;  archiveInfo.VersionMinor = ReadByte();	// cabinet file format version, minor  archiveInfo.VersionMajor = ReadByte();	// cabinet file format version, major  archiveInfo.NumFolders = ReadUInt16();	// number of CFFOLDER entries in this cabinet  archiveInfo.NumFiles  = ReadUInt16();	// number of CFFILE entries in this cabinet  archiveInfo.Flags = ReadUInt16();	// number of CFFILE entries in this cabinet  archiveInfo.SetID = ReadUInt16();	// must be the same for all cabinets in a set  archiveInfo.CabinetNumber = ReadUInt16();	// number of this cabinet file in a set  if (archiveInfo.ReserveBlockPresent())  {    archiveInfo.PerCabinetAreaSize = ReadUInt16();	// (optional) size of per-cabinet reserved area    archiveInfo.PerFolderAreaSize = ReadByte();	// (optional) size of per-folder reserved area    archiveInfo.PerDataBlockAreaSize = ReadByte();	// (optional) size of per-datablock reserved area    Skeep(archiveInfo.PerCabinetAreaSize);  }  {    if (archiveInfo.IsTherePrev())      ReadOtherArchive(archiveInfo.PreviousArchive);    if (archiveInfo.IsThereNext())      ReadOtherArchive(archiveInfo.NextArchive);  }    int i;  for(i = 0; i < archiveInfo.NumFolders; i++)  {    CFolder folder;    folder.DataStart = ReadUInt32();    folder.NumDataBlocks = ReadUInt16();    folder.CompressionTypeMajor = ReadByte();    folder.CompressionTypeMinor = ReadByte();    Skeep(archiveInfo.PerFolderAreaSize);    database.Folders.Add(folder);  }    RINOK(inStream->Seek(database.StartPosition + archiveInfo.FileHeadersOffset, STREAM_SEEK_SET, NULL));  inBuffer.SetStream(inStream);  inBuffer.Init();  for(i = 0; i < archiveInfo.NumFiles; i++)  {    CItem item;    item.Size = ReadUInt32();    item.Offset = ReadUInt32();    item.FolderIndex = ReadUInt16();    UInt16 pureDate = ReadUInt16();    UInt16 pureTime = ReadUInt16();    item.Time = ((UInt32(pureDate) << 16)) | pureTime;    item.Attributes = ReadUInt16();    item.Name = SafeReadName();    int folderIndex = item.GetFolderIndex(database.Folders.Size());    if (folderIndex >= database.Folders.Size())      return S_FALSE;    database.Items.Add(item);  }  return S_OK;}#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }HRESULT CInArchive::Open(    const UInt64 *searchHeaderSizeLimit,    CDatabaseEx &database){  return Open2(database.Stream, searchHeaderSizeLimit, database);}static int CompareMvItems2(const CMvItem *p1, const CMvItem *p2){  RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));  return MyCompare(p1->ItemIndex, p2->ItemIndex);}static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param){  const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;  const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];  const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];  const CItem &item1 = db1.Items[p1->ItemIndex];  const CItem &item2 = db2.Items[p2->ItemIndex];;  bool isDir1 = item1.IsDirectory();  bool isDir2 = item2.IsDirectory();  if (isDir1 && !isDir2)    return -1;  if (isDir2 && !isDir1)    return 1;  int f1 = mvDb.GetFolderIndex(p1);  int f2 = mvDb.GetFolderIndex(p2);  RINOZ(MyCompare(f1, f2));  RINOZ(MyCompare(item1.Offset, item2.Offset));  RINOZ(MyCompare(item1.Size, item2.Size));  return CompareMvItems2(p1, p2);}bool CMvDatabaseEx::AreItemsEqual(int i1, int i2){  const CMvItem *p1 = &Items[i1];  const CMvItem *p2 = &Items[i2];  const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];  const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];  const CItem &item1 = db1.Items[p1->ItemIndex];  const CItem &item2 = db2.Items[p2->ItemIndex];;  int f1 = GetFolderIndex(p1);  int f2 = GetFolderIndex(p2);  if (f1 != f2)    return false;  if (item1.Offset != item2.Offset)    return false;  if (item1.Size != item2.Size)    return false;  return true;}void CMvDatabaseEx::FillSortAndShrink(){  Items.Clear();  StartFolderOfVol.Clear();  FolderStartFileIndex.Clear();  int offset = 0;  for (int v = 0; v < Volumes.Size(); v++)  {    const CDatabaseEx &db = Volumes[v];    int curOffset = offset;    if (db.IsTherePrevFolder())      curOffset--;    StartFolderOfVol.Add(curOffset);    offset += db.GetNumberOfNewFolders();    CMvItem mvItem;    mvItem.VolumeIndex = v;    for (int i = 0 ; i < db.Items.Size(); i++)    {      mvItem.ItemIndex = i;      Items.Add(mvItem);    }  }  Items.Sort(CompareMvItems, (void *)this);  int j = 1;  int i;  for (i = 1; i < Items.Size(); i++)    if (!AreItemsEqual(i, i -1))      Items[j++] = Items[i];  Items.DeleteFrom(j);  for (i = 0; i < Items.Size(); i++)  {    const CMvItem &mvItem = Items[i];    int folderIndex = GetFolderIndex(&mvItem);    if (folderIndex >= FolderStartFileIndex.Size())      FolderStartFileIndex.Add(i);  }}bool CMvDatabaseEx::Check(){  for (int v = 1; v < Volumes.Size(); v++)  {    const CDatabaseEx &db1 = Volumes[v];    if (db1.IsTherePrevFolder())    {      const CDatabaseEx &db0 = Volumes[v - 1];      if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())        return false;      const CFolder &f0 = db0.Folders.Back();      const CFolder &f1 = db1.Folders.Front();      if (f0.CompressionTypeMajor != f1.CompressionTypeMajor ||          f0.CompressionTypeMinor != f1.CompressionTypeMinor)        return false;    }  }  UInt64 maxPos = 0;  int prevFolder = -2;  for(int i = 0; i < Items.Size(); i++)  {    const CMvItem &mvItem = Items[i];    int fIndex = GetFolderIndex(&mvItem);    if (fIndex >= FolderStartFileIndex.Size())      return false;    const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];    if (item.IsDirectory())      continue;    int folderIndex = GetFolderIndex(&mvItem);    if (folderIndex != prevFolder)    {      prevFolder = folderIndex;      maxPos = 0;      continue;    }    if (item.Offset < maxPos)      return false;    maxPos = item.GetEndOffset();    if (maxPos < item.Offset)      return false;  }  return true;}}}

⌨️ 快捷键说明

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