7zout.cpp
来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 1,124 行 · 第 1/2 页
CPP
1,124 行
RINOK(WriteUInt32(timeValue.dwLowDateTime)); RINOK(WriteUInt32(timeValue.dwHighDateTime)); } } return S_OK;}HRESULT COutArchive::EncodeStream(CEncoder &encoder, const Byte *data, size_t dataSize, CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders){ CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp; CMyComPtr<ISequentialInStream> stream = streamSpec; streamSpec->Init(data, dataSize); CFolder folderItem; folderItem.UnPackCRCDefined = true; folderItem.UnPackCRC = CCRC::CalculateDigest(data, dataSize); UInt64 dataSize64 = dataSize; RINOK(encoder.Encode(stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL)); 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);}static void WriteUInt32ToBuffer(Byte *data, UInt32 value){ for (int i = 0; i < 4; i++) { *data++ = (Byte)value; value >>= 8; }}static void WriteUInt64ToBuffer(Byte *data, UInt64 value){ for (int i = 0; i < 8; i++) { *data++ = (Byte)value; value >>= 8; }}HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database, const CCompressionMethodMode *options, UInt64 &headerOffset){ CObjectVector<CFolder> folders; bool compressHeaders = (options != NULL); CMyAutoPtr<CEncoder> encoder; if (compressHeaders) { // it's for gcc2.95.2 CMyAutoPtr<CEncoder> tmp(new CEncoder(*options)); encoder = tmp; } CRecordVector<UInt64> packSizes; CNum dataIndex = 0; ////////////////////////// // Folders CNum 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(WriteFolder(database.Folders[i])); } _countMode = false; CByteBuffer foldersData; foldersData.SetCapacity(_countSize); _outByte2.Init(foldersData, foldersData.GetCapacity()); for(i = 0; i < database.Folders.Size(); i++) { RINOK(WriteFolder(database.Folders[i])); } { externalFoldersStreamIndex = dataIndex++; RINOK(EncodeStream(*encoder, foldersData, packSizes, folders)); } } int i; ///////////////////////////////// // Names CNum numDefinedNames = 0; size_t namesDataSize = 0; for(i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; if (!name.IsEmpty()) numDefinedNames++; namesDataSize += (name.Length() + 1) * 2; } CByteBuffer namesData; CNum externalNamesStreamIndex; bool externalNames = (compressHeaders && database.Files.Size() > 8); if (numDefinedNames > 0) { namesData.SetCapacity((size_t)namesDataSize); size_t pos = 0; for(int i = 0; i < database.Files.Size(); i++) { const UString &name = database.Files[i].Name; for (int t = 0; t < name.Length(); t++) { wchar_t c = name[t]; namesData[pos++] = Byte(c); namesData[pos++] = Byte(c >> 8); } 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()); int numDefinedAttributes = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].AreAttributesDefined; attributesBoolVector.Add(defined); if (defined) numDefinedAttributes++; } CByteBuffer attributesData; CNum externalAttributesStreamIndex; bool externalAttributes = (compressHeaders && numDefinedAttributes > 8); if (numDefinedAttributes > 0) { attributesData.SetCapacity(numDefinedAttributes * 4); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.AreAttributesDefined) { WriteUInt32ToBuffer(attributesData + pos, file.Attributes); pos += 4; } } if (externalAttributes) { externalAttributesStreamIndex = dataIndex++; RINOK(EncodeStream(*encoder, attributesData, packSizes, folders)); } } ///////////////////////////////// // Write StartPos CBoolVector startsBoolVector; startsBoolVector.Reserve(database.Files.Size()); int numDefinedStarts = 0; for(i = 0; i < database.Files.Size(); i++) { bool defined = database.Files[i].IsStartPosDefined; startsBoolVector.Add(defined); if (defined) numDefinedStarts++; } CByteBuffer startsData; CNum externalStartStreamIndex; bool externalStarts = (compressHeaders && numDefinedStarts > 8); if (numDefinedStarts > 0) { startsData.SetCapacity(numDefinedStarts * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsStartPosDefined) { WriteUInt64ToBuffer(startsData + pos, file.StartPos); pos += 8; } } if (externalStarts) { externalStartStreamIndex = dataIndex++; RINOK(EncodeStream(*encoder, startsData, packSizes, folders)); } } ///////////////////////////////// // Write Last Write Time CNum externalLastWriteTimeStreamIndex; bool externalLastWriteTime = false; // /* CNum 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 * 8); size_t pos = 0; for(i = 0; i < database.Files.Size(); i++) { const CFileItem &file = database.Files[i]; if (file.IsLastWriteTimeDefined) { WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwLowDateTime); pos += 4; WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwHighDateTime); pos += 4; } } 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.SetStream(SeqStream); _outByte.Init(); _crc.Init(); RINOK(WriteByte(NID::kHeader)); // Archive Properties if (folders.Size() > 0) { RINOK(WriteByte(NID::kAdditionalStreamsInfo)); RINOK(WritePackInfo(packedSize, packSizes, CRecordVector<bool>(), CRecordVector<UInt32>())); RINOK(WriteUnPackInfo(false, 0, folders)); RINOK(WriteByte(NID::kEnd)); } //////////////////////////////////////////////////// if (database.Folders.Size() > 0) { RINOK(WriteByte(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.IsFileCRCDefined); digests.Add(file.FileCRC); } RINOK(WriteSubStreamsInfo( database.Folders, database.NumUnPackStreamsVector, unPackSizes, digestsDefined, digests)); RINOK(WriteByte(NID::kEnd)); } if (database.Files.IsEmpty()) { RINOK(WriteByte(NID::kEnd)); return _outByte.Flush(); } RINOK(WriteByte(NID::kFilesInfo)); RINOK(WriteNumber(database.Files.Size())); CBoolVector emptyStreamVector; emptyStreamVector.Reserve(database.Files.Size()); int 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(WriteByte(NID::kEmptyStream)); RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyStreamVector)); CBoolVector emptyFileVector, antiVector; emptyFileVector.Reserve(numEmptyStreams); antiVector.Reserve(numEmptyStreams); CNum 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(WriteByte(NID::kEmptyFile)); RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8)); RINOK(WriteBoolVector(emptyFileVector)); } if (numAntiItems > 0) { RINOK(WriteByte(NID::kAnti)); RINOK(WriteNumber((antiVector.Size() + 7) / 8)); RINOK(WriteBoolVector(antiVector)); } } if (numDefinedNames > 0) { ///////////////////////////////////////////////// RINOK(WriteByte(NID::kName)); if (externalNames) { RINOK(WriteNumber(1 + GetBigNumberSize(externalNamesStreamIndex))); RINOK(WriteByte(1)); RINOK(WriteNumber(externalNamesStreamIndex)); } else { RINOK(WriteNumber(1 + namesData.GetCapacity())); RINOK(WriteByte(0)); RINOK(WriteBytes(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(WriteByte(NID::kWinAttributes)); size_t 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(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(attributesBoolVector)); } if (externalAttributes) { RINOK(WriteByte(1)); RINOK(WriteNumber(externalAttributesStreamIndex)); } else { RINOK(WriteByte(0)); RINOK(WriteBytes(attributesData)); } } if (numDefinedStarts > 0) { RINOK(WriteByte(NID::kStartPos)); size_t size = 2; if (numDefinedStarts != database.Files.Size()) size += (startsBoolVector.Size() + 7) / 8 + 1; if (externalStarts) size += GetBigNumberSize(externalStartStreamIndex); else size += startsData.GetCapacity(); RINOK(WriteNumber(size)); if (numDefinedStarts == database.Files.Size()) { RINOK(WriteByte(1)); } else { RINOK(WriteByte(0)); RINOK(WriteBoolVector(startsBoolVector)); } if (externalAttributes) { RINOK(WriteByte(1)); RINOK(WriteNumber(externalStartStreamIndex)); } else { RINOK(WriteByte(0)); RINOK(WriteBytes(startsData)); } } RINOK(WriteByte(NID::kEnd)); // for files RINOK(WriteByte(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.SetStream(SeqStream); _outByte.Init(); _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(WriteByte(NID::kEnd)); for (int i = 0; i < packSizes.Size(); i++) headerOffset += packSizes[i]; RINOK(_outByte.Flush()); } headerCRC = _crc.GetDigest(); headerSize = _outByte.GetProcessedSize(); } #ifdef _7Z_VOL if (_endMarker) { CFinishHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = UInt64(0) - (headerSize + 4 + kFinishHeaderSize); h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset; h.AdditionalStartBlockSize = 0; RINOK(WriteFinishHeader(h)); return WriteFinishSignature(); } else #endif { CStartHeader h; h.NextHeaderSize = headerSize; h.NextHeaderCRC = headerCRC; h.NextHeaderOffset = headerOffset; RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL)); return WriteStartHeader(h); }}}}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?