I've seen the instructions for creating custom streambufs many times: All you need to do is implement overflow
, underflow
, and pbackfail
properly in a descendant of std::basic_streambuf
and you can create a stream that formats data using it. Those three routines define your custom stream's 'controlled sequence'.
But there are other monsters lurking in the protected member list of std::basic_streambuf
, namely setg
and setp
. These set up buffer areas for input and output. The public members that get and set data try to access these areas first before going after the controlled sequence.
For a couple of different custom streambufs there might be trouble if the stream sets up its own get/put areas. So I would like such streambufs to avoid using the get/put areas and always use overflow
, underflow
, and pbackfail
without any intermediate buffering.
For a naive simplified example, if you're wrapping another streambuf the implementation of underflow
might look like this:
template <class C, class TR>
typename TR::int_type wrapping_streambuf<C, TR>::underflow()
{
return m_wrapped_streambuf->sgetc();
}
Let the wrapped streambuf handle all of the dirty work. Here's another naive example for counting lines:
template <class C, class TR>
typename TR::int_type tracking_streambuf<C, TR>::uflow()
{
auto rv = m_wrapped_streambuf->sbumpc();
if (rv == (TR::int_type)'\n') ++ m_input_line_count;
return rv;
}
For such streams, there is no useful implementation of setg
because you can't get at the wrapped buffer's internal get area. For tracked_streambuf
, the imposition of get/put areas would make counting lines, in sync with the stream's logical sequence, impossible.
I think the answer is to never call setg
or setp
in the descendant classes. In fact, they probably should override setg
, setp
, gbump
, and pbump
to throw exceptions.
Looking at the <streambuf>
header I see that a custom streambuf
in my favorite library implementation might work the way I want (there are checks for null gptr/pptr) if I do this. But is it a guarantee?