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   */
34 typedef struct VBUF VBUF;
35 typedef int (*VBUF_GET_READY_FN) (VBUF *);
36 typedef int (*VBUF_PUT_READY_FN) (VBUF *);
37 typedef int (*VBUF_SPACE_FN) (VBUF *, ssize_t);
38 
39 struct 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 
95 extern int vbuf_get(VBUF *);
96 extern int vbuf_put(VBUF *, int);
97 extern int vbuf_unget(VBUF *, int);
98 extern ssize_t vbuf_read(VBUF *, void *, ssize_t);
99 extern 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