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