1370b324cSopenharmony_ci// MultiOutStream.h 2370b324cSopenharmony_ci 3370b324cSopenharmony_ci#ifndef ZIP7_INC_MULTI_OUT_STREAM_H 4370b324cSopenharmony_ci#define ZIP7_INC_MULTI_OUT_STREAM_H 5370b324cSopenharmony_ci 6370b324cSopenharmony_ci#include "FileStreams.h" 7370b324cSopenharmony_ci 8370b324cSopenharmony_ciZ7_CLASS_IMP_COM_2( 9370b324cSopenharmony_ci CMultiOutStream 10370b324cSopenharmony_ci , IOutStream 11370b324cSopenharmony_ci , IStreamSetRestriction 12370b324cSopenharmony_ci) 13370b324cSopenharmony_ci Z7_IFACE_COM7_IMP(ISequentialOutStream) 14370b324cSopenharmony_ci 15370b324cSopenharmony_ci Z7_CLASS_NO_COPY(CMultiOutStream) 16370b324cSopenharmony_ci 17370b324cSopenharmony_ci struct CVolStream 18370b324cSopenharmony_ci { 19370b324cSopenharmony_ci COutFileStream *StreamSpec; 20370b324cSopenharmony_ci CMyComPtr<IOutStream> Stream; 21370b324cSopenharmony_ci UInt64 Start; // start pos of current Stream in global stream 22370b324cSopenharmony_ci UInt64 Pos; // pos in current Stream 23370b324cSopenharmony_ci UInt64 RealSize; 24370b324cSopenharmony_ci int Next; // next older 25370b324cSopenharmony_ci int Prev; // prev newer 26370b324cSopenharmony_ci AString Postfix; 27370b324cSopenharmony_ci 28370b324cSopenharmony_ci HRESULT SetSize2(UInt64 size) 29370b324cSopenharmony_ci { 30370b324cSopenharmony_ci const HRESULT res = Stream->SetSize(size); 31370b324cSopenharmony_ci if (res == SZ_OK) 32370b324cSopenharmony_ci RealSize = size; 33370b324cSopenharmony_ci return res; 34370b324cSopenharmony_ci } 35370b324cSopenharmony_ci }; 36370b324cSopenharmony_ci 37370b324cSopenharmony_ci unsigned _streamIndex; // (_streamIndex >= Stream.Size()) is allowed in some internal code 38370b324cSopenharmony_ci UInt64 _offsetPos; // offset relative to Streams[_streamIndex] volume. (_offsetPos >= volSize is allowed) 39370b324cSopenharmony_ci UInt64 _absPos; 40370b324cSopenharmony_ci UInt64 _length; // virtual Length 41370b324cSopenharmony_ci UInt64 _absLimit; 42370b324cSopenharmony_ci 43370b324cSopenharmony_ci CObjectVector<CVolStream> Streams; 44370b324cSopenharmony_ci CRecordVector<UInt64> Sizes; 45370b324cSopenharmony_ci 46370b324cSopenharmony_ci UInt64 _restrict_Begin; 47370b324cSopenharmony_ci UInt64 _restrict_End; 48370b324cSopenharmony_ci UInt64 _restrict_Global; 49370b324cSopenharmony_ci 50370b324cSopenharmony_ci unsigned NumOpenFiles_AllowedMax; 51370b324cSopenharmony_ci 52370b324cSopenharmony_ci // ----- Double Linked List ----- 53370b324cSopenharmony_ci 54370b324cSopenharmony_ci unsigned NumListItems; 55370b324cSopenharmony_ci int Head; // newest 56370b324cSopenharmony_ci int Tail; // oldest 57370b324cSopenharmony_ci 58370b324cSopenharmony_ci void InitLinkedList() 59370b324cSopenharmony_ci { 60370b324cSopenharmony_ci Head = -1; 61370b324cSopenharmony_ci Tail = -1; 62370b324cSopenharmony_ci NumListItems = 0; 63370b324cSopenharmony_ci } 64370b324cSopenharmony_ci 65370b324cSopenharmony_ci void InsertToLinkedList(unsigned index) 66370b324cSopenharmony_ci { 67370b324cSopenharmony_ci { 68370b324cSopenharmony_ci CVolStream &node = Streams[index]; 69370b324cSopenharmony_ci node.Next = Head; 70370b324cSopenharmony_ci node.Prev = -1; 71370b324cSopenharmony_ci } 72370b324cSopenharmony_ci if (Head != -1) 73370b324cSopenharmony_ci Streams[(unsigned)Head].Prev = (int)index; 74370b324cSopenharmony_ci else 75370b324cSopenharmony_ci { 76370b324cSopenharmony_ci // if (Tail != -1) throw 1; 77370b324cSopenharmony_ci Tail = (int)index; 78370b324cSopenharmony_ci } 79370b324cSopenharmony_ci Head = (int)index; 80370b324cSopenharmony_ci NumListItems++; 81370b324cSopenharmony_ci } 82370b324cSopenharmony_ci 83370b324cSopenharmony_ci void RemoveFromLinkedList(unsigned index) 84370b324cSopenharmony_ci { 85370b324cSopenharmony_ci CVolStream &s = Streams[index]; 86370b324cSopenharmony_ci if (s.Next != -1) Streams[(unsigned)s.Next].Prev = s.Prev; else Tail = s.Prev; 87370b324cSopenharmony_ci if (s.Prev != -1) Streams[(unsigned)s.Prev].Next = s.Next; else Head = s.Next; 88370b324cSopenharmony_ci s.Next = -1; // optional 89370b324cSopenharmony_ci s.Prev = -1; // optional 90370b324cSopenharmony_ci NumListItems--; 91370b324cSopenharmony_ci } 92370b324cSopenharmony_ci 93370b324cSopenharmony_ci /* 94370b324cSopenharmony_ci void Delete_LastStream_Records() 95370b324cSopenharmony_ci { 96370b324cSopenharmony_ci if (Streams.Back().Stream) 97370b324cSopenharmony_ci RemoveFromLinkedList(Streams.Size() - 1); 98370b324cSopenharmony_ci Streams.DeleteBack(); 99370b324cSopenharmony_ci } 100370b324cSopenharmony_ci */ 101370b324cSopenharmony_ci 102370b324cSopenharmony_ci UInt64 GetVolSize_for_Stream(unsigned i) const 103370b324cSopenharmony_ci { 104370b324cSopenharmony_ci const unsigned last = Sizes.Size() - 1; 105370b324cSopenharmony_ci return Sizes[i < last ? i : last]; 106370b324cSopenharmony_ci } 107370b324cSopenharmony_ci UInt64 GetGlobalOffset_for_NewStream() const 108370b324cSopenharmony_ci { 109370b324cSopenharmony_ci return Streams.Size() == 0 ? 0: 110370b324cSopenharmony_ci Streams.Back().Start + 111370b324cSopenharmony_ci GetVolSize_for_Stream(Streams.Size() - 1); 112370b324cSopenharmony_ci } 113370b324cSopenharmony_ci unsigned GetStreamIndex_for_Offset(UInt64 offset, UInt64 &relOffset) const; 114370b324cSopenharmony_ci bool IsRestricted(const CVolStream &s) const; 115370b324cSopenharmony_ci bool IsRestricted_Empty(const CVolStream &s) const 116370b324cSopenharmony_ci { 117370b324cSopenharmony_ci // (s) must be stream that has (VolSize == 0). 118370b324cSopenharmony_ci // we treat empty stream as restricted, if next byte is restricted. 119370b324cSopenharmony_ci if (s.Start < _restrict_Global) 120370b324cSopenharmony_ci return true; 121370b324cSopenharmony_ci return 122370b324cSopenharmony_ci (_restrict_Begin != _restrict_End) 123370b324cSopenharmony_ci && (_restrict_Begin <= s.Start) 124370b324cSopenharmony_ci && (_restrict_Begin == s.Start || _restrict_End > s.Start); 125370b324cSopenharmony_ci } 126370b324cSopenharmony_ci // bool IsRestricted_for_Close(unsigned index) const; 127370b324cSopenharmony_ci FString GetFilePath(unsigned index); 128370b324cSopenharmony_ci 129370b324cSopenharmony_ci HRESULT CloseStream(unsigned index); 130370b324cSopenharmony_ci HRESULT CloseStream_and_DeleteFile(unsigned index); 131370b324cSopenharmony_ci HRESULT CloseStream_and_FinalRename(unsigned index); 132370b324cSopenharmony_ci 133370b324cSopenharmony_ci HRESULT PrepareToOpenNew(); 134370b324cSopenharmony_ci HRESULT CreateNewStream(UInt64 newSize); 135370b324cSopenharmony_ci HRESULT CreateStreams_If_Required(unsigned streamIndex); 136370b324cSopenharmony_ci HRESULT ReOpenStream(unsigned streamIndex); 137370b324cSopenharmony_ci HRESULT OptReOpen_and_SetSize(unsigned index, UInt64 size); 138370b324cSopenharmony_ci 139370b324cSopenharmony_ci HRESULT Normalize_finalMode(bool finalMode); 140370b324cSopenharmony_cipublic: 141370b324cSopenharmony_ci FString Prefix; 142370b324cSopenharmony_ci CFiTime MTime; 143370b324cSopenharmony_ci bool MTime_Defined; 144370b324cSopenharmony_ci bool FinalVol_WasReopen; 145370b324cSopenharmony_ci bool NeedDelete; 146370b324cSopenharmony_ci 147370b324cSopenharmony_ci CMultiOutStream() {} 148370b324cSopenharmony_ci ~CMultiOutStream(); 149370b324cSopenharmony_ci void Init(const CRecordVector<UInt64> &sizes); 150370b324cSopenharmony_ci bool SetMTime_Final(const CFiTime &mTime); 151370b324cSopenharmony_ci UInt64 GetSize() const { return _length; } 152370b324cSopenharmony_ci /* it makes final flushing, closes open files and renames to final name if required 153370b324cSopenharmony_ci but it still keeps Streams array of all closed files. 154370b324cSopenharmony_ci So we still can delete all files later, if required */ 155370b324cSopenharmony_ci HRESULT FinalFlush_and_CloseFiles(unsigned &numTotalVolumesRes); 156370b324cSopenharmony_ci // Destruct object without exceptions 157370b324cSopenharmony_ci HRESULT Destruct(); 158370b324cSopenharmony_ci}; 159370b324cSopenharmony_ci 160370b324cSopenharmony_ci#endif 161