xref: /aosp_15_r20/external/lzma/CPP/7zip/Common/MultiOutStream.h (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
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