In a previous article entitled C++ Override std::cout, std::cerr Streams, I wrote about some sites I found regarding the redirection of cout to some user supplied routine. After some fiddling about, I came up with a result that works for me in Visual Studio 2005 version of C++.
Many of the sites suggest overriding the xsputn function. I did that in conjunction with
buffered output through the setp function. I found that the xsputn function is used for
string delivery, but the user supplied buffer is used when cout formats binary values. I
had to come up with a mechanism to sync the two. The solution was to not over-ride xsputn, only
use the setp function, and rely on overriding the sync function.
The code in the sync override isn't perfect, but it does get the job done. The code
makes use of the
fastdelegate template to issue a 'callback' to code interested in
processing the buffer on each sync. The short coming with this code is that cout inserts a
0x0a into the buffer for each endl, and so the routine accepting the buffer has to scan and
interpret the character appropriately.
By not using setp, the routine becomes unbuffered, and then xsputn becomes necessary. I havn't
tried that scenario yet.
#pragma once
#include <iostream>
using namespace std;
#include "FastDelegate.h"
using namespace fastdelegate;
class CConsoleStream : public streambuf {
public:
CConsoleStream(void);
virtual ~CConsoleStream(void);
typedef FastDelegate2<const char*, streamsize> OnNewStringHandler;
void SetOnNewString( OnNewStringHandler function ) {
OnNewString = function;
}
typedef FastDelegate0<> OnFlushStringHandler;
void SetOnFlushString( OnFlushStringHandler function ) {
OnFlushString = function;
}
protected:
OnNewStringHandler OnNewString;
OnFlushStringHandler OnFlushString;
static const unsigned short BufSize = 1024;
char buf[ BufSize ]; virtual int sync( void );
virtual int_type overflow( int_type meta );
private:
};
#include "StdAfx.h"
#include "ConsoleStream.h"
#include <stdexcept>
CConsoleStream::CConsoleStream(void) { setp( buf, buf + BufSize );
}
CConsoleStream::~CConsoleStream(void) {
}
int CConsoleStream::sync() {
if ( NULL != OnNewString ) OnNewString( pbase(), (int) ( pptr() - pbase() -
1 ) ); if ( NULL != OnFlushString ) OnFlushString();
setp( pbase(), epptr() ); return 0;
}
int CConsoleStream::overflow(int_type meta) {
throw std::runtime_error( "ConsoleStream overflow" );
}
The code was formatted with the javascript found at
C++2HTML. I see there is
GNU Source-highlight 2.8, but I
don't see a web interactive version handy.