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