Hi,
I visited the page, thanks for the hint. You are right, this is exactly
what I need, even thought its a much more complicate solution than I hoped
to find. Unfortunatly the cited code does not compile on my platform
(Visual C++ .Net 2003), but I try to contact Dietmar Kuehl for a workaround.
Apologies, the code it very out of date and needs fixing for standard
streams. Here's the (hopefully) fixed code (sorry about the annoying
word wrap and tabs):
#ifndef _PRFXSTREAM_H_
#define _PRFXSTREAM_H_
// </PRE>
//----------------------------------------------------------------------------
#include <streambuf>
#include <ios>
#include <ostream>
#include <istream>
#include <vector>
// </PRE>
class prfxbuf: public std::streambuf
{
private:
std::streambuf *i_sbuf; // the actual streambuf used
to read and write chars
unsigned int i_len; // the
length of the prefix
char *i_prfx; // the
prefix
bool i_newline; //
remember whether we are at a new line
int i_cache; // may
cache a read character
std::vector<char> i_buf;
bool skip_prefix();
protected:
int overflow(int);
int underflow();
int uflow();
int sync();
public:
prfxbuf(std::streambuf *sb, const char *prfx);
~prfxbuf();
};
class iprfxstream: public std::istream
{
public:
iprfxstream(std::streambuf *sb, const char *prfx);
~iprfxstream();
};
class oprfxstream: public std:

stream
{
public:
oprfxstream(std::streambuf *sb, const char *prfx);
~oprfxstream();
};
#endif /* _PRFXSTREAM_H_ */
#include <cstring>
#include <vector>
//#include "prfxstream.h"
// </PRE>
//----------------------------------------------------------------------------
// The constructor of the prfxbuf initializes its pointer to the
streambuf
// with the argument sb: It is assumed that this streambuf is
initialized
// correctly. In addition no ownership is assumed for this streambuf.
It
// is not deleted in the destructor. Then the length of the prefix
string
// is cached and the prefix string is copied into a private version:
This
// is done to avoid problems when the user modifies or deletes the
string
// passed as constructor argument. The member i_newline is set to
indicate
// that the processing it at the beginning of a new line: in either
case
// (reading or writing) it starts with a new line. When reading a file
a
// prefix has to be skipped and when writing a file a prefix has to be
// added. EOF is used to indicate that the cache does not contain any
// valid character.
// <BR>
// In the body of the constructor the put area and the get area are
// initialized to be empty: no buffering is done by this streambuf.
All
// buffering is deferred to the actually used streambuf. This makes
sure
// that the function overflow() is called whenever a character is
written
// to this streambuf and that the function underflow() is called
whenever
// a character is read from this streambuf. The put buffer is
specified
// using streambuf::setp() and the get buffer is specified using
// streambuf::setg().
// <PRE>
prfxbuf:

rfxbuf(std::streambuf *sb, const char *prfx):
std::streambuf(),
i_sbuf(sb),
i_len(std::strlen(prfx)),
i_prfx(std::strcpy(new char[i_len + 1], prfx)),
i_newline(true),
i_cache(EOF),
i_buf(i_len)
{
setp(0, 0);
setg(0, 0, 0);
}
// </PRE>
// The destructor of prfxbuf has to release the copy of the prefix.
// <PRE>
prfxbuf::~prfxbuf()
{
delete[] i_prfx;
}
bool prfxbuf::skip_prefix()
{
if (i_sbuf->sgetn(&i_buf[0], i_len) != i_len)
return false;
if (std::strncmp(&i_buf[0], i_prfx, i_len))
{
// an expection could be thrown here...
return false;
}
i_newline = false;
return true;
}
int prfxbuf::underflow()
{
if (i_cache == EOF)
{
if (i_newline)
if (!skip_prefix())
return EOF;
i_cache = i_sbuf->sbumpc();
if (i_cache == traits_type::to_int_type('\n'))
i_newline = true;
return i_cache;
}
else
return i_cache;
}
int prfxbuf::uflow()
{
if (i_cache == EOF)
{
if (i_newline)
if (!skip_prefix())
return EOF;
int rc = i_sbuf->sbumpc();
if (rc == traits_type::to_int_type('\n'))
i_newline = true;
return rc;
}
else
{
int rc = i_cache;
i_cache = EOF;
return rc;
}
}
int prfxbuf:

verflow(int c)
{
if (c != EOF)
{
if (i_newline)
if (i_sbuf->sputn(i_prfx, i_len) != i_len)
return EOF;
else
i_newline = false;
char cc = traits_type::to_char_type(c);
int rc = i_sbuf->sputc(cc);
if (cc == '\n')
i_newline = true;
return rc;
}
return 0;
}
int prfxbuf::sync()
{
return i_sbuf->pubsync();
}
iprfxstream::iprfxstream(std::streambuf *sb, const char *prfx):
std::istream(new prfxbuf(sb, prfx))
{
}
oprfxstream:

prfxstream(std::streambuf *sb, const char *prfx):
std:

stream(new prfxbuf(sb, prfx))
{
}
iprfxstream::~iprfxstream()
{
delete rdbuf();
}
oprfxstream::~oprfxstream()
{
delete rdbuf();
}
// </PRE>
//----------------------------------------------------------------------------
// <HR>
// Please send comments, suggestions, problem reports, bug fixes etc.
to
// <BR>
// <A HREF="
http://www.informatik.uni-konstanz.de/~kuehl"><I>Dietmar
Kühl</I></A>:
// <A
HREF="mailto:
[email protected]">
[email protected]</A>
// </BODY>
// </HTML>
//test code
#include <iostream>
int main()
{
oprfxstream mystream(std::cout.rdbuf(), "Test prefix: ");
mystream << "This should have been prefixed.\nAlong with this.";
mystream << "\n" << 10 << '\n';
mystream.flush();
}