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