Object Model Example

Below is an abbreviated example of a context with virtual methods, io_ctx. The io_ctx context is used by SETREF to abstract nearly all input and output. Notice that no "create" method is defined. C++ programmers will recognize this as an "abstract base class". It is only possible to create an object of type io_ctx by creating an object of a subtype of io_ctx (for instance io_ctx_stdio, which is implemented using the stdio package). The interface for io_ctx is taken from the stdio package.

As is common to all contexts with virtual methods, the virtual methods are invoked using macros. In the case of io_ctx, the methods

are macros. However, only the ctx argument appears more than once in the macro expansion. Therefore, it is safe to use arguments with side effects (in particular, those using the ++ or -- operator) for all arguments except ctx. The macros should always be used to invoke the underlying functions, rather than invoking the functions directly.

/*  The following structure defines objects of type io_ctx.
 *  As with all contexts containing virtual methods, the type
 *  consists of 2 pieces of data: a "vtbl" pointer and a opaque
 *  pointer to subtype-specific data. */
typedef struct io_ctx_ *io_ctx;
struct io_ctx_ {

    /*  The virtual function table (vtbl) definition  
     *  for all objects of type io_ctx.  Do not call
     *  these functions directly.  Use the provided 
     *  macros. */
    struct io_ctx_vtbl_ {
        int     (*fgetc_)   PROTO_LIST((VOID*));
        int     (*fputc_)   PROTO_LIST((UCHAR, VOID*));
        int     (*fread_)   PROTO_LIST((char*, int, int, VOID*));
        int     (*fwrite_)  PROTO_LIST((CONST char*, int, int, VOID*));
        int     (*fseek_)   PROTO_LIST((VOID*, long, position));
        int     (*ftell_)   PROTO_LIST((VOID*));
        int     (*fflush_)  PROTO_LIST((VOID*));
        int     (*ungetc_)  PROTO_LIST((int, VOID*));

        /*  Contexts with virtual methods always contain a
         *  virtual delete function which is used to delete
         *  the context. */
        int     (*delete_io_ctx)  PROTO_LIST((io_ctx*));
    } *vtbl;
    
    /*  "handle" is a opaque pointer to subtype-specific data.
     *  Users should never manipulate this data directly. */
    VOID  *handle;
};

/*  int IO_delete(ctxp)
 *      io_ctx    *ctxp;  */
#define IO_delete(ctxp)  \
           SAFE_DELETE_VCALL__(ctxp,((*(ctxp))->vtbl->delete_io_ctx((ctxp))))

/*  int IO_fgetc(ctx)
 *      io_ctx     ctx;  */
#define IO_fgetc(ctx)            ((ctx)->vtbl->fgetc_((ctx)->handle))

/*  int IO_fputc(c, ctx)
 *      char       c;
 *      io_ctx     ctx;  */
#define IO_fputc(c, ctx)         ((ctx)->vtbl->fputc_((c), (ctx)->handle))

/* long IO_ftell(ctx)
 *      io_ctx     ctx;  */
#define IO_ftell(ctx)            ((ctx)->vtbl->ftell_((ctx)->handle))

/*  int IO_fflush(ctx)
 *      io_ctx     ctx;  */
#define IO_fflush(ctx)           ((ctx)->vtbl->fflush_((ctx)->handle))

/*  int IO_ungetc(c, ctx)
 *      char       c;
 *      io_ctx     ctx;  */
#define IO_ungetc(c, ctx)        ((ctx)->vtbl->ungetc_((c), (ctx)->handle))

/*  int IO_fread(ptr, size, nitems, ctx)
 *      char      *ptr;
 *      int        size;
 *      int        nitems;
 *      io_ctx     ctx;  */
#define IO_fread(ptr, size, nitems, ctx)      \
                    ((ctx)->vtbl->fread_((ptr),(size),(nitems),(ctx)->handle))

/*  int IO_fwrite(ptr, size, nitems, ctx)
 *      char      *ptr;
 *      int        size;
 *      int        nitems;
 *      io_ctx     ctx;  */
#define IO_fwrite(ptr, size, nitems, ctx)     \
                    ((ctx)->vtbl->fwrite_((ptr),(size),(nitems),(ctx)->handle))

/*  int IO_fseek(ctx, offset, ptrname)
 *      io_ctx     ctx;
 *      long       offset;
 *      position   ptrname;  */
#define IO_fseek(ctx, offset, pos)            \
                    ((ctx)->vtbl->fseek_((ctx)->handle,(offset),(pos)))

typedef int position;             /* either BOF, CUR, or EOF */ 
#ifndef FSEEK_BOF
#    define FSEEK_BOF   0
#    define FSEEK_CUR   1
#    define FSEEK_EOF   2
#endif


Copyright © 1996, 1997, Visa International Service Association and MasterCard International Incorporated
All Rights Reserved.