473,725 Members | 1,942 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Extend streams in C++

I would like to extend the functionality of all streams in C++ so I
can do some fancy stuff like redirecting the streams on the fly.

I don't want to reimplement the whole stream support in C++ and I
would like to keep as much as possible that is already existing.

However, the only thing that my user would like to see is the
following

#include "myiostream.hpp "

int main() {
my::cout << "Hello World" << std::endl;
}

cout will redirect anything from files to sockets and this redirection
will be handled by a runtime system without used intervention.

My first attempt was to extend ostream and istream and reimplement
some of the functions. But clearly it isn't what I'm looking for,
since I have also to reimplement all other functions such as endl().

I think the way to go is to reimplement basic_streambuf and filebuf.

Am I in the right direction or should I start from lower layers
(ios_base) ? Note that I do not want to remove the support for
whatever currently exists.

Thanks

Jan 13 '08 #1
6 2796
On Jan 12, 9:25 pm, Ioannis Papadopoulos
<giannis.papado pou...@gmail.co mwrote:
I would like to extend the functionality of all streams in C++ so I
can do some fancy stuff like redirecting the streams on the fly.

I don't want to reimplement the whole stream support in C++ and I
would like to keep as much as possible that is already existing.

However, the only thing that my user would like to see is the
following

#include "myiostream.hpp "

int main() {
my::cout << "Hello World" << std::endl;

}

cout will redirect anything from files to sockets and this redirection
will be handled by a runtime system without used intervention.

My first attempt was to extend ostream and istream and reimplement
some of the functions. But clearly it isn't what I'm looking for,
since I have also to reimplement all other functions such as endl().

I think the way to go is to reimplement basic_streambuf and filebuf.

Am I in the right direction or should I start from lower layers
(ios_base) ? Note that I do not want to remove the support for
whatever currently exists.

Thanks
Perhaps you are looking at the wrong end of the stick.
The problem with the design suggested above is that you'ld have to
define op<< and op>anyways.

Instead of reinventing the wheel, why not provide insertion and
extraction operators for your classes.
You could then stream its contents to standard output, a filestream,
etc, etc. Now imagine its a socket: same basic principle. You could
provide member operators too (make them part of the interface).

This is a silly example but it should give you a few ideas.

#include <iostream>
#include <ostream>
#include <fstream>
#include <string>

template < typename T >
class Concrete
{
T m_t;
public:
Concrete(const T& t) : m_t(t) { }
// member op<<
void operator<<(cons t T& t)
{
m_t += t;
}
// friend op<<
friend std::ostream&
operator<<(std: :ostream& os, const Concrete& c)
{
os << c.m_t;
return os;
}
};

int main()
{
Concrete<std::s tringinstance(" a short string");
std::cout << instance << std::endl;

std::string sfile("data.txt ");
std::ofstream ofs(sfile.c_str ());
if(!ofs)
{
std::cout << "failed to open file: ";
std::cout << sfile << std::endl;
return EXIT_FAILURE;
}
instance << " now got longer"; // inject
ofs << instance << std::endl;
}

/*
a short string
*/

/* data.txt
a short string now got longer
*/
Jan 13 '08 #2
On Jan 13, 3:25 am, Ioannis Papadopoulos
<giannis.papado pou...@gmail.co mwrote:
I would like to extend the functionality of all streams in C++ so I
can do some fancy stuff like redirecting the streams on the fly.
I don't want to reimplement the whole stream support in C++ and I
would like to keep as much as possible that is already existing.
However, the only thing that my user would like to see is the
following
#include "myiostream.hpp "
int main() {
my::cout << "Hello World" << std::endl;
}
cout will redirect anything from files to sockets and this
redirection will be handled by a runtime system without used
intervention.
My first attempt was to extend ostream and istream and reimplement
some of the functions. But clearly it isn't what I'm looking for,
since I have also to reimplement all other functions such as endl().
I think the way to go is to reimplement basic_streambuf and filebuf.
Am I in the right direction or should I start from lower layers
(ios_base) ?
Definitely not. Iostream's are carefully designed and have very
good separation of concerns. Sourcing and sinking are done in
the streambuf, using the strategy pattern. All you have to do
is arrange for your custom streambuf to replace the one
std::cout is using, something like:

std::cout.rdbuf ( &myCustomStream buf ) ;

