7zin.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 1,295 行 · 第 1/3 页

CPP
1,295
字号
HRESULT CInArchive::WaitAttribute(UInt64 attribute){  while(true)  {    UInt64 type;    RINOK(ReadID(type));    if (type == attribute)      return S_OK;    if (type == NID::kEnd)      return S_FALSE;    RINOK(SkeepData());  }}HRESULT CInArchive::ReadHashDigests(int numItems,    CRecordVector<bool> &digestsDefined,     CRecordVector<UInt32> &digests){  RINOK(ReadBoolVector2(numItems, digestsDefined));  digests.Clear();  digests.Reserve(numItems);  for(int i = 0; i < numItems; i++)  {    UInt32 crc;    if (digestsDefined[i])      RINOK(ReadUInt32(crc));    digests.Add(crc);  }  return S_OK;}HRESULT CInArchive::ReadPackInfo(    UInt64 &dataOffset,    CRecordVector<UInt64> &packSizes,    CRecordVector<bool> &packCRCsDefined,    CRecordVector<UInt32> &packCRCs){  RINOK(ReadNumber(dataOffset));  CNum numPackStreams;  RINOK(ReadNum(numPackStreams));  RINOK(WaitAttribute(NID::kSize));  packSizes.Clear();  packSizes.Reserve(numPackStreams);  for(CNum i = 0; i < numPackStreams; i++)  {    UInt64 size;    RINOK(ReadNumber(size));    packSizes.Add(size);  }  UInt64 type;  while(true)  {    RINOK(ReadID(type));    if (type == NID::kEnd)      break;    if (type == NID::kCRC)    {      RINOK(ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs));       continue;    }    RINOK(SkeepData());  }  if (packCRCsDefined.IsEmpty())  {    packCRCsDefined.Reserve(numPackStreams);    packCRCsDefined.Clear();    packCRCs.Reserve(numPackStreams);    packCRCs.Clear();    for(CNum i = 0; i < numPackStreams; i++)    {      packCRCsDefined.Add(false);      packCRCs.Add(0);    }  }  return S_OK;}HRESULT CInArchive::ReadUnPackInfo(    const CObjectVector<CByteBuffer> *dataVector,    CObjectVector<CFolder> &folders){  RINOK(WaitAttribute(NID::kFolder));  CNum numFolders;  RINOK(ReadNum(numFolders));  {    CStreamSwitch streamSwitch;    RINOK(streamSwitch.Set(this, dataVector));    folders.Clear();    folders.Reserve((UInt32)numFolders);    for(CNum i = 0; i < numFolders; i++)    {      folders.Add(CFolder());      RINOK(GetNextFolderItem(folders.Back()));    }  }  RINOK(WaitAttribute(NID::kCodersUnPackSize));  CNum i;  for(i = 0; i < numFolders; i++)  {    CFolder &folder = folders[i];    CNum numOutStreams = folder.GetNumOutStreams();    folder.UnPackSizes.Reserve(numOutStreams);    for(CNum j = 0; j < numOutStreams; j++)    {      UInt64 unPackSize;      RINOK(ReadNumber(unPackSize));      folder.UnPackSizes.Add(unPackSize);    }  }  while(true)  {    UInt64 type;    RINOK(ReadID(type));    if (type == NID::kEnd)      return S_OK;    if (type == NID::kCRC)    {      CRecordVector<bool> crcsDefined;      CRecordVector<UInt32> crcs;      RINOK(ReadHashDigests(numFolders, crcsDefined, crcs));       for(i = 0; i < numFolders; i++)      {        CFolder &folder = folders[i];        folder.UnPackCRCDefined = crcsDefined[i];        folder.UnPackCRC = crcs[i];      }      continue;    }    RINOK(SkeepData());  }}HRESULT CInArchive::ReadSubStreamsInfo(    const CObjectVector<CFolder> &folders,    CRecordVector<CNum> &numUnPackStreamsInFolders,    CRecordVector<UInt64> &unPackSizes,    CRecordVector<bool> &digestsDefined,     CRecordVector<UInt32> &digests){  numUnPackStreamsInFolders.Clear();  numUnPackStreamsInFolders.Reserve(folders.Size());  UInt64 type;  while(true)  {    RINOK(ReadID(type));    if (type == NID::kNumUnPackStream)    {      for(int i = 0; i < folders.Size(); i++)      {        CNum value;        RINOK(ReadNum(value));        numUnPackStreamsInFolders.Add(value);      }      continue;    }    if (type == NID::kCRC || type == NID::kSize)      break;    if (type == NID::kEnd)      break;    RINOK(SkeepData());  }  if (numUnPackStreamsInFolders.IsEmpty())    for(int i = 0; i < folders.Size(); i++)      numUnPackStreamsInFolders.Add(1);  int i;  for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)  {    // v3.13 incorrectly worked with empty folders    // v4.07: we check that folder is empty    CNum numSubstreams = numUnPackStreamsInFolders[i];    if (numSubstreams == 0)      continue;    UInt64 sum = 0;    for (CNum j = 1; j < numSubstreams; j++)    {      UInt64 size;      if (type == NID::kSize)      {        RINOK(ReadNumber(size));        unPackSizes.Add(size);        sum += size;      }    }    unPackSizes.Add(folders[i].GetUnPackSize() - sum);  }  if (type == NID::kSize)  {    RINOK(ReadID(type));  }  int numDigests = 0;  int numDigestsTotal = 0;  for(i = 0; i < folders.Size(); i++)  {    CNum numSubstreams = numUnPackStreamsInFolders[i];    if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)      numDigests += numSubstreams;    numDigestsTotal += numSubstreams;  }  while(true)  {    if (type == NID::kCRC)    {      CRecordVector<bool> digestsDefined2;       CRecordVector<UInt32> digests2;      RINOK(ReadHashDigests(numDigests, digestsDefined2, digests2));      int digestIndex = 0;      for (i = 0; i < folders.Size(); i++)      {        CNum numSubstreams = numUnPackStreamsInFolders[i];        const CFolder &folder = folders[i];        if (numSubstreams == 1 && folder.UnPackCRCDefined)        {          digestsDefined.Add(true);          digests.Add(folder.UnPackCRC);        }        else          for (CNum j = 0; j < numSubstreams; j++, digestIndex++)          {            digestsDefined.Add(digestsDefined2[digestIndex]);            digests.Add(digests2[digestIndex]);          }      }    }    else if (type == NID::kEnd)    {      if (digestsDefined.IsEmpty())      {        digestsDefined.Clear();        digests.Clear();        for (int i = 0; i < numDigestsTotal; i++)        {          digestsDefined.Add(false);          digests.Add(0);        }      }      return S_OK;    }    else    {      RINOK(SkeepData());    }    RINOK(ReadID(type));  }}HRESULT CInArchive::ReadStreamsInfo(    const CObjectVector<CByteBuffer> *dataVector,    UInt64 &dataOffset,    CRecordVector<UInt64> &packSizes,    CRecordVector<bool> &packCRCsDefined,    CRecordVector<UInt32> &packCRCs,    CObjectVector<CFolder> &folders,    CRecordVector<CNum> &numUnPackStreamsInFolders,    CRecordVector<UInt64> &unPackSizes,    CRecordVector<bool> &digestsDefined,     CRecordVector<UInt32> &digests){  while(true)  {    UInt64 type;    RINOK(ReadID(type));    switch(type)    {      case NID::kEnd:        return S_OK;      case NID::kPackInfo:      {        RINOK(ReadPackInfo(dataOffset, packSizes,            packCRCsDefined, packCRCs));        break;      }      case NID::kUnPackInfo:      {        RINOK(ReadUnPackInfo(dataVector, folders));        break;      }      case NID::kSubStreamsInfo:      {        RINOK(ReadSubStreamsInfo(folders, numUnPackStreamsInFolders,          unPackSizes, digestsDefined, digests));        break;      }    }  }}HRESULT CInArchive::ReadFileNames(CObjectVector<CFileItem> &files){  for(int i = 0; i < files.Size(); i++)  {    UString &name = files[i].Name;    name.Empty();    while (true)    {      wchar_t c;      RINOK(ReadWideCharLE(c));      if (c == L'\0')        break;      name += c;    }  }  return S_OK;}HRESULT CInArchive::ReadBoolVector(int numItems, CBoolVector &v){  v.Clear();  v.Reserve(numItems);  Byte b;  Byte mask = 0;  for(int i = 0; i < numItems; i++)  {    if (mask == 0)    {      RINOK(ReadByte(b));      mask = 0x80;    }    v.Add((b & mask) != 0);    mask >>= 1;  }  return S_OK;}HRESULT CInArchive::ReadBoolVector2(int numItems, CBoolVector &v){  Byte allAreDefined;  RINOK(ReadByte(allAreDefined));  if (allAreDefined == 0)    return ReadBoolVector(numItems, v);  v.Clear();  v.Reserve(numItems);  for (int i = 0; i < numItems; i++)    v.Add(true);  return S_OK;}HRESULT CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector,    CObjectVector<CFileItem> &files, UInt64 type){  CBoolVector boolVector;  RINOK(ReadBoolVector2(files.Size(), boolVector))  CStreamSwitch streamSwitch;  RINOK(streamSwitch.Set(this, &dataVector));  for(int i = 0; i < files.Size(); i++)  {    CFileItem &file = files[i];    CArchiveFileTime fileTime;    bool defined = boolVector[i];    if (defined)    {      UInt32 low, high;      RINOK(ReadUInt32(low));      RINOK(ReadUInt32(high));      fileTime.dwLowDateTime = low;      fileTime.dwHighDateTime = high;    }    switch(type)    {      case NID::kCreationTime:        file.IsCreationTimeDefined = defined;        if (defined)          file.CreationTime = fileTime;        break;      case NID::kLastWriteTime:        file.IsLastWriteTimeDefined = defined;        if (defined)          file.LastWriteTime = fileTime;        break;      case NID::kLastAccessTime:        file.IsLastAccessTimeDefined = defined;        if (defined)          file.LastAccessTime = fileTime;        break;    }  }  return S_OK;}HRESULT CInArchive::ReadAndDecodePackedStreams(UInt64 baseOffset,     UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector    #ifndef _NO_CRYPTO    , ICryptoGetTextPassword *getTextPassword    #endif    ){  CRecordVector<UInt64> packSizes;  CRecordVector<bool> packCRCsDefined;  CRecordVector<UInt32> packCRCs;  CObjectVector<CFolder> folders;    CRecordVector<CNum> numUnPackStreamsInFolders;  CRecordVector<UInt64> unPackSizes;  CRecordVector<bool> digestsDefined;  CRecordVector<UInt32> digests;    RINOK(ReadStreamsInfo(NULL,     dataOffset,    packSizes,     packCRCsDefined,     packCRCs,     folders,    numUnPackStreamsInFolders,    unPackSizes,    digestsDefined,     digests));    // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;    CNum packIndex = 0;  CDecoder decoder(    #ifdef _ST_MODE    false    #else    true    #endif    );  UInt64 dataStartPos = baseOffset + dataOffset;  for(int i = 0; i < folders.Size(); i++)  {    const CFolder &folder = folders[i];

⌨️ 快捷键说明

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