libzypp 17.37.17
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::finishReadChannel( uint channel )
45 {
46 Z_D();
47 if ( channel >= d->_readChannels.size() ) {
48 ERR << constants::outOfRangeErrMsg << std::endl;
49 return;
50 }
51
52 // just signal code that the read channel is finished)
53 d->_sigReadChannelFinished.emit( channel );
54 }
55
56 void IODevice::setReadChannel ( uint channel )
57 {
58 Z_D();
59 if ( !canRead() )
60 return;
61 if ( channel >= d->_readChannels.size() ) {
62 ERR << constants::outOfRangeErrMsg << std::endl;
63 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
64 }
65 d->_currentReadChannel = channel;
66 readChannelChanged( channel );
67 }
68
70 {
71 Z_D();
72 if ( !canRead() )
73 return 0;
74 return d->_currentReadChannel;
75 }
76
78 {
79 Z_D();
80 if ( !canRead() )
81 return 0;
82 return d->_readChannels.size();
83 }
84
85 bool IODevice::canRead() const
86 {
87 return ( d_func()->_mode & IODevice::ReadOnly );
88 }
89
90 bool IODevice::canWrite() const
91 {
92 return ( d_func()->_mode & IODevice::WriteOnly );
93 }
94
95 bool IODevice::isOpen() const
96 {
97 return d_func()->_mode != IODevice::Closed;
98 }
99
101 {
102 Z_D();
103 if ( !canRead() )
104 return false;
105
106 return canReadLine( d->_currentReadChannel );
107 }
108
110 {
111 Z_D();
112 return bytesAvailable( d->_currentReadChannel );
113 }
114
116 {
117 Z_D();
118 return readBufferCount( d->_currentReadChannel );
119 }
120
122 {
123 Z_D();
124 return readAll( d->_currentReadChannel );
125 }
126
127 ByteArray IODevice::read( int64_t maxSize )
128 {
129 if ( !canRead() || maxSize <= 0 )
130 return {};
131 return read( d_func()->_currentReadChannel, maxSize );
132 }
133
134 int64_t IODevice::read(char *buf, int64_t maxSize )
135 {
136 Z_D();
137 if ( !canRead() )
138 return -1;
139 return read( d->_currentReadChannel, buf, maxSize );
140 }
142 ByteArray IODevice::readLine( const int64_t maxSize )
143 {
144 if ( !canRead() )
145 return {};
146
147 return channelReadLine( d_func()->_currentReadChannel, maxSize );
148 }
149
151 {
152 return read( channel, bytesAvailable( channel ) );
153 }
154
155 ByteArray IODevice::read( uint channel, int64_t maxSize )
156 {
157 if ( !canRead() || maxSize <= 0 )
158 return {};
159
160 ByteArray res( maxSize, '\0' );
161 const auto r = read( channel, res.data(), maxSize );
162 res.resize( r );
163 return res;
164 }
165
166 int64_t IODevice::read( uint channel, char *buf, int64_t maxSize )
167 {
168 Z_D();
169 if ( !canRead() || maxSize < 0 )
170 return -1;
171
172 if ( channel >= d->_readChannels.size() ) {
173 ERR << constants::outOfRangeErrMsg << std::endl;
174 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
175 }
176
177 int64_t readSoFar = d->_readChannels[ channel ].read( buf, maxSize );
178
179 // try to read more from the device
180 if ( readSoFar < maxSize ) {
181 int64_t readFromDev = readData( channel, buf+readSoFar, maxSize - readSoFar );
182 if ( readFromDev > 0 )
183 return readSoFar + readFromDev;
184 }
185 return readSoFar;
186 }
187
188 ByteArray IODevice::channelReadUntil( uint channel, const char delim, int64_t maxSize )
189 {
190 Z_D();
191 if ( !canRead() || maxSize < 0 )
192 return {};
193
194 if ( channel >= d->_readChannels.size() ) {
195 ERR << constants::outOfRangeErrMsg << std::endl;
196 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
197 }
198
199 ByteArray result;
200 // largest possible ByteArray in int64_t boundaries
201 const auto maxBArrSize = int64_t( std::min( ByteArray::maxSize(), std::size_t(std::numeric_limits<int64_t>::max()) ) );
202 if ( maxSize > maxBArrSize ) {
203 ERR << "Calling channelReadUntil with maxSize > int64_t(ByteArray::maxSize) " << std::endl;
204 maxSize = maxBArrSize - 1;
205 }
206
207 // how much did we read?
208 int64_t readSoFar = 0;
209
210 // if we have no size or the size is really big we read incrementally, use the buffer chunk size
211 // to read full chunks from the buffer if possible
212 if ( maxSize == 0 || maxSize >= (maxBArrSize - 1) ) {
213
214 // largest possible ByteArray
215 maxSize = maxBArrSize;
216
217 // we need to read in chunks until we get a \n
218 int64_t lastReadSize = 0;
219 result.resize (1); // leave room for \0
220 do {
221 result.resize( std::min( std::size_t(maxSize), std::size_t(result.size() + d->_readBufChunkSize )) );
222 lastReadSize = channelReadUntil( channel, result.data() + readSoFar, delim, result.size() - readSoFar );
223 if ( lastReadSize > 0)
224 readSoFar += lastReadSize;
225
226 // check for equal _readBufSize,
227 // our readData request is always 1 byte bigger than the _readBufChunkSize because of the initial byte we allocated in the result buffer,
228 // so the \0 that is appended by readLine does not make a difference.
229 } while( lastReadSize == d->_readBufChunkSize
230 && result[readSoFar-1] != delim );
231
232 } else {
233 result.resize( maxSize );
234 readSoFar = channelReadUntil( channel, result.data(), delim, result.size() );
235 }
236
237 if ( readSoFar > 0 ) {
238 // we do not need to keep the \0 in the ByteArray
239 result.resize( readSoFar );
240 } else {
241 result.clear ();
242 }
243
244 // make sure we do not waste memory
245 result.shrink_to_fit();
246
247 return result;
248 }
249
250 ByteArray IODevice::channelReadLine( uint channel, int64_t maxSize )
251 {
252 return channelReadUntil( channel, '\n', maxSize );
253 }
254
255 int64_t IODevice::channelReadLine( uint channel, char *buf, const int64_t maxSize )
256 {
257 return channelReadUntil( channel, buf, '\n', maxSize );
258 }
259
260 int64_t IODevice::channelReadUntil(uint channel, char *buf, const char delimiter, const int64_t maxSize)
261 {
262 Z_D();
263
264 if ( !canRead() || maxSize < 0 )
265 return -1;
266
267 if ( channel >= d->_readChannels.size() ) {
268 ERR << constants::outOfRangeErrMsg << std::endl;
269 throw std::out_of_range( constants::outOfRangeErrMsg.data() );
270 }
271
272 if ( maxSize < 2 ) {
273 ERR << "channelReadUntil needs at least a buffsize of 2" << std::endl;
274 return -1;
275 }
276
277 int64_t toRead = maxSize - 1; // append \0 at the end
278 int64_t readSoFar = 0;
279 if ( d->_readChannels[channel].size () > 0 )
280 readSoFar = d->_readChannels[channel].readUntil( buf, delimiter, toRead + 1 /*IOBuffer appends \0*/ );
281
282 if ( readSoFar == toRead || ( readSoFar > 0 && buf[readSoFar-1] == delimiter ) ) {
283 buf[readSoFar] = '\0';
284 return readSoFar;
285 }
286
287 bool hasError = false;
288 // if we reach here, the buffer was either empty, or does not contain a \n, in both cases we need to
289 // read from the device directly until we hit a ending condition
290 while ( readSoFar < toRead ) {
291 const auto r = readData( channel, buf+readSoFar, 1 );
292 if ( r == 0 ) {
293 // no data available to be read -> EOF, or data stream empty
294 break;
295 }
296 else if ( r < 0 ) {
297 hasError = true;
298 break;
299 }
300 readSoFar+=r;
301
302 if ( buf[readSoFar-1] == delimiter )
303 break;
304 }
305
306 if ( readSoFar == 0 )
307 return hasError ? -1 : 0;
308
309 buf[readSoFar] = '\0';
310 return readSoFar;
311 }
312
313 int64_t IODevice::bytesAvailable ( uint channel ) const
314 {
315 Z_D();
316 if ( !canRead() )
317 return 0;
318 return d->_readChannels[channel].size() + rawBytesAvailable( channel );
319 }
320
321 int64_t IODevice::readBufferCount(uint channel) const
322 {
323 Z_D();
324 if ( !canRead() )
325 return 0;
326 return d->_readChannels[channel].size();
327 }
328
329 bool IODevice::canReadUntil(uint channel, const char delim) const
330 {
331 Z_D();
332 if ( !canRead() || channel >= d->_readChannels.size() )
333 return false;
334 return d->_readChannels[channel].canReadUntil( delim );
335 }
336
337 bool IODevice::canReadLine ( uint channel ) const
338 {
339 Z_D();
340 if ( !canRead() || channel >= d->_readChannels.size() )
341 return false;
342 return d->_readChannels[channel].canReadLine();
343 }
344
346 {
347 if ( !canWrite() )
348 return 0;
349 return write( data.data(), data.size() );
350 }
351
352 int64_t IODevice::write( const char *data, int64_t len)
353 {
354 if ( !canWrite() || len <= 0 )
355 return 0;
356 return writeData( data, len );
357 }
358
359 bool IODevice::waitForReadyRead( int timeout)
360 {
361 Z_D();
362 if ( !canRead() )
363 return false;
364
365 return waitForReadyRead( d->_currentReadChannel, timeout );
366 }
367
369 {
370 return d_func()->_readyRead;
371 }
372
374 {
375 return d_func()->_channelReadyRead;
376 }
377
379 {
380 return d_func()->_sigBytesWritten;
381 }
382
384 {
385 return d_func()->_sigAllBytesWritten;
386 }
387
389 {
390 return d_func()->_sigReadChannelFinished;
391 }
392
393
395 {}
396
397 IODeviceOStreamBuf::int_type IODeviceOStreamBuf::overflow( int_type __c )
398 {
399 if ( !_dev ){
400 return traits_type::eof();
401 }
402 char buf = __c;
403 if ( _dev->write ( &buf, 1 ) == 1 ) {
404 return traits_type::not_eof(__c);
405 }
406 return traits_type::eof();
407 }
408
409
410}
411
static std::size_t maxSize()
Definition ByteArray.h:38
BasePrivate(Base &b)
Definition base_p.h:17
IODeviceOStreamBuf(IODeviceRef dev)
Definition iodevice.cc:394
int_type overflow(int_type __c) override
Definition iodevice.cc:397
IODevicePrivate(IODevice &p)
Definition iodevice.cc:5
ByteArray channelReadUntil(uint channel, const char delim, int64_t maxSize=0)
Definition iodevice.cc:188
virtual void readChannelChanged(uint channel)=0
bool canReadLine() const
Definition iodevice.cc:100
virtual int64_t writeData(const char *data, int64_t count)=0
virtual ByteArray readLine(const int64_t maxSize=0)
Definition iodevice.cc:142
SignalProxy< void(uint)> sigChannelReadyRead()
Definition iodevice.cc:373
SignalProxy< void(uint) > sigReadChannelFinished()
Definition iodevice.cc:388
void setReadChannelCount(uint channels)
Definition iodevice.cc:37
SignalProxy< void()> sigReadyRead()
Definition iodevice.cc:368
virtual int64_t bytesAvailable() const
Definition iodevice.cc:109
virtual int64_t rawBytesAvailable(uint channel) const =0
SignalProxy< void(int64_t)> sigBytesWritten()
Definition iodevice.cc:378
bool canWrite() const
Definition iodevice.cc:90
virtual int64_t readData(uint channel, char *buffer, int64_t bufsize)=0
bool waitForReadyRead(int timeout)
Definition iodevice.cc:359
void finishReadChannel(uint channel)
Definition iodevice.cc:44
bool canReadUntil(uint channel, const char delim) const
Definition iodevice.cc:329
int64_t readBufferCount() const
Definition iodevice.cc:115
ByteArray readAll()
Definition iodevice.cc:121
virtual void close()
Definition iodevice.cc:30
bool canRead() const
Definition iodevice.cc:85
SignalProxy< void()> sigAllBytesWritten()
Definition iodevice.cc:383
void setReadChannel(uint channel)
Definition iodevice.cc:56
uint currentReadChannel() const
Definition iodevice.cc:69
bool isOpen() const
Definition iodevice.cc:95
ByteArray read(int64_t maxSize)
Definition iodevice.cc:127
ByteArray channelReadLine(uint channel, int64_t maxSize=0)
Definition iodevice.cc:250
int64_t write(const ByteArray &data)
Definition iodevice.cc:345
virtual bool open(const OpenMode mode)
Definition iodevice.cc:16
int readChannelCount() const
Definition iodevice.cc:77
constexpr std::string_view outOfRangeErrMsg("Channel index out of range")
#define ERR
Definition Logger.h:102
#define ZYPP_IMPL_PRIVATE(Class)
Definition zyppglobal.h:92
#define Z_D()
Definition zyppglobal.h:105