From then on, all output to std::cout will be directed to
myCustomStreamb uf, rather than to what it was before. (To avoid
any risk of undefined behavior, you should probably save the
original streambuf, and restore it before program termination.)

Whether this is a good idea or not is another question.
Generally, if a programmer outputs to std::cout, he has very
good reasons for doing so, and "redirectin g" his output is doing
him a disfavor. Such a trick might be useful, however, if you
have to deal with poorly written legacy code, which uses
std::cout when it should have used an std::ostream& passed in to
it.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jan 13 '08 #3
On Jan 13, 6:58 am, Salt_Peter <pj_h...@yahoo. comwrote:
On Jan 12, 9:25 pm, Ioannis Papadopoulos
[...]
Instead of reinventing the wheel, why not provide insertion and
extraction operators for your classes.
That addresses a different problem, and is a good reason why he
shouldn't try to replace istream and ostream---he'd have to
reimplement all of these insertion and extraction operators as
well. (There are cases where it is reasonable to wrap the
istream or the ostream; in such cases, the wrapper code uses
templates to recover the original << and >operators and use
them.)

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jan 13 '08 #4
On 13 Ιαν, 04:31, James Kanze <james.ka...@gm ail.comwrote:
On Jan 13, 3:25 am, Ioannis Papadopoulos

<giannis.papado pou...@gmail.co mwrote:
I would like to extend the functionality of all streams in C++ so I
can do some fancy stuff like redirecting the streams on the fly.
I don't want to reimplement the whole stream support in C++ and I
would like to keep as much as possible that is already existing.
However, the only thing that my user would like to see is the
following
#include "myiostream.hpp "
int main() {
my::cout << "Hello World" << std::endl;
}
cout will redirect anything from files to sockets and this
redirection will be handled by a runtime system without used
intervention.
My first attempt was to extend ostream and istream and reimplement
some of the functions. But clearly it isn't what I'm looking for,
since I have also to reimplement all other functions such as endl().
I think the way to go is to reimplement basic_streambuf and filebuf.
Am I in the right direction or should I start from lower layers
(ios_base) ?

Definitely not. Iostream's are carefully designed and have very
good separation of concerns. Sourcing and sinking are done in
the streambuf, using the strategy pattern. All you have to do
is arrange for your custom streambuf to replace the one
std::cout is using, something like:

std::cout.rdbuf ( &myCustomStream buf ) ;

From then on, all output to std::cout will be directed to
myCustomStreamb uf, rather than to what it was before. (To avoid
any risk of undefined behavior, you should probably save the
original streambuf, and restore it before program termination.)

Whether this is a good idea or not is another question.
Generally, if a programmer outputs to std::cout, he has very
good reasons for doing so, and "redirectin g" his output is doing
him a disfavor. Such a trick might be useful, however, if you
have to deal with poorly written legacy code, which uses
std::cout when it should have used an std::ostream& passed in to
it.

--
James Kanze (GABI Software) email:james.ka. ..@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 0034
I'm not talking about actually changing where std::cout directs
whatever it's written into it. I want my::cout and this will be
handled by a runtime system. The user should be able to use std::cout
as before and expect the same behavior. However, the behavior of
my::cout will be whatever the runtime wants.

I want to make my::cout as interoperable with current functions and
classes as possible - that is I don't want my user to implement any
new >and << operators for his/her classes.

Jan 14 '08 #5
In article <6de450ee-01bf-4ccf-895b-
b3**********@m7 7g2000hsc.googl egroups.com>,
gi************* *****@gmail.com says...

[ ... ]
I'm not talking about actually changing where std::cout directs
whatever it's written into it. I want my::cout and this will be
handled by a runtime system. The user should be able to use std::cout
as before and expect the same behavior. However, the behavior of
my::cout will be whatever the runtime wants.

I want to make my::cout as interoperable with current functions and
classes as possible - that is I don't want my user to implement any
new >and << operators for his/her classes.
You've told us one part of what you want: to allow the user's insertion
and extraction operators to work with your stream object(s).

The only other thing you've said is:
cout will redirect anything from files to sockets and this redirection
will be handled by a runtime system without used intervention.
To make this work, you'll probably have to do what James has advised
against (i.e. create your own stream class) as well as creating your own
socket-based stream buffer class. Making it happen entirely
transparently may be a bit difficult though. When you you write to a
file, you normally only need to supply the name of the file, and then
you can put data into it. Writing to a socket requires a bit more
information: the name/address of the server, the type of protocol to use
(e.g. TCP vs. UDP) and the socket number to write to (and possibly a few
more things specifying such things as timeouts and such).

