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