diff options
Diffstat (limited to 'src/util/vbuf.h')
-rw-r--r-- | src/util/vbuf.h | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/util/vbuf.h b/src/util/vbuf.h new file mode 100644 index 0000000..149fe0c --- /dev/null +++ b/src/util/vbuf.h @@ -0,0 +1,110 @@ +#ifndef _VBUF_H_INCLUDED_ +#define _VBUF_H_INCLUDED_ + +/*++ +/* NAME +/* vbuf 3h +/* SUMMARY +/* generic buffer +/* SYNOPSIS +/* #include <vbuf.h> +/* DESCRIPTION +/* .nf + + /* + * The VBUF buffer is defined by 1) its structure, by 2) the VBUF_GET() and + * 3) VBUF_PUT() operations that automatically handle buffer empty and + * buffer full conditions, and 4) by the VBUF_SPACE() operation that allows + * the user to reserve buffer space ahead of time, to allow for situations + * where calling VBUF_PUT() is not possible or desirable. + * + * The VBUF buffer does not specify primitives for memory allocation or + * deallocation. The purpose is to allow different applications to have + * different strategies: a memory-resident buffer; a memory-mapped file; or + * a stdio-like window to an open file. Each application provides its own + * get(), put() and space() methods that perform the necessary magic. + * + * This interface is pretty normal. With one exception: the number of bytes + * left to read is negated. This is done so that we can change direction + * between reading and writing on the fly. The alternative would be to use + * separate read and write counters per buffer. + */ +typedef struct VBUF VBUF; +typedef int (*VBUF_GET_READY_FN) (VBUF *); +typedef int (*VBUF_PUT_READY_FN) (VBUF *); +typedef int (*VBUF_SPACE_FN) (VBUF *, ssize_t); + +struct VBUF { + int flags; /* status, see below */ + unsigned char *data; /* variable-length buffer */ + ssize_t len; /* buffer length */ + ssize_t cnt; /* bytes left to read/write */ + unsigned char *ptr; /* read/write position */ + VBUF_GET_READY_FN get_ready; /* read buffer empty action */ + VBUF_PUT_READY_FN put_ready; /* write buffer full action */ + VBUF_SPACE_FN space; /* request for buffer space */ +}; + + /* + * Typically, an application will embed a VBUF structure into a larger + * structure that also contains application-specific members. This approach + * gives us the best of both worlds. The application can still use the + * generic VBUF primitives for reading and writing VBUFs. The macro below + * transforms a pointer from VBUF structure to the structure that contains + * it. + */ +#define VBUF_TO_APPL(vbuf_ptr,app_type,vbuf_member) \ + ((app_type *) (((char *) (vbuf_ptr)) - offsetof(app_type,vbuf_member))) + + /* + * Buffer status management. + */ +#define VBUF_FLAG_RD_ERR (1<<0) /* read error */ +#define VBUF_FLAG_WR_ERR (1<<1) /* write error */ +#define VBUF_FLAG_ERR (VBUF_FLAG_RD_ERR | VBUF_FLAG_WR_ERR) +#define VBUF_FLAG_EOF (1<<2) /* end of data */ +#define VBUF_FLAG_RD_TIMEOUT (1<<3) /* read timeout */ +#define VBUF_FLAG_WR_TIMEOUT (1<<4) /* write timeout */ +#define VBUF_FLAG_TIMEOUT (VBUF_FLAG_RD_TIMEOUT | VBUF_FLAG_WR_TIMEOUT) +#define VBUF_FLAG_BAD (VBUF_FLAG_ERR | VBUF_FLAG_EOF | VBUF_FLAG_TIMEOUT) +#define VBUF_FLAG_FIXED (1<<5) /* fixed-size buffer */ + +#define vbuf_rd_error(v) ((v)->flags & (VBUF_FLAG_RD_ERR | VBUF_FLAG_RD_TIMEOUT)) +#define vbuf_wr_error(v) ((v)->flags & (VBUF_FLAG_WR_ERR | VBUF_FLAG_WR_TIMEOUT)) +#define vbuf_rd_timeout(v) ((v)->flags & VBUF_FLAG_RD_TIMEOUT) +#define vbuf_wr_timeout(v) ((v)->flags & VBUF_FLAG_WR_TIMEOUT) + +#define vbuf_error(v) ((v)->flags & (VBUF_FLAG_ERR | VBUF_FLAG_TIMEOUT)) +#define vbuf_eof(v) ((v)->flags & VBUF_FLAG_EOF) +#define vbuf_timeout(v) ((v)->flags & VBUF_FLAG_TIMEOUT) +#define vbuf_clearerr(v) ((v)->flags &= ~VBUF_FLAG_BAD) + + /* + * Buffer I/O-like operations and results. + */ +#define VBUF_GET(v) ((v)->cnt < 0 ? ++(v)->cnt, \ + (int) *(v)->ptr++ : vbuf_get(v)) +#define VBUF_PUT(v,c) ((v)->cnt > 0 ? --(v)->cnt, \ + (int) (*(v)->ptr++ = (c)) : vbuf_put((v),(c))) +#define VBUF_SPACE(v,n) ((v)->space((v),(n))) + +#define VBUF_EOF (-1) /* no more space or data */ + +extern int vbuf_get(VBUF *); +extern int vbuf_put(VBUF *, int); +extern int vbuf_unget(VBUF *, int); +extern ssize_t vbuf_read(VBUF *, void *, ssize_t); +extern ssize_t vbuf_write(VBUF *, const void *, ssize_t); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif |