summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-05-28 06:52:12 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-05-28 06:52:12 -0700
commit31921a308074679a6fec36aa06a75df154f6bd21 (patch)
tree9c305e113149d69122c1045c3a98c8cb546c70fa
parent41db431321741fd89391278cddbf8b7a665eb6ba (diff)
downloadtxr-31921a308074679a6fec36aa06a75df154f6bd21.tar.gz
txr-31921a308074679a6fec36aa06a75df154f6bd21.tar.bz2
txr-31921a308074679a6fec36aa06a75df154f6bd21.zip
buf: implement fill_buf operation for buf streams.
* buf.c (buf_strm_fill_buf): New function. (buf_strm_ops): Wire in buf_strm_fill_buf operation. * tests/018/streams.tl: New tests.
-rw-r--r--buf.c26
-rw-r--r--tests/018/streams.tl13
2 files changed, 38 insertions, 1 deletions
diff --git a/buf.c b/buf.c
index c14f68b3..360d5bec 100644
--- a/buf.c
+++ b/buf.c
@@ -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')))