hare

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

commit 04e8af8c7bf18361766017738c48f11cf239e5cf
parent 8468b94e11d01aad94264074a43fa0613b9baa1a
Author: Bor Grošelj Simić <bor.groseljsimic@telemach.net>
Date:   Mon,  8 Mar 2021 22:54:46 +0100

bufio::dynamic: take io::mode argument

Diffstat:
Mbufio/dynamic.ha | 56++++++++++++++++++++++++++++++++------------------------
Mfmt/fmt.ha | 4++--
Mpath/join.ha | 2+-
3 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/bufio/dynamic.ha b/bufio/dynamic.ha @@ -13,29 +13,28 @@ type dynamic_stream = struct { // Calling [io::close] on this stream will free the buffer. Call [bufio::finish] // instead to free up resources associated with the stream, but transfer // ownership of the buffer to the caller. -export fn dynamic() *io::stream = alloc(dynamic_stream { - stream = io::stream { - writer = &dynamic_write, - closer = &dynamic_close, - reader = &dynamic_read, - ... - }, - buf = [], -}): *io::stream; +export fn dynamic(mode: io::mode) *io::stream = dynamic_from([], mode); // Like [dynamic], but takes an existing slice as input. Writes are appended to // it and reads consume bytes from the initial buffer, plus any additional // writes. Like [dynamic], calling [io::close] will free the buffer, and // [bufio::finish] can be used to return ownership of the buffer to the caller. -export fn dynamic_from(in: []u8) *io::stream = alloc(dynamic_stream { - stream = io::stream { - writer = &dynamic_write, - closer = &dynamic_close, - reader = &dynamic_read, - ... - }, - buf = in, -}): *io::stream; +export fn dynamic_from(in: []u8, mode: io::mode) *io::stream = { + let s = alloc(dynamic_stream { + stream = io::stream { + closer = &dynamic_close, + ... + }, + buf = in, + }): *io::stream; + if (mode & io::mode::READ == io::mode::READ) { + s.reader = &dynamic_read; + }; + if (mode & io::mode::WRITE == io::mode::WRITE) { + s.writer = &dynamic_write; + }; + return s; +}; fn dynamic_write(s: *io::stream, buf: const []u8) (size | io::error) = { let s = s: *dynamic_stream; @@ -60,7 +59,7 @@ fn dynamic_close(s: *io::stream) void = { // Closes the stream without freeing the buffer, instead transferring ownership // of it to the caller. export fn finish(s: *io::stream) []u8 = { - if (s.writer != &dynamic_write || s.closer != &dynamic_close) { + if (s.closer != &dynamic_close) { abort("bufio::finish called on non-bufio stream"); }; let s = s: *dynamic_stream; @@ -71,7 +70,7 @@ export fn finish(s: *io::stream) []u8 = { // Returns the current buffer. export fn buffer(s: *io::stream) []u8 = { - if (s.writer != &dynamic_write || s.closer != &dynamic_close) { + if (s.closer != &dynamic_close) { abort("bufio::buffer called on non-bufio stream"); }; let s = s: *dynamic_stream; @@ -81,7 +80,7 @@ export fn buffer(s: *io::stream) []u8 = { // Resets the buffer's length to zero, but keeps the allocated memory around for // future writes. export fn reset(s: *io::stream) void = { - if (s.writer != &dynamic_write || s.closer != &dynamic_close) { + if (s.closer != &dynamic_close) { abort("bufio::reset called on non-bufio stream"); }; const s = s: *dynamic_stream; @@ -91,7 +90,7 @@ export fn reset(s: *io::stream) void = { // Truncates the buffer, freeing memory associated with it and setting its // length to zero. export fn truncate(s: *io::stream) (void | io::unsupported) = { - if (s.writer != &dynamic_write || s.closer != &dynamic_close) { + if (s.closer != &dynamic_close) { return io::unsupported; }; let s = s: *dynamic_stream; @@ -100,7 +99,7 @@ export fn truncate(s: *io::stream) (void | io::unsupported) = { @test fn dynamic() void = { // TODO: slice/array equality - let s = dynamic(); + let s = dynamic(io::mode::RDWR); assert(io::write(s, [1, 2, 3]) as size == 3); assert(bytes::equal(buffer(s), [1, 2, 3])); assert(io::write(s, [4, 5]) as size == 2); @@ -118,8 +117,17 @@ export fn truncate(s: *io::stream) (void | io::unsupported) = { assert(len(buffer(s)) == 0); let sl: []u8 = alloc([1, 2, 3]); - let s = dynamic_from(sl); + let s = dynamic_from(sl, io::mode::WRITE); assert(io::write(s, [4, 5, 6]) as size == 3); assert(bytes::equal(buffer(s), [1, 2, 3, 4, 5, 6])); + // TODO: this should check for io::unsupported (harec bug prevents that) + assert(io::read(s, buf[..]) is io::error); io::close(s); + + sl = alloc([1, 2]); + let s = dynamic_from(sl, io::mode::READ); + assert(io::read(s, buf[..]) as size == 2 && bytes::equal(buf, [1, 2])); + assert(io::read(s, buf[..]) is io::EOF); + // TODO: this should check for io::unsupported (harec bug prevents that) + assert(io::write(s, [1, 2]) is io::error); }; diff --git a/fmt/fmt.ha b/fmt/fmt.ha @@ -70,7 +70,7 @@ export fn errorfln(fmt: str, args: formattable...) (io::error | size) = // Formats text for printing and writes it into a heap-allocated string. The // caller must free the return value. export fn asprintf(fmt: str, args: formattable...) str = { - let buf = bufio::dynamic(); + let buf = bufio::dynamic(io::mode::WRITE); assert(fprintf(buf, fmt, args...) is size); return strings::from_utf8_unsafe(bufio::buffer(buf)); }; @@ -124,7 +124,7 @@ export fn errorln(args: formattable...) (io::error | size) = // them into a heap-allocated string separated by spaces. The caller must free // the return value. export fn asprint(args: formattable...) str = { - let buf = bufio::dynamic(); + let buf = bufio::dynamic(io::mode::WRITE); assert(fprint(buf, args...) is size); return strings::from_utf8_unsafe(bufio::buffer(buf)); }; diff --git a/path/join.ha b/path/join.ha @@ -8,7 +8,7 @@ use io; export fn join(paths: path...) path = { // TODO: Normalize inputs so that if they end with a / we don't double // up on delimiters - let sink = bufio::dynamic(); + let sink = bufio::dynamic(io::mode::WRITE); let utf8 = true; for (let i = 0z; i < len(paths); i += 1) { utf8 = utf8 && paths[i] is str;