1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/other-licenses/7zstub/src/7zip/Common/StreamBinder.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,162 @@ 1.4 +// StreamBinder.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "StreamBinder.h" 1.9 +#include "../../Common/Defs.h" 1.10 +#include "../../Common/MyCom.h" 1.11 + 1.12 +using namespace NWindows; 1.13 +using namespace NSynchronization; 1.14 + 1.15 +class CSequentialInStreamForBinder: 1.16 + public ISequentialInStream, 1.17 + public CMyUnknownImp 1.18 +{ 1.19 +public: 1.20 + MY_UNKNOWN_IMP 1.21 + 1.22 + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); 1.23 +private: 1.24 + CStreamBinder *m_StreamBinder; 1.25 +public: 1.26 + ~CSequentialInStreamForBinder() { m_StreamBinder->CloseRead(); } 1.27 + void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } 1.28 +}; 1.29 + 1.30 +STDMETHODIMP CSequentialInStreamForBinder::Read(void *data, UInt32 size, UInt32 *processedSize) 1.31 + { return m_StreamBinder->Read(data, size, processedSize); } 1.32 + 1.33 +class CSequentialOutStreamForBinder: 1.34 + public ISequentialOutStream, 1.35 + public CMyUnknownImp 1.36 +{ 1.37 +public: 1.38 + MY_UNKNOWN_IMP 1.39 + 1.40 + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); 1.41 + 1.42 +private: 1.43 + CStreamBinder *m_StreamBinder; 1.44 +public: 1.45 + ~CSequentialOutStreamForBinder() { m_StreamBinder->CloseWrite(); } 1.46 + void SetBinder(CStreamBinder *streamBinder) { m_StreamBinder = streamBinder; } 1.47 +}; 1.48 + 1.49 +STDMETHODIMP CSequentialOutStreamForBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) 1.50 + { return m_StreamBinder->Write(data, size, processedSize); } 1.51 + 1.52 + 1.53 +////////////////////////// 1.54 +// CStreamBinder 1.55 +// (_thereAreBytesToReadEvent && _bufferSize == 0) means that stream is finished. 1.56 + 1.57 +void CStreamBinder::CreateEvents() 1.58 +{ 1.59 + _allBytesAreWritenEvent = new CManualResetEvent(true); 1.60 + _thereAreBytesToReadEvent = new CManualResetEvent(false); 1.61 + _readStreamIsClosedEvent = new CManualResetEvent(false); 1.62 +} 1.63 + 1.64 +void CStreamBinder::ReInit() 1.65 +{ 1.66 + _thereAreBytesToReadEvent->Reset(); 1.67 + _readStreamIsClosedEvent->Reset(); 1.68 + ProcessedSize = 0; 1.69 +} 1.70 + 1.71 +CStreamBinder::~CStreamBinder() 1.72 +{ 1.73 + if (_allBytesAreWritenEvent != NULL) 1.74 + delete _allBytesAreWritenEvent; 1.75 + if (_thereAreBytesToReadEvent != NULL) 1.76 + delete _thereAreBytesToReadEvent; 1.77 + if (_readStreamIsClosedEvent != NULL) 1.78 + delete _readStreamIsClosedEvent; 1.79 +} 1.80 + 1.81 + 1.82 + 1.83 + 1.84 +void CStreamBinder::CreateStreams(ISequentialInStream **inStream, 1.85 + ISequentialOutStream **outStream) 1.86 +{ 1.87 + CSequentialInStreamForBinder *inStreamSpec = new 1.88 + CSequentialInStreamForBinder; 1.89 + CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec); 1.90 + inStreamSpec->SetBinder(this); 1.91 + *inStream = inStreamLoc.Detach(); 1.92 + 1.93 + CSequentialOutStreamForBinder *outStreamSpec = new 1.94 + CSequentialOutStreamForBinder; 1.95 + CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec); 1.96 + outStreamSpec->SetBinder(this); 1.97 + *outStream = outStreamLoc.Detach(); 1.98 + 1.99 + _buffer = NULL; 1.100 + _bufferSize= 0; 1.101 + ProcessedSize = 0; 1.102 +} 1.103 + 1.104 +HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize) 1.105 +{ 1.106 + UInt32 sizeToRead = size; 1.107 + if (size > 0) 1.108 + { 1.109 + if(!_thereAreBytesToReadEvent->Lock()) 1.110 + return E_FAIL; 1.111 + sizeToRead = MyMin(_bufferSize, size); 1.112 + if (_bufferSize > 0) 1.113 + { 1.114 + MoveMemory(data, _buffer, sizeToRead); 1.115 + _buffer = ((const Byte *)_buffer) + sizeToRead; 1.116 + _bufferSize -= sizeToRead; 1.117 + if (_bufferSize == 0) 1.118 + { 1.119 + _thereAreBytesToReadEvent->Reset(); 1.120 + _allBytesAreWritenEvent->Set(); 1.121 + } 1.122 + } 1.123 + } 1.124 + if (processedSize != NULL) 1.125 + *processedSize = sizeToRead; 1.126 + ProcessedSize += sizeToRead; 1.127 + return S_OK; 1.128 +} 1.129 + 1.130 +void CStreamBinder::CloseRead() 1.131 +{ 1.132 + _readStreamIsClosedEvent->Set(); 1.133 +} 1.134 + 1.135 +HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize) 1.136 +{ 1.137 + if (size > 0) 1.138 + { 1.139 + _buffer = data; 1.140 + _bufferSize = size; 1.141 + _allBytesAreWritenEvent->Reset(); 1.142 + _thereAreBytesToReadEvent->Set(); 1.143 + 1.144 + HANDLE events[2]; 1.145 + events[0] = *_allBytesAreWritenEvent; 1.146 + events[1] = *_readStreamIsClosedEvent; 1.147 + DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE); 1.148 + if (waitResult != WAIT_OBJECT_0 + 0) 1.149 + { 1.150 + // ReadingWasClosed = true; 1.151 + return E_FAIL; 1.152 + } 1.153 + // if(!_allBytesAreWritenEvent.Lock()) 1.154 + // return E_FAIL; 1.155 + } 1.156 + if (processedSize != NULL) 1.157 + *processedSize = size; 1.158 + return S_OK; 1.159 +} 1.160 + 1.161 +void CStreamBinder::CloseWrite() 1.162 +{ 1.163 + // _bufferSize must be = 0 1.164 + _thereAreBytesToReadEvent->Set(); 1.165 +}