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 cur = size; 84 const UInt32 kMax = (UInt32)1 << 20; 85 if (cur > kMax) 86 cur = kMax; 87 RINOK(_stream->Read(data, cur, &cur)); 88 if (cur != 0) 89 { 90 _crc = CrcUpdate(_crc, data, cur); 91 _pos += cur; 92 if (processedSize) 93 *processedSize = cur; 94 return S_OK; 95 } 96 97 _stream.Release(); 98 _index++; 99 AddFileInfo(true); 100 101 _pos = 0; 102 _crc = CRC_INIT_VAL; 103 _size_Defined = false; 104 _size = 0; 105 106 RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); 107 } 108 109 if (_index >= _numFiles) 110 break; 111 RINOK(OpenStream()); 112 } 113 return S_OK; 114 } 115 116 STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value) 117 { 118 *value = 0; 119 if (subStream > Sizes.Size()) 120 return S_FALSE; // E_FAIL; 121 122 unsigned index = (unsigned)subStream; 123 if (index < Sizes.Size()) 124 { 125 *value = Sizes[index]; 126 return S_OK; 127 } 128 129 if (!_size_Defined) 130 { 131 *value = _pos; 132 return S_FALSE; 133 } 134 135 *value = (_pos > _size ? _pos : _size); 136 return S_OK; 137 } 138 139 }} 140