// 7zFolderInStream.cpp #include "StdAfx.h" #include "7zFolderInStream.h" namespace NArchive { namespace N7z { void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, const UInt32 *indexes, unsigned numFiles) { _updateCallback = updateCallback; _indexes = indexes; _numFiles = numFiles; _index = 0; Processed.ClearAndReserve(numFiles); CRCs.ClearAndReserve(numFiles); Sizes.ClearAndReserve(numFiles); _pos = 0; _crc = CRC_INIT_VAL; _size_Defined = false; _size = 0; _stream.Release(); } HRESULT CFolderInStream::OpenStream() { _pos = 0; _crc = CRC_INIT_VAL; _size_Defined = false; _size = 0; while (_index < _numFiles) { CMyComPtr stream; HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream); if (result != S_OK) { if (result != S_FALSE) return result; } _stream = stream; if (stream) { CMyComPtr streamGetSize; stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); if (streamGetSize) { if (streamGetSize->GetSize(&_size) == S_OK) _size_Defined = true; } return S_OK; } _index++; RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); AddFileInfo(result == S_OK); } return S_OK; } void CFolderInStream::AddFileInfo(bool isProcessed) { Processed.Add(isProcessed); Sizes.Add(_pos); CRCs.Add(CRC_GET_DIGEST(_crc)); } STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; while (size != 0) { if (_stream) { UInt32 cur = size; const UInt32 kMax = (UInt32)1 << 20; if (cur > kMax) cur = kMax; RINOK(_stream->Read(data, cur, &cur)); if (cur != 0) { _crc = CrcUpdate(_crc, data, cur); _pos += cur; if (processedSize) *processedSize = cur; return S_OK; } _stream.Release(); _index++; AddFileInfo(true); _pos = 0; _crc = CRC_INIT_VAL; _size_Defined = false; _size = 0; RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); } if (_index >= _numFiles) break; RINOK(OpenStream()); } return S_OK; } STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) { *value = 0; if (subStream > Sizes.Size()) return S_FALSE; // E_FAIL; unsigned index = (unsigned)subStream; if (index < Sizes.Size()) { *value = Sizes[index]; return S_OK; } if (!_size_Defined) { *value = _pos; return S_FALSE; } *value = (_pos > _size ? _pos : _size); return S_OK; } }}