summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--stream.c38
-rw-r--r--tests/018/streams.tl15
2 files changed, 51 insertions, 2 deletions
diff --git a/stream.c b/stream.c
index 0fbca432..0ae38153 100644
--- a/stream.c
+++ b/stream.c
@@ -2264,6 +2264,40 @@ static ucnum byte_in_fill_buf(val stream, mem_t *ptr, ucnum len, ucnum pos)
}
}
+static val byte_in_seek(val stream, val off, enum strm_whence whence)
+{
+ val self = lit("seek-stream");
+ struct byte_input *bi = coerce(struct byte_input *, stream->co.handle);
+ val pos, len = nil;
+
+ if (off == zero && whence == strm_cur) {
+ return unum(bi->index);
+ } else switch (whence) {
+ case strm_start: default:
+ pos = off;
+ break;
+ case strm_cur:
+ pos = plus(unum(bi->index), off);
+ break;
+ case strm_end:
+ pos = plus(len = unum(bi->size), off);
+ break;
+ }
+
+ if (minusp(pos))
+ uw_throwf(file_error_s,
+ lit("~a: ~s: negative position ~s disallowed"),
+ self, stream, pos, nao);
+
+ if (gt(pos, len ? len : (len = unum(bi->size))))
+ uw_throwf(file_error_s,
+ lit("~a: ~s: position ~s lies beyond buffer length ~s"),
+ self, stream, pos, len, nao);
+
+ bi->index = c_unum(pos, self);
+ return t;
+}
+
static val byte_in_get_error(val stream)
{
struct byte_input *bi = coerce(struct byte_input *, stream->co.handle);
@@ -2290,7 +2324,9 @@ static struct strm_ops byte_in_ops =
byte_in_unget_byte,
0,
byte_in_fill_buf,
- 0, 0, 0, 0, 0, 0,
+ 0, 0,
+ byte_in_seek,
+ 0, 0, 0,
byte_in_get_error,
byte_in_get_error_str,
0, 0);
diff --git a/tests/018/streams.tl b/tests/018/streams.tl
index 4c4bde7d..3bdab5bd 100644
--- a/tests/018/streams.tl
+++ b/tests/018/streams.tl
@@ -66,12 +66,25 @@
(get-char s) #\A
(get-byte s) 66
(get-char s) #\C
+ (seek-stream s 0 :from-current) 3
(unget-char #\x3042 s) #\x3042
+ (seek-stream s 0 :from-current) 0
(get-char s) #\x3042
(unget-char #\x3042 s) #\x3042
(get-byte s) #xe3
(get-char s) #\xdc81
- (unget-char #\x3042 s) :error))
+ (seek-stream s 0 :from-current) 2
+ (unget-char #\x3042 s) :error
+ (seek-stream s -1 :from-start) :error
+ (seek-stream s 0 :from-start) t
+ (seek-stream s 0 :from-end) t
+ (seek-stream s 0 :from-current) 4
+ (seek-stream s 1 :from-end) :error
+ (seek-stream s -1 :from-end) t
+ (seek-stream s 0 :from-current) 3
+ (seek-stream s -4 :from-end) t
+ (seek-stream s 0 :from-current) 0
+ (seek-stream s -5 :from-end) :error))
(with-in-string-byte-stream (s "[1][foo]")
(mtest