/* ISC license. */ #ifndef CBUFFER_H #define CBUFFER_H #include #include #include #include typedef struct cbuffer_s cbuffer_t, *cbuffer_t_ref ; struct cbuffer_s { char *x ; unsigned int a ; /* total length */ unsigned int p ; /* head */ unsigned int n ; /* tail */ } ; #define CBUFFER_ZERO { .x = 0, .a = 0, .p = 0, .n = 0 } /* Circular buffers need to be 1 char bigger than the storage space, so that the head == tail case is nonambiguous (empty). */ #define CBUFFER_INIT(buf, len) { .x = (buf), .a = (len), .p = 0, .n = 0 } extern int cbuffer_init (cbuffer_t *, char *, unsigned int) ; /* Writing */ extern unsigned int cbuffer_put (cbuffer_t *, char const *, unsigned int) ; extern unsigned int cbuffer_putv (cbuffer_t *, siovec_t const *, unsigned int) ; #define cbuffer_puts(b, s) cbuffer_put(b, (s), str_len(s)) #define cbuffer_UNPUT(b, w) ((b)->n = ((b)->a + (b)->n - w) % (b)->a, w) ; extern unsigned int cbuffer_unput (cbuffer_t *, unsigned int) ; extern void cbuffer_wpeek (cbuffer_t *, siovec_t *) ; #define cbuffer_WSEEK(b, w) ((b)->n = ((b)->n + (w)) % (b)->a, w) extern unsigned int cbuffer_wseek (cbuffer_t *, unsigned int) ; /* Reading */ extern unsigned int cbuffer_get (cbuffer_t *, char *, unsigned int) ; extern unsigned int cbuffer_getv (cbuffer_t *, siovec_t const *, unsigned int) ; #define cbuffer_UNGET(b, n) ((b)->p = ((b)->a + (b)->p - n) % (b)->a, n) ; extern unsigned int cbuffer_unget (cbuffer_t *, unsigned int) ; extern void cbuffer_rpeek (cbuffer_t *, siovec_t *) ; #define cbuffer_RSEEK(b, n) ((b)->p = ((b)->p + (n)) % (b)->a, n) extern unsigned int cbuffer_rseek (cbuffer_t *, unsigned int) ; /* Utility */ #define cbuffer_len(b) ((unsigned int)(((b)->a - (b)->p + (b)->n) % (b)->a)) #define cbuffer_available(b) ((unsigned int)(((b)->a - (b)->n + (b)->p - 1) % (b)->a)) #define cbuffer_isempty(b) (!cbuffer_len(b)) #define cbuffer_isfull(b) (!cbuffer_available(b)) #endif