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