Writing input stream with source - novalexei/nstream GitHub Wiki
In order to write your own intput stream with nova::stream you'll need to write source class. The source class has the following requirements:
- It should have type definitions for character type and for category (which in this case is always source):
typedef source category;
typedef /* character type */ char_type;
- It should implement the following method:
std::streamsize read(char_type* s, std::streamsize n);
Method read reads from the underlying stream into buffer s up to n characters and returns the actual number of characters read.
Let's write simple replacement for std::istringstream
#include <nova/io.h>
using namespace nova;
template<typename CharT>
class string_source
{
public:
typedef source category;
typedef CharT char_type;
typedef std::basic_string<CharT> string_type;
explicit string_source(string_type str) : _buffer{std::move(str)} {}
std::streamsize read(char_type* s, std::streamsize n)
{
if (ptr >= _buffer.size()) return 0;
std::streamsize toWrite = n < _buffer.size() - ptr ? n : _buffer.size() - ptr;
std::copy(_buffer.data()+ptr, _buffer.data()+ptr+toWrite, s);
ptr += toWrite;
return toWrite;
}
private:
const string_type _buffer;
typename string_type::size_type ptr = 0;
};
And here is how it can be used:
int main()
{
std::string s{"123 456"};
instream<string_source<char>> in{s};
int i1, i2;
in >> i1 >> i2;
std::cout << i1 << " " << i2 << std::endl;
return 0;
}
By default nova::instream is unbuffered. Template class nova::instream accepts buffering info class as a second template argument. For example if we want to have 1Kb buffer we can create the object as follows:
instream<string_source<char>, buffering<1024>> in{s};
or
instream<string_source<char>, buffer_1k> in{s};
To the next section: Writing output stream with sink
Back to the Tutorial