diff options
-rw-r--r-- | buf.c | 26 | ||||
-rw-r--r-- | tests/018/streams.tl | 13 |
2 files changed, 38 insertions, 1 deletions
@@ -52,6 +52,8 @@ #include "txr.h" #include "buf.h" +#define min(a, b) ((a) < (b) ? (a) : (b)) + static struct buf *buf_handle(val buf, val ctx); static cnum buf_check_len(val len, val self) @@ -1196,6 +1198,28 @@ static val buf_strm_unget_byte(val stream, int byte) return num_fast(byte); } +static ucnum buf_strm_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos) +{ + val self = lit("fill-buf"); + struct buf_strm *s = coerce(struct buf_strm *, stream->co.handle); + struct buf *b = us_buf_handle(s->buf); + + if (convert(size_t, len) != len || len > INT_PTR_MAX) + uw_throwf(error_s, lit("~a: buffer too large"), self, nao); + if (pos >= len) { + return len; + } else { + size_t index = c_unum(s->pos, self); + size_t room = len - pos; + size_t avail = c_u(b->size) - index; + size_t copy = min(room, avail); + memcpy(ptr + pos, b->data + index, copy); + s->pos = plus(s->pos, unum(copy)); + return pos + copy; + } +} + + static val buf_strm_seek(val stream, val offset, enum strm_whence whence) { val self = lit("seek-stream"); @@ -1307,7 +1331,7 @@ static struct strm_ops buf_strm_ops = buf_strm_unget_char, buf_strm_unget_byte, 0, - 0, + buf_strm_fill_buf, 0, 0, buf_strm_seek, diff --git a/tests/018/streams.tl b/tests/018/streams.tl index 3bdab5bd..f82bc06e 100644 --- a/tests/018/streams.tl +++ b/tests/018/streams.tl @@ -236,3 +236,16 @@ (seek-stream s 0 :from-current) 0 (truncate-stream s 0) t (get-buf-from-stream s) #b'')) + +(with-in-buf-stream (s #b'00112233445566778899AABCCCDDEEFF') + (let ((b (make-buf 0))) + (mtest + (fill-buf-adjust b 0 s) 0 + b #b'' + (seek-stream s 0 :from-current) 0 + (buf-set-length b 5) 0 + (fill-buf-adjust b 0 s) 5 + b #b'0011223344' + (seek-stream s -3 :from-end) t + (fill-buf-adjust b 0 s) 3 + b #b'DDEEFF'))) |