std :: ostream接口到OLE IStream

时间:2010-05-21 20:16:30

标签: c++ istream streambuf

我有一个使用IStream的Visual Studio 2008 C ++应用程序。我想在std::ostream中使用IStream连接。像这样:

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

1 个答案:

答案 0 :(得分:0)

我的建议是使用Boost.IOStreams Device来包装IStream。它照顾了所有C ++ IO流的内容,因此您不必这样做。