Lightweight input and output file descriptor iterators

This is simpler than using getistream() or getostream() and constructing a std::istreambuf_iterator or a std::ostreambuf_iterator:

#include <x/fditer.H>

x::fdbase filedesc=x::fd::base::open("file", O_RDONLY);

std::string str;

std::copy(x::fdinputiter(filedesc, 1024), x::fdinputiter(),
          std::back_insert_iterator<std::string>(str));
	

x::fdinputiter constructs an input iterator that reads from the underlying file descriptor transport. The second optional parameter is the size of the internal buffer, which defaults to the x::fd::buffer_size property. The default constructor instantiates an ending iterator value.

x::fdbase filedesc=x::fd::base::create("file", 0777);

std::string str;

x::fd::outputiter iter(filedesc, 1024);

iter=std::copy(str.begin(), str.end(), iter);

// ...

iter.flush();
	

x::fdoutputiter constructs an output iterator that writes to the underlying file descriptor transport, also using an internal buffer. It's destructor does not flush unwritten buffer contents, flush() must be explicitly invoked to do that.

Note

An input and an output iterator can be constructed concurrently, however they are completely independent from each other, and use their own separate buffers. Reading from the input iterator does not flush the output iterator, and writing to the output iterator does not clear the input buffer.

The iterators can be constructed from any subclass of the file descriptor transport superclass, and not just x::fd. This includes x::gnutls::session. The iterators also hold their own reference to the file descriptor transport object they're iterating over. Using std::istreambuf_iterator or std::ostreambuf_iterator requires that the underlying stream objects remain in scope. x::fdinputiter and x::fdoutputiter, in addition to being references to reference-counted objects themselves, hold their own reference on the underlying reference-counted file descriptor transport superclass.