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