libzypp  17.37.5
iodevice.cc
Go to the documentation of this file.
1 #include "private/iodevice_p.h"
2 
3 namespace zyppng {
4 
6  { }
7 
9 
10  IODevice::IODevice() : Base( *( new IODevicePrivate(*this)) )
11  { }
12 
14  { }
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 
109  int64_t IODevice::bytesAvailable() const
110  {
111  Z_D();
112  return bytesAvailable( d->_currentReadChannel );
113  }
114 
115  int64_t IODevice::readBufferCount () const
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  }
141 
142  ByteArray IODevice::readLine( const int64_t maxSize )
143  {
144  if ( !canRead() )
145  return {};
146 
147  return channelReadLine( d_func()->_currentReadChannel, maxSize );
148  }
149 
150  ByteArray IODevice::readAll( uint channel )
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 
394  IODeviceOStreamBuf::IODeviceOStreamBuf(IODeviceRef dev) : _dev(dev)
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 
bool canReadLine() const
Definition: iodevice.cc:100
virtual int64_t rawBytesAvailable(uint channel) const =0
uint currentReadChannel() const
Definition: iodevice.cc:69
bool canRead() const
Definition: iodevice.cc:85
SignalProxy< void(int64_t)> sigBytesWritten()
Definition: iodevice.cc:378
int readChannelCount() const
Definition: iodevice.cc:77
virtual bool open(const OpenMode mode)
Definition: iodevice.cc:16
void setReadChannelCount(uint channels)
Definition: iodevice.cc:37
IODevicePrivate(IODevice &p)
Definition: iodevice.cc:5
ByteArray readAll()
Definition: iodevice.cc:121
void setReadChannel(uint channel)
Definition: iodevice.cc:56
ByteArray channelReadLine(uint channel, int64_t maxSize=0)
Definition: iodevice.cc:250
int64_t readBufferCount() const
Definition: iodevice.cc:115
bool isOpen() const
Definition: iodevice.cc:95
#define ERR
Definition: Logger.h:102
#define Z_D()
Definition: zyppglobal.h:105
static std::size_t maxSize()
Definition: ByteArray.h:38
virtual int64_t writeData(const char *data, int64_t count)=0
bool canReadUntil(uint channel, const char delim) const
Definition: iodevice.cc:329
virtual void readChannelChanged(uint channel)=0
int64_t write(const ByteArray &data)
Definition: iodevice.cc:345
ByteArray channelReadUntil(uint channel, const char delim, int64_t maxSize=0)
Definition: iodevice.cc:188
int_type overflow(int_type __c) override
Definition: iodevice.cc:397
ByteArray read(int64_t maxSize)
Definition: iodevice.cc:127
void finishReadChannel(uint channel)
Definition: iodevice.cc:44
constexpr std::string_view outOfRangeErrMsg("Channel index out of range")
SignalProxy< void(uint)> sigChannelReadyRead()
Definition: iodevice.cc:373
IODeviceOStreamBuf(IODeviceRef dev)
Definition: iodevice.cc:394
SignalProxy< void()> sigReadyRead()
Definition: iodevice.cc:368
SignalProxy< void()> sigAllBytesWritten()
Definition: iodevice.cc:383
SignalProxy< void(uint) > sigReadChannelFinished()
Definition: iodevice.cc:388
ZYPP_IMPL_PRIVATE(UnixSignalSource)
virtual int64_t bytesAvailable() const
Definition: iodevice.cc:109
virtual ByteArray readLine(const int64_t maxSize=0)
Definition: iodevice.cc:142
virtual void close()
Definition: iodevice.cc:30
bool write(const Pathname &path_r, const std::string &key_r, const std::string &val_r, const std::string &newcomment_r)
Add or change a value in sysconfig file path_r.
Definition: sysconfig.cc:80
virtual int64_t readData(uint channel, char *buffer, int64_t bufsize)=0
bool canWrite() const
Definition: iodevice.cc:90
bool waitForReadyRead(int timeout)
Definition: iodevice.cc:359