Boost logo

Boost :

From: Jonathan Graehl (jonathan_at_[hidden])
Date: 2004-09-08 16:40:42


>
>
> struct alphabetic_input_filter : public input_filter {
> template<typename Source>
> int get(Source& src)
> {
> character c;
> while ((c = boost::io::get(src)).good() && !isalpha(c))
> ;
> return c;
> }
> };
>
>
>

(boost::io::)character is just a type that wraps an int with a good() test?

>Here, eof and fail values are passed on to the caller unchanged. If you want to
>send an eof or fail notification explicitly, you'd write return eof() or return
>fail().
>
>Now the big question: is the above formulation too convoluted to teach to an
>average user who is interested only in plain, blocking i/o?
>
>
>
That seems fine. For such a user, this is just boilerplate code pasted
from documentation examples.

If you really care to make filters written by naive users via a simple
blocking interface applicable to more advanced nonblocking scenarios,
you can design a generic adapter that turns a blocking filter into a
nonblocking one. That is, it would wrap both the upstream and
downstream, I imagine with a dynamically growing buffer that will accept
any single output the naive user wants to produce, but then flagging
when its downstream consumer doesn't accept the entire amount, and
returning the EAGAIN equivalent to its upstream instead of calling the
user's naive blocking method. This strategy would require a close
notification since the buffered unaccepted stuff would be left alone
until the next write attempt (unless you want to spawn a thread to spin
attempting to empty the buffer).

About the close() or open() methods for a filter that wants to write
some prelude or coda (e.g. gzip): aren't these only necessary because
you can't guarantee that the constructors and destructors for the filter
stack are called in the proper order? It would be nice if source -> A
-> B -> sink could guarantee that B is (finally) constructed after sink,
and then A is constructed after having been linked to B. That is,
aren't the filters passed by const reference and only copy constructed
once into the filter stack? I guess the part about ensuring that A is
linked to B before the user constructor code might be accomplished by
inheritance (superclass constructors always complete before subclass
constructor executes, and the reverse for destructors?) I'm not sure if
this is too clever, or can't be made to work portably, though.

I don't think a second, simpler interface would be that much of a win;
the complexity of having two interfaces or types of filters would add as
much confusion as it simplifies the blocking case.


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