1 // MultiOutStream.h 2 3 #ifndef ZIP7_INC_MULTI_OUT_STREAM_H 4 #define ZIP7_INC_MULTI_OUT_STREAM_H 5 6 #include "FileStreams.h" 7 8 Z7_CLASS_IMP_COM_2( 9 CMultiOutStream 10 , IOutStream 11 , IStreamSetRestriction 12 ) 13 Z7_IFACE_COM7_IMP(ISequentialOutStream) 14 15 Z7_CLASS_NO_COPY(CMultiOutStream) 16 17 struct CVolStream 18 { 19 COutFileStream *StreamSpec; 20 CMyComPtr<IOutStream> Stream; 21 UInt64 Start; // start pos of current Stream in global stream 22 UInt64 Pos; // pos in current Stream 23 UInt64 RealSize; 24 int Next; // next older 25 int Prev; // prev newer 26 AString Postfix; 27 SetSize2CVolStream28 HRESULT SetSize2(UInt64 size) 29 { 30 const HRESULT res = Stream->SetSize(size); 31 if (res == SZ_OK) 32 RealSize = size; 33 return res; 34 } 35 }; 36 37 unsigned _streamIndex; // (_streamIndex >= Stream.Size()) is allowed in some internal code 38 UInt64 _offsetPos; // offset relative to Streams[_streamIndex] volume. (_offsetPos >= volSize is allowed) 39 UInt64 _absPos; 40 UInt64 _length; // virtual Length 41 UInt64 _absLimit; 42 43 CObjectVector<CVolStream> Streams; 44 CRecordVector<UInt64> Sizes; 45 46 UInt64 _restrict_Begin; 47 UInt64 _restrict_End; 48 UInt64 _restrict_Global; 49 50 unsigned NumOpenFiles_AllowedMax; 51 52 // ----- Double Linked List ----- 53 54 unsigned NumListItems; 55 int Head; // newest 56 int Tail; // oldest 57 InitLinkedList()58 void InitLinkedList() 59 { 60 Head = -1; 61 Tail = -1; 62 NumListItems = 0; 63 } 64 InsertToLinkedList(unsigned index)65 void InsertToLinkedList(unsigned index) 66 { 67 { 68 CVolStream &node = Streams[index]; 69 node.Next = Head; 70 node.Prev = -1; 71 } 72 if (Head != -1) 73 Streams[(unsigned)Head].Prev = (int)index; 74 else 75 { 76 // if (Tail != -1) throw 1; 77 Tail = (int)index; 78 } 79 Head = (int)index; 80 NumListItems++; 81 } 82 RemoveFromLinkedList(unsigned index)83 void RemoveFromLinkedList(unsigned index) 84 { 85 CVolStream &s = Streams[index]; 86 if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev; 87 if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next; 88 s.Next = -1; // optional 89 s.Prev = -1; // optional 90 NumListItems--; 91 } 92 93 /* 94 void Delete_LastStream_Records() 95 { 96 if (Streams.Back().Stream) 97 RemoveFromLinkedList(Streams.Size() - 1); 98 Streams.DeleteBack(); 99 } 100 */ 101 GetVolSize_for_Stream(unsigned i)102 UInt64 GetVolSize_for_Stream(unsigned i) const 103 { 104 const unsigned last = Sizes.Size() - 1; 105 return Sizes[i < last ? i : last]; 106 } GetGlobalOffset_for_NewStream()107 UInt64 GetGlobalOffset_for_NewStream() const 108 { 109 return Streams.Size() == 0 ? 0: 110 Streams.Back().Start + 111 GetVolSize_for_Stream(Streams.Size() - 1); 112 } 113 unsigned GetStreamIndex_for_Offset(UInt64 offset, UInt64 &relOffset) const; 114 bool IsRestricted(const CVolStream &s) const; IsRestricted_Empty(const CVolStream & s)115 bool IsRestricted_Empty(const CVolStream &s) const 116 { 117 // (s) must be stream that has (VolSize == 0). 118 // we treat empty stream as restricted, if next byte is restricted. 119 if (s.Start < _restrict_Global) 120 return true; 121 return 122 (_restrict_Begin != _restrict_End) 123 && (_restrict_Begin <= s.Start) 124 && (_restrict_Begin == s.Start || _restrict_End > s.Start); 125 } 126 // bool IsRestricted_for_Close(unsigned index) const; 127 FString GetFilePath(unsigned index); 128 129 HRESULT CloseStream(unsigned index); 130 HRESULT CloseStream_and_DeleteFile(unsigned index); 131 HRESULT CloseStream_and_FinalRename(unsigned index); 132 133 HRESULT PrepareToOpenNew(); 134 HRESULT CreateNewStream(UInt64 newSize); 135 HRESULT CreateStreams_If_Required(unsigned streamIndex); 136 HRESULT ReOpenStream(unsigned streamIndex); 137 HRESULT OptReOpen_and_SetSize(unsigned index, UInt64 size); 138 139 HRESULT Normalize_finalMode(bool finalMode); 140 public: 141 FString Prefix; 142 CFiTime MTime; 143 bool MTime_Defined; 144 bool FinalVol_WasReopen; 145 bool NeedDelete; 146 CMultiOutStream()147 CMultiOutStream() {} 148 ~CMultiOutStream(); 149 void Init(const CRecordVector<UInt64> &sizes); 150 bool SetMTime_Final(const CFiTime &mTime); GetSize()151 UInt64 GetSize() const { return _length; } 152 /* it makes final flushing, closes open files and renames to final name if required 153 but it still keeps Streams array of all closed files. 154 So we still can delete all files later, if required */ 155 HRESULT FinalFlush_and_CloseFiles(unsigned &numTotalVolumesRes); 156 // Destruct object without exceptions 157 HRESULT Destruct(); 158 }; 159 160 #endif 161