📄 7zout.cpp
字号:
folders.Add(folderItem);
return S_OK;
}
HRESULT COutArchive::EncodeStream(CEncoder &encoder, const CByteBuffer &data,
CRecordVector<UINT64> &packSizes, CObjectVector<CFolder> &folders)
{
return EncodeStream(encoder, data, data.GetCapacity(), packSizes, folders);
}
HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
const CCompressionMethodMode *options, UINT64 &headerOffset)
{
CObjectVector<CFolder> folders;
bool compressHeaders = (options != NULL);
std::auto_ptr<CEncoder> encoder;
if (compressHeaders)
encoder = std::auto_ptr<CEncoder>(new CEncoder(*options));
CRecordVector<UINT64> packSizes;
UINT64 dataIndex = 0;
//////////////////////////
// Folders
UINT64 externalFoldersStreamIndex;
bool externalFolders = (compressHeaders && database.Folders.Size() > 8);
if (externalFolders)
{
_mainMode = false;
_countMode = true;
_countSize = 0;
int i;
for(i = 0; i < database.Folders.Size(); i++)
{
RINOK(WriteFolderHeader(database.Folders[i]));
}
_countMode = false;
CByteBuffer foldersData;
foldersData.SetCapacity(_countSize);
_outByte2.Init(foldersData, foldersData.GetCapacity());
for(i = 0; i < database.Folders.Size(); i++)
{
RINOK(WriteFolderHeader(database.Folders[i]));
}
{
externalFoldersStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, foldersData, packSizes, folders));
}
}
/////////////////////////////////
// Names
CByteBuffer namesData;
UINT64 externalNamesStreamIndex;
bool externalNames = (compressHeaders && database.Files.Size() > 8);
{
UINT64 namesDataSize = 0;
int i;
for(i = 0; i < database.Files.Size(); i++)
namesDataSize += (database.Files[i].Name.Length() + 1) * sizeof(wchar_t);
namesData.SetCapacity(namesDataSize);
UINT32 pos = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const UString &name = database.Files[i].Name;
int length = name.Length() * sizeof(wchar_t);
memmove(namesData + pos, name, length);
pos += length;
namesData[pos++] = 0;
namesData[pos++] = 0;
}
if (externalNames)
{
externalNamesStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, namesData, packSizes, folders));
}
}
/////////////////////////////////
// Write Attributes
CBoolVector attributesBoolVector;
attributesBoolVector.Reserve(database.Files.Size());
UINT32 numDefinedAttributes = 0;
int i;
for(i = 0; i < database.Files.Size(); i++)
{
bool defined = database.Files[i].AreAttributesDefined;
attributesBoolVector.Add(defined);
if (defined)
numDefinedAttributes++;
}
CByteBuffer attributesData;
UINT64 externalAttributesStreamIndex;
bool externalAttributes = (compressHeaders && numDefinedAttributes > 8);
if (numDefinedAttributes > 0)
{
attributesData.SetCapacity(numDefinedAttributes * sizeof(UINT32));
UINT32 pos = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (file.AreAttributesDefined)
{
memmove(attributesData + pos, &database.Files[i].Attributes, sizeof(UINT32));
pos += sizeof(UINT32);
}
}
if (externalAttributes)
{
externalAttributesStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, attributesData, packSizes, folders));
}
}
/////////////////////////////////
// Write Last Write Time
UINT64 externalLastWriteTimeStreamIndex;
bool externalLastWriteTime = false;
// /*
UINT32 numDefinedLastWriteTimes = 0;
for(i = 0; i < database.Files.Size(); i++)
if (database.Files[i].IsLastWriteTimeDefined)
numDefinedLastWriteTimes++;
externalLastWriteTime = (compressHeaders && numDefinedLastWriteTimes > 64);
if (numDefinedLastWriteTimes > 0)
{
CByteBuffer lastWriteTimeData;
lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * sizeof(CArchiveFileTime));
UINT32 pos = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (file.IsLastWriteTimeDefined)
{
memmove(lastWriteTimeData + pos, &database.Files[i].LastWriteTime, sizeof(CArchiveFileTime));
pos += sizeof(CArchiveFileTime);
}
}
if (externalLastWriteTime)
{
externalLastWriteTimeStreamIndex = dataIndex++;
RINOK(EncodeStream(*encoder, lastWriteTimeData, packSizes, folders));
}
}
// */
UINT64 packedSize = 0;
for(i = 0; i < database.PackSizes.Size(); i++)
packedSize += database.PackSizes[i];
UINT64 headerPackSize = 0;
for (i = 0; i < packSizes.Size(); i++)
headerPackSize += packSizes[i];
headerOffset = packedSize + headerPackSize;
_mainMode = true;
_outByte.Init(Stream);
_crc.Init();
RINOK(WriteByte2(NID::kHeader));
// Archive Properties
if (folders.Size() > 0)
{
RINOK(WriteByte2(NID::kAdditionalStreamsInfo));
RINOK(WritePackInfo(packedSize, packSizes,
CRecordVector<bool>(), CRecordVector<UINT32>()));
RINOK(WriteUnPackInfo(false, 0, folders));
RINOK(WriteByte2(NID::kEnd));
}
////////////////////////////////////////////////////
if (database.Folders.Size() > 0)
{
RINOK(WriteByte2(NID::kMainStreamsInfo));
RINOK(WritePackInfo(0, database.PackSizes,
database.PackCRCsDefined,
database.PackCRCs));
RINOK(WriteUnPackInfo(
externalFolders, externalFoldersStreamIndex, database.Folders));
CRecordVector<UINT64> unPackSizes;
CRecordVector<bool> digestsDefined;
CRecordVector<UINT32> digests;
for (i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (!file.HasStream)
continue;
unPackSizes.Add(file.UnPackSize);
digestsDefined.Add(file.FileCRCIsDefined);
digests.Add(file.FileCRC);
}
RINOK(WriteSubStreamsInfo(
database.Folders,
database.NumUnPackStreamsVector,
unPackSizes,
digestsDefined,
digests));
RINOK(WriteByte2(NID::kEnd));
}
if (database.Files.IsEmpty())
{
RINOK(WriteByte2(NID::kEnd));
return _outByte.Flush();
}
RINOK(WriteByte2(NID::kFilesInfo));
RINOK(WriteNumber(database.Files.Size()));
CBoolVector emptyStreamVector;
emptyStreamVector.Reserve(database.Files.Size());
UINT64 numEmptyStreams = 0;
for(i = 0; i < database.Files.Size(); i++)
if (database.Files[i].HasStream)
emptyStreamVector.Add(false);
else
{
emptyStreamVector.Add(true);
numEmptyStreams++;
}
if (numEmptyStreams > 0)
{
RINOK(WriteByte2(NID::kEmptyStream));
RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8));
RINOK(WriteBoolVector(emptyStreamVector));
CBoolVector emptyFileVector, antiVector;
emptyFileVector.Reserve(numEmptyStreams);
antiVector.Reserve(numEmptyStreams);
UINT64 numEmptyFiles = 0, numAntiItems = 0;
for(i = 0; i < database.Files.Size(); i++)
{
const CFileItem &file = database.Files[i];
if (!file.HasStream)
{
emptyFileVector.Add(!file.IsDirectory);
if (!file.IsDirectory)
numEmptyFiles++;
antiVector.Add(file.IsAnti);
if (file.IsAnti)
numAntiItems++;
}
}
if (numEmptyFiles > 0)
{
RINOK(WriteByte2(NID::kEmptyFile));
RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8));
RINOK(WriteBoolVector(emptyFileVector));
}
if (numAntiItems > 0)
{
RINOK(WriteByte2(NID::kAnti));
RINOK(WriteNumber((antiVector.Size() + 7) / 8));
RINOK(WriteBoolVector(antiVector));
}
}
{
/////////////////////////////////////////////////
RINOK(WriteByte2(NID::kName));
if (externalNames)
{
RINOK(WriteNumber(1 +
GetBigNumberSize(externalNamesStreamIndex)));
RINOK(WriteByte2(1));
RINOK(WriteNumber(externalNamesStreamIndex));
}
else
{
RINOK(WriteNumber(1 + namesData.GetCapacity()));
RINOK(WriteByte2(0));
RINOK(WriteBytes2(namesData));
}
}
RINOK(WriteTime(database.Files, NID::kCreationTime, false, 0));
RINOK(WriteTime(database.Files, NID::kLastAccessTime, false, 0));
RINOK(WriteTime(database.Files, NID::kLastWriteTime,
// false, 0));
externalLastWriteTime, externalLastWriteTimeStreamIndex));
if (numDefinedAttributes > 0)
{
/////////////////////////////////////////////////
RINOK(WriteByte2(NID::kWinAttributes));
UINT32 size = 2;
if (numDefinedAttributes != database.Files.Size())
size += (attributesBoolVector.Size() + 7) / 8 + 1;
if (externalAttributes)
size += GetBigNumberSize(externalAttributesStreamIndex);
else
size += attributesData.GetCapacity();
RINOK(WriteNumber(size));
if (numDefinedAttributes == database.Files.Size())
{
RINOK(WriteByte2(1));
}
else
{
RINOK(WriteByte2(0));
RINOK(WriteBoolVector(attributesBoolVector));
}
if (externalAttributes)
{
RINOK(WriteByte2(1));
RINOK(WriteNumber(externalAttributesStreamIndex));
}
else
{
RINOK(WriteByte2(0));
RINOK(WriteBytes2(attributesData));
}
}
RINOK(WriteByte2(NID::kEnd)); // for files
RINOK(WriteByte2(NID::kEnd)); // for headers
return _outByte.Flush();
}
HRESULT COutArchive::WriteDatabase(const CArchiveDatabase &database,
const CCompressionMethodMode *options,
bool useAdditionalStreams, bool compressMainHeader)
{
UINT64 headerOffset;
UINT32 headerCRC;
UINT64 headerSize;
if (database.IsEmpty())
{
headerSize = 0;
headerOffset = 0;
headerCRC = CCRC::CalculateDigest(0, 0);
}
else
{
_dynamicBuffer.Init();
_dynamicMode = false;
if (options != 0)
if (options->IsEmpty())
options = 0;
const CCompressionMethodMode *additionalStreamsOptions = options;
if (!useAdditionalStreams)
additionalStreamsOptions = 0;
/*
if (database.Files.Size() < 2)
compressMainHeader = false;
*/
if (options != 0)
if (options->PasswordIsDefined || compressMainHeader)
_dynamicMode = true;
RINOK(WriteHeader(database, additionalStreamsOptions, headerOffset));
if (_dynamicMode)
{
CCompressionMethodMode encryptOptions;
encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
encryptOptions.Password = options->Password;
CEncoder encoder(compressMainHeader ?
*options : encryptOptions);
CRecordVector<UINT64> packSizes;
CObjectVector<CFolder> folders;
RINOK(EncodeStream(encoder, _dynamicBuffer,
_dynamicBuffer.GetSize(), packSizes, folders));
_dynamicMode = false;
_mainMode = true;
_outByte.Init(Stream);
_crc.Init();
if (folders.Size() == 0)
throw 1;
RINOK(WriteID(NID::kEncodedHeader));
RINOK(WritePackInfo(headerOffset, packSizes,
CRecordVector<bool>(), CRecordVector<UINT32>()));
RINOK(WriteUnPackInfo(false, 0, folders));
RINOK(WriteByte2(NID::kEnd));
for (int i = 0; i < packSizes.Size(); i++)
headerOffset += packSizes[i];
RINOK(_outByte.Flush());
}
headerCRC = _crc.GetDigest();
headerSize = _outByte.GetProcessedSize();
}
RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
CStartHeader startHeader;
startHeader.NextHeaderOffset = headerOffset;
startHeader.NextHeaderSize = headerSize;
startHeader.NextHeaderCRC = headerCRC;
UINT32 crc = CCRC::CalculateDigest(&startHeader, sizeof(startHeader));
RINOK(WriteBytes(&crc, sizeof(crc)));
return WriteBytes(&startHeader, sizeof(startHeader));
}
}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -