1 // 7zOut.h 2 3 #ifndef __7Z_OUT_H 4 #define __7Z_OUT_H 5 6 #include "7zCompressionMode.h" 7 #include "7zEncode.h" 8 #include "7zHeader.h" 9 #include "7zItem.h" 10 11 #include "../../Common/OutBuffer.h" 12 #include "../../Common/StreamUtils.h" 13 14 namespace NArchive { 15 namespace N7z { 16 17 class CWriteBufferLoc 18 { 19 Byte *_data; 20 size_t _size; 21 size_t _pos; 22 public: CWriteBufferLoc()23 CWriteBufferLoc(): _size(0), _pos(0) {} Init(Byte * data,size_t size)24 void Init(Byte *data, size_t size) 25 { 26 _data = data; 27 _size = size; 28 _pos = 0; 29 } WriteBytes(const void * data,size_t size)30 void WriteBytes(const void *data, size_t size) 31 { 32 if (size == 0) 33 return; 34 if (size > _size - _pos) 35 throw 1; 36 memcpy(_data + _pos, data, size); 37 _pos += size; 38 } WriteByte(Byte b)39 void WriteByte(Byte b) 40 { 41 if (_size == _pos) 42 throw 1; 43 _data[_pos++] = b; 44 } GetPos()45 size_t GetPos() const { return _pos; } 46 }; 47 48 struct CHeaderOptions 49 { 50 bool CompressMainHeader; 51 /* 52 bool WriteCTime; 53 bool WriteATime; 54 bool WriteMTime; 55 */ 56 CHeaderOptionsCHeaderOptions57 CHeaderOptions(): 58 CompressMainHeader(true) 59 /* 60 , WriteCTime(false) 61 , WriteATime(false) 62 , WriteMTime(true) 63 */ 64 {} 65 }; 66 67 68 struct CFileItem2 69 { 70 UInt64 CTime; 71 UInt64 ATime; 72 UInt64 MTime; 73 UInt64 StartPos; 74 bool CTimeDefined; 75 bool ATimeDefined; 76 bool MTimeDefined; 77 bool StartPosDefined; 78 bool IsAnti; 79 // bool IsAux; 80 InitCFileItem281 void Init() 82 { 83 CTimeDefined = false; 84 ATimeDefined = false; 85 MTimeDefined = false; 86 StartPosDefined = false; 87 IsAnti = false; 88 // IsAux = false; 89 } 90 }; 91 92 struct COutFolders 93 { 94 CUInt32DefVector FolderUnpackCRCs; // Now we use it for headers only. 95 96 CRecordVector<CNum> NumUnpackStreamsVector; 97 CRecordVector<UInt64> CoderUnpackSizes; // including unpack sizes of bond coders 98 OutFoldersClearCOutFolders99 void OutFoldersClear() 100 { 101 FolderUnpackCRCs.Clear(); 102 NumUnpackStreamsVector.Clear(); 103 CoderUnpackSizes.Clear(); 104 } 105 OutFoldersReserveDownCOutFolders106 void OutFoldersReserveDown() 107 { 108 FolderUnpackCRCs.ReserveDown(); 109 NumUnpackStreamsVector.ReserveDown(); 110 CoderUnpackSizes.ReserveDown(); 111 } 112 }; 113 114 struct CArchiveDatabaseOut: public COutFolders 115 { 116 CRecordVector<UInt64> PackSizes; 117 CUInt32DefVector PackCRCs; 118 CObjectVector<CFolder> Folders; 119 120 CRecordVector<CFileItem> Files; 121 UStringVector Names; 122 CUInt64DefVector CTime; 123 CUInt64DefVector ATime; 124 CUInt64DefVector MTime; 125 CUInt64DefVector StartPos; 126 CRecordVector<bool> IsAnti; 127 128 /* 129 CRecordVector<bool> IsAux; 130 131 CByteBuffer SecureBuf; 132 CRecordVector<UInt32> SecureSizes; 133 CRecordVector<UInt32> SecureIDs; 134 135 void ClearSecure() 136 { 137 SecureBuf.Free(); 138 SecureSizes.Clear(); 139 SecureIDs.Clear(); 140 } 141 */ 142 ClearCArchiveDatabaseOut143 void Clear() 144 { 145 OutFoldersClear(); 146 147 PackSizes.Clear(); 148 PackCRCs.Clear(); 149 Folders.Clear(); 150 151 Files.Clear(); 152 Names.Clear(); 153 CTime.Clear(); 154 ATime.Clear(); 155 MTime.Clear(); 156 StartPos.Clear(); 157 IsAnti.Clear(); 158 159 /* 160 IsAux.Clear(); 161 ClearSecure(); 162 */ 163 } 164 ReserveDownCArchiveDatabaseOut165 void ReserveDown() 166 { 167 OutFoldersReserveDown(); 168 169 PackSizes.ReserveDown(); 170 PackCRCs.ReserveDown(); 171 Folders.ReserveDown(); 172 173 Files.ReserveDown(); 174 Names.ReserveDown(); 175 CTime.ReserveDown(); 176 ATime.ReserveDown(); 177 MTime.ReserveDown(); 178 StartPos.ReserveDown(); 179 IsAnti.ReserveDown(); 180 181 /* 182 IsAux.ReserveDown(); 183 */ 184 } 185 IsEmptyCArchiveDatabaseOut186 bool IsEmpty() const 187 { 188 return ( 189 PackSizes.IsEmpty() && 190 NumUnpackStreamsVector.IsEmpty() && 191 Folders.IsEmpty() && 192 Files.IsEmpty()); 193 } 194 CheckNumFilesCArchiveDatabaseOut195 bool CheckNumFiles() const 196 { 197 unsigned size = Files.Size(); 198 return ( 199 CTime.CheckSize(size) && 200 ATime.CheckSize(size) && 201 MTime.CheckSize(size) && 202 StartPos.CheckSize(size) && 203 (size == IsAnti.Size() || IsAnti.Size() == 0)); 204 } 205 IsItemAntiCArchiveDatabaseOut206 bool IsItemAnti(unsigned index) const { return (index < IsAnti.Size() && IsAnti[index]); } 207 // bool IsItemAux(unsigned index) const { return (index < IsAux.Size() && IsAux[index]); } 208 SetItem_AntiCArchiveDatabaseOut209 void SetItem_Anti(unsigned index, bool isAnti) 210 { 211 while (index >= IsAnti.Size()) 212 IsAnti.Add(false); 213 IsAnti[index] = isAnti; 214 } 215 /* 216 void SetItem_Aux(unsigned index, bool isAux) 217 { 218 while (index >= IsAux.Size()) 219 IsAux.Add(false); 220 IsAux[index] = isAux; 221 } 222 */ 223 224 void AddFile(const CFileItem &file, const CFileItem2 &file2, const UString &name); 225 }; 226 227 class COutArchive 228 { 229 UInt64 _prefixHeaderPos; 230 WriteDirect(const void * data,UInt32 size)231 HRESULT WriteDirect(const void *data, UInt32 size) { return WriteStream(SeqStream, data, size); } 232 233 UInt64 GetPos() const; 234 void WriteBytes(const void *data, size_t size); WriteBytes(const CByteBuffer & data)235 void WriteBytes(const CByteBuffer &data) { WriteBytes(data, data.Size()); } 236 void WriteByte(Byte b); 237 void WriteUInt32(UInt32 value); 238 void WriteUInt64(UInt64 value); 239 void WriteNumber(UInt64 value); WriteID(UInt64 value)240 void WriteID(UInt64 value) { WriteNumber(value); } 241 242 void WriteFolder(const CFolder &folder); 243 HRESULT WriteFileHeader(const CFileItem &itemInfo); 244 void WriteBoolVector(const CBoolVector &boolVector); 245 void WritePropBoolVector(Byte id, const CBoolVector &boolVector); 246 247 void WriteHashDigests(const CUInt32DefVector &digests); 248 249 void WritePackInfo( 250 UInt64 dataOffset, 251 const CRecordVector<UInt64> &packSizes, 252 const CUInt32DefVector &packCRCs); 253 254 void WriteUnpackInfo( 255 const CObjectVector<CFolder> &folders, 256 const COutFolders &outFolders); 257 258 void WriteSubStreamsInfo( 259 const CObjectVector<CFolder> &folders, 260 const COutFolders &outFolders, 261 const CRecordVector<UInt64> &unpackSizes, 262 const CUInt32DefVector &digests); 263 264 void SkipAlign(unsigned pos, unsigned alignSize); 265 void WriteAlignedBoolHeader(const CBoolVector &v, unsigned numDefined, Byte type, unsigned itemSize); 266 void WriteUInt64DefVector(const CUInt64DefVector &v, Byte type); 267 268 HRESULT EncodeStream( 269 DECL_EXTERNAL_CODECS_LOC_VARS 270 CEncoder &encoder, const CByteBuffer &data, 271 CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders, COutFolders &outFolders); 272 void WriteHeader( 273 const CArchiveDatabaseOut &db, 274 // const CHeaderOptions &headerOptions, 275 UInt64 &headerOffset); 276 277 bool _countMode; 278 bool _writeToStream; 279 size_t _countSize; 280 UInt32 _crc; 281 COutBuffer _outByte; 282 CWriteBufferLoc _outByte2; 283 284 #ifdef _7Z_VOL 285 bool _endMarker; 286 #endif 287 288 bool _useAlign; 289 290 HRESULT WriteSignature(); 291 #ifdef _7Z_VOL 292 HRESULT WriteFinishSignature(); 293 #endif 294 HRESULT WriteStartHeader(const CStartHeader &h); 295 #ifdef _7Z_VOL 296 HRESULT WriteFinishHeader(const CFinishHeader &h); 297 #endif 298 CMyComPtr<IOutStream> Stream; 299 public: 300 COutArchive()301 COutArchive() { _outByte.Create(1 << 16); } 302 CMyComPtr<ISequentialOutStream> SeqStream; 303 HRESULT Create(ISequentialOutStream *stream, bool endMarker); 304 void Close(); 305 HRESULT SkipPrefixArchiveHeader(); 306 HRESULT WriteDatabase( 307 DECL_EXTERNAL_CODECS_LOC_VARS 308 const CArchiveDatabaseOut &db, 309 const CCompressionMethodMode *options, 310 const CHeaderOptions &headerOptions); 311 312 #ifdef _7Z_VOL 313 static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false); 314 static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false); 315 #endif 316 317 }; 318 319 }} 320 321 #endif 322