On 16 Oct 2003 07:16:23 -0700,
go***@nexgo.de (Boris) wrote:
tom_usenet <to********@hotmail.com> wrote in message news:<m8********************************@4ax.com>. .. On 15 Oct 2003 09:00:51 -0700, go***@nexgo.de (Boris) wrote:
>Bob Smith <bo******@jippii.fi> wrote in message news:<3F**************@jippii.fi>...
>>
>> do you mean simply:
>> strstream s;
>> s << "prepended:" << myClass.member_;
>> stream << s;
>> -..
>> or maybe stream << s.str(),
>>
>
>Hi,
>streaming MyClass is a multiline message, I need the prefix for each line.
>Your solution prepends only a prefix for the first line.
In that case, the prefix stream at this site does *exactly* what you
want. There's no other good way to do it within the iostreams
heirarchy.
http://www.informatik.uni-konstanz.de/~kuehl/
Tom
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::ostream
{
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::prfxbuf(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::overflow(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::oprfxstream(std::streambuf *sb, const char *prfx):
std::ostream(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:di***********@claas-solutions.de">Di***********@claas-solutions.de</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();
}