Stream Internals

The concepts embodied by a fz_stream object, and details of how to use them were given in Stream Stream. The above, relatively rich, set of functions are implemented on a fairly simple basic structure.

To implement your own fz_stream, simply define a creation function, of the form:


\begin{lstlisting}
fz_stream *fz_new_stream_foo(fz_context *ctx, <more parameter...
...->seek if required>
<set stm->meta if required>
return stm;
}
\end{lstlisting}

Note that some fz_try/fz_catch-ery may be required as part of the setup for state.

The hard work for this function is done using fz_new_stream, and two `foo' specific functions, foo_next and foo_close. First let's look at fz_new_stream:


\begin{lstlisting}
/*
fz_new_stream: Create a new stream object with the given
...
...id *state, fz_stream_next_fn *next, fz_stream_close_fn *close);
\end{lstlisting}

This creates the main fz_stream structure, populates it with the given pointers (state, foo_next and foo_close) and sets the internal buffer pointers up to indicate an empty buffer.

As soon as anyone tries to read from the buffer (or to find out how many bytes are available), the MuPDF stream functions will cause foo_next to be called. This is a function of the following type:


\begin{lstlisting}
/*
fz_stream_next_fn: A function type for use when implement...
...z_stream_next_fn)(fz_context *ctx, fz_stream *stm, size_t max);
\end{lstlisting}

When the stream is closed, the foo_close function will be called. This should be a function of type fz_stream_close_fn:


\begin{lstlisting}
/*
fz_stream_close_fn: A function type for use when implemen...
... state information.
\par
state: The stream state to release.
*/
\end{lstlisting}

In our example, if the state was created by a simple fz_malloc_struct(ctx, foo_state) then foo_close might be as simple as a fz_free(ctx, state). If the internal state of the stream is more complex then the destructor will be similarly more complex.

These three functions (creation, next and close) are all that is required to define a stream.

Optionally, you can also define a seek and/or a meta function, using functions of the following types:


\begin{lstlisting}
/*
fz_stream_seek_fn: A function type for use when implement...
...fz_context *ctx, fz_stream *stm, int key, int size, void *ptr);
\end{lstlisting}