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 void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
     11     const UInt32 *indexes, unsigned numFiles)
     12 {
     13   _updateCallback = updateCallback;
     14   _indexes = indexes;
     15   _numFiles = numFiles;
     16   _index = 0;
     17 
     18   Processed.ClearAndReserve(numFiles);
     19   CRCs.ClearAndReserve(numFiles);
     20   Sizes.ClearAndReserve(numFiles);
     21 
     22   _pos = 0;
     23   _crc = CRC_INIT_VAL;
     24   _size_Defined = false;
     25   _size = 0;
     26 
     27   _stream.Release();
     28 }
     29 
     30 HRESULT CFolderInStream::OpenStream()
     31 {
     32   _pos = 0;
     33   _crc = CRC_INIT_VAL;
     34   _size_Defined = false;
     35   _size = 0;
     36 
     37   while (_index < _numFiles)
     38   {
     39     CMyComPtr<ISequentialInStream> stream;
     40     HRESULT result = _updateCallback->GetStream(_indexes[_index], &stream);
     41     if (result != S_OK)
     42     {
     43       if (result != S_FALSE)
     44         return result;
     45     }
     46 
     47     _stream = stream;
     48 
     49     if (stream)
     50     {
     51       CMyComPtr<IStreamGetSize> streamGetSize;
     52       stream.QueryInterface(IID_IStreamGetSize, &streamGetSize);
     53       if (streamGetSize)
     54       {
     55         if (streamGetSize->GetSize(&_size) == S_OK)
     56           _size_Defined = true;
     57       }
     58       return S_OK;
     59     }
     60 
     61     _index++;
     62     RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
     63     AddFileInfo(result == S_OK);
     64   }
     65   return S_OK;
     66 }
     67 
     68 void CFolderInStream::AddFileInfo(bool isProcessed)
     69 {
     70   Processed.Add(isProcessed);
     71   Sizes.Add(_pos);
     72   CRCs.Add(CRC_GET_DIGEST(_crc));
     73 }
     74 
     75 STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
     76 {
     77   if (processedSize)
     78     *processedSize = 0;
     79   while (size != 0)
     80   {
     81     if (_stream)
     82     {
     83       UInt32 processed2;
     84       RINOK(_stream->Read(data, size, &processed2));
     85       if (processed2 != 0)
     86       {
     87         _crc = CrcUpdate(_crc, data, processed2);
     88         _pos += processed2;
     89         if (processedSize)
     90           *processedSize = processed2;
     91         return S_OK;
     92       }
     93 
     94       _stream.Release();
     95       _index++;
     96       AddFileInfo(true);
     97 
     98       _pos = 0;
     99       _crc = CRC_INIT_VAL;
    100       _size_Defined = false;
    101       _size = 0;
    102 
    103       RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
    104     }
    105 
    106     if (_index >= _numFiles)
    107       break;
    108     RINOK(OpenStream());
    109   }
    110   return S_OK;
    111 }
    112 
    113 STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
    114 {
    115   *value = 0;
    116   if (subStream > Sizes.Size())
    117     return S_FALSE; // E_FAIL;
    118 
    119   unsigned index = (unsigned)subStream;
    120   if (index < Sizes.Size())
    121   {
    122     *value = Sizes[index];
    123     return S_OK;
    124   }
    125 
    126   if (!_size_Defined)
    127   {
    128     *value = _pos;
    129     return S_FALSE;
    130   }
    131 
    132   *value = (_pos > _size ? _pos : _size);
    133   return S_OK;
    134 }
    135 
    136 }}
    137