// 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<CNum> NumUnpackStreamsVector; | |
CRecordVector<UInt64> 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<UInt64> PackSizes; | |
CUInt32DefVector PackCRCs; | |
CObjectVector<CFolder> Folders; | |
CRecordVector<CFileItem> Files; | |
UStringVector Names; | |
CUInt64DefVector CTime; | |
CUInt64DefVector ATime; | |
CUInt64DefVector MTime; | |
CUInt64DefVector StartPos; | |
CRecordVector<bool> IsAnti; | |
/* | |
CRecordVector<bool> IsAux; | |
CByteBuffer SecureBuf; | |
CRecordVector<UInt32> SecureSizes; | |
CRecordVector<UInt32> 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<UInt64> &packSizes, | |
const CUInt32DefVector &packCRCs); | |
void WriteUnpackInfo( | |
const CObjectVector<CFolder> &folders, | |
const COutFolders &outFolders); | |
void WriteSubStreamsInfo( | |
const CObjectVector<CFolder> &folders, | |
const COutFolders &outFolders, | |
const CRecordVector<UInt64> &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<UInt64> &packSizes, CObjectVector<CFolder> &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<IOutStream> Stream; | |
public: | |
COutArchive() { _outByte.Create(1 << 16); } | |
CMyComPtr<ISequentialOutStream> 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 |