Boost logo

Boost :

From: Daryle Walker (darylew_at_[hidden])
Date: 2004-08-28 02:28:16


On 8/26/04 1:38 AM, "Jonathan Turkanis" <technews_at_[hidden]> wrote:

[SNIP]
> ----------------------------------------
>
> <boost/io/streambuf_wrapping.hpp>:
>
> I vote to reject, for the following reasons.
>
> I don't accept the criticism that the proper way to use a custom
> streambuf is with a plain istream, ostream or iostream; it's nice to
> have matching stream classes to go with a custom stream buffer class.
>
> However, if one has written a custom stream buffer, the name
> basic_wrapping_xstream is not what most people want for the matching
> streams. If the streambuf is called mapped_filebuf, a matching i/o
> stream might be named mapped_fstream. This could be solved with
> template aliases:
>
> template<typename Ch>
> using mapped_fstream =
> basic_wrapping_iostream< mapped_filebuf<Ch> >;
>
>
> Using streambuf_wrapping.hpp and the current language, the way to
> achieve this is to derive a stream class from basic_wrapping_iostream<
> mapped_filebuf<...> >:
>
> template<typename Ch>
> class mapped_fstream :
> basic_wrapping_iostream<mapped_filebuf>
> {
> ...
> };
>
> The problem with this is that one has to write new constructors, since
> they are not inherited. If one wants to follow the example of the
> standard library file and string streams, one should also repeat the
> typedefs char_type, traits_type, pos_type, etc. As a result, the above
> is scarcely easier than writing mapped_fstream from scratch, since
> writing the constructors (and typedefs) is the principle difficulty.

You didn't notice the extra "rdbuf" and "is_using_internal_streambuf" helper
member functions? I admit that the examples basically are doing the
repetition you're complaining about. But, it's better than nothing, right?

> Without template aliases, a macro-based approach would be more useful:
>
> #define BOOST_IO_DEFINE_WRAPPING_ISTREAM(stream, streambuf, arity)
> #define BOOST_IO_DEFINE_WRAPPING_OSTREAM(stream, streambuf, arity)
> #define BOOST_IO_DEFINE_WRAPPING_IOSTREAM(stream, streambuf,
> arity)
>
> BOOST_IO_DEFINE_WRAPPING_ISTREAM(mapped_fstream, mapped_filebuf,
> 1)

You generally can't do a blind wrapping. Doing that prevents you from
passing along the extra member functions from the stream buffer to the
stream class.

> Also, let me note that with my library, streams and stream buffers
> are generated simultaneously using stream_facade and
> streambuf_facade, so you will rarely need to write a stream buffer
> from scratch and wrap it in a stream. E.g.
>
> struct tcp_resource { ... };
> typedef streambuf_facade<tcp_resource> tcp_streambuf;
> typedef stream_facade<tcp_resource> tcp_stream;

Your framework and my wrappers work at different levels. Your framework is
all about turning sources/sinks/filters into stream buffers. My wrappers
only do a stream buffer to stream conversion. You have a stream facility
too, but I guess it just does the main stream buffer conversion followed by
a wrapping scheme similar to mine.

> ----------------------------------------
>
> <boost/io/array_stream.hpp>:
>
> I vote to reject, for the following reasons.
>
> 1. std::stringstream already writes to an internally managed character
> array, but it suffers from the following limitations (both resaonable
> in context)
>
> a. You can't define a stringstream to access a region of memory
> specified in advance
> b. when you finish performing i/o, you can't get direct access to
> the underlying array.
>
> array_stream addresses b but not a, and doesn't address b very well,
> since the lifetime of the array is included in the lifetime of the
> stream. I believe the pointer streams are better in every respect than
> the array streams.

There are times where you don't need the character buffer to be around
outside the stream's lifetime. (The std::stringstream class has a similar
limitation, except you can copy out the string easier.) In those cases, why
bother allocating an array object outside the stream?

> 2. basic_array_streambuf should be implemented as a thin wrapper
> around basic_pointerbuf. Otherwise, you've got unnecessary code bloat,
> since all the code is duplicated for each value of N.

That's the inherent trade-off using compile-time arrays.

> ----------------------------------------
>
> <boost/io/pointer_stream.hpp>:
>
> I think pointer streams and stream buffers are moderately useful, and
> would vote for acceptance, but I have the following objections.
>
> 1. Having separate classes for const and non-const pointers leads to
> far too many templates. Const-correctness can be enforced by
> the stream buffer by not allowing constructors taking const char* to
> set the put area.

I deliberately didn't want that. The old std::strstream class has at least
three distinct modes. It can act like std::stringstream, like
pointerstream, or like iconstpointerstream. And I think it can sometimes
switch between those behaviors in mid-use. I wanted separate classes for
those uses, especially after the Standard only included one separation.

> 2. The interface is strange and poorly documented. For example, the
> specification of begin_pointer and end_pointer refer to the 'utilized
> array-segment'. What does this mean? Looking at the source, I see that
> they return pointer delimiting the get area, if the get area is valid,
> and pointers delimiting the put area otherwise. Why not simply make
> them return the pointers passed to the constructor, and call them
> begin and end? Together with the current seek positions -- available
> using pubseekoff -- this should give the user all the necessary
> information in a less confusing way.
[TRUNCATE]

The "utilized array-segment" is the begin-end pair of pointers you passed in
as the buffer. That pointer pair has to be either the get area, the put
area, or both. That's why the functions returning the bounding pointers
look in those areas; storing two extra pointer members would have been a
waste of space. I don't call the functions "begin" or "end" because I don't
want the stream to be directly useable as a STL-like container.

The "?count" member functions can return the seek positions in a much faster
way.

-- 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT hotmail DOT com

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