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