Defining a couple of hooks would be sufficient:
- file_overflow to provide the 'write' functionality and
- file_underflow to provide 'read' functionality.
I put this sort of thing, too, into the 4.3BSD stdio. In addition
to snprintf() (which did get into C99), I have "funopen":
FILE *funopen(cookie, readfn, writefn, seekfn, closefn)
where "cookie" is a "void *" (const-qualified in funopen but not
in the underlying functions), and the read, write, seek, and close
function parameters are pointers to functions that implement reading,
writing, seeking, and closing. Each function is optional; passing
NULL means "nothing to do for this". You cannot pass NULL for both
read and write functions -- using NULL for one of them makes it a
read-only or write-only stream as appropriate; using NULL for both
would make it a close-only stream.
Giving NULL as the seek
function makes it an unseekable stream (fseek() returns errors).
The cookie is simply passed back to your functions, giving you a
place to store data you want to associate with that particular stream,
e.g., the memory area for a "memory-stream", or window data
structure for a window-system output-message window, or compression
data for a zip/unzip stream, etc. Note that a compression stream
would typically sit atop a regular-file stream:
struct compression_data {
FILE *lower_file;
... rest of compression data ...
};
int compressor_write(void *cookie, const char *buf, int len) {
struct compression_data *cd = cookie;
... compress the data from buf[] using whatever algorithm ...
... put each character out via putc(c, cd->lower_file),
or fwrite(ptr, size, n, cd->lower_file) ...
return n_written_successfully;
}
but of course the "lower file" could be anything stdio handles,
including a memory stream, or an encryptor stream, or a binary-to-base64
mime-encoder stream, etc. It might well be reasonable to stack a
compressor above an encryptor that sits above a mime-encoder (and,
conversely, a mime-decoder below a decryptor below a decompressor).
For whatever reason, these "stackable" streams did not get into
C99.