xref: /aosp_15_r20/external/lzma/CPP/7zip/Common/StreamBinder.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // StreamBinder.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyCom.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "StreamBinder.h"
8*f6dc9357SAndroid Build Coastguard Worker 
9*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
10*f6dc9357SAndroid Build Coastguard Worker   CBinderInStream
11*f6dc9357SAndroid Build Coastguard Worker   , ISequentialInStream
12*f6dc9357SAndroid Build Coastguard Worker )
13*f6dc9357SAndroid Build Coastguard Worker   CStreamBinder *_binder;
14*f6dc9357SAndroid Build Coastguard Worker public:
15*f6dc9357SAndroid Build Coastguard Worker   ~CBinderInStream() { _binder->CloseRead_CallOnce(); }
16*f6dc9357SAndroid Build Coastguard Worker   CBinderInStream(CStreamBinder *binder): _binder(binder) {}
17*f6dc9357SAndroid Build Coastguard Worker };
18*f6dc9357SAndroid Build Coastguard Worker 
19*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CBinderInStream::Read(void *data, UInt32 size, UInt32 *processedSize))
20*f6dc9357SAndroid Build Coastguard Worker   { return _binder->Read(data, size, processedSize); }
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker 
23*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
24*f6dc9357SAndroid Build Coastguard Worker   CBinderOutStream
25*f6dc9357SAndroid Build Coastguard Worker   , ISequentialOutStream
26*f6dc9357SAndroid Build Coastguard Worker )
27*f6dc9357SAndroid Build Coastguard Worker   CStreamBinder *_binder;
28*f6dc9357SAndroid Build Coastguard Worker public:
29*f6dc9357SAndroid Build Coastguard Worker   ~CBinderOutStream() { _binder->CloseWrite(); }
30*f6dc9357SAndroid Build Coastguard Worker   CBinderOutStream(CStreamBinder *binder): _binder(binder) {}
31*f6dc9357SAndroid Build Coastguard Worker };
32*f6dc9357SAndroid Build Coastguard Worker 
33*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CBinderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize))
34*f6dc9357SAndroid Build Coastguard Worker   { return _binder->Write(data, size, processedSize); }
35*f6dc9357SAndroid Build Coastguard Worker 
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker static HRESULT Event_Create_or_Reset(NWindows::NSynchronization::CAutoResetEvent &event)
38*f6dc9357SAndroid Build Coastguard Worker {
39*f6dc9357SAndroid Build Coastguard Worker   const WRes wres = event.CreateIfNotCreated_Reset();
40*f6dc9357SAndroid Build Coastguard Worker   return HRESULT_FROM_WIN32(wres);
41*f6dc9357SAndroid Build Coastguard Worker }
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker HRESULT CStreamBinder::Create_ReInit()
44*f6dc9357SAndroid Build Coastguard Worker {
45*f6dc9357SAndroid Build Coastguard Worker   RINOK(Event_Create_or_Reset(_canRead_Event))
46*f6dc9357SAndroid Build Coastguard Worker   // RINOK(Event_Create_or_Reset(_canWrite_Event))
47*f6dc9357SAndroid Build Coastguard Worker 
48*f6dc9357SAndroid Build Coastguard Worker   // _canWrite_Semaphore.Close();
49*f6dc9357SAndroid Build Coastguard Worker   // we need at least 3 items of maxCount: 1 for normal unlock in Read(), 2 items for unlock in CloseRead_CallOnce()
50*f6dc9357SAndroid Build Coastguard Worker   _canWrite_Semaphore.OptCreateInit(0, 3);
51*f6dc9357SAndroid Build Coastguard Worker 
52*f6dc9357SAndroid Build Coastguard Worker   // _readingWasClosed = false;
53*f6dc9357SAndroid Build Coastguard Worker   _readingWasClosed2 = false;
54*f6dc9357SAndroid Build Coastguard Worker 
55*f6dc9357SAndroid Build Coastguard Worker   _waitWrite = true;
56*f6dc9357SAndroid Build Coastguard Worker   _bufSize = 0;
57*f6dc9357SAndroid Build Coastguard Worker   _buf = NULL;
58*f6dc9357SAndroid Build Coastguard Worker   ProcessedSize = 0;
59*f6dc9357SAndroid Build Coastguard Worker   // WritingWasCut = false;
60*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
61*f6dc9357SAndroid Build Coastguard Worker }
62*f6dc9357SAndroid Build Coastguard Worker 
63*f6dc9357SAndroid Build Coastguard Worker 
64*f6dc9357SAndroid Build Coastguard Worker void CStreamBinder::CreateStreams2(CMyComPtr<ISequentialInStream> &inStream, CMyComPtr<ISequentialOutStream> &outStream)
65*f6dc9357SAndroid Build Coastguard Worker {
66*f6dc9357SAndroid Build Coastguard Worker   inStream = new CBinderInStream(this);
67*f6dc9357SAndroid Build Coastguard Worker   outStream = new CBinderOutStream(this);
68*f6dc9357SAndroid Build Coastguard Worker }
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker // (_canRead_Event && _bufSize == 0) means that stream is finished.
71*f6dc9357SAndroid Build Coastguard Worker 
72*f6dc9357SAndroid Build Coastguard Worker HRESULT CStreamBinder::Read(void *data, UInt32 size, UInt32 *processedSize)
73*f6dc9357SAndroid Build Coastguard Worker {
74*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
75*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
76*f6dc9357SAndroid Build Coastguard Worker   if (size != 0)
77*f6dc9357SAndroid Build Coastguard Worker   {
78*f6dc9357SAndroid Build Coastguard Worker     if (_waitWrite)
79*f6dc9357SAndroid Build Coastguard Worker     {
80*f6dc9357SAndroid Build Coastguard Worker       WRes wres = _canRead_Event.Lock();
81*f6dc9357SAndroid Build Coastguard Worker       if (wres != 0)
82*f6dc9357SAndroid Build Coastguard Worker         return HRESULT_FROM_WIN32(wres);
83*f6dc9357SAndroid Build Coastguard Worker       _waitWrite = false;
84*f6dc9357SAndroid Build Coastguard Worker     }
85*f6dc9357SAndroid Build Coastguard Worker     if (size > _bufSize)
86*f6dc9357SAndroid Build Coastguard Worker       size = _bufSize;
87*f6dc9357SAndroid Build Coastguard Worker     if (size != 0)
88*f6dc9357SAndroid Build Coastguard Worker     {
89*f6dc9357SAndroid Build Coastguard Worker       memcpy(data, _buf, size);
90*f6dc9357SAndroid Build Coastguard Worker       _buf = ((const Byte *)_buf) + size;
91*f6dc9357SAndroid Build Coastguard Worker       ProcessedSize += size;
92*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
93*f6dc9357SAndroid Build Coastguard Worker         *processedSize = size;
94*f6dc9357SAndroid Build Coastguard Worker       _bufSize -= size;
95*f6dc9357SAndroid Build Coastguard Worker 
96*f6dc9357SAndroid Build Coastguard Worker       /*
97*f6dc9357SAndroid Build Coastguard Worker       if (_bufSize == 0), then we have read whole buffer
98*f6dc9357SAndroid Build Coastguard Worker       we have two ways here:
99*f6dc9357SAndroid Build Coastguard Worker         - if we       check (_bufSize == 0) here, we unlock Write only after full data Reading - it reduces the number of syncs
100*f6dc9357SAndroid Build Coastguard Worker         - if we don't check (_bufSize == 0) here, we unlock Write after partial data Reading
101*f6dc9357SAndroid Build Coastguard Worker       */
102*f6dc9357SAndroid Build Coastguard Worker       if (_bufSize == 0)
103*f6dc9357SAndroid Build Coastguard Worker       {
104*f6dc9357SAndroid Build Coastguard Worker         _waitWrite = true;
105*f6dc9357SAndroid Build Coastguard Worker         // _canWrite_Event.Set();
106*f6dc9357SAndroid Build Coastguard Worker         _canWrite_Semaphore.Release();
107*f6dc9357SAndroid Build Coastguard Worker       }
108*f6dc9357SAndroid Build Coastguard Worker     }
109*f6dc9357SAndroid Build Coastguard Worker   }
110*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
111*f6dc9357SAndroid Build Coastguard Worker }
112*f6dc9357SAndroid Build Coastguard Worker 
113*f6dc9357SAndroid Build Coastguard Worker 
114*f6dc9357SAndroid Build Coastguard Worker HRESULT CStreamBinder::Write(const void *data, UInt32 size, UInt32 *processedSize)
115*f6dc9357SAndroid Build Coastguard Worker {
116*f6dc9357SAndroid Build Coastguard Worker   if (processedSize)
117*f6dc9357SAndroid Build Coastguard Worker     *processedSize = 0;
118*f6dc9357SAndroid Build Coastguard Worker   if (size == 0)
119*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
120*f6dc9357SAndroid Build Coastguard Worker 
121*f6dc9357SAndroid Build Coastguard Worker   if (!_readingWasClosed2)
122*f6dc9357SAndroid Build Coastguard Worker   {
123*f6dc9357SAndroid Build Coastguard Worker     _buf = data;
124*f6dc9357SAndroid Build Coastguard Worker     _bufSize = size;
125*f6dc9357SAndroid Build Coastguard Worker     _canRead_Event.Set();
126*f6dc9357SAndroid Build Coastguard Worker 
127*f6dc9357SAndroid Build Coastguard Worker     /*
128*f6dc9357SAndroid Build Coastguard Worker     _canWrite_Event.Lock();
129*f6dc9357SAndroid Build Coastguard Worker     if (_readingWasClosed)
130*f6dc9357SAndroid Build Coastguard Worker       _readingWasClosed2 = true;
131*f6dc9357SAndroid Build Coastguard Worker     */
132*f6dc9357SAndroid Build Coastguard Worker 
133*f6dc9357SAndroid Build Coastguard Worker     _canWrite_Semaphore.Lock();
134*f6dc9357SAndroid Build Coastguard Worker 
135*f6dc9357SAndroid Build Coastguard Worker     // _bufSize : is remain size that was not read
136*f6dc9357SAndroid Build Coastguard Worker     size -= _bufSize;
137*f6dc9357SAndroid Build Coastguard Worker 
138*f6dc9357SAndroid Build Coastguard Worker     // size : is size of data that was read
139*f6dc9357SAndroid Build Coastguard Worker     if (size != 0)
140*f6dc9357SAndroid Build Coastguard Worker     {
141*f6dc9357SAndroid Build Coastguard Worker       // if some data was read, then we report that size and return
142*f6dc9357SAndroid Build Coastguard Worker       if (processedSize)
143*f6dc9357SAndroid Build Coastguard Worker         *processedSize = size;
144*f6dc9357SAndroid Build Coastguard Worker       return S_OK;
145*f6dc9357SAndroid Build Coastguard Worker     }
146*f6dc9357SAndroid Build Coastguard Worker     _readingWasClosed2 = true;
147*f6dc9357SAndroid Build Coastguard Worker   }
148*f6dc9357SAndroid Build Coastguard Worker 
149*f6dc9357SAndroid Build Coastguard Worker   // WritingWasCut = true;
150*f6dc9357SAndroid Build Coastguard Worker   return k_My_HRESULT_WritingWasCut;
151*f6dc9357SAndroid Build Coastguard Worker }
152