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 9 2657
"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
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
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.
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
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
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
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.
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.
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
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...
|
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...
|
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.
|
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...
|
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...
|
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...
|
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...
|
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...
|
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) )
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 4 Oct 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: tracyyun |
last post by:
Hello everyone,
I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
|
by: Teri B |
last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course.
0ne-to-many. One course many roles.
Then I created a report based on the Course form and...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM)
Please note that the UK and Europe revert to winter time on...
|
by: nia12 |
last post by:
Hi there,
I am very new to Access so apologies if any of this is obvious/not clear.
I am creating a data collection tool for health care employees to complete. It consists of a number of...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
|
by: isladogs |
last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, Mike...
|
by: GKJR |
last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...
|
by: SueHopson |
last post by:
Hi All,
I'm trying to create a single code (run off a button that calls the Private Sub) for our parts list report that will allow the user to filter by either/both PartVendor and PartType. On...
| |