commit b2f9cad339eb3c6d48df27267304a24aad39253d
parent 9ca9a6af97d0d88e90cafd52a7af44ac0c1912c6
Author: Eyal Sawady <ecs@d2evs.net>
Date: Thu, 4 Feb 2021 09:48:18 -0500
Add io::seeker interface
Also implement it for os::fdstream
Diffstat:
6 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/io/arch+aarch64.ha b/io/arch+aarch64.ha
@@ -0,0 +1 @@
+export type off = i64;
diff --git a/io/arch+x86_64.ha b/io/arch+x86_64.ha
@@ -0,0 +1 @@
+export type off = i64;
diff --git a/io/stream.ha b/io/stream.ha
@@ -25,6 +25,7 @@ export type stream = struct {
writer: nullable *writer,
closer: nullable *closer,
copier: nullable *copier,
+ seeker: nullable *seeker,
};
// Reads up to len(buf) bytes from the reader into the given buffer, returning
@@ -52,3 +53,19 @@ export fn close(s: *stream) (error | void) = {
c: *closer => c(s),
};
};
+
+// Sets the offset within the stream.
+export fn seek(s: *stream, off: off, w: whence) (off | error) = {
+ return match (s.seeker) {
+ null => unsupported,
+ sk: *seeker => sk(s, off, w),
+ };
+};
+
+// Returns the current offset within the stream.
+export fn tell(s: *stream) (off | error) = {
+ return match (s.seeker) {
+ null => unsupported,
+ sk: *seeker => sk(s, 0, whence::CUR),
+ };
+};
diff --git a/io/types.ha b/io/types.ha
@@ -31,6 +31,12 @@ export type mode = enum uint {
RDWR = 2u,
};
+export type whence = enum {
+ SET = 0,
+ CUR = 1,
+ END = 2,
+};
+
// The interface for a stream which can be read from. Reads up to len(buf)
// bytes from the reader into the given buffer, returning the number of bytes
// read or an error.
@@ -58,3 +64,12 @@ export type closer = fn(s: *stream) void;
// streams, return [io::unsupported] to have [io::copy] proceed with its
// fallback implementation.
export type copier = fn(to: *stream, from: *stream) (size | error);
+
+// The interface for a stream which can be seeked. Sets the offset for the next
+// read or write to offset, interpreted according to whence:
+// whence::SET means relative to the start of the file,
+// whence::CUR means relative to the current offset, and
+// whence::END means relative to the end.
+//
+// Returns the new offset relative to the start or an error.
+export type seeker = fn(s: *stream, off: off, w: whence) (off | error);
diff --git a/os/+linux/fdstream.ha b/os/+linux/fdstream.ha
@@ -15,6 +15,7 @@ fn static_fdopen(
name = name,
closer = &fd_close_static,
copier = &fd_copy,
+ seeker = &fd_seek,
...
},
fd = fd,
@@ -118,3 +119,12 @@ fn fd_copy(_to: *io::stream, _from: *io::stream) (size | io::error) = {
};
return sum;
};
+
+fn fd_seek(s: *io::stream, off: io::off, whence: io::whence) (io::off | io::error) = {
+ let stream = s: *fd_stream;
+ let r = rt::lseek(stream.fd, off: i64, whence: uint);
+ return match (rt::wrap_return(r: size)) {
+ err: rt::errno => errno_to_io(err),
+ n: size => n: io::off,
+ };
+};
diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha
@@ -121,3 +121,6 @@ export fn munmap(addr: *void, length: size) int =
export fn mprotect(addr: *void, length: size, prot: uint) int =
syscall3(SYS_mprotect, addr: uintptr: u64, length: u64, prot: u64): int;
+
+export fn lseek(fd: int, off: i64, whence: uint) i64 =
+ syscall3(SYS_lseek, fd: u64, off: u64, whence: u64): i64;