Input output with shared devices - novalexei/nstream GitHub Wiki

Input-output with shared devices

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.

Example

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

⚠️ **GitHub.com Fallback** ⚠️