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