Upload 2.0.2
[physicsfs] / lzma / CPP / 7zip / Archive / 7z / 7zFolderInStream.cpp
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 }}