annotate 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
rev   line source
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 }