stream switch

  • Thread starter Gabriel Schreiber
  • Start date
G

Gabriel Schreiber

Hy

I need some help on this problem:

I want to send some output to a number of streams. So I need an object,
that behaves (or is) like an std::eek:stream. (additional wish: the object
is an ostream or derived from an ostream.) And I need the data you give
to the ostream-like object to be written to a varying number of
ostreams.

Is it possible to do this with some magic with the streambuffers, or do
I have to write my own class?

TIA
Gabriel

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Gabriel Akira Schreiber /"\
(e-mail address removed) \ / ASCII Ribbon Campaign
X against HTML eMail &
/ \ gratuitous graphics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Wenn sie dich dazu bringen, falsche Fragen zu stellen,
müssen sie sich um die Antworten keine Sorgen machen.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
T

tom_usenet

Hy =


I need some help on this problem:

I want to send some output to a number of streams. So I need an object,
that behaves (or is) like an std::eek:stream. (additional wish: the object
is an ostream or derived from an ostream.) And I need the data you give
to the ostream-like object to be written to a varying number of
ostreams.

Is it possible to do this with some magic with the streambuffers, or do
I have to write my own class?

You need some magic streambufs. The heiroglyphics come from templating
it on character and traits type - without the template stuff (e.g.
char only) it is much simpler.

Obviously you can easily add more control over the list of buffers
(even expose the vector member) if required.

Tom


#include <streambuf>
#include <vector>

template <class CharT, class Traits = std::char_traits<CharT> >
class basic_multioutputbuf: public std::basic_streambuf<CharT, Traits>
{

public:
typedef std::basic_streambuf<CharT, Traits> streambuf_t;
typedef CharT char_type;
typedef Traits traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::eek:ff_type off_type;

void add_buf(streambuf_t* buf)
{
m_bufs.push_back(buf);
}

protected:

int_type overflow(int_type c)
{
int_type result = traits_type::not_eof(c);
if (traits_type::eq_int_type(traits_type::eof(), c))
{
return result;
}
char_type cc = traits_type::to_char_type(c);
for (vector_t::iterator i = m_bufs.begin(), end = m_bufs.end();
i != end; ++i)
{
int_type example = (*i)->sputc(cc);
if (traits_type::eq_int_type(traits_type::eof(), example))
{
result = traits_type::eof();
}
}
return result;
}

int sync()
{
int result = 0;
for (vector_t::iterator i = m_bufs.begin(), end = m_bufs.end();
i != end; ++i)
{
int example = (*i)->pubsync();
if (example == -1)
{
result = -1;
}
}
return result;
}

private:
typedef std::vector<std::streambuf*> vector_t;
vector_t m_bufs;
};

template <class CharT, class Traits = std::char_traits<CharT> >
class basic_multioutputostream: public std::basic_ostream<CharT,
Traits>
{
public:
basic_multioutputostream()
:std::basic_ostream<CharT, Traits>(0)
{
this->rdbuf(&m_streambuf);
this->clear();
//that was all in case the ostream constructor
//does anything odd with the streambuf argument.
//The "this" bit was to make the names dependent.
}

void add(std::basic_streambuf<CharT, Traits>* buf)
{
m_streambuf.add_buf(buf);
}

void add(std::basic_ostream<CharT, Traits>& os)
{
m_streambuf.add_buf(os.rdbuf());
}

private:
basic_multioutputbuf<CharT, Traits> m_streambuf;
};

typedef basic_multioutputbuf<char> multioutputbuf;
typedef basic_multioutputbuf<wchar_t> wmultioutputbuf;
typedef basic_multioutputostream<char> multioutputostream;
typedef basic_multioutputostream<wchar_t> wmultioutputostream;

#include <iostream>
#include <fstream>

int main()
{
std::eek:fstream ofs1("Test1.txt");
std::eek:fstream ofs2("Test2.txt");
multioutputostream os;
os.add(std::cout);
os.add(ofs1);
os.add(ofs2);

os << "This should go all over the place!\n";
os << std::flush << "That was a quick flush test.\n";
}
 
G

Gabriel Schreiber

tom_usenet said:
You need some magic streambufs. The heiroglyphics come from templating
it on character and traits type - without the template stuff (e.g.
char only) it is much simpler.

Obviously you can easily add more control over the list of buffers
(even expose the vector member) if required.

Tom

Tanx very much, Tom. This is exactly was I was thinking of...
The templates do not make me headaches, but not knowing how a
streambuffer really works somehow slowed the process of understanding
the code down. Is that part of any library?

Sincerely
Gabriel

// code starts here
 
T

tom_usenet

Tanx very much, Tom. This is exactly was I was thinking of...
The templates do not make me headaches, but not knowing how a
streambuffer really works somehow slowed the process of understanding
the code down. Is that part of any library?

Sorry, not that I know of (I just wrote it off the top of my head).
Such a thing (with buffering, etc. added) should probably be part of
boost (www.boost.org).

Tom
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top