std::ostream manipulator

B

Boris

Is it possible to manipulate the std::eek:stream to prepend a string when
performing output, e.g.

// manipute std::cout to prepend "prefix "
std::cout << "hallo" << std::endl;
// results in "prefix hallo"

I need this to overwrite the "<<" operator for MyClass in a recursive
way, e.g.

std::eek:stream&
operator<<( std::eek:stream& stream, MyClass const& myClass )
{
// do some output
// prepend '\t' to stream, how?
stream << myClass.member_ << '\n'; // recursive call of << operator
// remove prefix '\t' from stream
return stream;
}

when MyClass has a pointer to another MyClass as a member
(MyClass const* member_). I like to prepend tabs when streaming the
members without saving the prefixes in MyClass.

Thanks,

Boris
 
B

Bob Smith

Boris said:
Is it possible to manipulate the std::eek:stream to prepend a string when
performing output, e.g.

// manipute std::cout to prepend "prefix "
std::cout << "hallo" << std::endl;
// results in "prefix hallo"

I need this to overwrite the "<<" operator for MyClass in a recursive
way, e.g.

std::eek:stream&
operator<<( std::eek:stream& stream, MyClass const& myClass )
{
// do some output
// prepend '\t' to stream, how?
stream << myClass.member_ << '\n'; // recursive call of << operator
// remove prefix '\t' from stream
return stream;
}

do you mean simply:
strstream s;
s << "prepended:" << myClass.member_;
stream << s;
-..
or maybe stream << s.str(),

????
/B
 
T

tom_usenet

Is it possible to manipulate the std::eek:stream to prepend a string when
performing output, e.g.

// manipute std::cout to prepend "prefix "
std::cout << "hallo" << std::endl;
// results in "prefix hallo"

I need this to overwrite the "<<" operator for MyClass in a recursive
way, e.g.

std::eek:stream&
operator<<( std::eek:stream& stream, MyClass const& myClass )
{
// do some output
// prepend '\t' to stream, how?
stream << myClass.member_ << '\n'; // recursive call of << operator
// remove prefix '\t' from stream
return stream;
}

when MyClass has a pointer to another MyClass as a member
(MyClass const* member_). I like to prepend tabs when streaming the
members without saving the prefixes in MyClass.

It's unclear from this whether you need a prefix for each line or
something else. For the former you need the prefix_buf. See the prefix
stuff under IOStreams here:
http://www.informatik.uni-konstanz.de/~kuehl/

Tom
 
B

Boris

Bob Smith said:
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.

Thanks,
Boris
 
G

Guest

Is it possible to manipulate the std::eek:stream to prepend a string when
performing output, e.g.

// manipute std::cout to prepend "prefix "
std::cout << "hallo" << std::endl;
// results in "prefix hallo"

I need this to overwrite the "<<" operator for MyClass in a recursive
way, e.g.

std::eek:stream& operator<<( std::eek:stream& stream, MyClass const& myClass )
{
// do some output
// prepend '\t' to stream, how?
stream << myClass.member_ << '\n'; // recursive call of << operator
// remove prefix '\t' from stream return stream;
}

when MyClass has a pointer to another MyClass as a member
(MyClass const* member_). I like to prepend tabs when streaming the
members without saving the prefixes in MyClass.

Thanks,

Boris

I am not sure what you are trying to do here.
If you want a table like output ( tab may do it ) then you just have to
set the
width of next output field by calling,
os.width(...) or os << setw(...)

If you want the tabs to accumulate then you should create an object that
would accumulate the tabs with the << operator to send it to ostream.
Inserting such code to the ostream class seems unnecessery.
 
B

Boris

Hi,
thanks for your answer.
I am not sure what you are trying to do here.
If you want a table like output ( tab may do it ) then you just have to
set the
width of next output field by calling,
os.width(...) or os << setw(...)

I like to do proper indentation for multiline output of
nested data structures.
If you want the tabs to accumulate then you should create an object that
would accumulate the tabs with the << operator to send it to ostream.

Maybe you are right, that seams to be the simplest solution.
Inserting such code to the ostream class seems unnecessery.

Do you think so? You can do nice formating of floating point numbers
with
std::cout << std::scientific for example. Now the formating behaviour
of the stream changes for all succeeding floating point output. I
would appreciate a similar mechanism for strings and prefixes.

Regards,
Boris
 
B

Boris

tom_usenet said:
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.

Regards,
Boris
 
T

tom_usenet

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::eek: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::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::eek: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::eek:prfxstream(std::streambuf *sb, const char *prfx):
std::eek: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();
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top