Input output with shared devices - novalexei/nstream GitHub Wiki
nova::stream doesn't support iostream for various reasons. One of them is that I have never needed one in my work. Many languages (like Java) don't have iostreams at all and I don't see any complains about this. But if you still want to have shared buffer for input and output in nova::stream you can achieve it with device_instream and device_outstream.
In order to do this we will need to write a device class with the following requirements:
- It should have type definitions for character type, for in_category (source or in_buffer_provider) and out_category (sink or out_buffer_provider):
typedef /* input category */ in_category;
typedef /* output category */ out_category;
typedef /* character type */ char_type;
-
It should implement all the methods required by both in_category and out_category
-
After that device_instream and device_outstream should be created with the instance of this device class.
As an example let's write a simple device with string buffer. For the demonstration we will use sink as out_category and in_buffer_provider as in_category.
#include <nova/io.h>
using namespace nova;
template<typename CharT>
class string_device
{
public:
typedef CharT char_type;
typedef std::basic_string<CharT> string_type;
typedef std::basic_string_view<CharT> string_view_type;
typedef in_buffer_provider in_category;
typedef sink out_category;
string_device() : _buffer{} {}
explicit string_device(string_type str) : _buffer{std::move(str)} {}
~string_device() noexcept = default;
/* sink methods */
std::streamsize write(const char_type* s, std::streamsize n)
{
_buffer.append(s, n);
return n;
}
void flush() { }
/* in_buffer_provider method */
std::pair<const char_type*, std::size_t> get_in_buffer()
{
if (_in_size == _buffer.size()) return {nullptr, 0};
auto in_start = _in_size;
_in_size = _buffer.size();
return {_buffer.data() + in_start, _in_size};
}
string_view_type view() const { return string_view_type{_buffer}; }
private:
string_type _buffer;
std::size_t _in_size = 0;
};
Now we create an instance of it and use streams with it:
int main()
{
string_device<char> device;
device_instream<string_device<char>> in{device};
device_outstream<string_device<char>> out{device};
out << 123 << ' ' << 456;
int i1, i2;
in >> i1 >> i2;
std::cout << device.view() << std::endl;
std::cout << i1 << ' ' << i2 << std::endl;
return 0;
}
And now we are done with this tutorial.
Back to the Tutorial