// forward declaration(s)
template< class char_type, class traits_type = std::char_traits< char_type> >
class basic_message_handler_log;
// represents the stream buffer for a message_handler_log (see below)
// Note: NOT thread-safe
template< class char_type , class traits_type = std::char_traits< char_type> >
class basic_message_handler_log_streambuf
: public std::basic_streambuf< char_type, traits_type>
{
private:
friend basic_message_handler_log< char_type, traits_type>;
typedef std::basic_streambuf< char_type, traits_type> streambuf_type;
typedef basic_message_handler_log< char_type, traits_type> ostream_type;
// base class
typedef std::basic_streambuf< char_type, traits_type> base_class;
enum
{ _BADOFF = -1 /* bad offset - for positioning functions */ };
protected:
// input, not allowed
virtual int_type pbackfail(int_type = traits_type::eof())
{
// only for output, not for input
assert( false);
return (traits_type::eof());
}
virtual int showmanyc()
{
// only for output, not for input
assert( false);
return 0;
}
virtual int_type underflow()
{
// only for output, not for input
assert( false);
return (traits_type::eof());
}
virtual int_type uflow()
{
// only for output, not for input
assert( false);
return (traits_type::eof());
}
virtual std::streamsize xsgetn(char_type * _S, std::streamsize _N)
{
// only for output, not for input
assert( false);
return 0;
}
// called to write out from the internal
// buffer, into the external buffer
virtual int sync()
{
m_pOwnerStream->on_new_message( get_stream_buffer().str() );
m_pStreamBuffer = std::auto_ptr< string_stream_type>( new string_stream_type);
return 0;
}
virtual streambuf_type *setbuf( char_type * buffer, std::streamsize n)
{
// ... note: this function MUST be called
// before working with this stream buffer
// we don't use a buffer - we forward everything
assert( buffer == NULL && n == 0);
setp( NULL, NULL);
return this;
}
// write the characters from the buffer
// to their real destination
virtual int_type overflow(int_type nChar = traits_type::eof())
{
if ( traits_type::not_eof( nChar))
get_stream_buffer() << ( char_type)nChar;
return traits_type::not_eof( nChar);
}
virtual std::streamsize xsputn(const char_type *S, std::streamsize N)
{
get_stream_buffer().write( S, N);
return N;
}
public:
basic_message_handler_log_streambuf():m_pStreamBuffer( new string_stream_type) {}
private:
typedef std::basic_ostringstream< char_type> string_stream_type;
string_stream_type & get_stream_buffer()
{ return *m_pStreamBuffer; }
private:
// holds the Message, until it's flushed
std::auto_ptr< string_stream_type> m_pStreamBuffer;
// the Message Handler Log - where we write into
ostream_type * m_pOwnerStream;
};
// derive your class from this, and implement the PROTECTED on_new_message function
template< class char_type, class traits_type = std::char_traits< char_type> >
class basic_message_handler_log : public std::basic_ostream< char_type, traits_type>
{
typedef basic_message_handler_log_streambuf< char_type, traits_type> handler_streambuf_type;
friend handler_streambuf_type;
typedef std::basic_ostream< char_type, traits_type> base_class;
protected:
typedef std::basic_string< char_type> string_type;