Интерфейс std :: ostream для OLE IStream - PullRequest
2 голосов
/ 22 мая 2010

У меня есть приложение Visual Studio 2008 C ++, использующее IStream s. Я хотел бы использовать соединение IStream в std::ostream. Примерно так:

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;

Для этого я реализовал следующий код:

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

Да, код компилируется и, кажется, работает, но я не имел удовольствия реализовать std::streambuf раньше. Итак, я просто хотел бы знать, если это правильно и полно.

Спасибо, PaulH

...