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