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 S_OK; 15 16 { 17 unsigned 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: break; 57 case STREAM_SEEK_CUR: offset += _pos; break; 58 case STREAM_SEEK_END: offset += _totalLength; break; 59 default: return STG_E_INVALIDFUNCTION; 60 } 61 if (offset < 0) 62 return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; 63 _pos = offset; 64 if (newPosition) 65 *newPosition = offset; 66 return S_OK; 67 } 68 69 70 /* 71 class COutVolumeStream: 72 public ISequentialOutStream, 73 public CMyUnknownImp 74 { 75 unsigned _volIndex; 76 UInt64 _volSize; 77 UInt64 _curPos; 78 CMyComPtr<ISequentialOutStream> _volumeStream; 79 COutArchive _archive; 80 CCRC _crc; 81 82 public: 83 MY_UNKNOWN_IMP 84 85 CFileItem _file; 86 CUpdateOptions _options; 87 CMyComPtr<IArchiveUpdateCallback2> VolumeCallback; 88 void Init(IArchiveUpdateCallback2 *volumeCallback, 89 const UString &name) 90 { 91 _file.Name = name; 92 _file.IsStartPosDefined = true; 93 _file.StartPos = 0; 94 95 VolumeCallback = volumeCallback; 96 _volIndex = 0; 97 _volSize = 0; 98 } 99 100 HRESULT Flush(); 101 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); 102 }; 103 104 HRESULT COutVolumeStream::Flush() 105 { 106 if (_volumeStream) 107 { 108 _file.UnPackSize = _curPos; 109 _file.FileCRC = _crc.GetDigest(); 110 RINOK(WriteVolumeHeader(_archive, _file, _options)); 111 _archive.Close(); 112 _volumeStream.Release(); 113 _file.StartPos += _file.UnPackSize; 114 } 115 return S_OK; 116 } 117 */ 118 119 /* 120 STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize) 121 { 122 if(processedSize != NULL) 123 *processedSize = 0; 124 while(size > 0) 125 { 126 if (_streamIndex >= Streams.Size()) 127 { 128 CSubStreamInfo subStream; 129 RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size)); 130 RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream)); 131 subStream.Pos = 0; 132 Streams.Add(subStream); 133 continue; 134 } 135 CSubStreamInfo &subStream = Streams[_streamIndex]; 136 if (_offsetPos >= subStream.Size) 137 { 138 _offsetPos -= subStream.Size; 139 _streamIndex++; 140 continue; 141 } 142 if (_offsetPos != subStream.Pos) 143 { 144 CMyComPtr<IOutStream> outStream; 145 RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream)); 146 RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL)); 147 subStream.Pos = _offsetPos; 148 } 149 150 UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos); 151 UInt32 realProcessed; 152 RINOK(subStream.Stream->Write(data, curSize, &realProcessed)); 153 data = (void *)((Byte *)data + realProcessed); 154 size -= realProcessed; 155 subStream.Pos += realProcessed; 156 _offsetPos += realProcessed; 157 _absPos += realProcessed; 158 if (_absPos > _length) 159 _length = _absPos; 160 if(processedSize != NULL) 161 *processedSize += realProcessed; 162 if (subStream.Pos == subStream.Size) 163 { 164 _streamIndex++; 165 _offsetPos = 0; 166 } 167 if (realProcessed != curSize && realProcessed == 0) 168 return E_FAIL; 169 } 170 return S_OK; 171 } 172 173 STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition) 174 { 175 switch (seekOrigin) 176 { 177 case STREAM_SEEK_SET: break; 178 case STREAM_SEEK_CUR: offset += _absPos; break; 179 case STREAM_SEEK_END: offset += _length; break; 180 default: return STG_E_INVALIDFUNCTION; 181 } 182 if (offset < 0) 183 return HRESULT_WIN32_ERROR_NEGATIVE_SEEK; 184 _absPos = offset; 185 _offsetPos = _absPos; 186 _streamIndex = 0; 187 if (newPosition) 188 *newPosition = offset; 189 return S_OK; 190 } 191 */ 192