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) 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 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