summaryrefslogtreecommitdiffstats
path: root/lib/vio_fifo.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vio_fifo.c')
-rw-r--r--lib/vio_fifo.c90
1 files changed, 78 insertions, 12 deletions
diff --git a/lib/vio_fifo.c b/lib/vio_fifo.c
index e6365861..46a087f7 100644
--- a/lib/vio_fifo.c
+++ b/lib/vio_fifo.c
@@ -957,8 +957,11 @@ vio_fifo_vprintf(vio_fifo vff, const char *format, va_list args)
/*------------------------------------------------------------------------------
* Read part of file into FIFO -- assuming non-blocking file
*
- * Will read up to the end of the lump which meets, or exceeds the number of
- * bytes requested, or until would block.
+ * Will read up to the end of the current lump, then will read as may whole
+ * lumps as are requested -- request of 0 reads up to the end of the current
+ * lump (at least 1 byte). Will stop if would block.
+ *
+ * Except where blocking intervenes, this reads in units of the lump size.
*
* Returns: 0..n -- number of bytes read
* -1 => failed -- see errno
@@ -969,7 +972,7 @@ vio_fifo_vprintf(vio_fifo vff, const char *format, va_list args)
* something, error or EOF.
*/
extern int
-vio_fifo_read_nb(vio_fifo vff, int fd, size_t request)
+vio_fifo_read_nb(vio_fifo vff, int fd, uint request)
{
size_t total ;
@@ -980,7 +983,12 @@ vio_fifo_read_nb(vio_fifo vff, int fd, size_t request)
int got ;
if (vff->put_ptr >= vff->put_end)
- vio_fifo_lump_new(vff, 0) ; /* traps put_ptr > put_end */
+ {
+ vio_fifo_lump_new(vff, 0) ; /* traps put_ptr > put_end */
+
+ if (request > 0)
+ --request ;
+ } ;
got = read_nb(fd, vff->put_ptr, vff->put_end - vff->put_ptr) ;
@@ -995,7 +1003,7 @@ vio_fifo_read_nb(vio_fifo vff, int fd, size_t request)
vff->put_ptr += got ;
total += got ;
- } while (total < request) ;
+ } while (request > 0) ;
return total ;
} ;
@@ -1024,9 +1032,6 @@ vio_fifo_copy(vio_fifo dst, vio_fifo src)
vio_fifo_lump src_lump ;
char* src_ptr ;
- if (src->get_ptr >= src->get_end)
- vio_fifo_sync_get(src) ;
-
src_lump = src->get_lump ;
src_ptr = src->get_ptr ;
@@ -1346,7 +1351,7 @@ vio_fifo_step_get(vio_fifo vff, size_t* p_have, size_t step)
* Write contents of FIFO -- assuming non-blocking file
*
* Will write all of FIFO up to end mark or put_ptr, or upto but excluding
- * the last lump.
+ * the end_lump.
*
* Returns: > 0 => blocked
* 0 => all gone (up to last lump if !all)
@@ -1492,9 +1497,10 @@ vio_fifo_clear_hold_mark(vio_fifo vff)
} ;
/*------------------------------------------------------------------------------
- * If there is an hold_mark, reset get_ptr *back* to it.
+ * If there is an hold_mark, reset get_ptr *back* to it, and leave the mark
+ * set or clear.
*
- * Leave hold mark set or clear.
+ * If there is no hold mark, set one at the current position, if required.
*/
extern void
vio_fifo_back_to_hold_mark(vio_fifo vff, bool mark)
@@ -1516,7 +1522,67 @@ vio_fifo_back_to_hold_mark(vio_fifo vff, bool mark)
VIO_FIFO_DEBUG_VERIFY(vff) ;
}
else if (mark)
- vio_fifo_set_end_mark(vff) ;
+ vio_fifo_set_hold_mark(vff) ;
+} ;
+
+/*------------------------------------------------------------------------------
+ * Set the get_ptr to the hold_mark plus the given offset.
+ *
+ * If the offset is zero, and there was no hold mark, set one at the current
+ * get_ptr.
+ *
+ * If the offset is not zero, it is a mistake to do this if there is no
+ * hold_mark, or if the offset would take the get_ptr beyond the end_mark
+ * (if any) or the put_ptr.
+ */
+extern void
+vio_fifo_set_get_wrt_hold(vio_fifo vff, size_t hold_offset)
+{
+ if (hold_offset == 0)
+ {
+ /* Offset of zero can be set under all conditions */
+ vio_fifo_back_to_hold_mark(vff, true) ;
+ }
+ else
+ {
+ vio_fifo_lump lump ;
+ char* ptr ;
+
+ /* There must be a hold_mark and must have something held */
+ assert(vff->hold_mark && vff->set) ;
+
+ lump = ddl_head(vff->base) ;
+ ptr = vff->hold_ptr ;
+
+ while (1)
+ {
+ size_t have ;
+
+ if (lump == vff->end_lump)
+ have = (vff->end_mark ? vff->end_end : vff->put_ptr) - ptr ;
+ else
+ have = lump->end - ptr ;
+
+ if (have <= hold_offset)
+ break ;
+
+ hold_offset -= have ;
+
+ assert(lump != vff->end_lump) ;
+
+ lump = ddl_next(lump, list) ;
+ ptr = lump->data ;
+ } ;
+
+ /* Note that may be about to set the get_ptr to the end of the
+ * current lump, which will be correct if that is the end of the
+ * fifo, but in any case is dealt with by vio_fifo_sync_get().
+ */
+ vio_fifo_set_get_ptr(vff, ptr + hold_offset, lump) ;
+ vio_fifo_sync_get(vff) ;
+ } ;
+
+ VIO_FIFO_DEBUG_VERIFY(vff) ;
} ;
/*==============================================================================