hare

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

commit e46ba1931727f2ebefa851733b23bc8a9e841d05
parent bd6b519d8af036db3bcc99339f81f9c182d687a3
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 31 Jan 2021 13:02:12 -0500

os::fdstream: add static_fdopen (private)

Eventually for the purpose of reducing allocations on startup. Blocked
by lack of struct globals from harec.

Diffstat:
Mio/stream.ha | 2+-
Mos/+linux/fdstream.ha | 46++++++++++++++++++++++++++++------------------
Mos/+linux/stdfd.ha | 1+
3 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/io/stream.ha b/io/stream.ha @@ -45,7 +45,7 @@ export fn write(s: *stream, buf: const []u8) (size | error) = { }; // Closes the stream. -export fn close(s: *stream, buf: []u8) (error | void) = { +export fn close(s: *stream) (error | void) = { return match (s.closer) { null => unsupported: error, c: *closer => c(s), diff --git a/os/+linux/fdstream.ha b/os/+linux/fdstream.ha @@ -6,6 +6,26 @@ type fd_stream = struct { fd: int, }; +// Opens a Unix file descriptor as an io::stream. If 'name' is an empty string, +// a name will be generated based on the file descriptor number. +export fn fdopen(fd: int, name: str) *io::stream = { + // TODO: strings::dup the name, and if empty, generate a name from the + // file descriptor number. + // + // Also TODO: consider making the caller specify what subset of + // operations should be supported + let stream = alloc(*fd_stream, struct { + stream: io::stream = struct { + name: str = name, + reader: nullable *io::reader = &fd_read, + writer: nullable *io::writer = &fd_write, + closer: nullable *io::closer = &fd_close, + }, + fd: int = fd, + }); + return &stream.stream; +}; + fn fd_read(s: *io::stream, buf: []u8) (size | io::error) = { let stream = s: *fd_stream; let r = rt::read(stream.fd, (&buf: *types::slice).data: *[*]u8, len(buf)); @@ -36,22 +56,12 @@ fn fd_close(s: *io::stream) void = { free(stream); }; -// Opens a Unix file descriptor as an io::stream. If 'name' is an empty string, -// a name will be generated based on the file descriptor number. -export fn fdopen(fd: int, name: str) *io::stream = { - // TODO: strings::dup the name, and if empty, generate a name from the - // file descriptor number. - // - // Also TODO: consider making the caller specify what subset of - // operations should be supported - let stream = alloc(*fd_stream, struct { - stream: io::stream = struct { - name: str = name, - reader: nullable *io::reader = &fd_read, - writer: nullable *io::writer = &fd_write, - closer: nullable *io::closer = &fd_close, - }, - fd: int = fd, - }); - return &stream.stream; +fn static_fdopen(fd: int, name: str, stream: *fd_stream) void = { + stream.stream = struct { + name: str = name, + reader: nullable *io::reader = &fd_read, + writer: nullable *io::writer = &fd_write, + closer: nullable *io::closer = &fd_close, + }; + stream.fd = fd; }; diff --git a/os/+linux/stdfd.ha b/os/+linux/stdfd.ha @@ -1,6 +1,7 @@ use io; @init fn init_stdfd() void = { + // TODO: use static_fdopen for these stdin = fdopen(0, "<stdin>"); stdout = fdopen(1, "<stdout>"); stderr = fdopen(2, "<stderr>");