xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/Common/MultiStream.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // MultiStream.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "MultiStream.h"
6*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CMultiStream::Read (void * data,UInt32 size,UInt32 * processedSize))7*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize))
8*f6dc9357SAndroid Build Coastguard Worker {
9*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
10*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
11*f6dc9357SAndroid Build Coastguard Worker   if (size == 0)
12*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
13*f6dc9357SAndroid Build Coastguard Worker   if (_pos >= _totalLength)
14*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
15*f6dc9357SAndroid Build Coastguard Worker 
16*f6dc9357SAndroid Build Coastguard Worker   {
17*f6dc9357SAndroid Build Coastguard Worker     unsigned left = 0, mid = _streamIndex, right = Streams.Size();
18*f6dc9357SAndroid Build Coastguard Worker     for (;;)
19*f6dc9357SAndroid Build Coastguard Worker     {
20*f6dc9357SAndroid Build Coastguard Worker       CSubStreamInfo &m = Streams[mid];
21*f6dc9357SAndroid Build Coastguard Worker       if (_pos < m.GlobalOffset)
22*f6dc9357SAndroid Build Coastguard Worker         right = mid;
23*f6dc9357SAndroid Build Coastguard Worker       else if (_pos >= m.GlobalOffset + m.Size)
24*f6dc9357SAndroid Build Coastguard Worker         left = mid + 1;
25*f6dc9357SAndroid Build Coastguard Worker       else
26*f6dc9357SAndroid Build Coastguard Worker         break;
27*f6dc9357SAndroid Build Coastguard Worker       mid = (left + right) / 2;
28*f6dc9357SAndroid Build Coastguard Worker     }
29*f6dc9357SAndroid Build Coastguard Worker     _streamIndex = mid;
30*f6dc9357SAndroid Build Coastguard Worker   }
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker   CSubStreamInfo &s = Streams[_streamIndex];
33*f6dc9357SAndroid Build Coastguard Worker   UInt64 localPos = _pos - s.GlobalOffset;
34*f6dc9357SAndroid Build Coastguard Worker   if (localPos != s.LocalPos)
35*f6dc9357SAndroid Build Coastguard Worker   {
36*f6dc9357SAndroid Build Coastguard Worker     RINOK(s.Stream->Seek((Int64)localPos, STREAM_SEEK_SET, &s.LocalPos))
37*f6dc9357SAndroid Build Coastguard Worker   }
38*f6dc9357SAndroid Build Coastguard Worker   {
39*f6dc9357SAndroid Build Coastguard Worker     const UInt64 rem = s.Size - localPos;
40*f6dc9357SAndroid Build Coastguard Worker     if (size > rem)
41*f6dc9357SAndroid Build Coastguard Worker       size = (UInt32)rem;
42*f6dc9357SAndroid Build Coastguard Worker   }
43*f6dc9357SAndroid Build Coastguard Worker   const HRESULT result = s.Stream->Read(data, size, &size);
44*f6dc9357SAndroid Build Coastguard Worker   _pos += size;
45*f6dc9357SAndroid Build Coastguard Worker   s.LocalPos += size;
46*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
47*f6dc9357SAndroid Build Coastguard Worker     *processedSize = size;
48*f6dc9357SAndroid Build Coastguard Worker   return result;
49*f6dc9357SAndroid Build Coastguard Worker }
50*f6dc9357SAndroid Build Coastguard Worker 
Z7_COM7F_IMF(CMultiStream::Seek (Int64 offset,UInt32 seekOrigin,UInt64 * newPosition))51*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
52*f6dc9357SAndroid Build Coastguard Worker {
53*f6dc9357SAndroid Build Coastguard Worker   switch (seekOrigin)
54*f6dc9357SAndroid Build Coastguard Worker   {
55*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_SET: break;
56*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_CUR: offset += _pos; break;
57*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_END: offset += _totalLength; break;
58*f6dc9357SAndroid Build Coastguard Worker     default: return STG_E_INVALIDFUNCTION;
59*f6dc9357SAndroid Build Coastguard Worker   }
60*f6dc9357SAndroid Build Coastguard Worker   if (offset < 0)
61*f6dc9357SAndroid Build Coastguard Worker     return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
62*f6dc9357SAndroid Build Coastguard Worker   _pos = (UInt64)offset;
63*f6dc9357SAndroid Build Coastguard Worker   if (newPosition)
64*f6dc9357SAndroid Build Coastguard Worker     *newPosition = (UInt64)offset;
65*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
66*f6dc9357SAndroid Build Coastguard Worker }
67*f6dc9357SAndroid Build Coastguard Worker 
68*f6dc9357SAndroid Build Coastguard Worker 
69*f6dc9357SAndroid Build Coastguard Worker /*
70*f6dc9357SAndroid Build Coastguard Worker class COutVolumeStream:
71*f6dc9357SAndroid Build Coastguard Worker   public ISequentialOutStream,
72*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker   Z7_COM_UNKNOWN_IMP_0
75*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACE_COM7_IMP(ISequentialOutStream)
76*f6dc9357SAndroid Build Coastguard Worker 
77*f6dc9357SAndroid Build Coastguard Worker   unsigned _volIndex;
78*f6dc9357SAndroid Build Coastguard Worker   UInt64 _volSize;
79*f6dc9357SAndroid Build Coastguard Worker   UInt64 _curPos;
80*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> _volumeStream;
81*f6dc9357SAndroid Build Coastguard Worker   COutArchive _archive;
82*f6dc9357SAndroid Build Coastguard Worker   CCRC _crc;
83*f6dc9357SAndroid Build Coastguard Worker 
84*f6dc9357SAndroid Build Coastguard Worker public:
85*f6dc9357SAndroid Build Coastguard Worker   CFileItem _file;
86*f6dc9357SAndroid Build Coastguard Worker   CUpdateOptions _options;
87*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
88*f6dc9357SAndroid Build Coastguard Worker   void Init(IArchiveUpdateCallback2 *volumeCallback,
89*f6dc9357SAndroid Build Coastguard Worker       const UString &name)
90*f6dc9357SAndroid Build Coastguard Worker   {
91*f6dc9357SAndroid Build Coastguard Worker     _file.Name = name;
92*f6dc9357SAndroid Build Coastguard Worker     _file.IsStartPosDefined = true;
93*f6dc9357SAndroid Build Coastguard Worker     _file.StartPos = 0;
94*f6dc9357SAndroid Build Coastguard Worker 
95*f6dc9357SAndroid Build Coastguard Worker     VolumeCallback = volumeCallback;
96*f6dc9357SAndroid Build Coastguard Worker     _volIndex = 0;
97*f6dc9357SAndroid Build Coastguard Worker     _volSize = 0;
98*f6dc9357SAndroid Build Coastguard Worker   }
99*f6dc9357SAndroid Build Coastguard Worker 
100*f6dc9357SAndroid Build Coastguard Worker   HRESULT Flush();
101*f6dc9357SAndroid Build Coastguard Worker };
102*f6dc9357SAndroid Build Coastguard Worker 
103*f6dc9357SAndroid Build Coastguard Worker HRESULT COutVolumeStream::Flush()
104*f6dc9357SAndroid Build Coastguard Worker {
105*f6dc9357SAndroid Build Coastguard Worker   if (_volumeStream)
106*f6dc9357SAndroid Build Coastguard Worker   {
107*f6dc9357SAndroid Build Coastguard Worker     _file.UnPackSize = _curPos;
108*f6dc9357SAndroid Build Coastguard Worker     _file.FileCRC = _crc.GetDigest();
109*f6dc9357SAndroid Build Coastguard Worker     RINOK(WriteVolumeHeader(_archive, _file, _options))
110*f6dc9357SAndroid Build Coastguard Worker     _archive.Close();
111*f6dc9357SAndroid Build Coastguard Worker     _volumeStream.Release();
112*f6dc9357SAndroid Build Coastguard Worker     _file.StartPos += _file.UnPackSize;
113*f6dc9357SAndroid Build Coastguard Worker   }
114*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
115*f6dc9357SAndroid Build Coastguard Worker }
116*f6dc9357SAndroid Build Coastguard Worker */
117*f6dc9357SAndroid Build Coastguard Worker 
118*f6dc9357SAndroid Build Coastguard Worker /*
119*f6dc9357SAndroid Build Coastguard Worker 
120*f6dc9357SAndroid Build Coastguard Worker #include "../../../Common/Defs.h"
121*f6dc9357SAndroid Build Coastguard Worker 
122*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
123*f6dc9357SAndroid Build Coastguard Worker {
124*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
125*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
126*f6dc9357SAndroid Build Coastguard Worker   while (size > 0)
127*f6dc9357SAndroid Build Coastguard Worker   {
128*f6dc9357SAndroid Build Coastguard Worker     if (_streamIndex >= Streams.Size())
129*f6dc9357SAndroid Build Coastguard Worker     {
130*f6dc9357SAndroid Build Coastguard Worker       CSubStreamInfo subStream;
131*f6dc9357SAndroid Build Coastguard Worker       RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size))
132*f6dc9357SAndroid Build Coastguard Worker       RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream))
133*f6dc9357SAndroid Build Coastguard Worker       subStream.Pos = 0;
134*f6dc9357SAndroid Build Coastguard Worker       Streams.Add(subStream);
135*f6dc9357SAndroid Build Coastguard Worker       continue;
136*f6dc9357SAndroid Build Coastguard Worker     }
137*f6dc9357SAndroid Build Coastguard Worker     CSubStreamInfo &subStream = Streams[_streamIndex];
138*f6dc9357SAndroid Build Coastguard Worker     if (_offsetPos >= subStream.Size)
139*f6dc9357SAndroid Build Coastguard Worker     {
140*f6dc9357SAndroid Build Coastguard Worker       _offsetPos -= subStream.Size;
141*f6dc9357SAndroid Build Coastguard Worker       _streamIndex++;
142*f6dc9357SAndroid Build Coastguard Worker       continue;
143*f6dc9357SAndroid Build Coastguard Worker     }
144*f6dc9357SAndroid Build Coastguard Worker     if (_offsetPos != subStream.Pos)
145*f6dc9357SAndroid Build Coastguard Worker     {
146*f6dc9357SAndroid Build Coastguard Worker       CMyComPtr<IOutStream> outStream;
147*f6dc9357SAndroid Build Coastguard Worker       RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream))
148*f6dc9357SAndroid Build Coastguard Worker       RINOK(outStream->Seek((Int64)_offsetPos, STREAM_SEEK_SET, NULL))
149*f6dc9357SAndroid Build Coastguard Worker       subStream.Pos = _offsetPos;
150*f6dc9357SAndroid Build Coastguard Worker     }
151*f6dc9357SAndroid Build Coastguard Worker 
152*f6dc9357SAndroid Build Coastguard Worker     const UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
153*f6dc9357SAndroid Build Coastguard Worker     UInt32 realProcessed;
154*f6dc9357SAndroid Build Coastguard Worker     RINOK(subStream.Stream->Write(data, curSize, &realProcessed))
155*f6dc9357SAndroid Build Coastguard Worker     data = (const void *)((const Byte *)data + realProcessed);
156*f6dc9357SAndroid Build Coastguard Worker     size -= realProcessed;
157*f6dc9357SAndroid Build Coastguard Worker     subStream.Pos += realProcessed;
158*f6dc9357SAndroid Build Coastguard Worker     _offsetPos += realProcessed;
159*f6dc9357SAndroid Build Coastguard Worker     _absPos += realProcessed;
160*f6dc9357SAndroid Build Coastguard Worker     if (_absPos > _length)
161*f6dc9357SAndroid Build Coastguard Worker       _length = _absPos;
162*f6dc9357SAndroid Build Coastguard Worker     if (processedSize)
163*f6dc9357SAndroid Build Coastguard Worker       *processedSize += realProcessed;
164*f6dc9357SAndroid Build Coastguard Worker     if (subStream.Pos == subStream.Size)
165*f6dc9357SAndroid Build Coastguard Worker     {
166*f6dc9357SAndroid Build Coastguard Worker       _streamIndex++;
167*f6dc9357SAndroid Build Coastguard Worker       _offsetPos = 0;
168*f6dc9357SAndroid Build Coastguard Worker     }
169*f6dc9357SAndroid Build Coastguard Worker     if (realProcessed != curSize && realProcessed == 0)
170*f6dc9357SAndroid Build Coastguard Worker       return E_FAIL;
171*f6dc9357SAndroid Build Coastguard Worker   }
172*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
173*f6dc9357SAndroid Build Coastguard Worker }
174*f6dc9357SAndroid Build Coastguard Worker 
175*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition))
176*f6dc9357SAndroid Build Coastguard Worker {
177*f6dc9357SAndroid Build Coastguard Worker   switch (seekOrigin)
178*f6dc9357SAndroid Build Coastguard Worker   {
179*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_SET: break;
180*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_CUR: offset += _absPos; break;
181*f6dc9357SAndroid Build Coastguard Worker     case STREAM_SEEK_END: offset += _length; break;
182*f6dc9357SAndroid Build Coastguard Worker     default: return STG_E_INVALIDFUNCTION;
183*f6dc9357SAndroid Build Coastguard Worker   }
184*f6dc9357SAndroid Build Coastguard Worker   if (offset < 0)
185*f6dc9357SAndroid Build Coastguard Worker     return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
186*f6dc9357SAndroid Build Coastguard Worker   _absPos = (UInt64)offset;
187*f6dc9357SAndroid Build Coastguard Worker   _offsetPos = _absPos;
188*f6dc9357SAndroid Build Coastguard Worker   _streamIndex = 0;
189*f6dc9357SAndroid Build Coastguard Worker   if (newPosition)
190*f6dc9357SAndroid Build Coastguard Worker     *newPosition = (UInt64)offset;
191*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
192*f6dc9357SAndroid Build Coastguard Worker }
193*f6dc9357SAndroid Build Coastguard Worker */
194