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