📄 7zin.cpp
字号:
}
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(false);
UInt64 dataStartPos = baseOffset + dataOffset;
for(int i = 0; i < folders.Size(); i++)
{
const CFolder &folder = folders[i];
dataVector.Add(CByteBuffer());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -