473,387 Members | 1,864 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Sanity check output streambuf scheme?

Hello,

I posted previously under the thread:

How to break this up into streambuf/ostream

I've asked our library to get "C++ IOStreams and Locales..." by A.
Langer et al. Meantime, I've looked at the C++ standard (ISO/IEC
14882) from the web to get a grip on the relationship between ostream
methods and streambuf methods: flush(), operator<<(), sputc(),
sputn(), xsputn(), overflow(), sync(), and pubsync().

My problem is that I don't want to use a fixed size buffer in my
output streambuf derivative (mostreambuf), and I don't want the buffer
to flush automatically. I want the buffer to continue amassing data
until the user explicitly invokes ostream::flush(), possibly using
endl. This means mostreambuf will not use the pbase(), pptr(), or
epptr(). Instead, it will use a member ostringstream object "oss" to
buffer output. This way, the buffer can grow indefinitely as
required, until the user does a flush.

Before going further, I should point out that the standard does not
say anything about whether sync calls overload or vice-versa, so I
can't presume either.

My approach to realizing the above scheme is based on Josuttis's
example code in "The C++ Standard Library", as well as seeing that
flush() calls pubsync(), which calls the virtual (overloadable)
sync(). First, I set all 3 buffer pointers are set to NULL so that
sputc(c) calls overflow(), which I will overload so that c is written
to oss. Likewise, xsputn() will be overloaded to write to oss. I
will also overload sync() so that ostream::flush() causes the contents
of oss to be sent to its destination, followed by nulling oss to "".

Is this a reasonable approach?

Thanks for any feedback.

Fred
--
Fred Ma
Dept. of Electronics, Carleton University
1125 Colonel By Drive, Ottawa, Ontario
Canada, K1S 5B6
Jul 22 '05 #1
9 2685

"Fred Ma" <fm*@doe.carleton.ca> wrote in message
news:40***************@doe.carleton.ca...
Hello,

I posted previously under the thread:

How to break this up into streambuf/ostream

I've asked our library to get "C++ IOStreams and Locales..." by A.
Langer et al. Meantime, I've looked at the C++ standard (ISO/IEC
14882) from the web to get a grip on the relationship between ostream
methods and streambuf methods: flush(), operator<<(), sputc(),
sputn(), xsputn(), overflow(), sync(), and pubsync().

My problem is that I don't want to use a fixed size buffer in my
output streambuf derivative (mostreambuf), and I don't want the buffer
to flush automatically. I want the buffer to continue amassing data
until the user explicitly invokes ostream::flush(), possibly using
endl. This means mostreambuf will not use the pbase(), pptr(), or
epptr(). Instead, it will use a member ostringstream object "oss" to
buffer output. This way, the buffer can grow indefinitely as
required, until the user does a flush.

Before going further, I should point out that the standard does not
say anything about whether sync calls overload or vice-versa, so I
overflow
can't presume either.
Well it the code you write that does this, you decide if sync calls overflow
or vice versa. Normally I would do neither.

My approach to realizing the above scheme is based on Josuttis's
example code in "The C++ Standard Library", as well as seeing that
flush() calls pubsync(), which calls the virtual (overloadable)
sync(). First, I set all 3 buffer pointers are set to NULL so that
sputc(c) calls overflow(), which I will overload so that c is written
to oss. Likewise, xsputn() will be overloaded to write to oss. I
will also overload sync() so that ostream::flush() causes the contents
of oss to be sent to its destination, followed by nulling oss to "".

Is this a reasonable approach?


Seems fine to me.

john
Jul 22 '05 #2
John Harrison wrote:
Before going further, I should point out that the standard does not
say anything about whether sync calls overload or vice-versa, so I


overflow


Yes, my bad.
can't presume either.


Well it the code you write that does this, you decide if sync calls overflow
or vice versa. Normally I would do neither.


Duh. Yeah, you're right. I was thinking about the default
behaviour, but it doesn't matter in my case.
Is this a reasonable approach?


Seems fine to me.


Thanks for the sanity check, John. Time to code it up.

Fred
Jul 22 '05 #3
Fred Ma wrote:
I want the buffer to continue amassing data
until the user explicitly invokes ostream::flush(), possibly using
endl. This means mostreambuf will not use the pbase(), pptr(), or
epptr(). Instead, it will use a member ostringstream object "oss" to
buffer output. This way, the buffer can grow indefinitely as
required, until the user does a flush.


I would suggest using a std::vector or maybe std::deque for your buffer,
instead of an ostringstream. Using ostringstream requires rather a lot
of overhead for simple buffering (including construction of the stream
and buffer objects, the std::string used internally, and all the
overhead involved in the actual I/O, such as creating and destroying
sentry objects).

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #4
Kevin Goodsell wrote:
I want the buffer to continue amassing data
until the user explicitly invokes ostream::flush(), possibly using
endl. This means mostreambuf will not use the pbase(), pptr(), or
epptr(). Instead, it will use a member ostringstream object "oss" to
buffer output. This way, the buffer can grow indefinitely as
required, until the user does a flush.


