1 // 7zFolderInStream.cpp
2
3 #include "StdAfx.h"
4
5 #include "7zFolderInStream.h"
6
7 namespace NArchive {
8 namespace N7z {
9
Init(IArchiveUpdateCallback * updateCallback,const UInt32 * indexes,unsigned numFiles)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
OpenStream()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
AddFileInfo(bool isProcessed)68 void CFolderInStream::AddFileInfo(bool isProcessed)
69 {
70 Processed.Add(isProcessed);
71 Sizes.Add(_pos);
72 CRCs.Add(CRC_GET_DIGEST(_crc));
73 }
74
Read(void * data,UInt32 size,UInt32 * processedSize)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
GetSubStreamSize(UInt64 subStream,UInt64 * value)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