Friday 6 February 2009

Logging

It's often useful to use logging messages or error messages in case something abnormal happens. Or just for fun. A useful trick is to send them straight to the visual studio output window. Using a small amount of code we can even override std::cout and std::cerr which is pretty cool. I'm just going to dive straight into some code:

class logbuf : public std::streambuf
{
public:
    virtual std::streamsize xsputn( const char *s, std::streamsize n )
    {
        // Output to visual studio output window
        OutputDebugStringW(widen(s).c_str());
        return n;
    }
    virtual int overflow(int c = EOF)
    {
        if(c != EOF) OutputDebugString(widen(std::string(1, c)).c_str());
        return 1;
    }
private:
    int indent_;
    char last_;
};
int main(int argc, const char* argv[])
{
    // Create the new stream to redirect cout and cerr output to vs.
    logbuf merr;
    std::ostream out(&merr);

    // Smart class that will swap streambufs and replace them
    // when object goes out of scope.
    class StreamBuf_Swapper
    {
    public:
        StreamBuf_Swapper( std::ostream& orig, std::ostream& replacement )
            : buf_(orig.rdbuf()), str_(orig)
        { orig.rdbuf( replacement.rdbuf() ); }
        ~StreamBuf_Swapper() { str_.rdbuf( buf_ ); }
    private:
        std::streambuf* buf_;
        std::ostream& str_;
    } cerrswap(std::cerr, out), coutswap(std::cout, out);

    try
    {
        // ... Lots of code
    }
    catch( const std::exception& e )
    {
        std::cerr << e.what();
    }

    return 0;
}

This code takes the streambuf associated with cout and cerr and simply swaps it with a streambuf derived class (vsstream) that prints anything to the visual studio output window. Simple and useful. One other thing to note is that if the output window contains a line formatted:

<filename>(<line number>) : <message>

then it will automatically display that file and line in the editor when double clicked. A few more things you could do with it would be to log errors to a file as well or maybe have something differentiate between normal log messages and error messages (in fact, I'll probably have to do this at some point).

No comments:

Post a Comment