1 // StreamBinder.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../Common/MyCom.h"
6
7 #include "StreamBinder.h"
8
9 class CBinderInStream:
10 public ISequentialInStream,
11 public CMyUnknownImp
12 {
13 CStreamBinder *_binder;
14 public:
15 MY_UNKNOWN_IMP1(ISequentialInStream)
16 STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
~CBinderInStream()17 ~CBinderInStream() { _binder->CloseRead(); }
CBinderInStream(CStreamBinder * binder)18 CBinderInStream(CStreamBinder *binder): _binder(binder) {}
19 };
20
Read(void * data,UInt32 size,UInt32 * processedSize)21 STDMETHODIMP CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
22 { return _binder->Read(data, size, processedSize); }
23
24 class CBinderOutStream:
25 public ISequentialOutStream,
26 public CMyUnknownImp
27 {
28 CStreamBinder *_binder;
29 public:
30 MY_UNKNOWN_IMP1(ISequentialOutStream)
31 STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
~CBinderOutStream()32 ~CBinderOutStream() { _binder->CloseWrite(); }
CBinderOutStream(CStreamBinder * binder)33 CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
34 };
35
Write(const void * data,UInt32 size,UInt32 * processedSize)36 STDMETHODIMP CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
37 { return _binder->Write(data, size, processedSize); }
38
39
40
CreateEvents()41 WRes CStreamBinder::CreateEvents()
42 {
43 RINOK(_canWrite_Event.Create());
44 RINOK(_canRead_Event.Create());
45 return _readingWasClosed_Event.Create();
46 }
47
ReInit()48 void CStreamBinder::ReInit()
49 {
50 _canWrite_Event.Reset();
51 _canRead_Event.Reset();
52 _readingWasClosed_Event.Reset();
53
54 // _readingWasClosed = false;
55 _readingWasClosed2 = false;
56
57 _waitWrite = true;
58 _bufSize = 0;
59 _buf = NULL;
60 ProcessedSize = 0;
61 // WritingWasCut = false;
62 }
63
64
CreateStreams(ISequentialInStream ** inStream,ISequentialOutStream ** outStream)65 void CStreamBinder::CreateStreams(ISequentialInStream **inStream, ISequentialOutStream **outStream)
66 {
67 // _readingWasClosed = false;
68 _readingWasClosed2 = false;
69
70 _waitWrite = true;
71 _bufSize = 0;
72 _buf = NULL;
73 ProcessedSize = 0;
74 // WritingWasCut = false;
75
76 CBinderInStream *inStreamSpec = new CBinderInStream(this);
77 CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
78 *inStream = inStreamLoc.Detach();
79
80 CBinderOutStream *outStreamSpec = new CBinderOutStream(this);
81 CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
82 *outStream = outStreamLoc.Detach();
83 }
84
85 // (_canRead_Event && _bufSize == 0) means that stream is finished.
86
Read(void * data,UInt32 size,UInt32 * processedSize)87 HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
88 {
89 if (processedSize)
90 *processedSize = 0;
91 if (size != 0)
92 {
93 if (_waitWrite)
94 {
95 RINOK(_canRead_Event.Lock());
96 _waitWrite = false;
97 }
98 if (size > _bufSize)
99 size = _bufSize;
100 if (size != 0)
101 {
102 memcpy(data, _buf, size);
103 _buf = ((const Byte *)_buf) + size;
104 ProcessedSize += size;
105 if (processedSize)
106 *processedSize = size;
107 _bufSize -= size;
108 if (_bufSize == 0)
109 {
110 _waitWrite = true;
111 _canRead_Event.Reset();
112 _canWrite_Event.Set();
113 }
114 }
115 }
116 return S_OK;
117 }
118
Write(const void * data,UInt32 size,UInt32 * processedSize)119 HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
120 {
121 if (processedSize)
122 *processedSize = 0;
123 if (size == 0)
124 return S_OK;
125
126 if (!_readingWasClosed2)
127 {
128 _buf = data;
129 _bufSize = size;
130 _canRead_Event.Set();
131
132 /*
133 _canWrite_Event.Lock();
134 if (_readingWasClosed)
135 _readingWasClosed2 = true;
136 */
137
138 HANDLE events[2] = { _canWrite_Event, _readingWasClosed_Event };
139 DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
140 if (waitResult >= WAIT_OBJECT_0 + 2)
141 return E_FAIL;
142
143 size -= _bufSize;
144 if (size != 0)
145 {
146 if (processedSize)
147 *processedSize = size;
148 return S_OK;
149 }
150 // if (waitResult == WAIT_OBJECT_0 + 1)
151 _readingWasClosed2 = true;
152 }
153
154 // WritingWasCut = true;
155 return k_My_HRESULT_WritingWasCut;
156 }
157