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 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
GetSubStreamSize(UInt64 subStream,UInt64 * value)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