1 #ifndef _VBUF_H_INCLUDED_ 2 #define _VBUF_H_INCLUDED_ 3 4 /*++ 5 /* NAME 6 /* vbuf 3h 7 /* SUMMARY 8 /* generic buffer 9 /* SYNOPSIS 10 /* #include <vbuf.h> 11 /* DESCRIPTION 12 /* .nf 13 14 /* 15 * The VBUF buffer is defined by 1) its structure, by 2) the VBUF_GET() and 16 * 3) VBUF_PUT() operations that automatically handle buffer empty and 17 * buffer full conditions, and 4) by the VBUF_SPACE() operation that allows 18 * the user to reserve buffer space ahead of time, to allow for situations 19 * where calling VBUF_PUT() is not possible or desirable. 20 * 21 * The VBUF buffer does not specify primitives for memory allocation or 22 * deallocation. The purpose is to allow different applications to have 23 * different strategies: a memory-resident buffer; a memory-mapped file; or 24 * a stdio-like window to an open file. Each application provides its own 25 * get(), put() and space() methods that perform the necessary magic. 26 * 27 * This interface is pretty normal. With one exception: the number of bytes 28 * left to read is negated. This is done so that we can change direction 29 * between reading and writing on the fly. The alternative would be to use 30 * separate read and write counters per buffer. 31 */ 32 typedef struct VBUF VBUF; 33 typedef int (*VBUF_GET_READY_FN) (VBUF *); 34 typedef int (*VBUF_PUT_READY_FN) (VBUF *); 35 typedef int (*VBUF_SPACE_FN) (VBUF *, ssize_t); 36 37 struct VBUF { 38 int flags; /* status, see below */ 39 unsigned char *data; /* variable-length buffer */ 40 ssize_t len; /* buffer length */ 41 ssize_t cnt; /* bytes left to read/write */ 42 unsigned char *ptr; /* read/write position */ 43 VBUF_GET_READY_FN get_ready; /* read buffer empty action */ 44 VBUF_PUT_READY_FN put_ready; /* write buffer full action */ 45 VBUF_SPACE_FN space; /* request for buffer space */ 46 }; 47 48 /* 49 * Typically, an application will embed a VBUF structure into a larger 50 * structure that also contains application-specific members. This approach 51 * gives us the best of both worlds. The application can still use the 52 * generic VBUF primitives for reading and writing VBUFs. The macro below 53 * transforms a pointer from VBUF structure to the structure that contains 54 * it. 55 */ 56 #define VBUF_TO_APPL(vbuf_ptr,app_type,vbuf_member) \ 57 ((app_type *) (((char *) (vbuf_ptr)) - offsetof(app_type,vbuf_member))) 58 59 /* 60 * Buffer status management. 61 */ 62 #define VBUF_FLAG_RD_ERR (1<<0) /* read error */ 63 #define VBUF_FLAG_WR_ERR (1<<1) /* write error */ 64 #define VBUF_FLAG_ERR (VBUF_FLAG_RD_ERR | VBUF_FLAG_WR_ERR) 65 #define VBUF_FLAG_EOF (1<<2) /* end of data */ 66 #define VBUF_FLAG_RD_TIMEOUT (1<<3) /* read timeout */ 67 #define VBUF_FLAG_WR_TIMEOUT (1<<4) /* write timeout */ 68 #define VBUF_FLAG_TIMEOUT (VBUF_FLAG_RD_TIMEOUT | VBUF_FLAG_WR_TIMEOUT) 69 #define VBUF_FLAG_BAD (VBUF_FLAG_ERR | VBUF_FLAG_EOF | VBUF_FLAG_TIMEOUT) 70 #define VBUF_FLAG_FIXED (1<<5) /* fixed-size buffer */ 71 72 #define vbuf_rd_error(v) ((v)->flags & (VBUF_FLAG_RD_ERR | VBUF_FLAG_RD_TIMEOUT)) 73 #define vbuf_wr_error(v) ((v)->flags & (VBUF_FLAG_WR_ERR | VBUF_FLAG_WR_TIMEOUT)) 74 #define vbuf_rd_timeout(v) ((v)->flags & VBUF_FLAG_RD_TIMEOUT) 75 #define vbuf_wr_timeout(v) ((v)->flags & VBUF_FLAG_WR_TIMEOUT) 76 77 #define vbuf_error(v) ((v)->flags & (VBUF_FLAG_ERR | VBUF_FLAG_TIMEOUT)) 78 #define vbuf_eof(v) ((v)->flags & VBUF_FLAG_EOF) 79 #define vbuf_timeout(v) ((v)->flags & VBUF_FLAG_TIMEOUT) 80 #define vbuf_clearerr(v) ((v)->flags &= ~VBUF_FLAG_BAD) 81 82 /* 83 * Buffer I/O-like operations and results. 84 */ 85 #define VBUF_GET(v) ((v)->cnt < 0 ? ++(v)->cnt, \ 86 (int) *(v)->ptr++ : vbuf_get(v)) 87 #define VBUF_PUT(v,c) ((v)->cnt > 0 ? --(v)->cnt, \ 88 (int) (*(v)->ptr++ = (c)) : vbuf_put((v),(c))) 89 #define VBUF_SPACE(v,n) ((v)->space((v),(n))) 90 91 #define VBUF_EOF (-1) /* no more space or data */ 92 93 extern int vbuf_get(VBUF *); 94 extern int vbuf_put(VBUF *, int); 95 extern int vbuf_unget(VBUF *, int); 96 extern ssize_t vbuf_read(VBUF *, void *, ssize_t); 97 extern ssize_t vbuf_write(VBUF *, const void *, ssize_t); 98 99 /* LICENSE 100 /* .ad 101 /* .fi 102 /* The Secure Mailer license must be distributed with this software. 103 /* AUTHOR(S) 104 /* Wietse Venema 105 /* IBM T.J. Watson Research 106 /* P.O. Box 704 107 /* Yorktown Heights, NY 10598, USA 108 /*--*/ 109 110 #endif 111