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