// 7zOut.h #ifndef __7Z_OUT_H #define __7Z_OUT_H #include "7zCompressionMode.h" #include "7zEncode.h" #include "7zHeader.h" #include "7zItem.h" #include "../../Common/OutBuffer.h" #include "../../Common/StreamUtils.h" namespace NArchive { namespace N7z { class CWriteBufferLoc { Byte *_data; size_t _size; size_t _pos; public: CWriteBufferLoc(): _size(0), _pos(0) {} void Init(Byte *data, size_t size) { _data = data; _size = size; _pos = 0; } void WriteBytes(const void *data, size_t size) { if (size > _size - _pos) throw 1; memcpy(_data + _pos, data, size); _pos += size; } void WriteByte(Byte b) { if (_size == _pos) throw 1; _data[_pos++] = b; } size_t GetPos() const { return _pos; } }; struct CHeaderOptions { bool CompressMainHeader; /* bool WriteCTime; bool WriteATime; bool WriteMTime; */ CHeaderOptions(): CompressMainHeader(true) /* , WriteCTime(false) , WriteATime(false) , WriteMTime(true) */ {} }; struct CFileItem2 { UInt64 CTime; UInt64 ATime; UInt64 MTime; UInt64 StartPos; bool CTimeDefined; bool ATimeDefined; bool MTimeDefined; bool StartPosDefined; bool IsAnti; // bool IsAux; void Init() { CTimeDefined = false; ATimeDefined = false; MTimeDefined = false; StartPosDefined = false; IsAnti = false; // IsAux = false; } }; struct COutFolders { CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. CRecordVector NumUnpackStreamsVector; CRecordVector CoderUnpackSizes; // including unpack sizes of bind coders void OutFoldersClear() { FolderUnpackCRCs.Clear(); NumUnpackStreamsVector.Clear(); CoderUnpackSizes.Clear(); } void OutFoldersReserveDown() { FolderUnpackCRCs.ReserveDown(); NumUnpackStreamsVector.ReserveDown(); CoderUnpackSizes.ReserveDown(); } }; struct CArchiveDatabaseOut: public COutFolders { CRecordVector PackSizes; CUInt32DefVector PackCRCs; CObjectVector Folders; CRecordVector Files; UStringVector Names; CUInt64DefVector CTime; CUInt64DefVector ATime; CUInt64DefVector MTime; CUInt64DefVector StartPos; CRecordVector IsAnti; /* CRecordVector IsAux; CByteBuffer SecureBuf; CRecordVector SecureSizes; CRecordVector SecureIDs; void ClearSecure() { SecureBuf.Free(); SecureSizes.Clear(); SecureIDs.Clear(); } */ void Clear() { OutFoldersClear(); PackSizes.Clear(); PackCRCs.Clear(); Folders.Clear(); Files.Clear(); Names.Clear(); CTime.Clear(); ATime.Clear(); MTime.Clear(); StartPos.Clear(); IsAnti.Clear(); /* IsAux.Clear(); ClearSecure(); */ } void ReserveDown() { OutFoldersReserveDown(); PackSizes.ReserveDown(); PackCRCs.ReserveDown(); Folders.ReserveDown(); Files.ReserveDown(); Names.ReserveDown(); CTime.ReserveDown(); ATime.ReserveDown(); MTime.ReserveDown(); StartPos.ReserveDown(); IsAnti.ReserveDown(); /* IsAux.ReserveDown(); */ } bool IsEmpty() const { return ( PackSizes.IsEmpty() && NumUnpackStreamsVector.IsEmpty() && Folders.IsEmpty() && Files.IsEmpty()); } bool CheckNumFiles() const { unsigned size = Files.Size(); return ( CTime.CheckSize(size) && ATime.CheckSize(size) && MTime.CheckSize(size) && StartPos.CheckSize(size) && (size == IsAnti.Size() || IsAnti.Size() == 0)); } bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } void SetItem_Anti(unsigned index, bool isAnti) { while (index >= IsAnti.Size()) IsAnti.Add(false); IsAnti[index] = isAnti; } /* void SetItem_Aux(unsigned index, bool isAux) { while (index >= IsAux.Size()) IsAux.Add(false); IsAux[index] = isAux; } */ void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); }; class COutArchive { UInt64 _prefixHeaderPos; HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); } UInt64 GetPos() const; void WriteBytes(const void *data, size_t size); void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } void WriteByte(Byte b); void WriteUInt32(UInt32 value); void WriteUInt64(UInt64 value); void WriteNumber(UInt64 value); void WriteID(UInt64 value) { WriteNumber(value); } void WriteFolder(const CFolder &folder); HRESULT WriteFileHeader(const CFileItem &itemInfo); void WriteBoolVector(const CBoolVector &boolVector); void WritePropBoolVector(Byte id, const CBoolVector &boolVector); void WriteHashDigests(const CUInt32DefVector &digests); void WritePackInfo( UInt64 dataOffset, const CRecordVector &packSizes, const CUInt32DefVector &packCRCs); void WriteUnpackInfo( const CObjectVector &folders, const COutFolders &outFolders); void WriteSubStreamsInfo( const CObjectVector &folders, const COutFolders &outFolders, const CRecordVector &unpackSizes, const CUInt32DefVector &digests); void SkipAlign(unsigned pos, unsigned alignSize); void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize); void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); HRESULT EncodeStream( DECL_EXTERNAL_CODECS_LOC_VARS CEncoder &encoder, const CByteBuffer &data, CRecordVector &packSizes, CObjectVector &folders, COutFolders &outFolders); void WriteHeader( const CArchiveDatabaseOut &db, // const CHeaderOptions &headerOptions, UInt64 &headerOffset); bool _countMode; bool _writeToStream; size_t _countSize; UInt32 _crc; COutBuffer _outByte; CWriteBufferLoc _outByte2; #ifdef _7Z_VOL bool _endMarker; #endif bool _useAlign; HRESULT WriteSignature(); #ifdef _7Z_VOL HRESULT WriteFinishSignature(); #endif HRESULT WriteStartHeader(const CStartHeader &h); #ifdef _7Z_VOL HRESULT WriteFinishHeader(const CFinishHeader &h); #endif CMyComPtr Stream; public: COutArchive() { _outByte.Create(1 << 16); } CMyComPtr SeqStream; HRESULT Create(ISequentialOutStream *stream, bool endMarker); void Close(); HRESULT SkipPrefixArchiveHeader(); HRESULT WriteDatabase( DECL_EXTERNAL_CODECS_LOC_VARS const CArchiveDatabaseOut &db, const CCompressionMethodMode *options, const CHeaderOptions &headerOptions); #ifdef _7Z_VOL static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); #endif }; }} #endif