Home | History | Annotate | Line # | Download | only in util
      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