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