StreamBinder.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. // StreamBinder.cpp
  2. #include "StdAfx.h"
  3. #include "StreamBinder.h"
  4. #include "../../Common/Defs.h"
  5. #include "../../Common/MyCom.h"
  6. using namespace NWindows;
  7. using namespace NSynchronization;
  8. class CSequentialInStreamForBinder:
  9. public ISequentialInStream,
  10. public CMyUnknownImp
  11. {
  12. public:
  13. MY_UNKNOWN_IMP
  14. STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
  15. private:
  16. CStreamBinder *m_StreamBinder;
  17. public:
  18. ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); }
  19. void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
  20. };
  21. STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
  22. { return m_StreamBinder->Read(data, size, processedSize); }
  23. class CSequentialOutStreamForBinder:
  24. public ISequentialOutStream,
  25. public CMyUnknownImp
  26. {
  27. public:
  28. MY_UNKNOWN_IMP
  29. STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
  30. private:
  31. CStreamBinder *m_StreamBinder;
  32. public:
  33. ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); }
  34. void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; }
  35. };
  36. STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
  37. { return m_StreamBinder->Write(data, size, processedSize); }
  38. //////////////////////////
  39. // CStreamBinder
  40. // (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished.
  41. HRes CStreamBinder::CreateEvents()
  42. {
  43. RINOK(_allBytesAreWritenEvent.Create(true));
  44. RINOK(_thereAreBytesToReadEvent.Create());
  45. return _readStreamIsClosedEvent.Create();
  46. }
  47. void CStreamBinder::ReInit()
  48. {
  49. _thereAreBytesToReadEvent.Reset();
  50. _readStreamIsClosedEvent.Reset();
  51. ProcessedSize = 0;
  52. }
  53. void CStreamBinder::CreateStreams(ISequentialInStream **inStream,
  54. ISequentialOutStream **outStream)
  55. {
  56. CSequentialInStreamForBinder *inStreamSpec = new
  57. CSequentialInStreamForBinder;
  58. CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
  59. inStreamSpec->SetBinder(this);
  60. *inStream = inStreamLoc.Detach();
  61. CSequentialOutStreamForBinder *outStreamSpec = new
  62. CSequentialOutStreamForBinder;
  63. CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
  64. outStreamSpec->SetBinder(this);
  65. *outStream = outStreamLoc.Detach();
  66. _buffer = NULL;
  67. _bufferSize= 0;
  68. ProcessedSize = 0;
  69. }
  70. HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
  71. {
  72. UInt32 sizeToRead = size;
  73. if (size > 0)
  74. {
  75. RINOK(_thereAreBytesToReadEvent.Lock());
  76. sizeToRead = MyMin(_bufferSize, size);
  77. if (_bufferSize > 0)
  78. {
  79. MoveMemory(data, _buffer, sizeToRead);
  80. _buffer = ((const Byte *)_buffer) + sizeToRead;
  81. _bufferSize -= sizeToRead;
  82. if (_bufferSize == 0)
  83. {
  84. _thereAreBytesToReadEvent.Reset();
  85. _allBytesAreWritenEvent.Set();
  86. }
  87. }
  88. }
  89. if (processedSize != NULL)
  90. *processedSize = sizeToRead;
  91. ProcessedSize += sizeToRead;
  92. return S_OK;
  93. }
  94. void CStreamBinder::CloseRead()
  95. {
  96. _readStreamIsClosedEvent.Set();
  97. }
  98. HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
  99. {
  100. if (size > 0)
  101. {
  102. _buffer = data;
  103. _bufferSize = size;
  104. _allBytesAreWritenEvent.Reset();
  105. _thereAreBytesToReadEvent.Set();
  106. HANDLE events[2];
  107. events[0] = _allBytesAreWritenEvent;
  108. events[1] = _readStreamIsClosedEvent;
  109. DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
  110. if (waitResult != WAIT_OBJECT_0 + 0)
  111. {
  112. // ReadingWasClosed = true;
  113. return S_FALSE;
  114. }
  115. // if(!_allBytesAreWritenEvent.Lock())
  116. // return E_FAIL;
  117. }
  118. if (processedSize != NULL)
  119. *processedSize = size;
  120. return S_OK;
  121. }
  122. void CStreamBinder::CloseWrite()
  123. {
  124. // _bufferSize must be = 0
  125. _thereAreBytesToReadEvent.Set();
  126. }