Home | History | Annotate | Download | only in 7z
      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     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 
     62 void CFolderInStream::AddDigest()
     63 {
     64   CRCs.Add(_inStreamWithHashSpec->GetCRC());
     65 }
     66 
     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 
     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 
    106 STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
    107 {
    108   *value = 0;
    109   int index2 = (int)subStream;
    110   if (index2 < 0 || 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