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 + -
显示快捷键?