libzypp 17.34.1
iodevice.cc
Go to the documentation of this file.
2
3namespace zyppng {
4
7
9
10 IODevice::IODevice() : Base( *( new IODevicePrivate(*this)) )
11 { }
12
15
16 bool IODevice::open( const OpenMode mode )
17 {
18 Z_D();
19
20 d->_mode = mode;
21 d->_readChannels.clear();
22 if ( canRead() ) {
23 d->_readChannels.push_back( IOBuffer( d->_readBufChunkSize ) );
24 setReadChannel( 0 );
25 }
26
27 return true;
28 }
29
31 {
32 Z_D();
33 d->_mode = IODevice::Closed;
34 d->_readChannels.clear();
35 }
36
37 void IODevice::setReadChannelCount ( uint channels ) {
38 Z_D();
39 if ( canRead() ) {
40 d->_readChannels.resize( channels );
41 }
42 }
43
44 void IODevice::setReadChannel ( uint channel )
45 {
46 Z_D();
47 if ( !canRead() )
48 return;
49 if ( channel >= d->_readChannels.size() ) {
50 ERR << constants::outOfRangeErrMsg << std::endl;
51 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
52 }
53 d->_currentReadChannel = channel;
54 readChannelChanged( channel );
55 }
56
58 {
59 Z_D();
60 if ( !canRead() )
61 return 0;
62 return d->_currentReadChannel;
63 }
64
66 {
67 Z_D();
68 if ( !canRead() )
69 return 0;
70 return d->_readChannels.size();
71 }
72
73 bool IODevice::canRead() const
74 {
75 return ( d_func()->_mode & IODevice::ReadOnly );
76 }
77
78 bool IODevice::canWrite() const
79 {
80 return ( d_func()->_mode & IODevice::WriteOnly );
81 }
82
83 bool IODevice::isOpen() const
84 {
85 return d_func()->_mode != IODevice::Closed;
86 }
87
89 {
90 Z_D();
91 if ( !canRead() )
92 return false;
93
94 return canReadLine( d->_currentReadChannel );
95 }
96
98 {
99 Z_D();
100 return bytesAvailable( d->_currentReadChannel );
101 }
102
105 Z_D();
106 return readAll( d->_currentReadChannel );
107 }
108
109 ByteArray IODevice::read( int64_t maxSize )
110 {
111 if ( !canRead() || maxSize <= 0 )
112 return {};
113 return read( d_func()->_currentReadChannel, maxSize );
114 }
115
116 int64_t IODevice::read(char *buf, int64_t maxSize )
117 {
118 Z_D();
119 if ( !canRead() )
120 return -1;
121 return read( d->_currentReadChannel, buf, maxSize );
122 }
123
124 ByteArray IODevice::readLine( const int64_t maxSize )
125 {
126 if ( !canRead() )
127 return {};
128
129 return channelReadLine( d_func()->_currentReadChannel, maxSize );
130 }
131
133 {
134 return read( channel, bytesAvailable( channel ) );
135 }
136
137 ByteArray IODevice::read( uint channel, int64_t maxSize )
138 {
139 if ( !canRead() || maxSize <= 0 )
140 return {};
141
142 ByteArray res( maxSize, '\0' );
143 const auto r = read( channel, res.data(), maxSize );
144 res.resize( r );
145 return res;
146 }
147
148 int64_t IODevice::read( uint channel, char *buf, int64_t maxSize )
149 {
150 Z_D();
151 if ( !canRead() || maxSize < 0 )
152 return -1;
153
154 if ( channel >= d->_readChannels.size() ) {
155 ERR << constants::outOfRangeErrMsg << std::endl;
156 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
157 }
158
159 int64_t readSoFar = d->_readChannels[ channel ].read( buf, maxSize );
160
161 // try to read more from the device
162 if ( readSoFar < maxSize ) {
163 int64_t readFromDev = readData( channel, buf+readSoFar, maxSize - readSoFar );
164 if ( readFromDev > 0 )
165 return readSoFar + readFromDev;
166 }
167 return readSoFar;
168 }
169
170 ByteArray IODevice::channelReadLine( uint channel, int64_t maxSize )
171 {
172 Z_D();
173 if ( !canRead() || maxSize < 0 )
174 return {};
175
176 if ( channel >= d->_readChannels.size() ) {
177 ERR << constants::outOfRangeErrMsg << std::endl;
178 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
179 }
180
181 ByteArray result;
182 // largest possible ByteArray in int64_t boundaries
183 const auto maxBArrSize = int64_t( std::min( ByteArray::maxSize(), std::size_t(std::numeric_limits<int64_t>::max()) ) );
184 if ( maxSize > maxBArrSize ) {
185 ERR << "Calling channelReadLine with maxSize > int64_t(ByteArray::maxSize) " << std::endl;
186 maxSize = maxBArrSize - 1;
187 }
188
189 // how much did we read?
190 int64_t readSoFar = 0;
191
192 // if we have no size or the size is really big we read incrementally, use the buffer chunk size
193 // to read full chunks from the buffer if possible
194 if ( maxSize == 0 || maxSize >= (maxBArrSize - 1) ) {
195
196 // largest possible ByteArray
197 maxSize = maxBArrSize;
198
199 // we need to read in chunks until we get a \n
200 int64_t lastReadSize = 0;
201 result.resize (1); // leave room for \0
202 do {
203 result.resize( std::min( std::size_t(maxSize), std::size_t(result.size() + d->_readBufChunkSize )) );
204 lastReadSize = channelReadLine( channel, result.data() + readSoFar, result.size() - readSoFar );
205 if ( lastReadSize > 0)
206 readSoFar += lastReadSize;
207
208 // check for equal _readBufSize,
209 // our readData request is always 1 byte bigger than the _readBufChunkSize because of the initial byte we allocated in the result buffer,
210 // so the \0 that is appended by readLine does not make a difference.
211 } while( lastReadSize == d->_readBufChunkSize
212 && result[readSoFar-1] != '\n' );
213
214 } else {
215 result.resize( maxSize );
216 readSoFar = channelReadLine( channel, result.data(), result.size() );
217 }
218
219 if ( readSoFar > 0 ) {
220 // we do not need to keep the \0 in the ByteArray
221 result.resize( readSoFar );
222 } else {
223 result.clear ();
224 }
225
226 // make sure we do not waste memory
227 result.shrink_to_fit();
228
229 return result;
230 }
231
232 int64_t IODevice::channelReadLine( uint channel, char *buf, const int64_t maxSize )
233 {
234 Z_D();
235
236 if ( !canRead() || maxSize < 0 )
237 return -1;
238
239 if ( channel >= d->_readChannels.size() ) {
240 ERR << constants::outOfRangeErrMsg << std::endl;
241 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
242 }
243
244 if ( maxSize < 2 ) {
245 ERR << "channelReadLine needs at least a buffsize of 2" << std::endl;
246 return -1;
247 }
248
249 int64_t toRead = maxSize - 1; // append \0 at the end
250 int64_t readSoFar = 0;
251 if ( d->_readChannels[channel].size () > 0 )
252 readSoFar = d->_readChannels[channel].readLine( buf, toRead + 1 /*IOBuffer appends \0*/ );
253
254 if ( readSoFar == toRead || ( readSoFar > 0 && buf[readSoFar-1] == '\n' ) ) {
255 buf[readSoFar] = '\0';
256 return readSoFar;
257 }
258
259 bool hasError = false;
260 // if we reach here, the buffer was either empty, or does not contain a \n, in both cases we need to
261 // read from the device directly until we hit a ending condition
262 while ( readSoFar < toRead ) {
263 const auto r = readData( channel, buf+readSoFar, 1 );
264 if ( r == 0 ) {
265 // no data available to be read -> EOF, or data stream empty
266 break;
267 }
268 else if ( r < 0 ) {
269 hasError = true;
270 break;
271 }
272 readSoFar+=r;
273
274 if ( buf[readSoFar-1] == '\n' )
275 break;
276 }
277
278 if ( readSoFar == 0 )
279 return hasError ? -1 : 0;
280
281 buf[readSoFar] = '\0';
282 return readSoFar;
283 }
284
285 int64_t IODevice::bytesAvailable ( uint channel ) const
286 {
287 Z_D();
288 if ( !canRead() )
289 return 0;
290 return d->_readChannels[channel].size() + rawBytesAvailable( channel );
291 }
292
293 bool IODevice::canReadLine ( uint channel ) const
294 {
295 Z_D();
296 if ( !canRead() || channel >= d->_readChannels.size() )
297 return false;
298 return d->_readChannels[channel].canReadLine();
299 }
300
302 {
303 if ( !canWrite() )
304 return 0;
305 return write( data.data(), data.size() );
306 }
307
308 int64_t IODevice::write( const char *data, int64_t len)
309 {
310 if ( !canWrite() || len <= 0 )
311 return 0;
312 return writeData( data, len );
313 }
314
315 bool IODevice::waitForReadyRead( int timeout)
316 {
317 Z_D();
318 if ( !canRead() )
319 return false;
320
321 return waitForReadyRead( d->_currentReadChannel, timeout );
322 }
323
325 {
326 return d_func()->_readyRead;
327 }
328
330 {
331 return d_func()->_channelReadyRead;
332 }
333
335 {
336 return d_func()->_sigBytesWritten;
337 }
338
340 {
341 return d_func()->_sigAllBytesWritten;
342 }
343}
344
static std::size_t maxSize()
Definition ByteArray.h:37
IODevicePrivate(IODevice &p)
Definition iodevice.cc:5
virtual void readChannelChanged(uint channel)=0
bool canReadLine() const
Definition iodevice.cc:88
virtual int64_t writeData(const char *data, int64_t count)=0
virtual ByteArray readLine(const int64_t maxSize=0)
Definition iodevice.cc:124
SignalProxy< void(uint)> sigChannelReadyRead()
Definition iodevice.cc:329
void setReadChannelCount(uint channels)
Definition iodevice.cc:37
SignalProxy< void()> sigReadyRead()
Definition iodevice.cc:324
virtual int64_t bytesAvailable() const
Definition iodevice.cc:97
virtual int64_t rawBytesAvailable(uint channel) const =0
SignalProxy< void(int64_t)> sigBytesWritten()
Definition iodevice.cc:334
bool canWrite() const
Definition iodevice.cc:78
virtual int64_t readData(uint channel, char *buffer, int64_t bufsize)=0
bool waitForReadyRead(int timeout)
Definition iodevice.cc:315
ByteArray readAll()
Definition iodevice.cc:103
virtual void close()
Definition iodevice.cc:30
bool canRead() const
Definition iodevice.cc:73
SignalProxy< void()> sigAllBytesWritten()
Definition iodevice.cc:339
void setReadChannel(uint channel)
Definition iodevice.cc:44
uint currentReadChannel() const
Definition iodevice.cc:57
bool isOpen() const
Definition iodevice.cc:83
ByteArray read(int64_t maxSize)
Definition iodevice.cc:109
ByteArray channelReadLine(uint channel, int64_t maxSize=0)
Definition iodevice.cc:170
int64_t write(const ByteArray &data)
Definition iodevice.cc:301
virtual bool open(const OpenMode mode)
Definition iodevice.cc:16
int readChannelCount() const
Definition iodevice.cc:65
constexpr std::string_view outOfRangeErrMsg("Channel index out of range")
#define ERR
Definition Logger.h:100
#define ZYPP_IMPL_PRIVATE(Class)
Definition zyppglobal.h:91
#define Z_D()
Definition zyppglobal.h:104