hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Aio/arch+aarch64.ha | 1+
Aio/arch+x86_64.ha | 1+
Mio/stream.ha | 17+++++++++++++++++
Mio/types.ha | 15+++++++++++++++
Mos/+linux/fdstream.ha | 10++++++++++
Mrt/+linux/syscalls.ha | 3+++
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;