I am trying to write a custom std::ostream that invokes a function for every line written to it. That is, I would like the following code to work as documented in comments:
my_output_stream s([] (const std::string& line) {
WriteLineToSomeOutput(line);
});
s << "Hello world"; // do not invoke anything. The line has not ended yet!
s << ", from Alex" << std::endl; // here we invoke WriteLineToSomeOutput("hello world, from Alex")
s << "What's up"; // do not invoke anything. The line has not ended yet.
s << ", doc?!\nHow u doing?\n"; // Now we have two lines. We invoke WriteLineToSomeOutput("What's up, doc?!) and WriteLineToSomeOutput("How u doing?")
Note that the data is not written anywhere and not stored anywhere. The only thing that I need the stream to store is the current line that is being aggregated, until we encounter an end of line.
I did not find any easy way of doing so, even when using the boost.Iostreams library. Can I avoid writing my own line tokenizer here by using some built-in facilities of STL and Boost?
Background
The my_output_stream class will be used to adapt between an external library and a logging library used in my application. The external library requires that I provide an std::ostream. And I want to log each line that is logged by the external library using my application's logging framework.
If I understand correctly, you want to unconditionally flush at
end of line, and only at end of line. To do this, you must
implement your own streambuf; it could be based on
std::stringbuf, but if you're only concerned with output,
and not worried about seeking, it's probably just as easy to do
it yourself.
Something like the following should do the trick:
class LineBufferedOutput : public std::streambuf
{
std::vector<char> myBuffer;
protected:
int overflow( int ch ) override
{
myBuffer.push_back( ch );
if ( ch == '\n' ) {
// whatever you have to do...
}
// return traits::eof() for failure...
}
};
I'm not sure what you mean by implementing your own tokenizer;
there's no tokenization involved. You do have to look at each
character, in order to compare it to '\n', but that's all.
And you ignore any explicit requests to sync().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With