This is the mail archive of the libstdc++@sourceware.cygnus.com mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ostringstream buffers (was Re: stringstream status)



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.)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]