You _could_ create a buffer object specifying all that, then attach it
to an object of one of the existing stream classes, but if you're using
it much, you probably want a new stream class that allows you to specify
all that and pass it through when it creates the buffer object.

There are quite a few existing samples of how to do this. One that's
relatively small and simple is Socket++, available from:

http://www.cs.utexas.edu/users/laven...rses/socket++/

Another that's well known is ACE, though it's far from small or simple.
Available from:

http://www.cs.wustl.edu/~schmidt/ACE.html

If you want something to download and use as-is, ACE may be a better
choice as it's in current development (whereas Socket++ doesn't seem to
have been touched in years, though that may just be because it's fine
the way it is). If you just want some guidance as to the basics of how
to do the job, Socket++ is probably better due to its smaller size and
relative simplicity.

One last note: I've used things like this a few times, and while they
initially seem like a great idea, they haven't worked out very well in
the long run, at least for me. For building simple clients they aren't
too bad, but for servers (especially) they're pretty close to useless.

The problem is that streams are built around the idea that you decide
when to read or write a stream. A server mostly doesn't have that luxury
-- rather, it waits for a client, and then reacts to the client's
request. That said, some people have built some fairly serious systems
on top of ACE (for one example) so it's clearly workable even though I'm
not sure it's the ideal model for the job. Then again, ACE provides a
LOT of other stuff, and I suspect quite a bit of what's really used is
that other stuff...

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jan 14 '08 #6
On Jan 14, 7:26 am, Jerry Coffin <jcof...@taeus. comwrote:
In article <6de450ee-01bf-4ccf-895b-
b34c0cebc...@m7 7g2000hsc.googl egroups.com>,
giannis.papadop ou...@gmail.com says...
[ ... ]
I'm not talking about actually changing where std::cout directs
whatever it's written into it. I want my::cout and this will be
handled by a runtime system. The user should be able to use std::cout
as before and expect the same behavior. However, the behavior of
my::cout will be whatever the runtime wants.
I want to make my::cout as interoperable with current functions and
classes as possible - that is I don't want my user to implement any
new >and << operators for his/her classes.
You've told us one part of what you want: to allow the user's insertion
and extraction operators to work with your stream object(s).
The only other thing you've said is:
cout will redirect anything from files to sockets and this redirection
will be handled by a runtime system without used intervention.
To make this work, you'll probably have to do what James has advised
against (i.e. create your own stream class) as well as creating your own
socket-based stream buffer class.
Not at all:

namespace my
{
std::ostream cout( (getDesiredStre ambuf()) ) ;
}

