📄 7zin.c
字号:
void * (*allocFunc)(size_t size))
{
UInt32 i;
RINOK(SzReadSize(sd, dataOffset));
RINOK(SzReadNumber32(sd, numPackStreams));
RINOK(SzWaitAttribute(sd, k7zIdSize));
MY_ALLOC(CFileSize, *packSizes, (size_t)*numPackStreams, allocFunc);
for(i = 0; i < *numPackStreams; i++)
{
RINOK(SzReadSize(sd, (*packSizes) + i));
}
for (;;)
{
UInt64 type;
RINOK(SzReadID(sd, &type));
if (type == k7zIdEnd)
break;
if (type == k7zIdCRC)
{
RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, allocFunc));
continue;
}
RINOK(SzSkeepData(sd));
}
if (*packCRCsDefined == 0)
{
MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, allocFunc);
MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, allocFunc);
for(i = 0; i < *numPackStreams; i++)
{
(*packCRCsDefined)[i] = 0;
(*packCRCs)[i] = 0;
}
}
return SZ_OK;
}
SZ_RESULT SzReadSwitch(CSzData *sd)
{
Byte external;
RINOK(SzReadByte(sd, &external));
return (external == 0) ? SZ_OK: SZE_ARCHIVE_ERROR;
}
SZ_RESULT SzGetNextFolderItem(CSzData *sd, CFolder *folder, void * (*allocFunc)(size_t size))
{
UInt32 numCoders;
UInt32 numBindPairs;
UInt32 numPackedStreams;
UInt32 i;
UInt32 numInStreams = 0;
UInt32 numOutStreams = 0;
RINOK(SzReadNumber32(sd, &numCoders));
folder->NumCoders = numCoders;
MY_ALLOC(CCoderInfo, folder->Coders, (size_t)numCoders, allocFunc);
for (i = 0; i < numCoders; i++)
SzCoderInfoInit(folder->Coders + i);
for (i = 0; i < numCoders; i++)
{
Byte mainByte;
CCoderInfo *coder = folder->Coders + i;
{
unsigned idSize, j;
Byte longID[15];
RINOK(SzReadByte(sd, &mainByte));
idSize = (unsigned)(mainByte & 0xF);
RINOK(SzReadBytes(sd, longID, idSize));
if (idSize > sizeof(coder->MethodID))
return SZE_NOTIMPL;
coder->MethodID = 0;
for (j = 0; j < idSize; j++)
coder->MethodID |= (CMethodID)longID[idSize - 1 - j] << (8 * j);
if ((mainByte & 0x10) != 0)
{
RINOK(SzReadNumber32(sd, &coder->NumInStreams));
RINOK(SzReadNumber32(sd, &coder->NumOutStreams));
}
else
{
coder->NumInStreams = 1;
coder->NumOutStreams = 1;
}
if ((mainByte & 0x20) != 0)
{
UInt64 propertiesSize = 0;
RINOK(SzReadNumber(sd, &propertiesSize));
if (!SzByteBufferCreate(&coder->Properties, (size_t)propertiesSize, allocFunc))
return SZE_OUTOFMEMORY;
RINOK(SzReadBytes(sd, coder->Properties.Items, (size_t)propertiesSize));
}
}
while ((mainByte & 0x80) != 0)
{
RINOK(SzReadByte(sd, &mainByte));
RINOK(SzSkeepDataSize(sd, (mainByte & 0xF)));
if ((mainByte & 0x10) != 0)
{
UInt32 n;
RINOK(SzReadNumber32(sd, &n));
RINOK(SzReadNumber32(sd, &n));
}
if ((mainByte & 0x20) != 0)
{
UInt64 propertiesSize = 0;
RINOK(SzReadNumber(sd, &propertiesSize));
RINOK(SzSkeepDataSize(sd, propertiesSize));
}
}
numInStreams += (UInt32)coder->NumInStreams;
numOutStreams += (UInt32)coder->NumOutStreams;
}
numBindPairs = numOutStreams - 1;
folder->NumBindPairs = numBindPairs;
MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, allocFunc);
for (i = 0; i < numBindPairs; i++)
{
CBindPair *bindPair = folder->BindPairs + i;;
RINOK(SzReadNumber32(sd, &bindPair->InIndex));
RINOK(SzReadNumber32(sd, &bindPair->OutIndex));
}
numPackedStreams = numInStreams - (UInt32)numBindPairs;
folder->NumPackStreams = numPackedStreams;
MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackedStreams, allocFunc);
if (numPackedStreams == 1)
{
UInt32 j;
UInt32 pi = 0;
for (j = 0; j < numInStreams; j++)
if (SzFolderFindBindPairForInStream(folder, j) < 0)
{
folder->PackStreams[pi++] = j;
break;
}
}
else
for(i = 0; i < numPackedStreams; i++)
{
RINOK(SzReadNumber32(sd, folder->PackStreams + i));
}
return SZ_OK;
}
SZ_RESULT SzReadUnPackInfo(
CSzData *sd,
UInt32 *numFolders,
CFolder **folders, /* for allocFunc */
void * (*allocFunc)(size_t size),
ISzAlloc *allocTemp)
{
UInt32 i;
RINOK(SzWaitAttribute(sd, k7zIdFolder));
RINOK(SzReadNumber32(sd, numFolders));
{
RINOK(SzReadSwitch(sd));
MY_ALLOC(CFolder, *folders, (size_t)*numFolders, allocFunc);
for(i = 0; i < *numFolders; i++)
SzFolderInit((*folders) + i);
for(i = 0; i < *numFolders; i++)
{
RINOK(SzGetNextFolderItem(sd, (*folders) + i, allocFunc));
}
}
RINOK(SzWaitAttribute(sd, k7zIdCodersUnPackSize));
for(i = 0; i < *numFolders; i++)
{
UInt32 j;
CFolder *folder = (*folders) + i;
UInt32 numOutStreams = SzFolderGetNumOutStreams(folder);
MY_ALLOC(CFileSize, folder->UnPackSizes, (size_t)numOutStreams, allocFunc);
for(j = 0; j < numOutStreams; j++)
{
RINOK(SzReadSize(sd, folder->UnPackSizes + j));
}
}
for (;;)
{
UInt64 type;
RINOK(SzReadID(sd, &type));
if (type == k7zIdEnd)
return SZ_OK;
if (type == k7zIdCRC)
{
SZ_RESULT res;
Byte *crcsDefined = 0;
UInt32 *crcs = 0;
res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp->Alloc);
if (res == SZ_OK)
{
for(i = 0; i < *numFolders; i++)
{
CFolder *folder = (*folders) + i;
folder->UnPackCRCDefined = crcsDefined[i];
folder->UnPackCRC = crcs[i];
}
}
allocTemp->Free(crcs);
allocTemp->Free(crcsDefined);
RINOK(res);
continue;
}
RINOK(SzSkeepData(sd));
}
}
SZ_RESULT SzReadSubStreamsInfo(
CSzData *sd,
UInt32 numFolders,
CFolder *folders,
UInt32 *numUnPackStreams,
CFileSize **unPackSizes,
Byte **digestsDefined,
UInt32 **digests,
ISzAlloc *allocTemp)
{
UInt64 type = 0;
UInt32 i;
UInt32 si = 0;
UInt32 numDigests = 0;
for(i = 0; i < numFolders; i++)
folders[i].NumUnPackStreams = 1;
*numUnPackStreams = numFolders;
for (;;)
{
RINOK(SzReadID(sd, &type));
if (type == k7zIdNumUnPackStream)
{
*numUnPackStreams = 0;
for(i = 0; i < numFolders; i++)
{
UInt32 numStreams;
RINOK(SzReadNumber32(sd, &numStreams));
folders[i].NumUnPackStreams = numStreams;
*numUnPackStreams += numStreams;
}
continue;
}
if (type == k7zIdCRC || type == k7zIdSize)
break;
if (type == k7zIdEnd)
break;
RINOK(SzSkeepData(sd));
}
if (*numUnPackStreams == 0)
{
*unPackSizes = 0;
*digestsDefined = 0;
*digests = 0;
}
else
{
*unPackSizes = (CFileSize *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(CFileSize));
RINOM(*unPackSizes);
*digestsDefined = (Byte *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(Byte));
RINOM(*digestsDefined);
*digests = (UInt32 *)allocTemp->Alloc((size_t)*numUnPackStreams * sizeof(UInt32));
RINOM(*digests);
}
for(i = 0; i < numFolders; i++)
{
/*
v3.13 incorrectly worked with empty folders
v4.07: we check that folder is empty
*/
CFileSize sum = 0;
UInt32 j;
UInt32 numSubstreams = folders[i].NumUnPackStreams;
if (numSubstreams == 0)
continue;
if (type == k7zIdSize)
for (j = 1; j < numSubstreams; j++)
{
CFileSize size;
RINOK(SzReadSize(sd, &size));
(*unPackSizes)[si++] = size;
sum += size;
}
(*unPackSizes)[si++] = SzFolderGetUnPackSize(folders + i) - sum;
}
if (type == k7zIdSize)
{
RINOK(SzReadID(sd, &type));
}
for(i = 0; i < *numUnPackStreams; i++)
{
(*digestsDefined)[i] = 0;
(*digests)[i] = 0;
}
for(i = 0; i < numFolders; i++)
{
UInt32 numSubstreams = folders[i].NumUnPackStreams;
if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
numDigests += numSubstreams;
}
si = 0;
for (;;)
{
if (type == k7zIdCRC)
{
int digestIndex = 0;
Byte *digestsDefined2 = 0;
UInt32 *digests2 = 0;
SZ_RESULT res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp->Alloc);
if (res == SZ_OK)
{
for (i = 0; i < numFolders; i++)
{
CFolder *folder = folders + i;
UInt32 numSubstreams = folder->NumUnPackStreams;
if (numSubstreams == 1 && folder->UnPackCRCDefined)
{
(*digestsDefined)[si] = 1;
(*digests)[si] = folder->UnPackCRC;
si++;
}
else
{
UInt32 j;
for (j = 0; j < numSubstreams; j++, digestIndex++)
{
(*digestsDefined)[si] = digestsDefined2[digestIndex];
(*digests)[si] = digests2[digestIndex];
si++;
}
}
}
}
allocTemp->Free(digestsDefined2);
allocTemp->Free(digests2);
RINOK(res);
}
else if (type == k7zIdEnd)
return SZ_OK;
else
{
RINOK(SzSkeepData(sd));
}
RINOK(SzReadID(sd, &type));
}
}
SZ_RESULT SzReadStreamsInfo(
CSzData *sd,
CFileSize *dataOffset,
CArchiveDatabase *db,
UInt32 *numUnPackStreams,
CFileSize **unPackSizes, /* allocTemp */
Byte **digestsDefined, /* allocTemp */
UInt32 **digests, /* allocTemp */
void * (*allocFunc)(size_t size),
ISzAlloc *allocTemp)
{
for (;;)
{
UInt64 type;
RINOK(SzReadID(sd, &type));
if ((UInt64)(int)type != type)
return SZE_FAIL;
switch((int)type)
{
case k7zIdEnd:
return SZ_OK;
case k7zIdPackInfo:
{
RINOK(SzReadPackInfo(sd, dataOffset, &db->NumPackStreams,
&db->PackSizes, &db->PackCRCsDefined, &db->PackCRCs, allocFunc));
break;
}
case k7zIdUnPackInfo:
{
RINOK(SzReadUnPackInfo(sd, &db->NumFolders, &db->Folders, allocFunc, allocTemp));
break;
}
case k7zIdSubStreamsInfo:
{
RINOK(SzReadSubStreamsInfo(sd, db->NumFolders, db->Folders,
numUnPackStreams, unPackSizes, digestsDefined, digests, allocTemp));
break;
}
default:
return SZE_FAIL;
}
}
}
Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
SZ_RESULT SzReadFileNames(CSzData *sd, UInt32 numFiles, CFileItem *files,
void * (*allocFunc)(size_t size))
{
UInt32 i;
for(i = 0; i < numFiles; i++)
{
UInt32 len = 0;
UInt32 pos = 0;
CFileItem *file = files + i;
while(pos + 2 <= sd->Size)
{
int numAdds;
UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
pos += 2;
len++;
if (value == 0)
break;
if (value < 0x80)
continue;
if (value >= 0xD800 && value < 0xE000)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -