[Contents] [index] [Help] [Retrace] [browse <] [Browse >]

When the library calls your stream handler, you'll be passed a pointer to
the hook structure (hook in the example used here), a pointer to the
iffhandle (iff), and a pointer to an iffstreamcmd structure (actionpkt).
Your stream pointer may be found in iff->iff_stream where you previously
stored it.  The IFFStreamCmd (actionpkt) will describe the action that
IFFParse needs you to perform on your stream:


/* Custom stream handler is passed struct IFFStreamCmd *actionpkt */
struct IFFStreamCmd {
    LONG    sc_Command;     /*  Operation to be performed (IFFCMD_) */
    APTR    sc_Buf;         /*  Pointer to data buffer              */
    LONG    sc_NBytes;      /*  Number of bytes to be affected      */
    };

/* Possible call-back command values.  (Using 0 as the value for
 * IFFCMD_INIT was, in retrospect, probably a bad idea.)
 */
#define IFFCMD_INIT     0   /*  Prepare the stream for a session    */
#define IFFCMD_CLEANUP  1   /*  Terminate stream session            */
#define IFFCMD_READ     2   /*  Read bytes from stream              */
#define IFFCMD_WRITE    3   /*  Write bytes to stream               */
#define IFFCMD_SEEK     4   /*  Seek on stream                      */
#define IFFCMD_ENTRY    5   /*  You just entered a new context      */
#define IFFCMD_EXIT     6   /*  You're about to leave a context     */
#define IFFCMD_PURGELCI 7   /*  Purge a LocalContextItem            */


Your custom stream handler should perform the requested action on your
custom stream, and then return 0 for success or an IFFParse error if an
error occurred.  The following code demonstrates a sample stream handler
for a stream which was opened with a compiler's fopen() buffered file i/o
function:


static LONG mystreamhandler ( struct Hook *hook,
                              struct IFFHandle *iff,
                              struct IFFStreamCmd *actionpkt )
{
    register FILE   *stream;
    register LONG   nbytes, error;
    register UBYTE  *buf;


    stream  = (FILE *) iff->iff_Stream;    /* get stream pointer */
    nbytes  = actionpkt->sc_NBytes;        /* length for command */
    buf     = (UBYTE *) actionpkt->sc_Buf; /* buffer for the command */

    /* Now perform the action specified by the actionpkt->sc_Command */

    switch (actionpkt->sc_Command) {
    case IFFCMD_READ:
        /*
         * IFFCMD_READ means read sc_NBytes from the stream and place
         * it in the memory pointed to by sc_Buf.  Be aware that
         * sc_NBytes may be larger than can be contained in an int.
         * This is important if you plan on recompiling this for
         * 16-bit ints, since fread() takes int arguments.
         *
         * Any error code returned will be remapped by IFFParse into
         * IFFERR_READ.
         */
        error = (fread (buf, 1, nbytes, stream) != nbytes);
        break;

    case IFFCMD_WRITE:
        /*
         * IFFCMD_WRITE is analogous to IFFCMD_READ.
         *
         * Any error code returned will be remapped by IFFParse into
         * IFFERR_WRITE.
         */
        error = (fwrite (buf, 1, nbytes, stream) != nbytes);
        break;

    case IFFCMD_SEEK:
        /*
         * IFFCMD_SEEK asks that you performs a seek relative to the
         * current position.  sc_NBytes is a signed number,
         * indicating seek direction (positive for forward, negative
         * for backward).  sc_Buf has no meaning here.
         *
         * Any error code returned will be remapped by IFFParse into
         * IFFERR_SEEK.
         */
        error = (fseek (stream, nbytes, 1) == -1);
        break;

    case IFFCMD_INIT:
        /*
         * IFFCMD_INIT means to prepare your stream for reading.
         * This is used for certain streams that can't be read
         * immediately upon opening, and need further preparation.
         * This operation is allowed to fail;  the error code placed
         * in D0 will be returned directly to the client.
         *
         * An example of such a stream is the clipboard.  The
         * clipboard.device requires you to set the io_ClipID and
         * io_Offset to zero before starting a read.  You would
         * perform such a sequence here.  (Stdio files need no such
         * preparation, so we simply return zero for success.)
         */
    case IFFCMD_CLEANUP:
        /*
         * IFFCMD_CLEANUP means to terminate the transaction with
         * the associated stream.  This is used for streams that
         * can't simply be closed.  This operation is not allowed to
         * fail;  any error returned will be ignored.
         *
         * An example of such a stream is (surprise!) the clipboard.
         * It requires you to explicitly end reads by CMD_READing
         * past the end of a clip, and end writes by sending a
         * CMD_UPDATE.  You would perform such a sequence here.
         * (Again, stdio needs no such sequence.)
         */
        error = 0;
        break;
    }
    return (error);
}