About the only reason to create a new ostream class would be to
provide convenience initializers, so that the user can create an
ostream using your streambuf in a single declaration (along the
lines of ofstream).
Making it happen entirely transparently may be a bit difficult
though. When you you write to a file, you normally only need
to supply the name of the file, and then you can put data into
it. Writing to a socket requires a bit more information: the
name/address of the server, the type of protocol to use (e.g.
TCP vs. UDP) and the socket number to write to (and possibly a
few more things specifying such things as timeouts and such).
Actually, it wouldn't be too difficult if an implementation of
filebuf recognizeds URL's. (At one point I experimented with
one which would create a separate process, and read or write to
a pipe connected to the process, if the filename started with a
"!". So you could do things like:
std::ifstream input( "! gunzip < gzippedData.gz" ) ;
. I don't think handling URL's would be much more difficult,
conceptually.)
You _could_ create a buffer object specifying all that, then
attach it to an object of one of the existing stream classes,
but if you're using it much, you probably want a new stream
class that allows you to specify all that and pass it through
when it creates the buffer object.
There are quite a few existing samples of how to do this. One that's
relatively small and simple is Socket++, available from:
http://www.cs.utexas.edu/users/laven...rses/socket++/
Another that's well known is ACE, though it's far from small or simple.
Available from:
http://www.cs.wustl.edu/~schmidt/ACE.html
If you want something to download and use as-is, ACE may be a better
choice as it's in current development (whereas Socket++ doesn't seem to
have been touched in years, though that may just be because it's fine
the way it is). If you just want some guidance as to the basics of how
to do the job, Socket++ is probably better due to its smaller size and
relative simplicity.
One last note: I've used things like this a few times, and while they
initially seem like a great idea, they haven't worked out very well in
the long run, at least for me. For building simple clients they aren't
too bad, but for servers (especially) they're pretty close to useless.
The problem is that streams are built around the idea that you
decide when to read or write a stream. A server mostly doesn't
have that luxury -- rather, it waits for a client, and then
reacts to the client's request.
Typically, the server has two different levels: in the main
thread, it "accepts", with no streams involved. Once it has a
TCP connection, however, the input can often be read as a
stream, at least if each connection is handled in a separate
thread. It input has to be active while processing previous
input (not necessary in a lot of protocols), then you just spawn
another thread for the processing, and you're still OK.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jan 14 '08 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
2959
by: Ronald Legere | last post by:
The new itertools stuff is pretty cool. One thing that bothers me though is that there seems to be no way to copy an iterator. How does one work around this? Is there a trick that I am missing? Without being able to 'split' an iterator, I can't think of how to do some of the cool things you can do with lazy lists in Haskell. It seems quite often you want to be able to do this 'splitting', and if I
3
3495
by: Tron Thomas | last post by:
What does binary mode for an ofstream object do anyway? Despite which mode the stream uses, operator << writes numeric value as their ASCII representation. I read on the Internet that it is possible to change the behavior of operator << so it will stream numeric values as their actual values when an ofstream is in binary mode. I did not, however, find any information on how this can be accomplished. What is involved in getting this...
8
2732
by: bonj | last post by:
hello I hope somebody can help me get my head around this area of 'stream' programming... I know that streams are very fashionable nowadays so hopefully there'll be lots of replies. ;-) Basically I have an operation which the input and output for are streams - a function which receives a certain 'chunk' of data each time it runs, and it runs many times until it has received all the data, in a similar way to a socket. What the...
11
1799
by: Kobu | last post by:
I have a question about C's abstract "streams" (that I can't seem to FULLY understand from reading several tutorials). Streams seems to suggest that input can be treated continously if needed. Is this true? So far as I know, I can only get a stream to "flow" when there is a '\r'. At that point the '\r' is turned into a '\n' and the whole stream is sent to some abstract area that is now only accessible to my programs (meanwhile, other...
2
1783
by: Peter Rilling | last post by:
One nice thing about collections and arrays is that they implement the IEnumerator and IEnumerable interfaces which allow for more then one iterator to walk the list of items without affecting the position of the other iterators. Is there a similar thing with streams? Is there anything in the framework that wraps a stream in such a way that the stream position is decoupled from the stream itself?
2
4031
by: bonk | last post by:
Hello how do I connect streams in c# ? Imagine the followung scenario: I have a StreamWriter that writes Text to a Stream. How can I tell that Stream to pass that Data to another Stream (connect it to another output Stream) ? In java I am used to connect streams to each other via thier Constructors. For example: new BufferedWriter(new OutputStreamWriter(new FileOutputStream("soc.txt"),
1
2424
by: Chris | last post by:
I'm reading up on streams and I have two articles that seem to conflict with each other. One article describes streams and lists a few of the major ones (FileStream, Memory Stream, Network Stream, etc.). It then goes on to discuss the restriction that streams only read bytes or byte arrays that the .net framework provides a StreamReader and StreamWriter class to do type conversions to and from bytes when using streams. The second...
2
2848
by: Abhishek | last post by:
what are the STDUPDATE, STDERR, STDOUT and STDIN streams and how does one access these streams in C language. I am aware of the function fprintf(FILE *fp, char * format, char *s) which puts the string into the corresponding streams. But can you please tellme where does the content go exactly when we put it into the above streams. In which cases can we see the outpt and in which cases cant we see and why so? It would be great if you can...
3
3583
by: jacobstr | last post by:
I've noticed Object.extend used in a few different ways and I'm having trouble distinguishing why certain usages apply to a given situation. On line 804 Ajax.Base is defined as follows: Ajax.Base = function() {}; Ajax.Base.prototype = { setOptions: function(options) { <...>
0
8888
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8752
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9257
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9174
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9111
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
4517
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4782
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2634
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2157
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.