summaryrefslogtreecommitdiffstats
path: root/lib/vio_fifo.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vio_fifo.h')
-rw-r--r--lib/vio_fifo.h196
1 files changed, 127 insertions, 69 deletions
diff --git a/lib/vio_fifo.h b/lib/vio_fifo.h
index 08af4590..1b7b05d3 100644
--- a/lib/vio_fifo.h
+++ b/lib/vio_fifo.h
@@ -22,37 +22,35 @@
#ifndef _ZEBRA_VIO_FIFO_H
#define _ZEBRA_VIO_FIFO_H
-#include "zebra.h"
#include "misc.h"
+#include "vargs.h"
+#include <stdio.h>
#include "list_util.h"
-#include "zassert.h"
-
-/* GCC have printf type attribute check. */
-#ifdef __GNUC__
-#define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
-#else
-#define PRINTF_ATTRIBUTE(a,b)
-#endif /* __GNUC__ */
/*==============================================================================
* VTY I/O FIFO -- buffering of arbitrary amounts of I/O.
*/
-#ifdef NDEBUG
-# define VIO_FIFO_DEBUG 0 /* NDEBUG override */
+#ifdef VIO_FIFO_DEBUG /* Can be forced from outside */
+# if VIO_FIFO_DEBUG
+# define VIO_FIFO_DEBUG 1 /* Force 1 or 0 */
+#else
+# define VIO_FIFO_DEBUG 0
+# endif
+#else
+# ifdef QDEBUG
+# define VIO_FIFO_DEBUG 1 /* Follow QDEBUG */
#else
-# ifndef VIO_FIFO_DEBUG
-# define VIO_FIFO_DEBUG 1 /* Set to 1 to turn on debug checks */
+# define VIO_FIFO_DEBUG 0
# endif
#endif
+enum { vio_fifo_debug = VIO_FIFO_DEBUG } ;
+
/*==============================================================================
* Data Structures
*/
-typedef struct vio_fifo vio_fifo_t ;
-typedef struct vio_fifo* vio_fifo ;
-
typedef struct vio_fifo_lump vio_fifo_lump_t ;
typedef struct vio_fifo_lump* vio_fifo_lump ;
@@ -60,22 +58,46 @@ struct vio_fifo
{
struct dl_base_pair(vio_fifo_lump) base ;
- bool one ;
+ bool set ; /* have at least one lump */
- char* put_ptr ;
- char* put_end ;
+ bool as_one ; /* get_lump == tail && !end_mark
+ => get_end may not be up to date */
+ bool hold_mark ; /* hold stuff while getting */
+ bool end_mark ; /* do not get beyond end */
+
+ char* hold_ptr ; /* implicitly in the head lump */
+ /* used only if "hold_mark" */
+
+ vio_fifo_lump get_lump ; /* head lump unless "hold_mark" */
char* get_ptr ;
char* get_end ;
- vio_fifo_lump rdr_lump ;
- char* rdr_ptr ;
+ vio_fifo_lump end_lump ; /* tail lump unless "end_mark" */
+ char* end_end ; /* used only if "end_mark" */
+
+ char* put_ptr ; /* implicitly in the tail lump */
+ char* put_end ;
size_t size ;
vio_fifo_lump spare ;
} ;
+typedef struct vio_fifo vio_fifo_t[1] ; /* embedded */
+typedef struct vio_fifo* vio_fifo ;
+
+/* Setting a FIFO object to all zeros is enough to initialise it to an
+ * empty FIFO (with default lump sizes).
+ */
+enum
+{
+ VIO_FIFO_INIT_ALL_ZEROS = true,
+ VIO_FIFO_DEFAULT_LUMP_SIZE = 4 * 1024
+} ;
+
+#define VIO_FIFO_INIT_EMPTY { 0 }
+
struct vio_fifo_lump
{
struct dl_list_pair(vio_fifo_lump) list ;
@@ -89,76 +111,114 @@ struct vio_fifo_lump
* Functions
*/
-extern vio_fifo vio_fifo_init_new(vio_fifo vf, size_t size) ;
-extern vio_fifo vio_fifo_reset(vio_fifo vf, int free_structure) ;
+extern vio_fifo vio_fifo_init_new(vio_fifo vff, size_t size) ;
+extern vio_fifo vio_fifo_reset(vio_fifo vff, free_keep_b free_structure) ;
-#define vio_fifo_reset_keep(vf) vio_fifo_reset(vf, 0)
-#define vio_fifo_reset_free(vf) vio_fifo_reset(vf, 1)
+extern void vio_fifo_clear(vio_fifo vff, bool clear_marks) ;
+Inline bool vio_fifo_empty(vio_fifo vff) ;
+extern size_t vio_fifo_room(vio_fifo vff) ;
-extern void vio_fifo_clear(vio_fifo vf) ;
-Inline bool vio_fifo_empty(vio_fifo vf) ;
-extern size_t vio_fifo_room(vio_fifo vf) ;
+extern void vio_fifo_put_bytes(vio_fifo vff, const char* src, size_t n) ;
+Inline void vio_fifo_put_byte(vio_fifo vff, char b) ;
-extern void vio_fifo_put(vio_fifo vf, const char* src, size_t n) ;
-Inline void vio_fifo_put_byte(vio_fifo vf, char b) ;
-
-extern int vio_fifo_printf(vio_fifo vf, const char* format, ...)
+extern int vio_fifo_printf(vio_fifo vff, const char* format, ...)
PRINTF_ATTRIBUTE(2, 3) ;
-extern int vio_fifo_vprintf(vio_fifo vf, const char *format, va_list args) ;
-
-extern size_t vio_fifo_get(vio_fifo vf, void* dst, size_t n) ;
-Inline int vio_fifo_get_byte(vio_fifo vf) ;
-extern void* vio_fifo_get_lump(vio_fifo vf, size_t* have) ;
-extern void vio_fifo_got_upto(vio_fifo vf, void* here) ;
-
-Inline bool vio_fifo_full_lump(vio_fifo vf) ;
-extern int vio_fifo_write_nb(vio_fifo vf, int fd, bool all) ;
-
-extern void* vio_fifo_get_rdr(vio_fifo vf, size_t* have) ;
-extern void* vio_fifo_step_rdr(vio_fifo vf, size_t* have, size_t step) ;
-extern void vio_fifo_sync_rdr(vio_fifo vf) ;
-extern void vio_fifo_drop_rdr(vio_fifo vf) ;
-
-Private void vio_fifo_lump_new(vio_fifo vf, size_t size) ;
-Private int vio_fifo_get_next_byte(vio_fifo vf) ;
+extern int vio_fifo_vprintf(vio_fifo vff, const char *format, va_list args) ;
+extern int vio_fifo_read_nb(vio_fifo vff, int fd, size_t request) ;
+
+extern size_t vio_fifo_get_bytes(vio_fifo vff, void* dst, size_t n) ;
+Inline int vio_fifo_get_byte(vio_fifo vff) ;
+extern void* vio_fifo_get(vio_fifo vff, size_t* have) ;
+extern void vio_fifo_step(vio_fifo vff, size_t step) ;
+extern void* vio_fifo_step_get(vio_fifo vff, size_t* p_have, size_t step) ;
+
+extern vio_fifo vio_fifo_copy(vio_fifo dst, vio_fifo src) ;
+extern vio_fifo vio_fifo_copy_tail(vio_fifo dst, vio_fifo src) ;
+
+Inline bool vio_fifo_full_lump(vio_fifo vff) ;
+extern int vio_fifo_write_nb(vio_fifo vff, int fd, bool all) ;
+extern int vio_fifo_fwrite(vio_fifo vff, FILE* file) ;
+
+extern void vio_fifo_skip_to_end(vio_fifo vff) ;
+extern void vio_fifo_set_end_mark(vio_fifo vff) ;
+extern void vio_fifo_step_end_mark(vio_fifo vff) ;
+extern void vio_fifo_clear_end_mark(vio_fifo vff) ;
+extern void vio_fifo_back_to_end_mark(vio_fifo vff, bool keep) ;
+extern void vio_fifo_set_hold_mark(vio_fifo vff) ;
+extern void vio_fifo_clear_hold_mark(vio_fifo vff) ;
+extern void vio_fifo_back_to_hold_mark(vio_fifo vff, bool keep) ;
/*==============================================================================
* Debug -- verification function
*/
-Private void vio_fifo_verify(vio_fifo vf) ;
+Private void vio_fifo_verify(vio_fifo vff) ;
#if VIO_FIFO_DEBUG
-# define VIO_FIFO_DEBUG_VERIFY(vf) vio_fifo_verify(vf)
+# define VIO_FIFO_DEBUG_VERIFY(vff) vio_fifo_verify(vff)
#else
-# define VIO_FIFO_DEBUG_VERIFY(vf)
+# define VIO_FIFO_DEBUG_VERIFY(vff)
#endif
/*==============================================================================
* Inline Functions
*/
+Private void vio_fifo_lump_new(vio_fifo vff, size_t size) ;
+Private int vio_fifo_get_next_byte(vio_fifo vff) ;
+Private bool vio_fifo_do_empty(vio_fifo vff) ;
+
/*------------------------------------------------------------------------------
- * Returns true <=> FIFO is empty
+ * Returns true <=> FIFO is empty -- at least: get_ptr == end_end (if any)
+ * or: get_ptr == put_ptr.
*/
Inline bool
-vio_fifo_empty(vio_fifo vf)
+vio_fifo_empty(vio_fifo vff)
{
- return (vf->get_ptr == vf->put_ptr) ;
-}
+ /* if vff is NULL, treat as empty !
+ * if !set, then all pointers should be NULL (so get_ptr == put_ptr)
+ * if !end_mark, then vff->end_end will be NULL (so get_ptr != end_end,
+ * unless !set)
+ * Is definitely empty if any of the following is true.
+ */
+ if ((vff == NULL) || (vff->get_ptr == vff->put_ptr)
+ || (vff->get_ptr == vff->end_end))
+ return true ;
+
+ /* If get_ptr < get_end is NOT empty */
+ if (vff->get_ptr < vff->get_end)
+ return false ;
+
+ /* See if can advance get_ptr, and if so whether is then empty. */
+ return vio_fifo_do_empty(vff) ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Returns true <=> FIFO is empty beyond end_end (if any).
+ */
+Inline bool
+vio_fifo_empty_tail(vio_fifo vff)
+{
+ /* if vff is NULL, treat as empty !
+ * if !set, then all pointers should be NULL (so end_end == put_ptr)
+ * if !end_mark, then tail is empty !
+ * else tail is empty iff end_end == put_ptr.
+ */
+ return (vff == NULL) || !vff->end_mark || (vff->end_end == vff->put_ptr) ;
+} ;
/*------------------------------------------------------------------------------
* Put one byte to the FIFO
*/
Inline void
-vio_fifo_put_byte(vio_fifo vf, char b)
+vio_fifo_put_byte(vio_fifo vff, char b)
{
- if (vf->put_ptr >= vf->put_end)
- vio_fifo_lump_new(vf, vf->size) ; /* traps put_ptr > put_end */
+ if (vff->put_ptr >= vff->put_end)
+ vio_fifo_lump_new(vff, 0) ; /* traps put_ptr > put_end */
- VIO_FIFO_DEBUG_VERIFY(vf) ;
+ VIO_FIFO_DEBUG_VERIFY(vff) ;
- *vf->put_ptr++ = b ;
+ *vff->put_ptr++ = b ;
} ;
/*------------------------------------------------------------------------------
@@ -168,14 +228,12 @@ vio_fifo_put_byte(vio_fifo vf, char b)
* -1 => FIFO is empty.
*/
Inline int
-vio_fifo_get_byte(vio_fifo vf)
+vio_fifo_get_byte(vio_fifo vff)
{
- if (vf->get_end <= (vf->get_ptr + 1))
- return vio_fifo_get_next_byte(vf) ;
-
- VIO_FIFO_DEBUG_VERIFY(vf) ;
+ if (vff->get_ptr < vff->get_end)
+ return (uchar)*vff->get_ptr++ ;
- return (unsigned char)*vf->get_ptr++ ;
+ return vio_fifo_get_next_byte(vff) ;
} ;
/*------------------------------------------------------------------------------
@@ -188,9 +246,9 @@ vio_fifo_get_byte(vio_fifo vf)
* (excluding the last lump if it happens to be full)
*/
Inline bool
-vio_fifo_full_lump(vio_fifo vf)
+vio_fifo_full_lump(vio_fifo vff)
{
- return (!vf->one && (vf->put_ptr != NULL)) ;
+ return (ddl_head(vff->base) != ddl_tail(vff->base)) ;
} ;
#endif /* _ZEBRA_VIO_FIFO_H */