1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
// -*- C++ -*- (c) 2008 Petr Rockai <me@mornfall.net>
#include <fcntl.h>
#include <sys/select.h>
#include <deque>
#include <cerrno>
#include <wibble/exception.h>
#ifndef WIBBLE_SYS_PIPE_H
#define WIBBLE_SYS_PIPE_H
namespace wibble {
namespace sys {
namespace wexcept = wibble::exception;
struct Pipe {
typedef std::deque< char > Buffer;
Buffer buffer;
int fd;
bool _eof;
Pipe( int p ) : fd( p ), _eof( false )
{
if ( p == -1 )
return;
if ( fcntl( fd, F_SETFL, O_NONBLOCK ) == -1 )
throw wexcept::System( "fcntl on a pipe" );
}
Pipe() : fd( -1 ), _eof( false ) {}
void write( std::string what ) {
::write( fd, what.c_str(), what.length() );
}
bool active() {
return fd != -1 && !_eof;
}
bool eof() {
return _eof;
}
int readMore() {
char _buffer[1024];
int r = ::read( fd, _buffer, 1023 );
if ( r == -1 && errno != EAGAIN )
throw wexcept::System( "reading from pipe" );
else if ( r == -1 )
return 0;
if ( r == 0 )
_eof = true;
else
std::copy( _buffer, _buffer + r, std::back_inserter( buffer ) );
return r;
}
std::string nextLine() {
Buffer::iterator nl =
std::find( buffer.begin(), buffer.end(), '\n' );
while ( nl == buffer.end() && readMore() );
nl = std::find( buffer.begin(), buffer.end(), '\n' );
if ( nl == buffer.end() )
return "";
std::string line( buffer.begin(), nl );
++ nl;
buffer.erase( buffer.begin(), nl );
return line;
}
std::string nextLineBlocking() {
fd_set fds;
FD_ZERO( &fds );
std::string l;
while ( !eof() ) {
l = nextLine();
if ( !l.empty() )
return l;
FD_SET( fd, &fds );
select( fd + 1, &fds, 0, 0, 0 );
}
return l;
}
};
}
}
#endif
|