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 cur = size;
     84       const UInt32 kMax = (UInt32)1 << 20;
     85       if (cur > kMax)
     86         cur = kMax;
     87       RINOK(_stream->Read(data, cur, &cur));
     88       if (cur != 0)
     89       {
     90         _crc = CrcUpdate(_crc, data, cur);
     91         _pos += cur;
     92         if (processedSize)
     93           *processedSize = cur;
     94         return S_OK;
     95       }
     96 
     97       _stream.Release();
     98       _index++;
     99       AddFileInfo(true);
    100 
    101       _pos = 0;
    102       _crc = CRC_INIT_VAL;
    103       _size_Defined = false;
    104       _size = 0;
    105 
    106       RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
    107     }
    108 
    109     if (_index >= _numFiles)
    110       break;
    111     RINOK(OpenStream());
    112   }
    113   return S_OK;
    114 }
    115 
    116 STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
    117 {
    118   *value = 0;
    119   if (subStream > Sizes.Size())
    120     return S_FALSE; // E_FAIL;
    121 
    122   unsigned index = (unsigned)subStream;
    123   if (index < Sizes.Size())
    124   {
    125     *value = Sizes[index];
    126     return S_OK;
    127   }
    128 
    129   if (!_size_Defined)
    130   {
    131     *value = _pos;
    132     return S_FALSE;
    133   }
    134 
    135   *value = (_pos > _size ? _pos : _size);
    136   return S_OK;
    137 }
    138 
    139 }}
    140