tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: fun (not so much) with funopen



On 03/16/12 12:26, Mouse wrote:
Bad idea.  funopen() needs to be a wrapper around something with the
new functionality.

That's possible only if the wrapper is part of stdio, because fpos_t is
too opaque.

??  Of course.  funopen() is *part* of BSD's stdio.h.
I use software probes to detect if my target platform supports funopen.
I don't use probes to detect if funopen() is a #define wrapper.

And, as long as you are doing that, it makes *MUCH* more sense to go
with an interface that takes a ops structure:

Like the Linux one.  Hmm, @gnu.org...coincidence? :-)

You could also use bruce dot korb at gmail.
I try not to be a bigot.  :)  In fact, I really use my own interface
that layers on top of either funopen or fopencookie, but not
either of the POSIX interfaces.  They don't cut it.
Anyway, truthfully, my teething was on SVR1 and using
file ops structures makes sense in this context.  Linux, I think,
goes a little over the top in using them.

Please, no.  I've written glue to run code designed for funopen() using
fopencookie; while I haven't written it, I've sketched out how to do
the converse.  Implementing funopen with fopencookie is annoying (it

Not getting a full FILE* interface into POSIX is annoying.
They adopted fmemopen() and open_memstream(), both of which are
inadequate.  Read/write access and rewind all need to be functional.
With fmemopen vs. fopencookie, the annoyance is primarily interface
inconsistencies and the interface efficiency has essentially no value:

http://autogen.git.sourceforge.net/git/gitweb.cgi?p=autogen/autogen;a=blob;f=agen5/fmemopen.c;h=4ac29383328af09a0ff6d9722a6b6fd8ded3639d;hb=HEAD#l333
http://autogen.git.sourceforge.net/git/gitweb.cgi?p=autogen/autogen;a=blob;f=agen5/fmemopen.c;h=4ac29383328af09a0ff6d9722a6b6fd8ded3639d;hb=HEAD#l632

costs an extra malloc on stream open, free on close, and one more
function call for each method operation on the stream); the converse is
trivial.  Which way is easier to write glue for is a fairly clear
indication which interface is preferable.

The glue is important because I've released software that depends upon
funopen() that likely won't disappear for years into the future.
So it will be some years after your new interface comes along that
my stuff will be able to cope.  I still have clients using Guile 1.6,
lo these many years after Guile 1.8 and now 2.0 have been released.

What do you think?
If you're going to break something, then go whole hog and fix it so
you won't have to break the API ever again. :)

How does an ops struct do that?  You still have an API flag day

API flag *YEARS*.  That's my point.  It isn't a day.  It is years.
A struct does it by using an initializer that stamps it with the
initializer version.  I was sketching an interface, not fleshing
it out. :)  Consequently, the handling code can then look at the
version and decide to go ahead or not:

funopen(const void *cookie, [...]
{
   struct user_io_ops uio;
   user_io_ops_init(&uio);
   uio.readf = readf;
   return uio_fopen(cookie, &uio);

better?  There is a lot more to do, this is only a sketch.

whenever you change the ops struct, which is just a somewhat obscured,
inconvenient, and textually separate version of the arglist to funopen.

The funopen() interface needs to be locked at what it has been for years.
A new interface needs to imply a new interface name, too.

Thank you!  Regards, Bruce


Home | Main Index | Thread Index | Old Index