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