• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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