1// 7zFolderInStream.cpp 2 3#include "StdAfx.h" 4 5#include "7zFolderInStream.h" 6 7namespace NArchive { 8namespace N7z { 9 10CFolderInStream::CFolderInStream() 11{ 12 _inStreamWithHashSpec = new CSequentialInStreamWithCRC; 13 _inStreamWithHash = _inStreamWithHashSpec; 14} 15 16void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback, 17 const UInt32 *fileIndices, UInt32 numFiles) 18{ 19 _updateCallback = updateCallback; 20 _numFiles = numFiles; 21 _fileIndex = 0; 22 _fileIndices = fileIndices; 23 Processed.Clear(); 24 CRCs.Clear(); 25 Sizes.Clear(); 26 _fileIsOpen = false; 27 _currentSizeIsDefined = false; 28} 29 30HRESULT CFolderInStream::OpenStream() 31{ 32 _filePos = 0; 33 while (_fileIndex < _numFiles) 34 { 35 CMyComPtr<ISequentialInStream> stream; 36 HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream); 37 if (result != S_OK && result != S_FALSE) 38 return result; 39 _fileIndex++; 40 _inStreamWithHashSpec->SetStream(stream); 41 _inStreamWithHashSpec->Init(); 42 if (stream) 43 { 44 _fileIsOpen = true; 45 CMyComPtr<IStreamGetSize> streamGetSize; 46 stream.QueryInterface(IID_IStreamGetSize, &streamGetSize); 47 if (streamGetSize) 48 { 49 RINOK(streamGetSize->GetSize(&_currentSize)); 50 _currentSizeIsDefined = true; 51 } 52 return S_OK; 53 } 54 RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); 55 Sizes.Add(0); 56 Processed.Add(result == S_OK); 57 AddDigest(); 58 } 59 return S_OK; 60} 61 62void CFolderInStream::AddDigest() 63{ 64 CRCs.Add(_inStreamWithHashSpec->GetCRC()); 65} 66 67HRESULT CFolderInStream::CloseStream() 68{ 69 RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); 70 _inStreamWithHashSpec->ReleaseStream(); 71 _fileIsOpen = false; 72 _currentSizeIsDefined = false; 73 Processed.Add(true); 74 Sizes.Add(_filePos); 75 AddDigest(); 76 return S_OK; 77} 78 79STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize) 80{ 81 if (processedSize != 0) 82 *processedSize = 0; 83 while (size > 0) 84 { 85 if (_fileIsOpen) 86 { 87 UInt32 processed2; 88 RINOK(_inStreamWithHash->Read(data, size, &processed2)); 89 if (processed2 == 0) 90 { 91 RINOK(CloseStream()); 92 continue; 93 } 94 if (processedSize != 0) 95 *processedSize = processed2; 96 _filePos += processed2; 97 break; 98 } 99 if (_fileIndex >= _numFiles) 100 break; 101 RINOK(OpenStream()); 102 } 103 return S_OK; 104} 105 106STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) 107{ 108 *value = 0; 109 unsigned index2 = (unsigned)subStream; 110 if (subStream > Sizes.Size()) 111 return E_FAIL; 112 if (index2 < Sizes.Size()) 113 { 114 *value = Sizes[index2]; 115 return S_OK; 116 } 117 if (!_currentSizeIsDefined) 118 return S_FALSE; 119 *value = _currentSize; 120 return S_OK; 121} 122 123}} 124