I would suggest using a std::vector or maybe std::deque for your buffer,
instead of an ostringstream. Using ostringstream requires rather a lot
of overhead for simple buffering (including construction of the stream
and buffer objects, the std::string used internally, and all the
overhead involved in the actual I/O, such as creating and destroying
sentry objects).


Thanks for the cautionary note, Kevin. I'm going to hang on to
it as an additional migration step. Right now, I'm trying to
get broken code to work again, so the smaller step above would
be a bit of a godsend in the short term. I'll have to see
whether my use of the my ostream's operator<<() relies on
the characteristics of my ostringstream buffer when the data is
sent to my streambuf [I've got operator<<() code sprinkled
throughout my sprawling programing]. See how much modification
(if any) is needed to use a vector buffer instead. Probably not
much, since I now actually derive from ostream, which takes care
of the manipulators. Prior to that, I had created my own
abomination: ostream/streambuf hybrid. Before our compiler
was upgraded, it worked (probably because the manipulators were
being taken care of by the ostringstream object.

Fred
--
Fred Ma
Dept. of Electronics, Carleton University
1125 Colonel By Drive, Ottawa, Ontario
Canada, K1S 5B6
Jul 22 '05 #5
Kevin Goodsell wrote:
I want the buffer to continue amassing data
until the user explicitly invokes ostream::flush(), possibly using
endl. This means mostreambuf will not use the pbase(), pptr(), or
epptr(). Instead, it will use a member ostringstream object "oss" to
buffer output. This way, the buffer can grow indefinitely as
required, until the user does a flush.


I would suggest using a std::vector or maybe std::deque for your buffer,
instead of an ostringstream. Using ostringstream requires rather a lot
of overhead for simple buffering (including construction of the stream
and buffer objects, the std::string used internally, and all the
overhead involved in the actual I/O, such as creating and destroying
sentry objects).


So I've revamped all my ostream derivatives to use my streambuf
derivatives. Instead of using ostringstream for buffering, I'm
using a vector<char> (still debugging). Part of the debugging
led me to read up on traits for strings and streams. It's not
all clear yet, but I did find mention of reasons to use strings
rather than vector<char>, related to traits. The professed
reason was that traits encapsulate possibly platform-dependent
optimized implementations of string processing functions. So
I looked again at the the above reasoning for using vector<char>.
It seems to be one of saving memory. Am I right in concluding
that it isn't directly a speed issue to use ostringstream for
buffering, and that's only a memory issue? I will only create
these ostring objects once when the program starts.

Fred
--
Fred Ma
Dept. of Electronics, Carleton University
1125 Colonel By Drive, Ottawa, Ontario
Canada, K1S 5B6
Jul 22 '05 #6
Fred Ma wrote:

Kevin Goodsell wrote:
I want the buffer to continue amassing data
until the user explicitly invokes ostream::flush(), possibly using
endl. This means mostreambuf will not use the pbase(), pptr(), or
epptr(). Instead, it will use a member ostringstream object "oss" to
buffer output. This way, the buffer can grow indefinitely as
required, until the user does a flush.


I would suggest using a std::vector or maybe std::deque for your buffer,
instead of an ostringstream. Using ostringstream requires rather a lot
of overhead for simple buffering (including construction of the stream
and buffer objects, the std::string used internally, and all the
overhead involved in the actual I/O, such as creating and destroying
sentry objects).


I did find mention of reasons to use strings
rather than vector<char>, related to traits. The professed
reason was that traits encapsulate possibly platform-dependent
optimized implementations of string processing functions. So
I looked again at the the above reasoning for using vector<char>.
It seems to be one of saving memory. Am I right in concluding
that it isn't directly a speed issue to use ostringstream for
buffering, and that's only a memory issue? I will only create
these ostring objects once when the program starts.

I'm answering my own question (correctly, I hope). It seems like
a good way around the overhead of ostringstream as a buffer within
streambuf is to simply use a string. In contrast to a vector, this
would benefit from any platform-optimizations in string handling.

Fred
--
Fred Ma
Dept. of Electronics, Carleton University
1125 Colonel By Drive, Ottawa, Ontario
Canada, K1S 5B6
Jul 22 '05 #7
Fred Ma wrote:

So I've revamped all my ostream derivatives to use my streambuf
derivatives. Instead of using ostringstream for buffering, I'm
using a vector<char> (still debugging). Part of the debugging
led me to read up on traits for strings and streams. It's not
all clear yet, but I did find mention of reasons to use strings
rather than vector<char>, related to traits. The professed
reason was that traits encapsulate possibly platform-dependent
optimized implementations of string processing functions.
I don't see any reason that using a vector<char> would prevent you from
using traits.
So
I looked again at the the above reasoning for using vector<char>.
It seems to be one of saving memory. Am I right in concluding
that it isn't directly a speed issue to use ostringstream for
buffering, and that's only a memory issue? I will only create
these ostring objects once when the program starts.


The main issue I had in mind is speed. The job of a streambuf is to
store bytes and dump them to or read them from some other location when
appropriate. A ostringstream is a very round about way of doing this.
Essentially you are making your class a wrapper for a (rather
inefficient) wrapper for stringbuf. Every byte you write will require a
redundant call to a formatting function, which includes considerable
overhead.

Implementing a streambuf (which is the sports car of the C++ I/O world,
fast but not terribly functional) in terms of a stream (which is the van
of the C++ I/O world - it's full of all the tools that provide advanced
functionality, but it's not exactly speedy) is silly. It's like building
a sports-car-shaped shell around your van. It looks like a sports car...
sort of... but it's big and bulky, and as slow as a van. Plus, you can't
get to the parts of the van with all your tools anymore. So you've got
something that's as slow as a van (actually a bit slower due to the
extra bulk of the shell), and has the functionality of the sports car
(which is to say, not much).

Think about it. Once you're done with this, you'll be using a stream
that's implemented using a streambuf that's implemented using a stream
that's implemented using a streambuf! There's two extra steps there that
make no sense!

You could make your streambuf a direct wrapper for stringbuf. This would
make more sense, and it would be faster and probably easier to write.
Implementing a new streambuf using a vector is probably a bit more
difficult, but you get the functionality you need without a lot of extra
stuff you don't need, and it would probably be a bit faster still.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #8
Fred Ma wrote:


I'm answering my own question (correctly, I hope). It seems like
a good way around the overhead of ostringstream as a buffer within
streambuf is to simply use a string. In contrast to a vector, this
would benefit from any platform-optimizations in string handling.


What string handling? This is a streambuf, all it does is store bytes.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.
Jul 22 '05 #9
Kevin Goodsell wrote:
I'm answering my own question (correctly, I hope). It seems like
a good way around the overhead of ostringstream as a buffer within
streambuf is to simply use a string. In contrast to a vector, this
would benefit from any platform-optimizations in string handling.


What string handling? This is a streambuf, all it does is store
bytes.


Here's an example "mostreambuf" of what I mean. I'm still debugging,
but it is the basic idea. The only difference with a streambuf that
just overloads overflow() is can only be flushed by ostream::flush().
It is not flushed by a buffer-filled condition because the buffer
grows as needed. Hence, I also don't have alot of code to check EOF.
It's a dumbing down of streambuf.

| class mostreambuf : public std::streambuf
| {
| protected:
| string sbuf;
|
| public:
|
| virtual int sync()
| {
| if( ! sbuf.empty() )
| {
| sbuf += '\0';
| SendStringToDestination( sbuf.c_str() );
| sbuf.clear();
| }
| return 0;
| }
|
| virtual int_type
| overflow( int_type c )
| {
| sbuf += c ;
| return c;
| };
|
| virtual streamsize
| xsputn( const char_type* s, streamsize n )
| {
| sbuf.append( s, s+n );
| return n;
| };
| };

Judging from your previous post, I might have given the impression
that I was considering going back to ostringstream instead of the
"string sbuf" above for the buffer within mostreambuf. Actually, I
understood your comment about the inefficiency in putting a stream
object inside a streambuf, at least in a general level. That scheme
is quite backward. It's just a hold-over from a prior implementation,
which was not based on much familiarity with stream internals or the
underlying streambuf. Fortunately, a simple string ("sbuf" above)
does the job.

From your last post, I'm also clear that the issue of relevance was
speed. Thanks for clarifying that.

Fred
Jul 22 '05 #10

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

Similar topics

12
by: Matt Garman | last post by:
I'd like to create a "custom output facility". In other words, I want an object whose use is similar to std::cout/std::cerr, but offers more flexibility. Instead of simply writing the parameter...
9
by: Fred Ma | last post by:
Hello, I posted previously under the thread: How to break this up into streambuf/ostream I've asked our library to get "C++ IOStreams and Locales..." by A. Langer et al. Meantime, I've...
19
by: Fraser Ross | last post by:
My program outputs to cout and I want it to output to a LOG file as well. Is there a simple way to do that? Fraser.
6
by: radnoraj | last post by:
Hi, I am sucessfull in redirecting console output to a file. but in this case nothing is displayed on the console, cout output is written to file without display. how do write the output to...
7
by: Lee | last post by:
Hi, I'm a stream virgin and am attempting to output strings to a file. My approach is to write the string initially to a 'stringstream' and only when complete write the stringstream to the file...
7
by: smith4894 | last post by:
Hello all, I'm working on writing my own streambuf classes (to use in my custom ostream/isteam classes that will handle reading/writing data to a mmap'd file). When reading from the mmap...
2
by: Thormod Johansen | last post by:
Hi, I am doing some embedded programming in Paradigm C++, and I would like to be able to output debugging information using the << operator and ostreams. I have a serial link for which I have...
2
by: eholz1 | last post by:
Hello CSS and StyleSheet members, I have decided to move away from Dreamweaver javascript rollover buttons, in favor of a CSS type rollover button. (hope that is ok). I plan to use PHP to...
7
by: mathieu | last post by:
Hi there, I am trying to rewrite this very slow function (due to AFAIK the extra copy): void DoAction(std::istream &is, std::ostream &os) { uint16_t c; while( is.read((char*)&c,2) )
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
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,...
0
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...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
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...

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.