1/*	$NetBSD: vbuf.h,v 1.2 2017/02/14 01:16:49 christos 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_RD_ERR	(1<<0)	/* read error */
65#define VBUF_FLAG_WR_ERR	(1<<1)	/* write error */
66#define VBUF_FLAG_ERR		(VBUF_FLAG_RD_ERR | VBUF_FLAG_WR_ERR)
67#define VBUF_FLAG_EOF		(1<<2)	/* end of data */
68#define VBUF_FLAG_RD_TIMEOUT	(1<<3)	/* read timeout */
69#define VBUF_FLAG_WR_TIMEOUT	(1<<4)	/* write timeout */
70#define VBUF_FLAG_TIMEOUT	(VBUF_FLAG_RD_TIMEOUT | VBUF_FLAG_WR_TIMEOUT)
71#define VBUF_FLAG_BAD	(VBUF_FLAG_ERR | VBUF_FLAG_EOF | VBUF_FLAG_TIMEOUT)
72#define VBUF_FLAG_FIXED		(1<<5)	/* fixed-size buffer */
73
74#define vbuf_rd_error(v) ((v)->flags & (VBUF_FLAG_RD_ERR | VBUF_FLAG_RD_TIMEOUT))
75#define vbuf_wr_error(v) ((v)->flags & (VBUF_FLAG_WR_ERR | VBUF_FLAG_WR_TIMEOUT))
76#define vbuf_rd_timeout(v)	((v)->flags & VBUF_FLAG_RD_TIMEOUT)
77#define vbuf_wr_timeout(v)	((v)->flags & VBUF_FLAG_WR_TIMEOUT)
78
79#define vbuf_error(v)	((v)->flags & (VBUF_FLAG_ERR | VBUF_FLAG_TIMEOUT))
80#define vbuf_eof(v)	((v)->flags & VBUF_FLAG_EOF)
81#define vbuf_timeout(v)	((v)->flags & VBUF_FLAG_TIMEOUT)
82#define vbuf_clearerr(v) ((v)->flags &= ~VBUF_FLAG_BAD)
83
84 /*
85  * Buffer I/O-like operations and results.
86  */
87#define VBUF_GET(v)	((v)->cnt < 0 ? ++(v)->cnt, \
88				(int) *(v)->ptr++ : vbuf_get(v))
89#define VBUF_PUT(v,c)	((v)->cnt > 0 ? --(v)->cnt, \
90				(int) (*(v)->ptr++ = (c)) : vbuf_put((v),(c)))
91#define VBUF_SPACE(v,n) ((v)->space((v),(n)))
92
93#define VBUF_EOF	(-1)		/* no more space or data */
94
95extern int vbuf_get(VBUF *);
96extern int vbuf_put(VBUF *, int);
97extern int vbuf_unget(VBUF *, int);
98extern ssize_t vbuf_read(VBUF *, void *, ssize_t);
99extern ssize_t vbuf_write(VBUF *, const void *, ssize_t);
100
101/* LICENSE
102/* .ad
103/* .fi
104/*	The Secure Mailer license must be distributed with this software.
105/* AUTHOR(S)
106/*	Wietse Venema
107/*	IBM T.J. Watson Research
108/*	P.O. Box 704
109/*	Yorktown Heights, NY 10598, USA
110/*--*/
111
112#endif
113