5 #include "MultiStream.h"
\r
7 STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
\r
13 if (_pos >= _totalLength)
\r
14 return (_pos == _totalLength) ? S_OK : E_FAIL;
\r
17 int left = 0, mid = _streamIndex, right = Streams.Size();
\r
20 CSubStreamInfo &m = Streams[mid];
\r
21 if (_pos < m.GlobalOffset)
\r
23 else if (_pos >= m.GlobalOffset + m.Size)
\r
30 mid = (left + right) / 2;
\r
35 CSubStreamInfo &s = Streams[_streamIndex];
\r
36 UInt64 localPos = _pos - s.GlobalOffset;
\r
37 if (localPos != s.LocalPos)
\r
39 RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));
\r
41 UInt64 rem = s.Size - localPos;
\r
44 HRESULT result = s.Stream->Read(data, size, &size);
\r
48 *processedSize = size;
\r
52 STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
\r
56 case STREAM_SEEK_SET: _pos = offset; break;
\r
57 case STREAM_SEEK_CUR: _pos = _pos + offset; break;
\r
58 case STREAM_SEEK_END: _pos = _totalLength + offset; break;
\r
59 default: return STG_E_INVALIDFUNCTION;
\r
61 if (newPosition != 0)
\r
62 *newPosition = _pos;
\r
68 class COutVolumeStream:
\r
69 public ISequentialOutStream,
\r
70 public CMyUnknownImp
\r
75 CMyComPtr<ISequentialOutStream> _volumeStream;
\r
76 COutArchive _archive;
\r
83 CUpdateOptions _options;
\r
84 CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
\r
85 void Init(IArchiveUpdateCallback2 *volumeCallback,
\r
86 const UString &name)
\r
89 _file.IsStartPosDefined = true;
\r
92 VolumeCallback = volumeCallback;
\r
98 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
\r
101 HRESULT COutVolumeStream::Flush()
\r
105 _file.UnPackSize = _curPos;
\r
106 _file.FileCRC = _crc.GetDigest();
\r
107 RINOK(WriteVolumeHeader(_archive, _file, _options));
\r
109 _volumeStream.Release();
\r
110 _file.StartPos += _file.UnPackSize;
\r
117 STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
\r
119 if(processedSize != NULL)
\r
120 *processedSize = 0;
\r
123 if (_streamIndex >= Streams.Size())
\r
125 CSubStreamInfo subStream;
\r
126 RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
\r
127 RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
\r
129 Streams.Add(subStream);
\r
132 CSubStreamInfo &subStream = Streams[_streamIndex];
\r
133 if (_offsetPos >= subStream.Size)
\r
135 _offsetPos -= subStream.Size;
\r
139 if (_offsetPos != subStream.Pos)
\r
141 CMyComPtr<IOutStream> outStream;
\r
142 RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
\r
143 RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
\r
144 subStream.Pos = _offsetPos;
\r
147 UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
\r
148 UInt32 realProcessed;
\r
149 RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
\r
150 data = (void *)((Byte *)data + realProcessed);
\r
151 size -= realProcessed;
\r
152 subStream.Pos += realProcessed;
\r
153 _offsetPos += realProcessed;
\r
154 _absPos += realProcessed;
\r
155 if (_absPos > _length)
\r
157 if(processedSize != NULL)
\r
158 *processedSize += realProcessed;
\r
159 if (subStream.Pos == subStream.Size)
\r
164 if (realProcessed != curSize && realProcessed == 0)
\r
170 STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
\r
172 if(seekOrigin >= 3)
\r
173 return STG_E_INVALIDFUNCTION;
\r
176 case STREAM_SEEK_SET:
\r
179 case STREAM_SEEK_CUR:
\r
182 case STREAM_SEEK_END:
\r
183 _absPos = _length + offset;
\r
186 _offsetPos = _absPos;
\r