aboutsummaryrefslogtreecommitdiff
path: root/libbutl/fdstream.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'libbutl/fdstream.hxx')
-rw-r--r--libbutl/fdstream.hxx84
1 files changed, 80 insertions, 4 deletions
diff --git a/libbutl/fdstream.hxx b/libbutl/fdstream.hxx
index 4dc89a3..9c8f786 100644
--- a/libbutl/fdstream.hxx
+++ b/libbutl/fdstream.hxx
@@ -137,6 +137,11 @@ namespace butl
class LIBBUTL_SYMEXPORT fdstreambuf: public bufstreambuf
{
public:
+ // Reasonable (for stack allocation) buffer size that provides decent
+ // performance.
+ //
+ static const std::size_t buffer_size = 8192;
+
fdstreambuf () = default;
// Unless specified, the current read/write position is assumed to
@@ -174,6 +179,9 @@ namespace butl
bool
blocking (bool);
+ bool
+ blocking () const {return !non_blocking_;}
+
public:
using base = bufstreambuf;
@@ -238,7 +246,7 @@ namespace butl
private:
auto_fd fd_;
- char buf_[8192];
+ char buf_[buffer_size];
bool non_blocking_ = false;
};
@@ -271,7 +279,9 @@ namespace butl
binary = 0x02,
skip = 0x04,
blocking = 0x08,
- non_blocking = 0x10
+ non_blocking = 0x10,
+
+ none = 0
};
inline fdstream_mode operator& (fdstream_mode, fdstream_mode);
@@ -311,6 +321,9 @@ namespace butl
int
fd () const {return buf_.fd ();}
+ bool
+ blocking () const {return buf_.blocking ();}
+
protected:
fdstreambuf buf_;
};
@@ -641,6 +654,54 @@ namespace butl
LIBBUTL_SYMEXPORT ifdstream&
getline (ifdstream&, std::string&, char delim = '\n');
+ // The non-blocking getline() version that reads the line in potentially
+ // multiple calls. Key differences compared to getline():
+ //
+ // - Stream must be in the non-blocking mode and exception mask must have
+ // at least badbit.
+ //
+ // - Return type is bool instead of stream. Return true if the line has been
+ // read or false if it should be called again once the stream has more
+ // data to read. Also return true on failure.
+ //
+ // - The string must be empty on the first call.
+ //
+ // - There could still be data to read in the stream's buffer (as opposed to
+ // file descriptor) after this function returns true and you should be
+ // careful not to block on fdselect() in this case. In fact, the
+ // recommended pattern is to call this function first and only call
+ // fdselect() if it returns false.
+ //
+ // The typical usage in combination with the eof() helper:
+ //
+ // fdselect_set fds {is.fd (), ...};
+ // fdselect_state& ist (fds[0]);
+ // fdselect_state& ...;
+ //
+ // for (string l; ist.fd != nullfd || ...; )
+ // {
+ // if (ist.fd != nullfd && getline_non_blocking (is, l))
+ // {
+ // if (eof (is))
+ // ist.fd = nullfd;
+ // else
+ // {
+ // // Consume line.
+ //
+ // l.clear ();
+ // }
+ //
+ // continue;
+ // }
+ //
+ // ifdselect (fds);
+ //
+ // // Handle other ready fds.
+ // }
+ //
+ LIBBUTL_SYMEXPORT bool
+ getline_non_blocking (ifdstream&, std::string&, char delim = '\n');
+
// Open a file returning an auto_fd that holds its file descriptor on
// success and throwing ios::failure otherwise.
//
@@ -840,6 +901,14 @@ namespace butl
LIBBUTL_SYMEXPORT bool
fdterm (int);
+ // Test whether a terminal file descriptor supports ANSI color output. If
+ // the enable argument is true, then also try to enable color output (only
+ // applicable on some platforms, such as Windows). Throw ios::failure on the
+ // underlying OS error.
+ //
+ LIBBUTL_SYMEXPORT bool
+ fdterm_color (int, bool enable);
+
// Wait until one or more file descriptors becomes ready for input (reading)
// or output (writing). Return the pair of numbers of descriptors that are
// ready. Throw std::invalid_argument if anything is wrong with arguments
@@ -847,7 +916,7 @@ namespace butl
// underlying OS error.
//
// Note that the function clears all the previously-ready entries on each
- // call. Entries with nullfd are ignored.
+ // call. Entries with nullfd are ignored (but cleared).
//
// On Windows only pipes and only their input (read) ends are supported.
//
@@ -855,11 +924,13 @@ namespace butl
{
int fd;
bool ready;
+ void* data; // Arbitrary data which can be associated with the descriptor.
// Note: intentionally non-explicit to allow implicit initialization when
// pushing to fdselect_set.
//
- fdselect_state (int fd): fd (fd), ready (false) {}
+ fdselect_state (int fd, void* d = nullptr)
+ : fd (fd), ready (false), data (d) {}
};
using fdselect_set = small_vector<fdselect_state, 4>;
@@ -912,6 +983,11 @@ namespace butl
//
LIBBUTL_SYMEXPORT std::streamsize
fdread (int, void*, std::size_t);
+
+ // POSIX write() function wrapper, for uniformity.
+ //
+ LIBBUTL_SYMEXPORT std::streamsize
+ fdwrite (int, const void*, std::size_t);
}
#include <libbutl/fdstream.ixx>