I have a Visual Studio 2008 C++ project where I'm trying to serialize data from several classes to a custom std::streambuf
implementation.
The data classes with their serialization:
struct Header { /*...*/ };
inline std::ostream& operator<<( std::ostream& os, const Header& h )
{
/* serialize the members of Header here */
os.write( h.some_member, sizeof( h.some_member ) );
return os;
}
struct Info { /*...*/ };
inline std::ostream& operator<<( std::ostream& os, const Info& i )
{
/* serialize the members of Info here */
return os;
}
The streambuffer implementation provides buffered i/o and overrides underflow
and overflow
.
class MyStreamBuf : public std::streambuf
{
public:
MyStreamBuf() { InitBuffers(); };
private:
void InitBuffers()
{
recv_buffer_.resize( buff_size );
send_buffer_.resize( buff_size );
setg( &recv_buffer_[ 0 ], &recv_buffer_[ 0 ], &recv_buffer_[ 0 ] );
setp( &send_buffer_[ 0 ], &send_buffer_[ 0 ] );
};
enum { buff_size = 512 };
std::vector< char_type > recv_buffer_;
std::vector< char_type > send_buffer_;
int_type underflow() { /* ... */ };
int_type overflow( char_type c )
{
*pptr() = c;
pbump( 1 );
// if the buffer is full, flush the data
if( pptr() == epptr() )
flush();
return c;
};
void flush()
{
std::ptrdiff_t n = pptr() - pbase();
int written = /* send n bytes to the data destination */
pbump( -written );
};
}; // class MyStreamBuf
My intended usage is something like this:
Header h( /* some useful info */ );
Info i( /* some useful info */ );
MyStreamBuf dest;
std::iostream my_stream( &dest );
dest << h << i; // MyStreambuf::overflow() is never called!
But, MyStreambuf::overflow
is never called. What do I need to do to get the data to my buffer?
Thanks, PaulH
You need to call flush()
on the iostream (or call pubsync()
on your streambuf).
Traditionally you'd do this in the destructor of your streambuf (in the same way that filebuf's destructor calls close()
), in which case you just need to destroy it.
Also it's conventional to provide a class inheriting from iostream that owns an instance of your streambuf and ensures it is flushed/destroyed when appropriate.