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