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