This is the mail archive of the
libstdc++@sourceware.cygnus.com
mailing list for the libstdc++ project.
ostringstream buffers (was Re: stringstream status)
- To: "Lib3 (E-mail)" <libstdc++@sourceware.cygnus.com>
- Subject: ostringstream buffers (was Re: stringstream status)
- From: "Edwards, Phil" <pedwards@ball.com>
- Date: Thu, 27 May 1999 08:44:09 -0600
This is longer than I intended. My apologies.
+ > What's the current status? I'm asking because ostringstreams are
functional
+ > with the exception of storage growth, i.e., you must supply an initial
+ > string, nor will it grow, but the basic sprintf()-like behavior is there
+
+ Hmm. stringbuf should dynamically resize and retain stream integrity: if
+ it doesn't and you have a testcase, show me and I'll fix it.
Done below.
+ There are two ctors for [io]stringstreams: one requires a string (which is
+ cloned and used as the internal buffer) and one defaults to a null string.
+ I believe this is exactly as the standard specifies.
The behavior (including the changes from yesterday) is thus:
(with-string ctor)
- The length of the initial string determines the maximum size of the
buffer. Inserting additional chars (with <<) only uses that much of
the string. Subsequent insertions fail (more below).
- The contents of the initial string don't matter. Stroustrup mentions
this on his "open issues" web page; that in order to append to the
initial string, one must create the ostringstream with ios_base::ate.
At the moment, this has no effect in v3; the initial string's contents
are /always/ overwritten. (His intentions were for ios_base::ate to
be unnecessary and understood).
(without-string ctor)
- Contrary to the example in Stroustrup, 3rd.ed., the zero-arg ctor
never does anything. Which, as you say, is what the standard seems to
say. This is (as they say in the trade) a real bummer, because
// more-or-less his example
ostringstream o;
o << stuff << more stuff << stuff << ends;
return o.str();
is much preferable to
// currently required
string temp_only_used_once (big_honkin'_number);
ostringstream o(temp_only_used_once);
o << stuff << more stuff << stuff << ends;
return o.str();
I know, I know, optimization-away of named temporaries. It's still ugly...
+ There are currently no testsuites for ostreams, which needs to change. If
+ your interested, that would be a great place to start, because it will
+ pinpoint what is wrong. I belive floating point insertion operators are a
+ problematic area.
So far I haven't been able to get a testsuite-style program to work with
mkcheck. I write small testbeds, but I always have to just run them
manually
and look at the output.
+ Does that help?
Very much so, thanks.
This is the testbed I've been using. It's based on the example that I give
in the "Received Wisdom / HOWTO" stuff (oops), which is based on old list
messages and the example in Stroustrup.
Ignore the istringstream stuff, they work fine.
=========================================================================
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
string f (string& incoming)
{
istringstream incoming_stream(incoming);
string the_word;
int the_number;
incoming_stream >> the_word // extract "foo"
>> the_number; // extract N
//string temp;
//string temp ("first");
//string temp (100, '\0');
ostringstream output_stream(temp); //, ios_base::ate // |
ios_base::out);
output_stream << "The word was ";
output_stream << the_word;
output_stream << " and 3*N was ";
output_stream << (3*the_number);
return output_stream.str();
}
int main (int argc, char *argv[]) // usage: "ss foo 3"
{
string incoming = argv[1];
incoming += " "; // musn't forget this, >> stops on whitespace...
incoming += argv[2];
string outgoing = f(incoming);
std::cerr << "Results: " << '<' << outgoing << '>' << std::endl;
return 0;
}
=========================================================================
There are four possible (important) compliations here. First, with
output_stream declared with no temp string. The other three are with
the three different declarations of temp, uncommenting one at a time.
Only the 100-character temp works, and that's only because the outgoing
string is small. The other combinations run out of space. In the cases
of no-temp-string or empty-temp-string, the program will print
Results: <T>
because the first letter of "The word was" is the only thing that gets
written out (during the += called in overflow()). Change "The" to "Horse"
for example, to see what happens.
sputc() and xsputn() are both inherited, so they don't do anything to take
advantage of the fact that it's a <string>. overflow() is overridden, and
on a resize successfully appends one character. Everything then returns
all the way back up to ostream::write, which compares the result size (1)
with the input size (__n), doesn't like the answer, and sets badbit. This
prevents any further appending, because the sentry objects become annoyed.
I know that the only functions that stringbuf overrides are the exact ones
listed as such in the standard, which is why sputc() and xsputn() are still
doing the generic streambuf behavior. There is, however, some provision
made in (yeah, get this) [27.5.2.4.3]/5, footnote 276, "Classes derived
from basic_streambuf can provide more efficient ways to implement xsgetn()
and xsputn() by overriding these definitions from the base class."
Could perhaps xsputn() be defined for stringbuf, to take advantage of the
reallocation that can be done by <string> instead of what the inherited
streambuf::xsputn() tries to do? I've fooled around with this idea a bit,
and everything magically takes effect due to the wonders of late binding,
but I'm not certain of the best way to write such an xsputn().
Phil
(If you reply to the list, please don't cc another copy to me. Thanks.)