7zFolderInStream.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // 7zFolderInStream.cpp
  2. #include "StdAfx.h"
  3. #include "7zFolderInStream.h"
  4. namespace NArchive {
  5. namespace N7z {
  6. CFolderInStream::CFolderInStream()
  7. {
  8. _inStreamWithHashSpec = new CSequentialInStreamWithCRC;
  9. _inStreamWithHash = _inStreamWithHashSpec;
  10. }
  11. void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
  12. const UInt32 *fileIndices, UInt32 numFiles)
  13. {
  14. _updateCallback = updateCallback;
  15. _numFiles = numFiles;
  16. _fileIndex = 0;
  17. _fileIndices = fileIndices;
  18. Processed.Clear();
  19. CRCs.Clear();
  20. Sizes.Clear();
  21. _fileIsOpen = false;
  22. _currentSizeIsDefined = false;
  23. }
  24. HRESULT CFolderInStream::OpenStream()
  25. {
  26. _filePos = 0;
  27. while (_fileIndex < _numFiles)
  28. {
  29. _currentSizeIsDefined = false;
  30. CMyComPtr<ISequentialInStream> stream;
  31. HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
  32. if (result != S_OK && result != S_FALSE)
  33. return result;
  34. _fileIndex++;
  35. _inStreamWithHashSpec->SetStream(stream);
  36. _inStreamWithHashSpec->Init();
  37. if (!stream)
  38. {
  39. RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
  40. Sizes.Add(0);
  41. Processed.Add(result == S_OK);
  42. AddDigest();
  43. continue;
  44. }
  45. CMyComPtr<IStreamGetSize> streamGetSize;
  46. if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
  47. {
  48. if(streamGetSize)
  49. {
  50. _currentSizeIsDefined = true;
  51. RINOK(streamGetSize->GetSize(&_currentSize));
  52. }
  53. }
  54. _fileIsOpen = true;
  55. return S_OK;
  56. }
  57. return S_OK;
  58. }
  59. void CFolderInStream::AddDigest()
  60. {
  61. CRCs.Add(_inStreamWithHashSpec->GetCRC());
  62. }
  63. HRESULT CFolderInStream::CloseStream()
  64. {
  65. RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
  66. _inStreamWithHashSpec->ReleaseStream();
  67. _fileIsOpen = false;
  68. Processed.Add(true);
  69. Sizes.Add(_filePos);
  70. AddDigest();
  71. return S_OK;
  72. }
  73. STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
  74. {
  75. UInt32 realProcessedSize = 0;
  76. while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
  77. {
  78. if (_fileIsOpen)
  79. {
  80. UInt32 localProcessedSize;
  81. RINOK(_inStreamWithHash->Read(
  82. ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
  83. if (localProcessedSize == 0)
  84. {
  85. RINOK(CloseStream());
  86. continue;
  87. }
  88. realProcessedSize += localProcessedSize;
  89. _filePos += localProcessedSize;
  90. size -= localProcessedSize;
  91. break;
  92. }
  93. else
  94. {
  95. RINOK(OpenStream());
  96. }
  97. }
  98. if (processedSize != 0)
  99. *processedSize = realProcessedSize;
  100. return S_OK;
  101. }
  102. STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
  103. {
  104. *value = 0;
  105. int subStreamIndex = (int)subStream;
  106. if (subStreamIndex < 0 || subStream > Sizes.Size())
  107. return E_FAIL;
  108. if (subStreamIndex < Sizes.Size())
  109. {
  110. *value= Sizes[subStreamIndex];
  111. return S_OK;
  112. }
  113. if (!_currentSizeIsDefined)
  114. return S_FALSE;
  115. *value = _currentSize;
  116. return S_OK;
  117. }
  118. }}