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