diff src/win32/7zip/7z/CPP/7zip/Common/StreamBinder.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Common/StreamBinder.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,150 @@
     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 +HRes CStreamBinder::CreateEvents()
    1.58 +{
    1.59 +  RINOK(_allBytesAreWritenEvent.Create(true));
    1.60 +  RINOK(_thereAreBytesToReadEvent.Create());
    1.61 +  return _readStreamIsClosedEvent.Create();
    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 +
    1.72 +  
    1.73 +void CStreamBinder::CreateStreams(ISequentialInStream **inStream,
    1.74 +      ISequentialOutStream **outStream)
    1.75 +{
    1.76 +  CSequentialInStreamForBinder *inStreamSpec = new
    1.77 +      CSequentialInStreamForBinder;
    1.78 +  CMyComPtr<ISequentialInStream> inStreamLoc(inStreamSpec);
    1.79 +  inStreamSpec->SetBinder(this);
    1.80 +  *inStream = inStreamLoc.Detach();
    1.81 +
    1.82 +  CSequentialOutStreamForBinder *outStreamSpec = new
    1.83 +      CSequentialOutStreamForBinder;
    1.84 +  CMyComPtr<ISequentialOutStream> outStreamLoc(outStreamSpec);
    1.85 +  outStreamSpec->SetBinder(this);
    1.86 +  *outStream = outStreamLoc.Detach();
    1.87 +
    1.88 +  _buffer = NULL;
    1.89 +  _bufferSize= 0;
    1.90 +  ProcessedSize = 0;
    1.91 +}
    1.92 +
    1.93 +HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
    1.94 +{
    1.95 +  UInt32 sizeToRead = size;
    1.96 +  if (size > 0)
    1.97 +  {
    1.98 +    RINOK(_thereAreBytesToReadEvent.Lock());
    1.99 +    sizeToRead = MyMin(_bufferSize, size);
   1.100 +    if (_bufferSize > 0)
   1.101 +    {
   1.102 +      memcpy(data, _buffer, sizeToRead);
   1.103 +      _buffer = ((const Byte *)_buffer) + sizeToRead;
   1.104 +      _bufferSize -= sizeToRead;
   1.105 +      if (_bufferSize == 0)
   1.106 +      {
   1.107 +        _thereAreBytesToReadEvent.Reset();
   1.108 +        _allBytesAreWritenEvent.Set();
   1.109 +      }
   1.110 +    }
   1.111 +  }
   1.112 +  if (processedSize != NULL)
   1.113 +    *processedSize = sizeToRead;
   1.114 +  ProcessedSize += sizeToRead;
   1.115 +  return S_OK;
   1.116 +}
   1.117 +
   1.118 +void CStreamBinder::CloseRead()
   1.119 +{
   1.120 +  _readStreamIsClosedEvent.Set();
   1.121 +}
   1.122 +
   1.123 +HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
   1.124 +{
   1.125 +  if (size > 0)
   1.126 +  {
   1.127 +    _buffer = data;
   1.128 +    _bufferSize = size;
   1.129 +    _allBytesAreWritenEvent.Reset();
   1.130 +    _thereAreBytesToReadEvent.Set();
   1.131 +
   1.132 +    HANDLE events[2];
   1.133 +    events[0] = _allBytesAreWritenEvent;
   1.134 +    events[1] = _readStreamIsClosedEvent;
   1.135 +    DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
   1.136 +    if (waitResult != WAIT_OBJECT_0 + 0)
   1.137 +    {
   1.138 +      // ReadingWasClosed = true;
   1.139 +      return S_FALSE;
   1.140 +    }
   1.141 +    // if(!_allBytesAreWritenEvent.Lock())
   1.142 +    //   return E_FAIL;
   1.143 +  }
   1.144 +  if (processedSize != NULL)
   1.145 +    *processedSize = size;
   1.146 +  return S_OK;
   1.147 +}
   1.148 +
   1.149 +void CStreamBinder::CloseWrite()
   1.150 +{
   1.151 +  // _bufferSize must be = 0
   1.152 +  _thereAreBytesToReadEvent.Set();
   1.153 +}