Boost logo

Boost :

From: Larry Evans (cppljevans_at_[hidden])
Date: 2004-09-02 09:31:37


On 08/31/2004 11:36 PM, Jonathan Turkanis wrote:
> "Larry Evans" <cppljevans_at_[hidden]> wrote in:

[snip]

>
http://www.tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF.htm
>
> This is getting pretty far afield, isn't it, Larry? ;-)

Yep. Sorry. No more.

[snip]

>
>
http://cvs.sourceforge.net/viewcvs.py/boost-sandbox/boost-sandbox/boost/io/filters/ofilter_leftmargin_adjustable.hpp?view=markup
>
>>Jonathan, I'll be trying to rewrite the above code with IOStreams.

[snip]

> I look forward to this. Maybe I can make it one of the examples, or
part of the
> library in the 'text-processing' category.

As you know, I've sent you a copy of the rewrite with IOStreams;
however, I had some problem with using the documentation during the
rewrite. Figuring out the filter was the easy part:

struct margin_output_filter {

     template<typename Sink>
     void put(Sink& snk, char c)
         {
             if(at_bol_)
             {
                 for(unsigned i=marg_len_; 0<i; --i)
                 {
                     boost::io::put(snk,' ');
                 }
             }
             boost::io::put(snk, c);
             at_bol_ = c == '\n';
         }

     bool at_bol_; //indicates at Beginning-Of-Line
     unsigned marg_len_; //margin length
};

However, understanding how to connect it to the stream was more
difficult. At first I thought just using the example code from:

libs/io/doc/tutorial.html#tutorial_output_filter

or, more specifically:

     filtered_streambuf<output> out;
     out.push(toupper_output_filter());
     out.push(cout);

but then I had to figure out if the filter was copied or not. From the
above, since the filter was a temporary, it had to be. This seemed
a needless copy; hence, I kept looking for other examples. I found
the file:

   libs/io/example/tab_expanding_example.cpp

much more helpful since it allowed:

   out<<" a string";

where:

     filtering_ostream out;

which is almost what I needed. I also needed methods allowing the
expressions:

     ++out;
     --out;

to increase and decrease the margin width. I also wanted to know that
filtering_ostream could be used everywhere that ostream could be used;
hence, I looked further at the docs:

    doc/tutorial.html#tutorial_sink
      - made no mention of ostream

    doc/filtering_streams.html
      - made no mention of ostream

So, I perused the source code in filtering_stream.hpp. Well, with all
the macros, that got pretty difficult, but it did have the comment:

   // Description: Defines a template derived from std::basic_streambuf
which uses
   // a chain to perform i/o. The template has the following
parameters:

So, I concluded that it wasn't derived from ostream, but then why did
it work with operator<< in tab_expanding_example.cpp? Looking a
little further down, it appears publicly derived from the template
parameter, Stream, whose default value is:

    BOOST_DEDUCED_TYPENAME \
                   boost::io::detail::filter_stream_traits< \
                       Mode, Ch, Tr \
>::type

I looked above at the definition of filter_stream_traits
( which BTW, is underneath:

//--------------Definition of
filtered_istream--------------------------------//

which is misleading since filtered_ostream is also defined there
)

and saw std::basic_ostream<Ch, Tr>, so I was pretty sure the Stream
default value, when Mode=output, was std::basic_ostream<Ch, Tr>. I
also remember reading somewhere (I forget where) that the filter was
actually stored by reference instead of by value as suggested by:

     out.push(toupper_output_filter());

as mentioned previously. Thus the outline of marg_ostream would be:

   class marg_ostream: public filtered_ostream
   {
    public:
       ...

       marg_ostream(std::ostream& a_ostrm)
       {
           push(marg_filt_);
           push(a_ostrm);
       }

       void adjust_margin(int delta)
       {
           marg_filt_.marg_len_+=delta;
       }
       ...
    private:
       margin_output_filter marg_filt_ ;

   };

Also, doc/filtering_streams.html contains:

   filtering_stream contains a chain of instances of streambuf_facade,
   accessed with an interface similar to that of std::stack.

and from that at the initially wrong conclusion about storing the
value of filters instead of just a reference, I thought I'd have to
access the stack of filters by some member function of
filtered_stream. That lead me to look at chain.hpp before I gave up.

Obviously, I was hoping it would be a little easier. Maybe more
examples, and explicitly showing the superclasses of each
xxx_<m>stream where m = 'o' or 'i' or whatever, would have helped as
well as emphasizing that each filter was stored as a reference.

I heartily recommend inclusion of the library in boost and will begin
using it instead of my marg_ostream as soon as it is.

Cheers,
Larry


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk