Redirecting cout to a callback function

One time or another during a lifetime it’s necessary to redirect cout or another stream to a callback function… I havn’t had the need for it yet, but I was asked if it was possible and here’s my answer:

#include <streambuf>
#include <iostream>
#include <ostream>    

template <class Elem = char, class Tr = std::char_traits<Elem> >
class callbackstream : public std::basic_streambuf<Elem, Tr>
{
    typedef void (*pfncb)(const Elem *, std::streamsize _Count);    

private:
    std::basic_ostream<Elem, Tr>  &m_stream;
    std::streambuf                *m_buf;
    pfncb                         m_cb;    

public:
    callbackstream(std::ostream &stream, pfncb cb)
        : m_stream(stream), m_cb(cb)
    {
        // redirect stream
        m_buf = m_stream.rdbuf(this);
    };    

    ~callbackstream()
    {
        // restore stream
        m_stream.rdbuf(m_buf);
    }    

    // override xsputn and make it forward data to the callback function
    std::streamsize xsputn(const Elem *_Ptr, std::streamsize _Count)
    {
        m_cb(_Ptr, _Count);
        return _Count;
    }
    // override overflow and make it forward data to the callback function
    typename Tr::int_type overflow(typename Tr::int_type v)
    {
        Elem ch = Tr::to_char_type(v);
        m_cb(&ch, 1);
        return Tr::not_eof(v);
    }
};

Now, to use this class:

void mycallback(const char *ptr, std::streamsize count)
{
    // handle data here...
}   

int main()
{
    //redirect std::cout to the callback function
    callbackstream<> redirect(std::cout, mycallback);   

    // this is sent to the callback function, not the console
    std::cout << "Hello" << std::endl;
    return 0;
}

Leave a comment...

Powered by WordPress. Entries (RSS) and Comments (RSS).