Writing input stream with in_buffer_provider - novalexei/nstream GitHub Wiki

Writing input stream with in_buffer_provider

After we wrote input stream with a source we might think: why couldn't we just give that string buffer directly to instream instead of writing its characters into an intermediary buffer? If we only could do this there would not be any need to allocate a buffer for the stream and to copy the bytes to that buffer. That could give us some performance and memory advantages. Fortunately, with nova::stream we can do exactly that. In order to do that we need to write in_buffer_provider class. This class has the following requirements:

  • It should have type definitions for character type and for category (which in this case is always in_buffer_provider):
typedef in_buffer_provider     category;
typedef /* character type */   char_type;
  • It should implement the following method:
std::pair<const char_type*, std::size_t> get_in_buffer();

Method get_in_buffer returns std::pair containing buffer for the stream to use and number of characters available in this buffer. This method can (and will) be called multiple times until it returns {nullptr, 0}.

Note that in C++17 this method can also return std::tuple<const char_type*, std::size_t> or struct {const char_type*, std::size_t}

Example

Let's try to rewrite the source from the first section as in_buffer_provider:

#include <nova/io.h>

using namespace nova;

template<class CharT>
class string_view_buffer_provider
{
public:
    typedef in_buffer_provider            category;

    typedef CharT                         char_type;
    typedef std::basic_string_view<CharT> string_view_type;

    explicit string_view_buffer_provider(string_view_type str) : _str{str} {}

    std::pair<const char_type*, std::size_t> get_in_buffer()
    {
        if (_buffer_provided) return {nullptr, 0};
        _buffer_provided = true;
        return {_str.data(), static_cast<std::size_t>(_str.size())};
    }
private:
    string_view_type _str;
    bool _buffer_provided = false;
};

And the usage is very similar:

int main()
{
    instream<string_view_buffer_provider<char>> in{"123 456"};
    int i1, i2;
    in >> i1 >> i2;
    std::cout << i1 << " " << i2 << std::endl;
    return 0;
}

Simple. Isn't it? Check out its performance.

To the next section: Writing output stream with out_buffer_provider

Back to the Tutorial

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