MultiStream.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // MultiStream.cpp
  2. #include "StdAfx.h"
  3. #include "MultiStream.h"
  4. STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
  5. {
  6. if(processedSize != NULL)
  7. *processedSize = 0;
  8. while(_streamIndex < Streams.Size() && size > 0)
  9. {
  10. CSubStreamInfo &s = Streams[_streamIndex];
  11. if (_pos == s.Size)
  12. {
  13. _streamIndex++;
  14. _pos = 0;
  15. continue;
  16. }
  17. RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0));
  18. UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos));
  19. UInt32 realProcessed;
  20. HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed);
  21. data = (void *)((Byte *)data + realProcessed);
  22. size -= realProcessed;
  23. if(processedSize != NULL)
  24. *processedSize += realProcessed;
  25. _pos += realProcessed;
  26. _seekPos += realProcessed;
  27. RINOK(result);
  28. break;
  29. }
  30. return S_OK;
  31. }
  32. STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
  33. UInt64 *newPosition)
  34. {
  35. UInt64 newPos;
  36. switch(seekOrigin)
  37. {
  38. case STREAM_SEEK_SET:
  39. newPos = offset;
  40. break;
  41. case STREAM_SEEK_CUR:
  42. newPos = _seekPos + offset;
  43. break;
  44. case STREAM_SEEK_END:
  45. newPos = _totalLength + offset;
  46. break;
  47. default:
  48. return STG_E_INVALIDFUNCTION;
  49. }
  50. _seekPos = 0;
  51. for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++)
  52. {
  53. UInt64 size = Streams[_streamIndex].Size;
  54. if (newPos < _seekPos + size)
  55. {
  56. _pos = newPos - _seekPos;
  57. _seekPos += _pos;
  58. if (newPosition != 0)
  59. *newPosition = newPos;
  60. return S_OK;
  61. }
  62. _seekPos += size;
  63. }
  64. if (newPos == _seekPos)
  65. {
  66. if (newPosition != 0)
  67. *newPosition = newPos;
  68. return S_OK;
  69. }
  70. return E_FAIL;
  71. }
  72. /*
  73. class COutVolumeStream:
  74. public ISequentialOutStream,
  75. public CMyUnknownImp
  76. {
  77. int _volIndex;
  78. UInt64 _volSize;
  79. UInt64 _curPos;
  80. CMyComPtr<ISequentialOutStream> _volumeStream;
  81. COutArchive _archive;
  82. CCRC _crc;
  83. public:
  84. MY_UNKNOWN_IMP
  85. CFileItem _file;
  86. CUpdateOptions _options;
  87. CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
  88. void Init(IArchiveUpdateCallback2 *volumeCallback,
  89. const UString &name)
  90. {
  91. _file.Name = name;
  92. _file.IsStartPosDefined = true;
  93. _file.StartPos = 0;
  94. VolumeCallback = volumeCallback;
  95. _volIndex = 0;
  96. _volSize = 0;
  97. }
  98. HRESULT Flush();
  99. STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
  100. };
  101. HRESULT COutVolumeStream::Flush()
  102. {
  103. if (_volumeStream)
  104. {
  105. _file.UnPackSize = _curPos;
  106. _file.FileCRC = _crc.GetDigest();
  107. RINOK(WriteVolumeHeader(_archive, _file, _options));
  108. _archive.Close();
  109. _volumeStream.Release();
  110. _file.StartPos += _file.UnPackSize;
  111. }
  112. return S_OK;
  113. }
  114. */
  115. /*
  116. STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
  117. {
  118. if(processedSize != NULL)
  119. *processedSize = 0;
  120. while(size > 0)
  121. {
  122. if (_streamIndex >= Streams.Size())
  123. {
  124. CSubStreamInfo subStream;
  125. RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
  126. RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
  127. subStream.Pos = 0;
  128. Streams.Add(subStream);
  129. continue;
  130. }
  131. CSubStreamInfo &subStream = Streams[_streamIndex];
  132. if (_offsetPos >= subStream.Size)
  133. {
  134. _offsetPos -= subStream.Size;
  135. _streamIndex++;
  136. continue;
  137. }
  138. if (_offsetPos != subStream.Pos)
  139. {
  140. CMyComPtr<IOutStream> outStream;
  141. RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
  142. RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
  143. subStream.Pos = _offsetPos;
  144. }
  145. UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
  146. UInt32 realProcessed;
  147. RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
  148. data = (void *)((Byte *)data + realProcessed);
  149. size -= realProcessed;
  150. subStream.Pos += realProcessed;
  151. _offsetPos += realProcessed;
  152. _absPos += realProcessed;
  153. if (_absPos > _length)
  154. _length = _absPos;
  155. if(processedSize != NULL)
  156. *processedSize += realProcessed;
  157. if (subStream.Pos == subStream.Size)
  158. {
  159. _streamIndex++;
  160. _offsetPos = 0;
  161. }
  162. if (realProcessed != curSize && realProcessed == 0)
  163. return E_FAIL;
  164. }
  165. return S_OK;
  166. }
  167. STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
  168. {
  169. if(seekOrigin >= 3)
  170. return STG_E_INVALIDFUNCTION;
  171. switch(seekOrigin)
  172. {
  173. case STREAM_SEEK_SET:
  174. _absPos = offset;
  175. break;
  176. case STREAM_SEEK_CUR:
  177. _absPos += offset;
  178. break;
  179. case STREAM_SEEK_END:
  180. _absPos = _length + offset;
  181. break;
  182. }
  183. _offsetPos = _absPos;
  184. _streamIndex = 0;
  185. return S_OK;
  186. }
  187. */