views:

102

answers:

0

I have a Visual Studio 2008 C++ application using IStreams. I would like to use the IStream connection in a std::ostream. Something like this:

IStream* stream = /*create valid IStream instance...*/; 
IStreamBuf< WIN32_FIND_DATA > sb( stream );
std::ostream os( &sb );

WIN32_FIND_DATA d = { 0 };
// send the structure along the IStream
os << d;

To accomplish this, I've implemented the following code:

template< class _CharT, class _Traits >
inline std::basic_ostream< _CharT, _Traits >& 
operator<<( std::basic_ostream< _CharT, _Traits >& os, const WIN32_FIND_DATA& i ) 
{
    const _CharT* c = reinterpret_cast< const _CharT* >( &i );
    const _CharT* const end = c + sizeof( WIN32_FIND_DATA ) / sizeof( _CharT );
    for( c; c < end; ++c ) os << *c;
    return os;
}

template< typename T >
class IStreamBuf : public std::streambuf
{
public:
    IStreamBuf( IStream* stream ) : stream_( stream )
    {
        setp( reinterpret_cast< char* >( &buffer_ ), 
              reinterpret_cast< char* >( &buffer_ ) + sizeof( buffer_ ) );
    };

    virtual ~IStreamBuf()
    {
        sync();
    };

protected:
    traits_type::int_type FlushBuffer()
    {
        int bytes = std::min< int >( pptr() - pbase(), sizeof( buffer_ ) );

        DWORD written = 0;
        HRESULT hr = stream_->Write( &buffer_, bytes, &written );
        if( FAILED( hr ) )
        {
            return traits_type::eof();
        }

        pbump( -bytes );
        return bytes;
    };

    virtual int sync()
    {
        if( FlushBuffer() == traits_type::eof() )
            return -1;
        return 0;
    };

    traits_type::int_type overflow( traits_type::int_type ch )
    {
        if( FlushBuffer() == traits_type::eof() )
            return traits_type::eof();

        if( ch != traits_type::eof() )
        {
            *pptr() = ch;
            pbump( 1 );
        }

        return ch;
    };

private:
    /// data queued up to be sent
    T buffer_;

    /// output stream
    IStream* stream_;
}; // class IStreamBuf

Yes, the code compiles and seems to work, but I've not had the pleasure of implementing a std::streambuf before. So, I'd just like to know if it's correct and complete.

Thanks, PaulH