commit ed762a228e72661c590da68177ae1a3011853915
parent 36011547815dcf6f5f1217227ccb9fd896d63bb5
Author: Autumn! <autumnull@posteo.net>
Date: Thu, 15 Jun 2023 23:05:20 +0000
strio,bufio: merge memstream implementation into memio
- memio functions will now error instead of aborting
- renames bufio::{buffered,bufstream} to bufio::{new,stream}
- removes truncate()
Signed-off-by: Autumn! <autumnull@posteo.net>
Diffstat:
90 files changed, 1617 insertions(+), 1718 deletions(-)
diff --git a/bufio/README b/bufio/README
@@ -1,30 +1,17 @@
-bufio provides [[io::stream]] implementations which provide buffered I/O
+bufio provides an [[io::stream]] implementation which provides buffered I/O
support, as well as scanner utility functions which pair well with buffered
streams for optimal efficiency.
-Two streams are provided which can read from or write to byte slices. [[fixed]]
-uses a caller-supplied statically-allocated buffer for storage, producing an
-[[io::stream]] which reads from or writes to this buffer. In effect, this allows
-the caller to statically allocate a byte array, then produce an [[io::stream]]
-which writes to or reads from it. [[dynamic]] is similar, but it uses a
-bufio-managed dynamically allocated buffer. This creates an [[io::stream]] which
-efficiently soaks up writes into a dynamically allocated byte slice.
+A [[stream]] is used to batch read and write operations against an underlying
+stream. The caller may use small, frequent read and write operations, which
+bufio will batch into larger, less frequent reads and writes. The caller must
+supply either one or two temporary buffers for reading and/or writing, which
+bufio will use to store future reads, or pending writes, as necessary. This
+improves performance when many small reads or writes would be inefficient, such
+as when I/O operations require syscalls or network transmissions. Buffered
+streams also support an "[[unread]]" operation, which allows you to "look-ahead"
+at future data without consuming it from the stream.
-Both [[fixed]] and [[dynamic]] provide access to the underlying buffer via
-[[buffer]]. The user may also call [[reset]], which empties the buffer but does
-not free the underlying storage, allowing the user to re-use the same buffer
-for many operations.
-
-A third stream implementation, [[buffered]], is used to batch read and write
-operations against an underlying stream. The caller may use small, frequent read
-and write operations, which bufio will batch into larger, less frequent reads
-and writes. The caller must supply either one or two temporary buffers for
-reading and/or writing, which bufio will use to store future reads, or pending
-writes, as necessary. This improves performance when many small reads or writes
-would be inefficient, such as when I/O operations require syscalls or network
-transmissions. Buffered streams also support an "[[unread]]" operation, which
-allows you to "look-ahead" at future data without consuming it from the stream.
-
-Finally, bufio provides several utilities for "scanning" streams, namely
+Additionally, bufio provides several utilities for "scanning" streams, namely
[[scantok]] et al, which require small, frequent reads, or take advantage of
-look-ahead, and thus are most efficient when paired with a [[buffered]] stream.
+look-ahead, and thus are most efficient when paired with a bufio [[stream]].
diff --git a/bufio/buffered.ha b/bufio/buffered.ha
@@ -1,346 +0,0 @@
-// License: MPL-2.0
-// (c) 2022 Alexey Yerin <yyp@disroot.org>
-// (c) 2021 Byron Torres <b@torresjrjr.com>
-// (c) 2021 Drew DeVault <sir@cmpwn.com>
-// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use bytes;
-use encoding::utf8;
-use errors;
-use io;
-use strings;
-
-const buffered_vtable_r: io::vtable = io::vtable {
- closer = &buffered_close_static,
- reader = &buffered_read,
- ...
-};
-
-const buffered_vtable_w: io::vtable = io::vtable {
- closer = &buffered_close_static,
- writer = &buffered_write,
- ...
-};
-
-const buffered_vtable_rw: io::vtable = io::vtable {
- closer = &buffered_close_static,
- reader = &buffered_read,
- writer = &buffered_write,
- ...
-};
-
-export type bufstream = struct {
- stream: io::stream,
- source: io::handle,
- rbuffer: []u8,
- wbuffer: []u8,
- rpos: size,
- ravail: size,
- wavail: size,
- flush: []u8,
-};
-
-// Creates a stream which buffers reads and writes for the underlying stream.
-// This is generally used to improve performance of small reads/writes for
-// sources where I/O operations are costly, such as if they invoke a syscall or
-// take place over the network.
-//
-// The caller should supply one or both of a read and write buffer as a slice of
-// the desired buffer, or empty slices if read or write functionality is
-// disabled. The same buffer may not be used for both reads and writes.
-//
-// The caller is responsible for closing the underlying stream, and freeing the
-// provided buffers if necessary, after the buffered stream is closed.
-//
-// let rbuf: [os::BUFSIZ]u8 = [0...];
-// let wbuf: [os::BUFSIZ]u8 = [0...];
-// let buffered = bufio::buffered(source, rbuf, wbuf);
-export fn buffered(
- src: io::handle,
- rbuf: []u8,
- wbuf: []u8,
-) bufstream = {
- static let flush_default = ['\n': u8];
-
- let stream =
- if (len(rbuf) != 0 && len(wbuf) != 0) {
- assert(rbuf: *[*]u8 != wbuf: *[*]u8,
- "Cannot use bufio::buffered with same buffer for reads and writes");
- yield &buffered_vtable_rw;
- } else if (len(rbuf) != 0) {
- yield &buffered_vtable_r;
- } else if (len(wbuf) != 0) {
- yield &buffered_vtable_w;
- } else {
- abort("Must provide at least one buffer to bufio::buffered");
- };
-
- return bufstream {
- stream = stream,
- source = src,
- rbuffer = rbuf,
- wbuffer = wbuf,
- flush = flush_default,
- rpos = len(rbuf), // necessary for unread() before read()
- ...
- };
-};
-
-// Flushes pending writes to the underlying stream.
-export fn flush(s: io::handle) (void | io::error) = {
- let s = match (s) {
- case let st: *io::stream =>
- if (st.writer != &buffered_write) {
- return errors::unsupported;
- };
- yield st: *bufstream;
- case =>
- return errors::unsupported;
- };
- if (s.wavail == 0) {
- return;
- };
- io::writeall(s.source, s.wbuffer[..s.wavail])?;
- s.wavail = 0;
- return;
-};
-
-// Sets the list of bytes which will cause the stream to flush when written. By
-// default, the stream will flush when a newline (\n) is written.
-export fn setflush(s: io::handle, b: []u8) void = {
- let s = match (s) {
- case let st: *io::stream =>
- if (st.writer != &buffered_write) {
- abort("Attempted to set flush bytes on unbuffered stream");
- };
- yield st: *bufstream;
- case =>
- abort("Attempted to set flush bytes on unbuffered stream");
- };
- s.flush = b;
-};
-
-// "Unreads" a slice of bytes, such that the next call to "read" will return
-// these bytes before reading any new data from the underlying source. The
-// unread data must fit into the read buffer's available space. The amount of
-// data which can be unread before the user makes any reads from a buffered
-// stream is equal to the length of the read buffer, and otherwise it is equal
-// to the length of the return value of the last call to [[io::read]] using this
-// buffered stream. Attempting to unread more data than can fit into the read
-// buffer will abort the program.
-export fn unread(s: io::handle, buf: []u8) void = {
- let s = match (s) {
- case let st: *io::stream =>
- if (st.reader != &buffered_read) {
- abort("Attempted unread on unbuffered stream");
- };
- yield st: *bufstream;
- case =>
- abort("Attempted unread on unbuffered stream");
- };
- assert(s.rpos >= len(buf),
- "Attempted to unread more data than buffer has available");
- s.rbuffer[s.rpos - len(buf)..s.rpos] = buf;
- s.rpos -= len(buf);
- s.ravail += len(buf);
-};
-
-// Unreads a rune; see [[unread]].
-export fn unreadrune(s: io::handle, rn: rune) void = {
- const buf = utf8::encoderune(rn);
- unread(s, buf);
-};
-
-// Returns true if an [[io::handle]] is a [[buffered]] stream.
-export fn isbuffered(in: io::handle) bool = {
- match (in) {
- case io::file =>
- return false;
- case let st: *io::stream =>
- return st.reader == &buffered_read || st.writer == &buffered_write;
- };
-};
-
-fn buffered_close_static(s: *io::stream) (void | io::error) = {
- assert(s.closer == &buffered_close_static);
- if (s.writer != null) {
- flush(s: *bufstream)?;
- };
-};
-
-fn buffered_read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
- assert(s.reader == &buffered_read);
- let s = s: *bufstream;
-
- if (s.ravail < len(buf) && s.ravail < len(s.rbuffer)) {
- s.rbuffer[..s.ravail] = s.rbuffer[s.rpos..s.rpos + s.ravail];
- s.rpos = 0;
- match (io::read(s.source, s.rbuffer[s.ravail..])) {
- case let err: io::error =>
- return err;
- case io::EOF =>
- if (s.ravail == 0) {
- return io::EOF;
- };
- case let z: size =>
- s.ravail += z;
- };
- };
-
- const n = if (len(buf) < s.ravail) len(buf) else s.ravail;
- buf[..n] = s.rbuffer[s.rpos..s.rpos + n];
- s.rpos += n;
- s.ravail -= n;
- return n;
-};
-
-fn buffered_write(s: *io::stream, buf: const []u8) (size | io::error) = {
- assert(s.writer == &buffered_write);
- let s = s: *bufstream;
- let buf = buf;
-
- let doflush = false;
- if (len(s.flush) != 0) {
- for (let i = 0z; i < len(buf); i += 1) :search {
- for (let j = 0z; j < len(s.flush); j += 1) {
- if (buf[i] == s.flush[j]) {
- doflush = true;
- break :search;
- };
- };
- };
- };
-
- let z = 0z;
- for (len(buf) > 0) {
- let avail = len(s.wbuffer) - s.wavail;
- if (avail == 0) {
- flush(s)?;
- avail = len(s.wbuffer);
- };
-
- const n = if (avail < len(buf)) avail else len(buf);
- s.wbuffer[s.wavail..s.wavail + n] = buf[..n];
- buf = buf[n..];
- s.wavail += n;
- z += n;
- };
-
- if (doflush) {
- flush(s)?;
- };
-
- return z;
-};
-
-@test fn buffered_read() void = {
- let sourcebuf: []u8 = [1, 3, 3, 7];
- let source = fixed(sourcebuf, io::mode::READ);
- defer io::close(&source)!;
-
- let rbuf: [1024]u8 = [0...];
- let f = buffered(&source, rbuf, []);
- defer io::close(&f)!;
-
- let buf: [1024]u8 = [0...];
- assert(io::read(&f, buf[..2]) as size == 2);
- assert(source.pos == len(source.buf), "fixed stream was not fully consumed");
- assert(bytes::equal(buf[..2], [1, 3]));
-
- assert(io::read(&f, buf[2..]) as size == 2);
- assert(bytes::equal(buf[..4], [1, 3, 3, 7]));
- assert(io::read(&f, buf) is io::EOF);
-
- let sourcebuf: [32]u8 = [1, 3, 3, 7, 0...];
- let source = fixed(sourcebuf, io::mode::READ);
-
- let rbuf: [16]u8 = [0...];
- let f = buffered(&source, rbuf, []);
- defer io::close(&f)!;
-
- let buf: [32]u8 = [0...];
- assert(io::read(&f, buf) as size == 16);
- assert(source.pos == 16);
-
- assert(io::read(&f, buf[16..]) as size == 16);
- assert(bytes::equal(buf, sourcebuf));
- assert(io::read(&f, buf) is io::EOF);
- assert(source.pos == len(source.buf));
-};
-
-@test fn buffered_write() void = {
- // Normal case
- let sink = dynamic(io::mode::WRITE);
- defer io::close(&sink)!;
-
- let wbuf: [1024]u8 = [0...];
- let f = buffered(&sink, [], wbuf);
- defer io::close(&f)!;
-
- assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
- assert(len(buffer(&sink)) == 0);
- assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
- assert(flush(&f) is void);
- assert(bytes::equal(buffer(&sink), [1, 3, 3, 7, 1, 3, 3, 7]));
-
- // Test flushing via buffer exhaustion
- let sink = dynamic(io::mode::WRITE);
- defer io::close(&sink)!;
-
- let wbuf: [4]u8 = [0...];
- let f = buffered(&sink, [], wbuf);
-
- assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
- assert(len(buffer(&sink)) == 0);
- assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
- assert(bytes::equal(buffer(&sink), [1, 3, 3, 7]));
- io::close(&f)!; // Should flush
- assert(bytes::equal(buffer(&sink), [1, 3, 3, 7, 1, 3, 3, 7]));
-
- // Test flushing via flush characters
- let sink = dynamic(io::mode::WRITE);
- defer io::close(&sink)!;
-
- let wbuf: [1024]u8 = [0...];
- let f = buffered(&sink, [], wbuf);
-
- assert(io::writeall(&f, strings::toutf8("hello")) as size == 5);
- assert(len(buffer(&sink)) == 0);
- assert(io::writeall(&f, strings::toutf8(" world!\n")) as size == 8);
- assert(bytes::equal(buffer(&sink), strings::toutf8("hello world!\n")));
-};
-
-@test fn unread() void = {
- let rbuf: [8]u8 = [0...];
- let f = buffered(io::zero, rbuf, []);
-
- let buf: [16]u8 = [42...];
- assert(io::read(&f, buf[..4]) as size == 4);
- assert(buf[0] == 0);
- assert(buf[1] == 0);
- assert(buf[2] == 0);
- assert(buf[3] == 0);
- unread(&f, [1, 2, 3, 4]);
-
- assert(io::read(&f, buf[..8]) as size == 8);
- assert(buf[0] == 1);
- assert(buf[1] == 2);
- assert(buf[2] == 3);
- assert(buf[3] == 4);
- assert(buf[4] == 0);
- assert(buf[5] == 0);
- assert(buf[6] == 0);
- assert(buf[7] == 0);
-
- assert(io::read(&f, buf) as size == 8);
- for (let i = 0z; i < 8; i += 1) {
- assert(buf[i] == 0);
- };
-
- let input: []u8 = [1, 2, 3, 4];
- let f = buffered(&fixed(input, io::mode::READ), rbuf, []);
-
- assert(io::read(&f, buf) as size == 4);
- unread(&f, [1, 2, 3, 4]);
- assert(io::read(&f, buf) as size == 4);
- assert(io::read(&f, buf) is io::EOF);
-};
diff --git a/bufio/memstream.ha b/bufio/memstream.ha
@@ -1,299 +0,0 @@
-// License: MPL-2.0
-// (c) 2022 Alexey Yerin <yyp@disroot.org>
-// (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
-// (c) 2021 Drew DeVault <sir@cmpwn.com>
-// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use bytes;
-use io;
-use strings;
-use errors;
-
-export type memstream = struct {
- stream: io::stream,
- buf: []u8,
- pos: size,
-};
-
-const memstream_vt_r: io::vtable = io::vtable {
- seeker = &seek,
- copier = ©,
- reader = &read,
- ...
-};
-
-const fixed_vt_w: io::vtable = io::vtable {
- seeker = &seek,
- copier = ©,
- writer = &fixed_write,
- ...
-};
-
-const fixed_vt_rw: io::vtable = io::vtable {
- seeker = &seek,
- copier = ©,
- reader = &read,
- writer = &fixed_write,
- ...
-};
-
-// Creates a stream for a fixed, caller-supplied buffer. All fixed streams are
-// seekable; seeking a write stream will cause subsequent writes to overwrite
-// existing contents of the buffer. The program aborts if writes would exceed
-// the buffer's capacity. The stream doesn't have to be closed.
-export fn fixed(in: []u8, mode: io::mode) memstream = {
- let s = memstream {
- stream = &memstream_vt_r,
- buf = in,
- pos = 0,
- };
- if (mode & io::mode::RDWR == io::mode::RDWR) {
- s.stream = &fixed_vt_rw;
- } else if (mode & io::mode::WRITE == io::mode::WRITE) {
- s.stream = &fixed_vt_w;
- } else if (mode & io::mode::READ == io::mode::READ) {
- s.stream = &memstream_vt_r;
- };
- return s;
-};
-
-fn fixed_write(s: *io::stream, buf: const []u8) (size | io::error) = {
- if (len(buf) == 0) {
- return 0z;
- };
- let s = s: *memstream;
- if (s.pos >= len(s.buf)) {
- abort("bufio::fixed buffer exceeded");
- };
- const n = if (len(buf) > len(s.buf[s.pos..])) {
- yield len(s.buf[s.pos..]);
- } else {
- yield len(buf);
- };
- s.buf[s.pos..s.pos+n] = buf[..n];
- s.pos += n;
- return n;
-};
-
-const dynamic_vt_w: io::vtable = io::vtable {
- seeker = &seek,
- copier = ©,
- writer = &dynamic_write,
- closer = &dynamic_close,
- ...
-};
-
-const dynamic_vt_rw: io::vtable = io::vtable {
- seeker = &seek,
- copier = ©,
- reader = &read,
- writer = &dynamic_write,
- closer = &dynamic_close,
- ...
-};
-
-// Creates an [[io::stream]] which dynamically allocates a buffer to store
-// writes into. Subsequent reads will consume the buffered data. Upon failure to
-// allocate sufficient memory to store writes, the program aborts.
-//
-// Calling [[io::close]] on this stream will free the buffer. If a stream's data
-// is transferred via [[buffer]], the stream shouldn't be closed as long as the
-// data is used.
-export fn dynamic(mode: io::mode) memstream = 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.
-export fn dynamic_from(in: []u8, mode: io::mode) memstream = {
- let s = memstream {
- stream = &memstream_vt_r,
- buf = in,
- pos = 0,
- };
- if (mode & io::mode::RDWR == io::mode::RDWR) {
- s.stream = &dynamic_vt_rw;
- } else if (mode & io::mode::WRITE == io::mode::WRITE) {
- s.stream = &dynamic_vt_w;
- } else if (mode & io::mode::READ == io::mode::READ) {
- s.stream = &memstream_vt_r;
- };
- return s;
-};
-
-// Returns the current buffer of a [[fixed]] or [[dynamic]] stream.
-export fn buffer(in: *memstream) []u8 = {
- return in.buf;
-};
-
-// Resets the dynamic buffer's length to zero, but keeps the allocated memory
-// around for future writes.
-export fn reset(in: *memstream) void = {
- in.pos = 0;
- in.buf = in.buf[..0];
-};
-
-// Truncates the dynamic buffer, freeing memory associated with it and setting
-// its length to zero.
-export fn truncate(in: *memstream) (void | errors::unsupported) = {
- in.pos = 0;
- delete(in.buf[..]);
-};
-
-// Reads data from a [[dynamic]] or [[fixed]] stream and returns a slice
-// borrowed from the internal buffer.
-export fn borrowedread(st: *memstream, amt: size) ([]u8 | io::EOF) = {
- if (len(st.buf) - st.pos < amt) {
- return io::EOF;
- };
- let buf = st.buf[st.pos..st.pos + amt];
- st.pos += len(buf);
- return buf;
-};
-
-fn dynamic_write(s: *io::stream, buf: const []u8) (size | io::error) = {
- let s = s: *memstream;
- insert(s.buf[s.pos], buf...);
- s.pos += len(buf);
- return len(buf);
-};
-
-fn dynamic_close(s: *io::stream) (void | io::error) = {
- const s = s: *memstream;
- free(s.buf);
-};
-
-fn read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
- let s = s: *memstream;
- if (len(s.buf) == s.pos && len(buf) != 0) {
- return io::EOF;
- };
- const n = if (len(s.buf) - s.pos < len(buf)) {
- yield len(s.buf) - s.pos;
- } else {
- yield len(buf);
- };
- assert(s.pos + n <= len(s.buf));
- buf[..n] = s.buf[s.pos..s.pos + n];
- s.pos += n;
- return n;
-};
-
-fn seek(
- s: *io::stream,
- off: io::off,
- w: io::whence
-) (io::off | io::error) = {
- let s = s: *memstream;
- switch (w) {
- case io::whence::SET =>
- if (len(s.buf) < off: size) {
- abort("invalid offset");
- };
- s.pos = off: size;
- case io::whence::CUR =>
- if (s.pos + off: size > len(s.buf)) {
- abort("invalid offset");
- };
- s.pos += off: size;
- case io::whence::END =>
- if (len(s.buf) - (-off): size < len(s.buf)) {
- abort("invalid offset");
- };
- s.pos = len(s.buf) - (-off): size;
- };
- return s.pos: io::off;
-};
-
-fn copy(dest: *io::stream, src: *io::stream) (size | io::error) = {
- if (src.reader != &read || src.writer == null) {
- return errors::unsupported;
- };
- let src = src: *memstream;
- return (dest.writer: *io::writer)(dest, src.buf[src.pos..]);
-};
-
-@test fn dynamic() void = {
- let s = dynamic(io::mode::RDWR);
- assert(io::writeall(&s, [1, 2, 3]) as size == 3);
- assert(bytes::equal(buffer(&s), [1, 2, 3]));
- assert(io::writeall(&s, [4, 5]) as size == 2);
- assert(bytes::equal(buffer(&s), [1, 2, 3, 4, 5]));
- let buf: [2]u8 = [0...];
- assert(io::seek(&s, 0, io::whence::SET) as io::off == 0: io::off);
- assert(io::read(&s, buf[..]) as size == 2 && bytes::equal(buf, [1, 2]));
- assert(io::read(&s, buf[..]) as size == 2 && bytes::equal(buf, [3, 4]));
- assert(io::read(&s, buf[..]) as size == 1 && buf[0] == 5);
- assert(io::read(&s, buf[..]) is io::EOF);
- assert(io::writeall(&s, [6, 7, 8]) as size == 3);
- assert(bytes::equal(buffer(&s), [1, 2, 3, 4, 5, 6, 7, 8]));
- reset(&s);
- assert(len(buffer(&s)) == 0);
- assert(io::writeall(&s, [1, 2, 3]) as size == 3);
- assert(truncate(&s) is void);
- assert(len(buffer(&s)) == 0);
-
- let sl: []u8 = alloc([1, 2, 3]);
- let s = dynamic_from(sl, io::mode::WRITE);
- assert(io::writeall(&s, [0, 0]) as size == 2);
- assert(io::seek(&s, 0, io::whence::END) as io::off == 5: io::off);
- assert(io::writeall(&s, [4, 5, 6]) as size == 3);
- assert(bytes::equal(buffer(&s), [0, 0, 1, 2, 3, 4, 5, 6]));
- assert(io::read(&s, buf[..]) as io::error is errors::unsupported);
- io::close(&s)!;
-
- sl = alloc([1, 2]);
- let s = dynamic_from(sl, io::mode::READ);
- assert(io::read(&s, buf[..1]) as size == 1 && buf[0] == 1);
- assert(io::seek(&s, 1, io::whence::CUR) as io::off == 2: io::off);
- assert(io::read(&s, buf[..]) is io::EOF);
- assert(io::write(&s, [1, 2]) as io::error is errors::unsupported);
- io::close(&s)!;
- assert(io::writeall(&s, [1, 2]) as io::error is errors::unsupported);
- io::close(&s)!;
-
- let in: [6]u8 = [0, 1, 2, 3, 4, 5];
- let source = dynamic_from(in, io::mode::READ);
- let sink = dynamic(io::mode::WRITE);
- io::copy(&sink, &source)!;
- assert(bytes::equal(in, buffer(&sink)));
-
- let in: [6]u8 = [0, 1, 2, 3, 4, 5];
- let source = dynamic_from(in, io::mode::READ);
- const borrowed = borrowedread(&source, len(in)-1) as []u8;
- assert(bytes::equal(borrowed, [0, 1, 2, 3, 4]));
- let source = dynamic_from(in, io::mode::READ);
- const borrowed = borrowedread(&source, len(in)) as []u8;
- assert(bytes::equal(borrowed, [0, 1, 2, 3, 4, 5]));
- let source = dynamic_from(in, io::mode::READ);
- assert(borrowedread(&source, len(in)+1) is io::EOF);
-};
-
-@test fn fixed() void = {
- let buf: [1024]u8 = [0...];
- let stream = fixed(buf, io::mode::WRITE);
- defer io::close(&stream)!;
-
- let n = 0z;
- n += io::writeall(&stream, strings::toutf8("hello ")) as size;
- n += io::writeall(&stream, strings::toutf8("world")) as size;
- assert(bytes::equal(buf[..n], strings::toutf8("hello world")));
- assert(io::seek(&stream, 6, io::whence::SET) as io::off == 6: io::off);
- io::writeall(&stream, strings::toutf8("asdf")) as size;
- assert(bytes::equal(buf[..n], strings::toutf8("hello asdfd")));
-
- let out: [2]u8 = [0...];
- let s = fixed([1u8, 2u8], io::mode::READ);
- defer io::close(&s)!;
- assert(io::read(&s, out[..1]) as size == 1 && out[0] == 1);
- assert(io::seek(&s, 1, io::whence::CUR) as io::off == 2: io::off);
- assert(io::read(&s, buf[..]) is io::EOF);
- assert(io::writeall(&s, [1, 2]) as io::error is errors::unsupported);
-
- let in: [6]u8 = [0, 1, 2, 3, 4, 5];
- let out: [6]u8 = [0...];
- let source = fixed(in, io::mode::READ);
- let sink = fixed(out, io::mode::WRITE);
- io::copy(&sink, &source)!;
- assert(bytes::equal(in, out));
-
- assert(io::write(&sink, [])! == 0);
-};
diff --git a/bufio/scanner.ha b/bufio/scanner.ha
@@ -212,16 +212,6 @@ export fn scan_rune(
};
};
-@test fn scan_rune() void = {
- let in = fixed(strings::toutf8("1234"), io::mode::READ);
- let scan = newscanner(&in, 4);
- assert(scan_rune(&scan) == '1', "expected '1'");
- assert(scan_rune(&scan) == '2', "expected '2'");
- assert(scan_rune(&scan) == '3', "expected '3'");
- assert(scan_rune(&scan) == '4', "expected '4'");
- finish(&scan);
-};
-
// Scans a string of text from a [[scanner]] up to some delimiter. The return
// value is borrowed from the internal scanner buffer, which is invalidated
// during subsequent operations which use this scanner.
@@ -335,111 +325,3 @@ export fn scanrune(
return utf8::invalid;
};
};
-
-@test fn scanbyte() void = {
- let buf = fixed([1, 3, 3, 7], io::mode::READ);
-
- assert(scanbyte(&buf) as u8 == 1);
- assert(scanbyte(&buf) as u8 == 3);
- assert(scanbyte(&buf) as u8 == 3);
- assert(scanbyte(&buf) as u8 == 7);
- assert(scanbyte(&buf) is io::EOF);
-};
-
-@test fn scantok() void = {
- let buf = fixed([1, 3, 4, 5, 3, 7], io::mode::READ);
-
- let tok = scantok(&buf, 4) as []u8;
- defer free(tok);
- assert(bytes::equal(tok, [1, 3]));
-
- let tok = scantok(&buf, 7) as []u8;
- defer free(tok);
- assert(bytes::equal(tok, [5, 3]));
-
- assert(scantok(&buf, 1) is io::EOF);
-};
-
-@test fn scanline() void = {
- let helloworld = strings::toutf8("hello\nworld");
- let buf = fixed(helloworld, io::mode::READ);
-
- let line = scanline(&buf) as []u8;
- defer free(line);
- assert(bytes::equal(line, strings::toutf8("hello")));
-
- let line = scanline(&buf) as []u8;
- defer free(line);
- assert(bytes::equal(line, strings::toutf8("world")));
-
- assert(scanline(&buf) is io::EOF);
-};
-
-@test fn scanrune() void = {
- let in = fixed([
- 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, 0xE3, 0x81,
- 0xAB, 0xE3, 0x81, 0xA1, 0xE3, 0x81, 0xAF, 0x00,
- ], io::mode::READ);
-
- const expected: [_](rune | utf8::invalid | io::EOF | io::error) = [
- 'こ', 'ん', 'に', 'ち', 'は', '\0', io::EOF,
- ];
- for (let i = 0z; i < len(expected); i += 1) {
- let want = expected[i];
-
- match (scanrune(&in)) {
- case let r: rune =>
- assert(want is rune && want as rune == r);
- case io::EOF =>
- assert(want is io::EOF);
- case =>
- abort();
- };
- };
-};
-
-@test fn scan_rune() void = {
- let in = fixed(strings::toutf8("hello"), io::mode::READ);
- let scanner = newscanner(&in, 32);
-
- const expected: [_](rune | utf8::invalid | io::EOF | io::error) = [
- 'h', 'e', 'l', 'l', 'o', io::EOF,
- ];
- for (let i = 0z; i < len(expected); i += 1) {
- let want = expected[i];
-
- match (scan_rune(&scanner)) {
- case let r: rune =>
- assert(want is rune && want as rune == r);
- case io::EOF =>
- assert(want is io::EOF);
- case =>
- abort();
- };
- };
-};
-
-@test fn scan_rune_cutoff() void = {
- let in = fixed([
- 'a', 0xE3,
- ], io::mode::READ);
- let scanner = newscanner(&in, 32);
-
- const expected: [_](rune | utf8::invalid | io::EOF | io::error) = [
- 'a', utf8::invalid,
- ];
- for (let i = 0z; i < len(expected); i += 1) {
- let want = expected[i];
-
- match (scan_rune(&scanner)) {
- case let r: rune =>
- assert(want is rune && want as rune == r);
- case io::EOF =>
- assert(want is io::EOF);
- case utf8::invalid =>
- assert(want is utf8::invalid);
- case =>
- abort();
- };
- };
-};
diff --git a/bufio/scanner_test+test.ha b/bufio/scanner_test+test.ha
@@ -0,0 +1,113 @@
+use bytes;
+use encoding::utf8;
+use io;
+use memio;
+use strings;
+
+@test fn scanbyte() void = {
+ let buf = memio::fixed([1, 3, 3, 7]);
+
+ assert(scanbyte(&buf) as u8 == 1);
+ assert(scanbyte(&buf) as u8 == 3);
+ assert(scanbyte(&buf) as u8 == 3);
+ assert(scanbyte(&buf) as u8 == 7);
+ assert(scanbyte(&buf) is io::EOF);
+};
+
+@test fn scantok() void = {
+ let buf = memio::fixed([1, 3, 4, 5, 3, 7]);
+
+ let tok = scantok(&buf, 4) as []u8;
+ defer free(tok);
+ assert(bytes::equal(tok, [1, 3]));
+
+ let tok = scantok(&buf, 7) as []u8;
+ defer free(tok);
+ assert(bytes::equal(tok, [5, 3]));
+
+ assert(scantok(&buf, 1) is io::EOF);
+};
+
+@test fn scanline() void = {
+ let helloworld = strings::toutf8("hello\nworld");
+ let buf = memio::fixed(helloworld);
+
+ let line = scanline(&buf) as []u8;
+ defer free(line);
+ assert(bytes::equal(line, strings::toutf8("hello")));
+
+ let line = scanline(&buf) as []u8;
+ defer free(line);
+ assert(bytes::equal(line, strings::toutf8("world")));
+
+ assert(scanline(&buf) is io::EOF);
+};
+
+@test fn scanrune() void = {
+ let in = memio::fixed([
+ 0xE3, 0x81, 0x93, 0xE3, 0x82, 0x93, 0xE3, 0x81,
+ 0xAB, 0xE3, 0x81, 0xA1, 0xE3, 0x81, 0xAF, 0x00,
+ ]);
+
+ const expected: [_](rune | utf8::invalid | io::EOF | io::error) = [
+ 'こ', 'ん', 'に', 'ち', 'は', '\0', io::EOF,
+ ];
+ for (let i = 0z; i < len(expected); i += 1) {
+ let want = expected[i];
+
+ match (scanrune(&in)) {
+ case let r: rune =>
+ assert(want is rune && want as rune == r);
+ case io::EOF =>
+ assert(want is io::EOF);
+ case =>
+ abort();
+ };
+ };
+};
+
+@test fn scan_rune() void = {
+ let in = memio::fixed(strings::toutf8("hello"));
+ let scanner = newscanner(&in, 32);
+
+ const expected: [_](rune | utf8::invalid | io::EOF | io::error) = [
+ 'h', 'e', 'l', 'l', 'o', io::EOF,
+ ];
+ for (let i = 0z; i < len(expected); i += 1) {
+ let want = expected[i];
+
+ match (scan_rune(&scanner)) {
+ case let r: rune =>
+ assert(want is rune && want as rune == r);
+ case io::EOF =>
+ assert(want is io::EOF);
+ case =>
+ abort();
+ };
+ };
+};
+
+@test fn scan_rune_cutoff() void = {
+ let in = memio::fixed([
+ 'a', 0xE3,
+ ]);
+ let scanner = newscanner(&in, 32);
+
+ const expected: [_](rune | utf8::invalid | io::EOF | io::error) = [
+ 'a', utf8::invalid,
+ ];
+ for (let i = 0z; i < len(expected); i += 1) {
+ let want = expected[i];
+
+ match (scan_rune(&scanner)) {
+ case let r: rune =>
+ assert(want is rune && want as rune == r);
+ case io::EOF =>
+ assert(want is io::EOF);
+ case utf8::invalid =>
+ assert(want is utf8::invalid);
+ case =>
+ abort();
+ };
+ };
+};
diff --git a/bufio/stream.ha b/bufio/stream.ha
@@ -0,0 +1,233 @@
+// License: MPL-2.0
+// (c) 2022 Alexey Yerin <yyp@disroot.org>
+// (c) 2021 Byron Torres <b@torresjrjr.com>
+// (c) 2021 Drew DeVault <sir@cmpwn.com>
+// (c) 2021 Ember Sawady <ecs@d2evs.net>
+use bytes;
+use encoding::utf8;
+use errors;
+use io;
+use strings;
+
+const vtable_r: io::vtable = io::vtable {
+ closer = &close_static,
+ reader = &read,
+ ...
+};
+
+const vtable_w: io::vtable = io::vtable {
+ closer = &close_static,
+ writer = &write,
+ ...
+};
+
+const vtable_rw: io::vtable = io::vtable {
+ closer = &close_static,
+ reader = &read,
+ writer = &write,
+ ...
+};
+
+export type stream = struct {
+ stream: io::stream,
+ source: io::handle,
+ rbuffer: []u8,
+ wbuffer: []u8,
+ rpos: size,
+ ravail: size,
+ wavail: size,
+ flush: []u8,
+};
+
+// Creates a stream which buffers reads and writes for the underlying stream.
+// This is generally used to improve performance of small reads/writes for
+// sources where I/O operations are costly, such as if they invoke a syscall or
+// take place over the network.
+//
+// The caller should supply one or both of a read and write buffer as a slice of
+// the desired buffer, or empty slices if read or write functionality is
+// disabled. The same buffer may not be used for both reads and writes.
+//
+// The caller is responsible for closing the underlying stream, and freeing the
+// provided buffers if necessary, after the buffered stream is closed.
+//
+// let rbuf: [os::BUFSIZ]u8 = [0...];
+// let wbuf: [os::BUFSIZ]u8 = [0...];
+// let buffered = bufio::init(source, rbuf, wbuf);
+export fn init(
+ src: io::handle,
+ rbuf: []u8,
+ wbuf: []u8,
+) stream = {
+ static let flush_default = ['\n': u8];
+
+ let st =
+ if (len(rbuf) != 0 && len(wbuf) != 0) {
+ assert(rbuf: *[*]u8 != wbuf: *[*]u8,
+ "Cannot use same buffer for reads and writes");
+ yield &vtable_rw;
+ } else if (len(rbuf) != 0) {
+ yield &vtable_r;
+ } else if (len(wbuf) != 0) {
+ yield &vtable_w;
+ } else {
+ abort("Must provide at least one buffer");
+ };
+
+ return stream {
+ stream = st,
+ source = src,
+ rbuffer = rbuf,
+ wbuffer = wbuf,
+ flush = flush_default,
+ rpos = len(rbuf), // necessary for unread() before read()
+ ...
+ };
+};
+
+// Flushes pending writes to the underlying stream.
+export fn flush(s: io::handle) (void | io::error) = {
+ let s = match (s) {
+ case let st: *io::stream =>
+ if (st.writer != &write) {
+ return errors::unsupported;
+ };
+ yield st: *stream;
+ case =>
+ return errors::unsupported;
+ };
+ if (s.wavail == 0) {
+ return;
+ };
+ io::writeall(s.source, s.wbuffer[..s.wavail])?;
+ s.wavail = 0;
+ return;
+};
+
+// Sets the list of bytes which will cause the stream to flush when written. By
+// default, the stream will flush when a newline (\n) is written.
+export fn setflush(s: io::handle, b: []u8) void = {
+ let s = match (s) {
+ case let st: *io::stream =>
+ if (st.writer != &write) {
+ abort("Attempted to set flush bytes on unbuffered stream");
+ };
+ yield st: *stream;
+ case =>
+ abort("Attempted to set flush bytes on unbuffered stream");
+ };
+ s.flush = b;
+};
+
+// "Unreads" a slice of bytes, such that the next call to "read" will return
+// these bytes before reading any new data from the underlying source. The
+// unread data must fit into the read buffer's available space. The amount of
+// data which can be unread before the user makes any reads from a buffered
+// stream is equal to the length of the read buffer, and otherwise it is equal
+// to the length of the return value of the last call to [[io::read]] using this
+// buffered stream. Attempting to unread more data than can fit into the read
+// buffer will abort the program.
+export fn unread(s: io::handle, buf: []u8) void = {
+ let s = match (s) {
+ case let st: *io::stream =>
+ if (st.reader != &read) {
+ abort("Attempted unread on unbuffered stream");
+ };
+ yield st: *stream;
+ case =>
+ abort("Attempted unread on unbuffered stream");
+ };
+ assert(s.rpos >= len(buf),
+ "Attempted to unread more data than buffer has available");
+ s.rbuffer[s.rpos - len(buf)..s.rpos] = buf;
+ s.rpos -= len(buf);
+ s.ravail += len(buf);
+};
+
+// Unreads a rune; see [[unread]].
+export fn unreadrune(s: io::handle, rn: rune) void = {
+ const buf = utf8::encoderune(rn);
+ unread(s, buf);
+};
+
+// Returns true if an [[io::handle]] is a [[stream]].
+export fn isbuffered(in: io::handle) bool = {
+ match (in) {
+ case io::file =>
+ return false;
+ case let st: *io::stream =>
+ return st.reader == &read || st.writer == &write;
+ };
+};
+
+fn close_static(s: *io::stream) (void | io::error) = {
+ assert(s.closer == &close_static);
+ if (s.writer != null) {
+ flush(s: *stream)?;
+ };
+};
+
+fn read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
+ assert(s.reader == &read);
+ let s = s: *stream;
+
+ if (s.ravail < len(buf) && s.ravail < len(s.rbuffer)) {
+ s.rbuffer[..s.ravail] = s.rbuffer[s.rpos..s.rpos + s.ravail];
+ s.rpos = 0;
+ match (io::read(s.source, s.rbuffer[s.ravail..])) {
+ case let err: io::error =>
+ return err;
+ case io::EOF =>
+ if (s.ravail == 0) {
+ return io::EOF;
+ };
+ case let z: size =>
+ s.ravail += z;
+ };
+ };
+
+ const n = if (len(buf) < s.ravail) len(buf) else s.ravail;
+ buf[..n] = s.rbuffer[s.rpos..s.rpos + n];
+ s.rpos += n;
+ s.ravail -= n;
+ return n;
+};
+
+fn write(s: *io::stream, buf: const []u8) (size | io::error) = {
+ assert(s.writer == &write);
+ let s = s: *stream;
+ let buf = buf;
+
+ let doflush = false;
+ if (len(s.flush) != 0) {
+ for (let i = 0z; i < len(buf); i += 1) :search {
+ for (let j = 0z; j < len(s.flush); j += 1) {
+ if (buf[i] == s.flush[j]) {
+ doflush = true;
+ break :search;
+ };
+ };
+ };
+ };
+
+ let z = 0z;
+ for (len(buf) > 0) {
+ let avail = len(s.wbuffer) - s.wavail;
+ if (avail == 0) {
+ flush(s)?;
+ avail = len(s.wbuffer);
+ };
+
+ const n = if (avail < len(buf)) avail else len(buf);
+ s.wbuffer[s.wavail..s.wavail + n] = buf[..n];
+ buf = buf[n..];
+ s.wavail += n;
+ z += n;
+ };
+
+ if (doflush) {
+ flush(s)?;
+ };
+
+ return z;
+};
diff --git a/bufio/stream_test+test.ha b/bufio/stream_test+test.ha
@@ -0,0 +1,117 @@
+use bytes;
+use io;
+use memio;
+use strings;
+
+@test fn read() void = {
+ let sourcebuf: []u8 = [1, 3, 3, 7];
+ let source = memio::fixed(sourcebuf);
+ defer io::close(&source)!;
+
+ let rbuf: [1024]u8 = [0...];
+ let f = init(&source, rbuf, []);
+ defer io::close(&f)!;
+
+ let buf: [1024]u8 = [0...];
+ assert(io::read(&f, buf[..2]) as size == 2);
+ assert(source.pos == len(source.buf), "fixed stream was not fully consumed");
+ assert(bytes::equal(buf[..2], [1, 3]));
+
+ assert(io::read(&f, buf[2..]) as size == 2);
+ assert(bytes::equal(buf[..4], [1, 3, 3, 7]));
+ assert(io::read(&f, buf) is io::EOF);
+
+ let sourcebuf: [32]u8 = [1, 3, 3, 7, 0...];
+ let source = memio::fixed(sourcebuf);
+
+ let rbuf: [16]u8 = [0...];
+ let f = init(&source, rbuf, []);
+ defer io::close(&f)!;
+
+ let buf: [32]u8 = [0...];
+ assert(io::read(&f, buf) as size == 16);
+ assert(source.pos == 16);
+
+ assert(io::read(&f, buf[16..]) as size == 16);
+ assert(bytes::equal(buf, sourcebuf));
+ assert(io::read(&f, buf) is io::EOF);
+ assert(source.pos == len(source.buf));
+};
+
+@test fn write() void = {
+ // Normal case
+ let sink = memio::dynamic();
+ defer io::close(&sink)!;
+
+ let wbuf: [1024]u8 = [0...];
+ let f = init(&sink, [], wbuf);
+ defer io::close(&f)!;
+
+ assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
+ assert(len(memio::buffer(&sink)) == 0);
+ assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
+ assert(flush(&f) is void);
+ assert(bytes::equal(memio::buffer(&sink), [1, 3, 3, 7, 1, 3, 3, 7]));
+
+ // Test flushing via buffer exhaustion
+ let sink = memio::dynamic();
+ defer io::close(&sink)!;
+
+ let wbuf: [4]u8 = [0...];
+ let f = init(&sink, [], wbuf);
+
+ assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
+ assert(len(memio::buffer(&sink)) == 0);
+ assert(io::writeall(&f, [1, 3, 3, 7]) as size == 4);
+ assert(bytes::equal(memio::buffer(&sink), [1, 3, 3, 7]));
+ io::close(&f)!; // Should flush
+ assert(bytes::equal(memio::buffer(&sink), [1, 3, 3, 7, 1, 3, 3, 7]));
+
+ // Test flushing via flush characters
+ let sink = memio::dynamic();
+ defer io::close(&sink)!;
+
+ let wbuf: [1024]u8 = [0...];
+ let f = init(&sink, [], wbuf);
+
+ assert(io::writeall(&f, strings::toutf8("hello")) as size == 5);
+ assert(len(memio::buffer(&sink)) == 0);
+ assert(io::writeall(&f, strings::toutf8(" world!\n")) as size == 8);
+ assert(bytes::equal(memio::buffer(&sink), strings::toutf8("hello world!\n")));
+};
+
+@test fn unread() void = {
+ let rbuf: [8]u8 = [0...];
+ let f = init(io::zero, rbuf, []);
+
+ let buf: [16]u8 = [42...];
+ assert(io::read(&f, buf[..4]) as size == 4);
+ assert(buf[0] == 0);
+ assert(buf[1] == 0);
+ assert(buf[2] == 0);
+ assert(buf[3] == 0);
+ unread(&f, [1, 2, 3, 4]);
+
+ assert(io::read(&f, buf[..8]) as size == 8);
+ assert(buf[0] == 1);
+ assert(buf[1] == 2);
+ assert(buf[2] == 3);
+ assert(buf[3] == 4);
+ assert(buf[4] == 0);
+ assert(buf[5] == 0);
+ assert(buf[6] == 0);
+ assert(buf[7] == 0);
+
+ assert(io::read(&f, buf) as size == 8);
+ for (let i = 0z; i < 8; i += 1) {
+ assert(buf[i] == 0);
+ };
+
+ let input: []u8 = [1, 2, 3, 4];
+ let f = init(&memio::fixed(input), rbuf, []);
+
+ assert(io::read(&f, buf) as size == 4);
+ unread(&f, [1, 2, 3, 4]);
+ assert(io::read(&f, buf) as size == 4);
+ assert(io::read(&f, buf) is io::EOF);
+};
diff --git a/cmd/hare/schedule.ha b/cmd/hare/schedule.ha
@@ -16,7 +16,6 @@ use os;
use path;
use shlex;
use strings;
-use strio;
fn getenv(var: str) []str = {
match (os::getenv(var)) {
diff --git a/cmd/harec/context.ha b/cmd/harec/context.ha
@@ -1,14 +1,14 @@
// License: GPL-3.0
// (c) 2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
-use bufio;
use io;
use hare::types;
use hare::unit;
+use memio;
type context = struct {
out: io::handle,
- buf: bufio::memstream,
+ buf: memio::stream,
store: *types::typestore,
unit: *unit::unit,
arch: struct {
diff --git a/cmd/harec/gen.ha b/cmd/harec/gen.ha
@@ -2,7 +2,6 @@
// (c) 2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use bufio;
use fmt;
use hare::ast;
use hare::lex;
@@ -12,6 +11,7 @@ use hare::types::{builtin};
use hare::unit;
use hare::unit::{object_kind};
use io;
+use memio;
use os;
use strings;
@@ -19,7 +19,7 @@ fn gen(out: io::handle, store: *types::typestore, unit: *unit::unit) void = {
// TODO: context_init
let ctx = context {
out = out,
- buf = bufio::dynamic(io::mode::WRITE),
+ buf = memio::dynamic(),
store = store,
unit = unit,
arch = struct {
@@ -77,7 +77,7 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = {
// on-demand at the start of the function, rather than spread out
// through the body. This is more reliable on qbe's ARM backend, and
// generates better IL besides.
- bufio::reset(&ctx.buf);
+ memio::reset(&ctx.buf);
fmt::fprintln(&ctx.buf, mklabel(ctx, "body"))!;
@@ -90,7 +90,7 @@ fn gen_func(ctx: *context, decl: *unit::decl) void = {
};
};
- io::writeall(ctx.out, bufio::buffer(&ctx.buf))!;
+ io::writeall(ctx.out, memio::buffer(&ctx.buf))!;
fmt::fprintln(ctx.out, "}\n")!;
};
diff --git a/cmd/harec/main.ha b/cmd/harec/main.ha
@@ -70,7 +70,7 @@ export fn main() void = {
};
defer io::close(input)!;
static let buf: [os::BUFSIZ]u8 = [0...];
- let bufin = bufio::buffered(input, buf, []);
+ let bufin = bufio::init(input, buf, []);
defer io::close(&bufin)!;
let lexer = lex::init(&bufin, cmd.args[i]);
diff --git a/cmd/haredoc/docstr.ha b/cmd/haredoc/docstr.ha
@@ -11,8 +11,8 @@ use fmt;
use hare::ast;
use hare::parse;
use io;
+use memio;
use strings;
-use strio;
type paragraph = void;
type text = str;
@@ -28,14 +28,14 @@ type docstate = enum {
};
type parser = struct {
- src: bufio::bufstream,
+ src: bufio::stream,
state: docstate,
};
fn parsedoc(in: io::handle) parser = {
static let buf: [4096]u8 = [0...];
return parser {
- src = bufio::buffered(in, buf[..], []),
+ src = bufio::init(in, buf[..], []),
state = docstate::PARAGRAPH,
};
};
@@ -84,7 +84,7 @@ fn scantext(par: *parser) (token | void) = {
return paragraph;
};
// TODO: Collapse whitespace
- const buf = strio::dynamic();
+ const buf = memio::dynamic();
for (true) {
const rn = match (bufio::scanrune(&par.src)!) {
case io::EOF => break;
@@ -96,7 +96,7 @@ fn scantext(par: *parser) (token | void) = {
bufio::unreadrune(&par.src, rn);
break;
case '\n' =>
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
const rn = match (bufio::scanrune(&par.src)!) {
case io::EOF => break;
case let rn: rune =>
@@ -111,10 +111,10 @@ fn scantext(par: *parser) (token | void) = {
break;
};
case =>
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
};
};
- let result = strio::string(&buf);
+ let result = memio::string(&buf)!;
if (len(result) == 0) {
return;
};
@@ -140,7 +140,7 @@ fn scanref(par: *parser) (token | void) = {
};
};
- const buf = strio::dynamic();
+ const buf = memio::dynamic();
defer io::close(&buf)!;
// TODO: Handle invalid syntax here
for (true) {
@@ -151,12 +151,12 @@ fn scanref(par: *parser) (token | void) = {
bufio::scanrune(&par.src) as rune; // ]
break;
case =>
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
};
case io::EOF => break;
};
};
- let id = parse::identstr(strio::string(&buf)) as ast::ident;
+ let id = parse::identstr(memio::string(&buf)!) as ast::ident;
return id: reference;
};
@@ -183,7 +183,7 @@ fn scansample(par: *parser) (token | void) = {
};
let cont = true;
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
for (cont) {
const rn = match (bufio::scanrune(&par.src)!) {
case io::EOF => break;
@@ -192,9 +192,9 @@ fn scansample(par: *parser) (token | void) = {
};
switch (rn) {
case '\n' =>
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
case =>
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
continue;
};
@@ -209,7 +209,7 @@ fn scansample(par: *parser) (token | void) = {
case '\t' =>
i += 8;
case '\n' =>
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
i = 0;
case =>
bufio::unreadrune(&par.src, rn);
@@ -220,7 +220,7 @@ fn scansample(par: *parser) (token | void) = {
};
};
- let buf = strio::string(&buf);
+ let buf = memio::string(&buf)!;
// Trim trailing newlines
buf = strings::rtrim(buf, '\n');
return buf: sample;
diff --git a/cmd/haredoc/hare.ha b/cmd/haredoc/hare.ha
@@ -11,7 +11,6 @@ use hare::unparse;
use io;
use os;
use strings;
-use strio;
// Formats output as Hare source code (prototypes)
fn emit_hare(ctx: *context) (void | error) = {
diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha
@@ -7,7 +7,6 @@
// (c) 2022 Umar Getagazov <umar@handlerug.me>
// Note: ast::ident should never have to be escaped
-use bufio;
use encoding::utf8;
use fmt;
use hare::ast;
@@ -16,12 +15,12 @@ use hare::lex;
use hare::module;
use hare::unparse;
use io;
+use memio;
use net::ip;
use net::uri;
use os;
use path;
use strings;
-use strio;
// Prints a string to an output handle, escaping any of HTML's reserved
// characters.
@@ -52,20 +51,20 @@ fn html_escape(out: io::handle, in: str) (size | io::error) = {
};
@test fn html_escape() void = {
- let sink = strio::dynamic();
+ let sink = memio::dynamic();
defer io::close(&sink)!;
html_escape(&sink, "hello world!")!;
- assert(strio::string(&sink) == "hello world!");
+ assert(memio::string(&sink)! == "hello world!");
- let sink = strio::dynamic();
+ let sink = memio::dynamic();
defer io::close(&sink)!;
html_escape(&sink, "\"hello world!\"")!;
- assert(strio::string(&sink) == ""hello world!"");
+ assert(memio::string(&sink)! == ""hello world!"");
- let sink = strio::dynamic();
+ let sink = memio::dynamic();
defer io::close(&sink)!;
html_escape(&sink, "<hello & 'world'!>")!;
- assert(strio::string(&sink) == "<hello & 'world'!>");
+ assert(memio::string(&sink)! == "<hello & 'world'!>");
};
// Formats output as HTML
@@ -331,7 +330,7 @@ fn details(ctx: *context, decl: ast::decl) (void | error) = {
const trimmed = trim_comment(decl.docs);
defer free(trimmed);
const buf = strings::toutf8(trimmed);
- markup_html(ctx, &bufio::fixed(buf, io::mode::READ))?;
+ markup_html(ctx, &memio::fixed(buf))?;
} else {
fmt::fprintln(ctx.out, "</details>")?;
};
@@ -632,10 +631,10 @@ fn type_html(
brief: bool,
) (size | io::error) = {
if (brief) {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
defer io::close(&buf)!;
unparse::_type(&buf, indent, _type)?;
- return html_escape(out, strio::string(&buf))?;
+ return html_escape(out, memio::string(&buf)!)?;
};
// TODO: More detailed formatter which can find aliases nested deeper in
@@ -854,7 +853,7 @@ fn breadcrumb(ident: ast::ident) str = {
if (len(ident) == 0) {
return "";
};
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
fmt::fprintf(&buf, "<a href='/'>stdlib</a> » ")!;
for (let i = 0z; i < len(ident) - 1; i += 1) {
let ipath = module::identpath(ident[..i+1]);
@@ -862,7 +861,7 @@ fn breadcrumb(ident: ast::ident) str = {
fmt::fprintf(&buf, "<a href='/{}'>{}</a>::", ipath, ident[i])!;
};
fmt::fprint(&buf, ident[len(ident) - 1])!;
- return strio::string(&buf);
+ return memio::string(&buf)!;
};
const harriet_b64 = "iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEUAAAD///+l2Z/dAAAK40lEQVRo3u3ZX2xb1R0H8O/NzWIXXGw0xILa1QE6Wk0gMspIESU3WSf2sD/wODFtpFC1Q1Ob0AJpacm5pYVUAxHENK2IUiONaQ/TBIjRFKXNvSHbijSDeaGja5vr/ovHlmIHQ66de+/57iF27Gv7um8TD/glUvzROb9z7jnnnp9/4GU++Ap8iYEeJ6EFA9k9SSlGgkFRFiizs8HgPKWQ33ZFIEgZjiYNSwsECTpxaViJQKDRSUnDSgUBKcjN0mAmEJAclAbtIOCRhiMNOkHAIVl0DRaDQJ6k5xr0gkCGpOuRbhDIkvzUWwi2IbBI8smF4TYEr5C0nzTIIGCQ5N1NgEbaPGaUZD2QgvKw0QxYzviJkSbAZXH8RPQVozSceuDROzw3ciYYFOkdPhE9YxhBwOGlwydGThtkqjHIk/98fOT06wtz3hBMnfh85HTWCAI2p6a+ME7zWCCQU3MfaUkRDBzL/mg0Sa8JcE4Mz/DY4rKui+HTY/cPz9AIBHJm6onhGVbWfS2Yn7F+uXfGYBD4wnGtGXVmLBjwsf5jTYHzpHdUvTDmBYGMw0tT6ucMBLZjfPoLpRnwjLmtvV+UNmlj8Piu3lwzQHu0N5cNBpLj+d5cfxOQH8/3FrYGgrx0lrX3Ok3BA2sVZyttJ2hVe8faFSdqB4F5/vxgu+JodnALYupfitMVDJytcgeKg8HAE3NCKTIQFN1B3tLrBc+k5261blG814OBXOFs6PX+3AREt3T0en8IBC6fvXSkpwmQ3P+1I/DeDgbyvbaP4R02AsFQsu09eIezweCvLWl41wZ2QbFR7YOL/mAwrXYoLoQVBLRzSidcPHkmCBj58Atw9WYA+hVyYksgSMzq5hXy4mNeICjqPbfKt78VAKy0dQQ9Qj59q5dvCEw9dQTKqNy7rL/h7i704d6j92FU/vpUAFASWbcdo+5Tp37VECRDzLirO+ha0tncALjZEWYkbqZNOr0NwPMik7MlHpMqKU+JepDRisxLXcuuIjnfANAaYp77jPxxkvP1XbjMWymHfzOOkqTM1gE5tDszeZKTTqpyD/ABzU7EeZI/c/OlC1Ut0Heet5hkf+nqkKkFxYnu3eQFitIrM1ULXHXEIrtZvsX9o66LUJ7kIWGUl1YtONS2m6RVvnn018XwaUgzFq4gJMl7a+fBLWzXFi8xpKx7+7vKzkTV8Pm7uqm23Or5YflaWwGmRkpt8WKRzdUAZ2+CVTEwNVcDCshmSBbKozhlCz+QLYP+N4et+UEiGr8MqAyAJHnRNmrmYeFPjo7hhkh6dqImhoWYCnSttEKymI/7QenZHBC2MCFIJ+cH7vWh0hulaOjQyHyhBnA2J0qPCUiQLERrpnrhmnsjbQGkGgFOkuQGOoSSqQcFU3guKQfpEWq+UQvqYlcLYHe0wRF0Xi63KKA69eB8QewhKc/atKAWSTkV8oHptigpzjJDsiHI2iRlnHGSUM6SHPWDUCFO0hWuQwJnSXK4QZAhFklCyZHMTtQsOS1TTkAAk+R/0z7wXKE9SroicxepK30knVkfWJfTSA5TdgvqAEk+EphnLYC5og8sbJOikAnSRIcgDbfhkpvuFjQBksd8QGrnF9bDlCDTCzF4vhbS0btJyqhkGVg1XZiCLh1mk2QOSiOgCZK0EinmECI55wOumCApGKVGuojXpdXF82nBAj/jXJykSZIc93WRSpPZImfnKhn3UX8MWZKajEoxXJVyVc3D1bl1dEnK7ZWLgC+G4lmNGdKtJLsUogpkmNNIg5PFFP0HwuKSm3U1Kcj8Sbsq/a2AwkAhcjxPSnGS5AdDlSjL4KGCUGjxrPy6IA++X3m+JZDrWtGmUmPc0wW5653Kdi+B9+QTK65ySTomKe3Buqn+GH1sd0hy4pAopWludQyzs89SJWWeE4mEb42VgwzFB6OC71BLrvEfayWQTu+IjguSorCqvIonq8Fes88qkJTiXLQExNPVIIdn4ueNcSbsd5eX/qP5DpBcy4pdz4id7LIPvVSKasVSXwybhrpyMs+u7FgpSDeyonqYE+qOyKRhc0vq/KrSeYru6mHGQvqy5zWXD2eT58pXD9+CGVCe6Sp0F+mIk/tLQLd9jxvron13k/Pisx2bSQ6Se3y7G+jsTgtSWnO59eT0JsG9ftDy6t05Usoxt0+1eCaZ5/BMFZDX5/Zft50Guf1IUknQGctyOFsNHppc3k5q5ODR0xtesmgbHPY9rLASW8LufjLjHei7K0GSz6+qbgFQVVd+YGezfCO55i2SfP4bVcDtiUVDnzCZGSuy80N1jSD53APVLehYHprUilk6o30vYns/OWreWh2Drq4N/Z351Jzd/8lhbN9iFV80Vf9ErR/RN9uJS/Lk2ZVQt1jFF+F7Lb6GNjUseNcu74WdK6EsPbmhBuiIqLGhoW27jNc6f4QYPn5Yb/G9L0yoz9y+Q5um6OgMAzjQgw5fC0/hytbIfSJJ66ftMewDwi1+cAhAGKnTjpErgxt94ICC5P1IFB0ndxuwD51hfMe3qtMK0vcpY/mxvHsH8BpiUGK+Fs6hZf/tapfdPchHASAGxHwtJDG8dvW1m4aG7uWjVwKIdaDFdwwWwti+ujU5ZU9l3CvQis4OoLoFcwB9Pwg/95KVOTPtXnFtK2JA9UxaPAdErx75zcvZ7PuFZS9CeQFQfCfMtBJbtmd4zctZeebUZh2qDiylf3cPqOqPeVf/7lOntqQBYKleHaQZ7klfhYfHh7bSeXkBRNZXgJzk7B59+bYfjouZFOc/eVAHYuH1vi7yKmLusrHBS2c4/5/vmUA7enyb92ALsFvt9C6+YnXMf9iDcASoasHFughwce+A4DtjFz42gchN1UCSbjuU48MDXXTeenyFiWtaWxTf+WBe1Qn1gz8ORBXnjjvu+FAHdGWv/5XUgfg+uTEykX+8bTSnA1AmfaO4qgdxTF1QzOOb2kZzaQAIVQNTAlAOXlInRnY/txJpAFCrQI4EoPxll/ryN9cl0ToBILykugVXjQHKd3/zoLZ07brV6AEQifsv3jrQsnlV34qlHdcsQw+A1hpgAh33bOu7xnsVoRvuaQDSQF9ywOwUb6DtBgDlFbe4HtJAZP/GyevFm0BLKwD4Uhg9WgCWHvj++o7Nb4aBlXWAhQFgyXVt2LRV+RMQ2wfAly2avx8A2te0tGzdqBLAPsRUzR/kNHD1bcAHSdhHAACqUQ3+jVbgxptiiCTx26M9PQCW1CRBLvBgayewBPvWnTYbAJq4R9GBPdBv9kwsbovF7a+aiAA9APSbb+kB4E+rcypNlD+RJX2PhDFY04UEAHQCQCT8RC68WKAozaQOFwAGVCAGbBtoDWk1LZh7dQA/ARCLoBPoqgEXoOrlGJZMdgJd9T+qL4Lw5FqgvjyR6yx9H8O7nQtJTPX7oh2YXRynuXi8+LrIl/sIm8CVhXjtPOjKCwCANvQAWBatbcEk3ygBLJ5w/nv1qy2ofKxa4CLqjFS+v7Nxqait/L268/N4I7Cp9H1L4s7F3NgHZjoA4KbtaqXM41tyiAMApgejlV+Ka/KLtLq8e9806ZlqQLFJ04xsk4IXECIzx11EgytiBUCp/OofWFMbaQ4KVRW1WpCGIuaDg6waXLYBSFdin2v0uCcqOyhqNAkSomllMK01Lx2evUxt8enLFB8roeXizae6Os2qBwXEm9U302heANUvUyEd/n9Vac3mwFW+qlZ/WcH/ADT9vVqjZ2RdAAAAAElFTkSuQmCC";
diff --git a/cmd/haredoc/main.ha b/cmd/haredoc/main.ha
@@ -3,7 +3,6 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
// (c) 2022 Sebastian <sebastian@sebsite.pw>
-use bufio;
use fmt;
use fs;
use getopt;
@@ -13,6 +12,7 @@ use hare::module;
use hare::parse;
use hare::unparse;
use io;
+use memio;
use os;
use os::exec;
use path;
@@ -232,7 +232,7 @@ export fn main() void = {
// to the ident in the string. For example, this function will parse `rt::abort`
// as a valid identifier.
fn parseident(in: str) (ast::ident | parse::error) = {
- const buf = bufio::fixed(strings::toutf8(in), io::mode::READ);
+ const buf = memio::fixed(strings::toutf8(in));
const lexer = lex::init(&buf, "<string>");
defer lex::finish(&lexer);
let ident: []str = []; // TODO: errdefer
diff --git a/cmd/haredoc/tty.ha b/cmd/haredoc/tty.ha
@@ -10,9 +10,9 @@ use hare::ast::{variadism};
use hare::lex;
use hare::unparse;
use io;
+use memio;
use os;
use strings;
-use strio;
let firstline: bool = true;
@@ -270,22 +270,22 @@ fn prototype_tty(
// estimate length of prototype to determine if it should span multiple
// lines
const linelen = if (len(t.params) == 0) {
- let strm = strio::dynamic();
+ let strm = memio::dynamic();
defer io::close(&strm)!;
type_tty(&strm, indent, *t.result)?;
- retname = strings::dup(strio::string(&strm));
+ retname = strings::dup(memio::string(&strm)!);
yield 0z; // only use one line if there's no parameters
} else {
- let strm = strio::dynamic();
+ let strm = memio::dynamic();
defer io::close(&strm)!;
let linelen = indent * 8 + 5;
linelen += if (len(t.params) != 0) len(t.params) * 3 - 1 else 0;
for (let i = 0z; i < len(t.params); i += 1) {
const param = t.params[i];
linelen += unparse::_type(&strm, indent, *param._type)?;
- typenames[i] = strings::dup(strio::string(&strm));
+ typenames[i] = strings::dup(memio::string(&strm)!);
linelen += if (param.name == "") 1 else len(param.name);
- strio::reset(&strm);
+ memio::reset(&strm);
};
switch (t.variadism) {
case variadism::NONE => void;
@@ -295,7 +295,7 @@ fn prototype_tty(
linelen += 5;
};
linelen += type_tty(&strm, indent, *t.result)?;
- retname = strings::dup(strio::string(&strm));
+ retname = strings::dup(memio::string(&strm)!);
yield linelen;
};
diff --git a/cmd/haredoc/util.ha b/cmd/haredoc/util.ha
@@ -5,8 +5,8 @@ use fmt;
use hare::ast;
use hare::module;
use io;
+use memio;
use strings;
-use strio;
// Forked from [[hare::unparse]].
fn newline(out: io::handle, indent: size) (size | io::error) = {
@@ -22,7 +22,7 @@ fn multiline_comment(s: str) bool =
strings::byteindex(s, '\n') as size != len(s) - 1;
fn trim_comment(s: str) str = {
- let trimmed = strio::dynamic();
+ let trimmed = memio::dynamic();
let tok = strings::tokenize(s, "\n");
for (true) {
const line = match (strings::next_token(&tok)) {
@@ -31,9 +31,9 @@ fn trim_comment(s: str) str = {
case let line: str =>
yield line;
};
- strio::concat(&trimmed, strings::trimprefix(line, " "), "\n")!;
+ memio::concat(&trimmed, strings::trimprefix(line, " "), "\n")!;
};
- return strings::dup(strio::string(&trimmed));
+ return strings::dup(memio::string(&trimmed)!);
};
fn submodules(ctx: *context) ([]str | error) = {
diff --git a/crypto/aes/+test/gcm.ha b/crypto/aes/+test/gcm.ha
@@ -1,8 +1,8 @@
-use bufio;
use bytes;
use crypto::cipher;
use errors;
use io;
+use memio;
type gcmtestcase = struct {
key: []u8,
@@ -605,7 +605,7 @@ const gcmtestcases: []gcmtestcase = [
} else {
yield alloc([0...], len(t.cipher));
};
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let gstream = cipher::gcm();
cipher::gcm_init(&gstream, &resultbuf, &b, t.iv, t.additional);
@@ -632,7 +632,7 @@ const gcmtestcases: []gcmtestcase = [
} else {
yield alloc([0...], len(t.cipher));
};
- let cipherbuf = bufio::fixed(t.cipher, io::mode::READ);
+ let cipherbuf = memio::fixed(t.cipher);
let gstream = cipher::gcm();
cipher::gcm_init(&gstream, &cipherbuf, &b, t.iv, t.additional);
@@ -668,7 +668,7 @@ const gcmtestcases: []gcmtestcase = [
r[..] = t.plain[..];
yield r;
};
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let gstream = cipher::gcm();
// beware: did not close the stream for sake of simplicity
@@ -681,7 +681,7 @@ const gcmtestcases: []gcmtestcase = [
assert(bytes::equal(t.cipher, result));
assert(bytes::equal(t.tag, tag));
- let resultbuf = bufio::fixed(result, io::mode::READ);
+ let resultbuf = memio::fixed(result);
let gstream = cipher::gcm();
cipher::gcm_init(&gstream, &resultbuf, &b, t.iv, t.additional);
io::readall(&gstream, result)!;
diff --git a/crypto/aes/ctr+test.ha b/crypto/aes/ctr+test.ha
@@ -2,10 +2,10 @@
// (c) 2022 Armin Preiml <apreiml@strohwolke.at>
// (c) 2022 Drew DeVault <sir@cmpwn.com>
use bytes;
-use bufio;
use crypto::cipher;
use errors;
use io;
+use memio;
@test fn ctr_zero_iv() void = {
const key: [_]u8 = [
@@ -30,7 +30,7 @@ use io;
let result: [16]u8 = [0...];
let buf: [CTR_BUFSIZE]u8 = [0...];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let b = ct64();
ct64_init(&b, key);
@@ -51,7 +51,7 @@ use io;
result = [0...];
buf = [0...];
- let cipherbuf = bufio::fixed(cipher, io::mode::READ);
+ let cipherbuf = memio::fixed(cipher);
let ctr = cipher::ctr(&cipherbuf, &b, iv[..], buf[..]);
const s = io::readall(&ctr, result)!;
assert(s as size == len(plain));
@@ -82,7 +82,7 @@ use io;
];
let result: [18]u8 = [0...];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let buf: [CTR_BUFSIZE]u8 = [0...];
let b = ct64();
@@ -133,7 +133,7 @@ use io;
];
let result: [80]u8 = [0...];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let buf: [CTR_BUFSIZE]u8 = [0...];
let b = ct64();
@@ -148,7 +148,7 @@ use io;
let b = ct64();
ct64_init(&b, key);
- let cipherbuf = bufio::fixed(cipher, io::mode::READ);
+ let cipherbuf = memio::fixed(cipher);
let ctr = cipher::ctr(&cipherbuf, &b, iv[..], buf[..]);
const n = io::readall(&ctr, result)!;
assert(n as size == len(plain));
@@ -194,7 +194,7 @@ use io;
];
let result: [80]u8 = [0...];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let buf: [CTR_BUFSIZE]u8 = [0...];
let b = ct64();
@@ -210,7 +210,7 @@ use io;
assert(n == len(plain));
assert(bytes::equal(cipher, result));
- let cipherbuf = bufio::fixed(cipher, io::mode::READ);
+ let cipherbuf = memio::fixed(cipher);
let ctr = cipher::ctr(&cipherbuf, &b, iv[..], buf[..]);
const n = io::readall(&ctr, result)!;
assert(n as size == len(plain));
@@ -245,7 +245,7 @@ use io;
defer cipher::finish(&b);
let buf: [CTR_BUFSIZE]u8 = [0...];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
defer io::close(&ctr)!;
@@ -281,7 +281,7 @@ use io;
defer cipher::finish(&b);
let buf: [64]u8 = [0...];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
defer io::close(&ctr)!;
@@ -307,7 +307,7 @@ use io;
let buf: [64]u8 = [0...];
let result: [1]u8 = [0];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let ctr = cipher::ctr(&resultbuf, &b, iv[..], buf[..]);
defer io::close(&ctr)!;
@@ -397,7 +397,7 @@ fn errwriter(out: io::handle, limit: size, err: io::error) err_stream = {
];
let result: [80]u8 = [0...];
- let resultbuf = bufio::fixed(result, io::mode::WRITE);
+ let resultbuf = memio::fixed(result);
let errw = errwriter(&resultbuf, 20, errors::again);
let buf: [CTR_BUFSIZE]u8 = [0...];
diff --git a/crypto/argon2/argon2.ha b/crypto/argon2/argon2.ha
@@ -1,7 +1,6 @@
// (c) 2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021-2022 Armin Preiml <apreiml@strohwolke.at>
// (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
-use bufio;
use bytes;
use crypto::blake2b;
use crypto::math;
@@ -9,6 +8,7 @@ use endian;
use errors::{nomem};
use hash;
use io;
+use memio;
use types;
// Latest version of argon2 supported by this implementation (1.3).
@@ -344,7 +344,7 @@ fn varhash(dest: []u8, block: []u8) void = {
const r = divceil(len(dest): u32, 32) - 2;
let v: [64]u8 = [0...];
- let destbuf = bufio::fixed(dest, io::mode::WRITE);
+ let destbuf = memio::fixed(dest);
let h = blake2b::blake2b([], 64);
hash_leputu32(&h, len(dest): u32);
diff --git a/crypto/authenc.ha b/crypto/authenc.ha
@@ -2,11 +2,11 @@
// (c) 2023 Armin Preiml <apreiml@strohwolke.at>
// (c) 2023 Drew DeVault <sir@cmpwn.com>
use bytes;
-use bufio;
use crypto::chachapoly;
use crypto::math;
use errors;
use io;
+use memio;
// A secret session key.
export type sessionkey = [32]u8;
@@ -79,12 +79,12 @@ export fn encrypt(
let s = chachapoly::chachapoly();
defer io::close(&s)!;
- let h = bufio::fixed(plaintext, io::mode::WRITE);
+ let h = memio::fixed(plaintext);
chachapoly::xinit(&s, &h, key, nonce, additional...);
io::writeall(&s, plaintext)!;
let m: mac = [0...];
chachapoly::seal(&s, m);
- return (m, *nonce, bufio::buffer(&h));
+ return (m, *nonce, memio::buffer(&h));
};
// Authenticates and decrypts a message encrypted with [[encrypt]]. If the
@@ -111,7 +111,7 @@ export fn decrypt(
defer io::close(&s)!;
let ciphertext = box.2;
- let h = bufio::fixed(ciphertext, io::mode::READ);
+ let h = memio::fixed(ciphertext);
chachapoly::xinit(&s, &h, key, box.1, additional...);
let plaintext = ciphertext;
diff --git a/crypto/bcrypt/base64.ha b/crypto/bcrypt/base64.ha
@@ -4,10 +4,10 @@
//
// bcrypt uses a crappy variant of base64 with its own special alphabet and no
// padding. This file glues encoding::base64 to the bcrypt semantics.
-use bufio;
use encoding::base64;
use errors;
use io;
+use memio;
const alpha: str = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const b64encoding: base64::encoding = base64::encoding { ... };
@@ -19,9 +19,9 @@ const b64encoding: base64::encoding = base64::encoding { ... };
// Encodes a slice in the bcrypt base64 style, returning a new slice. The caller
// must free the return value.
fn b64_encode(src: []u8) []u8 = {
- let sink = bufio::dynamic(io::mode::WRITE);
+ let sink = memio::dynamic();
base64::encode(&sink, &b64encoding, src)!;
- let buf = bufio::buffer(&sink);
+ let buf = memio::buffer(&sink);
let i = len(buf);
for (i > 0 && buf[i - 1] == '='; i -= 1) void;
return buf[..i];
diff --git a/crypto/bcrypt/bcrypt.ha b/crypto/bcrypt/bcrypt.ha
@@ -6,7 +6,6 @@
// ported from Go.
//
// TODO: Move me into the extlib (hare-x-crypto?)
-use bufio;
use bytes;
use crypto::blowfish;
use crypto::cipher;
@@ -15,6 +14,7 @@ use crypto;
use errors;
use fmt;
use io;
+use memio;
use strconv;
use strings;
@@ -78,7 +78,7 @@ export fn compare(hash: []u8, password: []u8) (bool | errors::invalid) = {
};
fn mkhash(h: *hash) []u8 = {
- let buf = bufio::dynamic(io::mode::WRITE);
+ let buf = memio::dynamic();
fmt::fprintf(&buf, "${}$", h.major: u32: rune)!;
if (h.minor != 0) {
fmt::fprintf(&buf, "{}", h.minor: u32: rune)!;
@@ -86,7 +86,7 @@ fn mkhash(h: *hash) []u8 = {
fmt::fprintf(&buf, "${:02}$", h.cost)!;
io::write(&buf, h.salt)!;
io::write(&buf, h.hash)!;
- return bufio::buffer(&buf);
+ return memio::buffer(&buf);
};
fn hash_password(
diff --git a/crypto/blake2b/+test.ha b/crypto/blake2b/+test.ha
@@ -8,8 +8,8 @@ use encoding::hex;
use fmt;
use hash;
use io;
+use memio;
use strings;
-use strio;
@test fn blake2b() void = {
for (let i = 0z; i < len(vectors); i += 1) {
@@ -28,11 +28,11 @@ use strio;
append(sum, 0);
};
hash::sum(&blake, sum);
- let out = strio::dynamic();
+ let out = memio::dynamic();
defer io::close(&out)!;
let enc = hex::newencoder(&out);
io::write(&enc, sum)!;
- assert(strio::string(&out) == vectors[i].out);
+ assert(memio::string(&out)! == vectors[i].out);
};
const vectors = [
@@ -56,16 +56,16 @@ use strio;
assert(len(sum) >= hash::sz(&blake));
hash::sum(&blake, sum);
- let hex = strio::dynamic();
+ let hex = memio::dynamic();
defer io::close(&hex)!;
for (let j = 0z; j < len(sum); j += 1) {
fmt::fprintf(&hex, "{:02x}", sum[j])!;
};
- if (strio::string(&hex) != vector.1) {
+ if (memio::string(&hex)! != vector.1) {
fmt::errorfln("Vector {}: {} != {}",
- i, strio::string(&hex), vector.1)!;
+ i, memio::string(&hex)!, vector.1)!;
abort();
};
};
diff --git a/crypto/chacha/+test.ha b/crypto/chacha/+test.ha
@@ -1,9 +1,9 @@
// License: MPL-2.0
// (c) 2022 Armin Preiml <apreiml@strohwolke.at>
-use bufio;
use bytes;
use crypto::cipher;
use io;
+use memio;
// test vector taken from rfc8439
@test fn chacha20() void = {
@@ -48,7 +48,7 @@ use io;
let result: [114]u8 = [0...];
- let cipherbuf = bufio::fixed(result, io::mode::WRITE);
+ let cipherbuf = memio::fixed(result);
let c = chacha20();
defer io::close(&c)!;
@@ -61,7 +61,7 @@ use io;
assert(bytes::equal(cipher, result));
result = [0...];
- cipherbuf = bufio::fixed(result, io::mode::WRITE);
+ cipherbuf = memio::fixed(result);
chacha20_init(&c, &cipherbuf, key, nonce);
setctr(&c, 1);
@@ -155,7 +155,7 @@ const xcipher: [_]u8 = [
@test fn xchacha20() void = {
let result: [304]u8 = [0...];
- let cipherbuf = bufio::fixed(result, io::mode::WRITE);
+ let cipherbuf = memio::fixed(result);
let c = chacha20();
defer io::close(&c)!;
@@ -169,7 +169,7 @@ const xcipher: [_]u8 = [
@test fn skipblocks() void = {
let result: [18]u8 = [0...];
- let cipherbuf = bufio::fixed(result, io::mode::WRITE);
+ let cipherbuf = memio::fixed(result);
let c = chacha20();
defer io::close(&c)!;
diff --git a/crypto/chachapoly/chachapoly.ha b/crypto/chachapoly/chachapoly.ha
@@ -1,6 +1,5 @@
// License: MPL-2.0
// (c) 2023 Armin Preiml <apreiml@strohwolke.at>
-use bufio;
use bytes;
use crypto::chacha;
use crypto::mac;
@@ -9,6 +8,7 @@ use crypto::poly1305;
use endian;
use errors;
use io;
+use memio;
use types;
// Nonce size as required by [[init]].
@@ -89,7 +89,7 @@ fn geninit(
let otk: poly1305::key = [0...];
defer bytes::zero(otk);
- let otkbuf = bufio::fixed(otk, io::mode::WRITE);
+ let otkbuf = memio::fixed(otk);
finit(&s.c, &otkbuf, key, nonce);
io::writeall(&s.c, otk[..])!;
diff --git a/crypto/chachapoly/encryption+test.ha b/crypto/chachapoly/encryption+test.ha
@@ -1,8 +1,8 @@
// License: MPL-2.0
// (c) 2023 Armin Preiml <apreiml@strohwolke.at>
-use bufio;
use bytes;
use io;
+use memio;
@test fn encrypt() void = {
let plain: [_]u8 = [
@@ -57,7 +57,7 @@ use io;
0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91,
];
- let out = bufio::dynamic(io::mode::RDWR);
+ let out = memio::dynamic();
defer io::close(&out)!;
let s = chachapoly();
@@ -67,13 +67,13 @@ use io;
let outtag: [TAGSZ]u8 = [0...];
seal(&s, outtag);
- let outbuf = bufio::buffer(&out);
+ let outbuf = memio::buffer(&out);
assert(bytes::equal(outbuf, cipher));
assert(bytes::equal(outtag, tag));
- let out = bufio::dynamic(io::mode::RDWR);
+ let out = memio::dynamic();
defer io::close(&out)!;
- let in = bufio::fixed(cipher, io::mode::READ);
+ let in = memio::fixed(cipher);
let s = chachapoly();
init(&s, &in, key, nonce, ad);
@@ -81,7 +81,7 @@ use io;
verify(&s, tag)!;
- let outbuf = bufio::buffer(&out);
+ let outbuf = memio::buffer(&out);
assert(bytes::equal(outbuf, plain));
io::close(&s)!;
@@ -150,7 +150,7 @@ const rfcsample: sample = sample {
@test fn xencrypt() void = {
let tc = rfcsample;
- let out = bufio::dynamic(io::mode::RDWR);
+ let out = memio::dynamic();
defer io::close(&out)!;
let s = chachapoly();
@@ -160,13 +160,13 @@ const rfcsample: sample = sample {
let outtag: [TAGSZ]u8 = [0...];
seal(&s, outtag);
- let outbuf = bufio::buffer(&out);
+ let outbuf = memio::buffer(&out);
assert(bytes::equal(outbuf, tc.cipher));
assert(bytes::equal(outtag, tc.mac));
- let out = bufio::dynamic(io::mode::RDWR);
+ let out = memio::dynamic();
defer io::close(&out)!;
- let in = bufio::fixed(tc.cipher, io::mode::READ);
+ let in = memio::fixed(tc.cipher);
let s = chachapoly();
xinit(&s, &in, tc.key, tc.nonce, tc.additional);
@@ -174,7 +174,7 @@ const rfcsample: sample = sample {
verify(&s, tc.mac)!;
- let outbuf = bufio::buffer(&out);
+ let outbuf = memio::buffer(&out);
assert(bytes::equal(outbuf, tc.msg));
io::close(&s)!;
diff --git a/crypto/rsa/keys.ha b/crypto/rsa/keys.ha
@@ -1,12 +1,12 @@
// License: MPL-2.0
// (c) 2022 Armin Preiml <apreiml@strohwolke.at>
-use bufio;
use bytes;
use crypto::bigint;
use crypto::math::*;
use endian;
use errors;
use io;
+use memio;
use types;
// The default bit size of RSA keys is 4096-bit. Used as base for buffer sizes.
@@ -78,7 +78,7 @@ export fn pubkey_init(pubkey: []u8, x: pubparams) (size | error) = {
return errors::invalid;
};
- let w = bufio::fixed(pubkey, io::mode::WRITE);
+ let w = memio::fixed(pubkey);
let s = 0z;
s += writeslice(&w, e)!;
@@ -180,7 +180,7 @@ export fn privkey_init(privkey: []u8, x: privparams, n: []u8...) (size | error)
};
let s = privkey_writehead(privkey, &x, n...)?;
- let w = bufio::fixed(privkey[s..], io::mode::WRITE);
+ let w = memio::fixed(privkey[s..]);
s += writeslice(&w, x.dp)!;
s += writeslice(&w, x.dq)!;
@@ -233,7 +233,7 @@ fn privkey_writehead(
return errors::invalid;
};
- let w = bufio::fixed(privkey, io::mode::WRITE);
+ let w = memio::fixed(privkey);
let lenbuf: [2]u8 = [0...];
endian::beputu16(lenbuf, nbitlen: u16);
return io::write(&w, lenbuf)!;
@@ -262,7 +262,7 @@ export fn privkey_initd(
s += privkey_dmod(privkey[s..], d, x.p);
s += privkey_dmod(privkey[s..], d, x.q);
- let w = bufio::fixed(privkey[s..], io::mode::WRITE);
+ let w = memio::fixed(privkey[s..]);
s += writeslice(&w, x.iq)!;
s += writeslice(&w, x.p)!;
s += writeslice(&w, x.q)!;
diff --git a/crypto/salsa/+test.ha b/crypto/salsa/+test.ha
@@ -1,10 +1,10 @@
// License: MPL-2.0
// (c) 2021 Armin Preiml <apreiml@strohwolke.at>
-use bufio;
use bytes;
use crypto::cipher;
-use types;
use io;
+use memio;
+use types;
@test fn qr() void = {
let s: [4]u32 = [0xe7e8c006, 0xc4f9417d, 0x6479b4b2, 0x68c67137];
@@ -57,7 +57,7 @@ use io;
];
let result: [116]u8 = [0...];
- let cipherbuf = bufio::fixed(result, io::mode::WRITE);
+ let cipherbuf = memio::fixed(result);
let c = salsa20();
defer io::close(&c)!;
@@ -110,7 +110,7 @@ use io;
];
let result: [116]u8 = [0...];
- let cipherbuf = bufio::fixed(result, io::mode::WRITE);
+ let cipherbuf = memio::fixed(result);
let c = salsa20();
defer io::close(&c)!;
@@ -165,7 +165,7 @@ use io;
let result: [116]u8 = [0...];
- let cipherbuf = bufio::fixed(result, io::mode::WRITE);
+ let cipherbuf = memio::fixed(result);
let c = salsa20();
defer io::close(&c)!;
diff --git a/encoding/base32/base32.ha b/encoding/base32/base32.ha
@@ -1,10 +1,10 @@
// License: MPL-2.0
// (c) 2022 Ajay R <ar324@protonmail.com>
use ascii;
-use bufio;
use bytes;
use errors;
use io;
+use memio;
use os;
use strings;
@@ -166,11 +166,11 @@ fn encode_closer(s: *io::stream) (void | io::error) = {
// Encodes a byte slice in base-32, using the given encoding, returning a slice
// of ASCII bytes. The caller must free the return value.
export fn encodeslice(enc: *encoding, in: []u8) []u8 = {
- let out = bufio::dynamic(io::mode::WRITE);
+ let out = memio::dynamic();
let encoder = newencoder(enc, &out);
io::writeall(&encoder, in)!;
io::close(&encoder)!;
- return bufio::buffer(&out);
+ return memio::buffer(&out);
};
// Encodes a byte slice in base-32, using the given encoding, returning a
@@ -201,11 +201,11 @@ export fn encodestr(enc: *encoding, in: []u8) str = {
"CPNMUOJ1E8======",
];
for (let i = 0z; i <= len(in); i += 1) {
- let out = bufio::dynamic(io::mode::RDWR);
+ let out = memio::dynamic();
let enc = newencoder(&std_encoding, &out);
io::writeall(&enc, in[..i]) as size;
io::close(&enc)!;
- let outb = bufio::buffer(&out);
+ let outb = memio::buffer(&out);
assert(bytes::equal(outb, strings::toutf8(expect[i])));
free(outb);
// Testing encodestr should cover encodeslice too
@@ -213,11 +213,11 @@ export fn encodestr(enc: *encoding, in: []u8) str = {
defer free(s);
assert(s == expect[i]);
- out = bufio::dynamic(io::mode::RDWR);
+ out = memio::dynamic();
enc = newencoder(&hex_encoding, &out);
io::writeall(&enc, in[..i]) as size;
io::close(&enc)!;
- let outb = bufio::buffer(&out);
+ let outb = memio::buffer(&out);
assert(bytes::equal(outb, strings::toutf8(expect_hex[i])));
free(outb);
let s = encodestr(&hex_encoding, in[..i]);
@@ -361,15 +361,15 @@ export fn decodeslice(
enc: *encoding,
in: []u8,
) ([]u8 | errors::invalid) = {
- let in = bufio::fixed(in, io::mode::READ);
+ let in = memio::fixed(in);
let decoder = newdecoder(enc, &in);
- let out = bufio::dynamic(io::mode::WRITE);
+ let out = memio::dynamic();
match (io::copy(&out, &decoder)) {
case io::error =>
io::close(&out)!;
return errors::invalid;
case size =>
- return bufio::buffer(&out);
+ return memio::buffer(&out);
};
};
@@ -397,7 +397,7 @@ export fn decodestr(enc: *encoding, in: str) ([]u8 | errors::invalid) = {
("CPNMUOJ1E8======", "foobar", &hex_encoding),
];
for (let i = 0z; i < len(cases); i += 1) {
- let in = bufio::fixed(strings::toutf8(cases[i].0), io::mode::READ);
+ let in = memio::fixed(strings::toutf8(cases[i].0));
let dec = newdecoder(cases[i].2, &in);
let buf: [1]u8 = [0];
let out: []u8 = [];
@@ -419,7 +419,7 @@ export fn decodestr(enc: *encoding, in: str) ([]u8 | errors::invalid) = {
};
// Repeat of the above, but with a larger buffer
for (let i = 0z; i < len(cases); i += 1) {
- let in = bufio::fixed(strings::toutf8(cases[i].0), io::mode::READ);
+ let in = memio::fixed(strings::toutf8(cases[i].0));
let dec = newdecoder(cases[i].2, &in);
let buf: [1024]u8 = [0...];
let out: []u8 = [];
@@ -454,7 +454,7 @@ export fn decodestr(enc: *encoding, in: str) ([]u8 | errors::invalid) = {
("CPNG====CPNG====", &std_encoding),
];
for (let i = 0z; i < len(invalid); i += 1) {
- let in = bufio::fixed(strings::toutf8(invalid[i].0), io::mode::READ);
+ let in = memio::fixed(strings::toutf8(invalid[i].0));
let dec = newdecoder(invalid[i].1, &in);
let buf: [1]u8 = [0...];
let valid = false;
diff --git a/encoding/base64/base64.ha b/encoding/base64/base64.ha
@@ -6,10 +6,10 @@
// (c) 2021 Thomas Bracht Laumann Jespersen <t@laumann.xyz>
// (c) 2023 Armin Preiml <apreiml@strohwolke.at>
use ascii;
-use bufio;
use bytes;
use errors;
use io;
+use memio;
use os;
use strings;
@@ -211,24 +211,24 @@ fn clear(e: *encoder) void = {
];
const expected: str = `AAAAB3NzaC1yc2EA`;
- let buf = bufio::dynamic(io::mode::WRITE);
+ let buf = memio::dynamic();
let e = newencoder(&std_encoding, &buf);
io::writeall(&e, raw[..4])!;
io::writeall(&e, raw[4..11])!;
io::writeall(&e, raw[11..])!;
io::close(&e)!;
- assert(strings::fromutf8(bufio::buffer(&buf))! == expected);
+ assert(memio::string(&buf)! == expected);
};
// Encodes a byte slice in base 64, using the given encoding, returning a slice
// of ASCII bytes. The caller must free the return value.
export fn encodeslice(enc: *encoding, in: []u8) []u8 = {
- let out = bufio::dynamic(io::mode::WRITE);
+ let out = memio::dynamic();
let encoder = newencoder(enc, &out);
io::writeall(&encoder, in)!;
io::close(&encoder)!;
- return bufio::buffer(&out);
+ return memio::buffer(&out);
};
// Encodes base64 data using the given alphabet and writes it to a stream,
@@ -268,11 +268,11 @@ export fn encodestr(enc: *encoding, in: []u8) str = {
"Zm9vYmFy"
];
for (let i = 0z; i <= len(in); i += 1) {
- let out = bufio::dynamic(io::mode::WRITE);
+ let out = memio::dynamic();
let encoder = newencoder(&std_encoding, &out);
io::writeall(&encoder, in[..i])!;
io::close(&encoder)!;
- let encb = bufio::buffer(&out);
+ let encb = memio::buffer(&out);
defer free(encb);
assert(bytes::equal(encb, strings::toutf8(expect[i])));
@@ -418,15 +418,15 @@ export fn decodeslice(
enc: *encoding,
in: []u8,
) ([]u8 | errors::invalid) = {
- let in = bufio::fixed(in, io::mode::READ);
+ let in = memio::fixed(in);
let decoder = newdecoder(enc, &in);
- let out = bufio::dynamic(io::mode::WRITE);
+ let out = memio::dynamic();
match (io::copy(&out, &decoder)) {
case io::error =>
io::close(&out)!;
return errors::invalid;
case size =>
- return bufio::buffer(&out);
+ return memio::buffer(&out);
};
};
@@ -466,7 +466,7 @@ export fn decode(
("Zm9vYmFy", "foobar", &std_encoding),
];
for (let i = 0z; i < len(cases); i += 1) {
- let in = bufio::fixed(strings::toutf8(cases[i].0), io::mode::READ);
+ let in = memio::fixed(strings::toutf8(cases[i].0));
let decoder = newdecoder(cases[i].2, &in);
let buf: [1]u8 = [0];
let decb: []u8 = [];
@@ -488,7 +488,7 @@ export fn decode(
};
// Repeat of the above, but with a larger buffer
for (let i = 0z; i < len(cases); i += 1) {
- let in = bufio::fixed(strings::toutf8(cases[i].0), io::mode::READ);
+ let in = memio::fixed(strings::toutf8(cases[i].0));
let decoder = newdecoder(cases[i].2, &in);
let buf: [1024]u8 = [0...];
let decb: []u8 = [];
@@ -519,7 +519,7 @@ export fn decode(
("Zm8=Zm8=", &std_encoding),
];
for (let i = 0z; i < len(invalid); i += 1) {
- let in = bufio::fixed(strings::toutf8(invalid[i].0), io::mode::READ);
+ let in = memio::fixed(strings::toutf8(invalid[i].0));
let decoder = newdecoder(invalid[i].1, &in);
let buf: [1]u8 = [0...];
let valid = false;
diff --git a/encoding/hex/hex.ha b/encoding/hex/hex.ha
@@ -4,15 +4,14 @@
// (c) 2021 Ember Sawady <ecs@d2evs.net>
// (c) 2022 Sebastian <sebastian@sebsite.pw>
use ascii;
-use bufio;
use bytes;
use errors;
use fmt;
use io;
+use memio;
use os;
use strconv;
use strings;
-use strio;
export type encoder = struct {
stream: io::stream,
@@ -70,10 +69,10 @@ fn encode_writer(s: *io::stream, in: const []u8) (size | io::error) = {
// Encodes a byte slice as a hexadecimal string and returns it. The caller must
// free the return value.
export fn encodestr(in: []u8) str = {
- const out = strio::dynamic();
+ const out = memio::dynamic();
const enc = newencoder(&out);
io::writeall(&enc, in)!;
- return strio::string(&out);
+ return memio::string(&out)!;
};
@test fn encodestr() void = {
@@ -93,11 +92,11 @@ export fn encode(out: io::handle, in: []u8) (size | io::error) = {
@test fn encode() void = {
const in: [_]u8 = [0xCA, 0xFE, 0xBA, 0xBE, 0xDE, 0xAD, 0xF0, 0x0D];
- let out = strio::dynamic();
+ let out = memio::dynamic();
defer io::close(&out)!;
encode(&out, in)!;
- assert(strio::string(&out) == "cafebabedeadf00d");
+ assert(memio::string(&out)! == "cafebabedeadf00d");
};
export type decoder = struct {
@@ -172,12 +171,12 @@ fn decode_reader(s: *io::stream, out: []u8) (size | io::EOF | io::error) = {
// the return value.
export fn decodestr(s: str) ([]u8 | io::error) = {
let s = strings::toutf8(s);
- const in = bufio::fixed(s, io::mode::READ);
+ const in = memio::fixed(s);
const decoder = newdecoder(&in);
- const out = bufio::dynamic(io::mode::WRITE);
+ const out = memio::dynamic();
match(io::copy(&out, &decoder)) {
case size =>
- return bufio::buffer(&out);
+ return memio::buffer(&out);
case let err: io::error =>
return err;
};
@@ -234,11 +233,11 @@ export fn dump(out: io::handle, data: []u8) (void | io::error) = {
0xDE, 0xAD, 0xF0, 0x0D
];
- let sink = strio::dynamic();
+ let sink = memio::dynamic();
defer io::close(&sink)!;
dump(&sink, in) as void;
- let s = strio::string(&sink);
+ let s = memio::string(&sink)!;
assert(s ==
"00000000 7f 45 4c 46 02 01 01 00 ca fe ba be de ad f0 0d |.ELF............|\n"
"00000010 ce fe ba be de ad f0 0d |........|\n");
diff --git a/encoding/pem/+test.ha b/encoding/pem/+test.ha
@@ -1,18 +1,17 @@
// License: MPL-2.0
// (c) 2022 Drew DeVault <sir@cmpwn.com>
-use bufio;
use bytes;
use io;
use fmt;
+use memio;
use strings;
-use strio;
@test fn read() void = {
const testcert_str = fmt::asprintf(
"garbage\ngarbage\ngarbage\n{}garbage\n", cert_str);
defer free(testcert_str);
- const in = bufio::fixed(strings::toutf8(testcert_str), io::mode::READ);
+ const in = memio::fixed(strings::toutf8(testcert_str));
const dec = newdecoder(&in);
defer finish(&dec);
@@ -30,7 +29,7 @@ use strio;
@test fn read_many() void = {
const testmany = fmt::asprintf("{}{}", cert_str, privkey_str);
defer free(testmany);
- const in = bufio::fixed(strings::toutf8(testmany), io::mode::READ);
+ const in = memio::fixed(strings::toutf8(testmany));
const dec = newdecoder(&in);
defer finish(&dec);
@@ -49,28 +48,28 @@ use strio;
};
@test fn write() void = {
- let out = strio::dynamic();
+ let out = memio::dynamic();
const stream = newencoder("CERTIFICATE", &out)!;
io::writeall(&stream, testcert_bin)!;
io::close(&stream)!;
- assert(strio::string(&out) == cert_str);
+ assert(memio::string(&out)! == cert_str);
io::close(&out)!;
- let out = strio::dynamic();
+ let out = memio::dynamic();
const stream = newencoder("PRIVATE KEY", &out)!;
io::writeall(&stream, testprivkey_bin)!;
io::close(&stream)!;
- assert(strio::string(&out) == privkey_str);
+ assert(memio::string(&out)! == privkey_str);
io::close(&out)!;
// test short writes
- let out = strio::dynamic();
+ let out = memio::dynamic();
const stream = newencoder("CERTIFICATE", &out)!;
for (let i = 0z; i < len(testcert_bin); i += 1) {
io::write(&stream, [testcert_bin[i]])!;
};
io::close(&stream)!;
- assert(strio::string(&out) == cert_str);
+ assert(memio::string(&out)! == cert_str);
io::close(&out)!;
};
@@ -168,7 +167,7 @@ const testprivkey_bin: [_]u8 = [
const test_str = fmt::asprintf(
"garbage\r\ngarbage\r\ngarbage\r\n{}garbage\r\n", testcrlf_str);
defer free(test_str);
- const in = bufio::fixed(strings::toutf8(test_str), io::mode::READ);
+ const in = memio::fixed(strings::toutf8(test_str));
const dec = newdecoder(&in);
defer finish(&dec);
diff --git a/encoding/pem/pem.ha b/encoding/pem/pem.ha
@@ -6,9 +6,9 @@ use encoding::base64;
use errors;
use fmt;
use io;
+use memio;
use os;
use strings;
-use strio;
const begin: str = "-----BEGIN ";
@@ -16,19 +16,19 @@ const end: str = "-----END ";
const suffix: str = "-----";
export type decoder = struct {
- in: bufio::bufstream,
- label: strio::stream,
+ in: bufio::stream,
+ label: memio::stream,
buf: []u8,
};
export type b64stream = struct {
stream: io::stream,
- in: *bufio::bufstream,
+ in: *bufio::stream,
};
export type pemdecoder = struct {
stream: io::stream,
- in: *bufio::bufstream,
+ in: *bufio::stream,
b64_in: b64stream,
b64: base64::decoder,
// XXX: kind of dumb but it saves us some memory management problems
@@ -50,9 +50,9 @@ const b64stream_r_vt: io::vtable = io::vtable {
export fn newdecoder(in: io::handle) decoder = {
let buf: []u8 = alloc([0...], os::BUFSIZ);
return decoder {
- in = bufio::buffered(in, buf, []),
+ in = bufio::init(in, buf, []),
buf = buf,
- label = strio::dynamic(),
+ label = memio::dynamic(),
};
};
@@ -104,12 +104,12 @@ export fn next(dec: *decoder) ((str, pemdecoder) | io::EOF | io::error) = {
continue;
};
- strio::reset(&dec.label);
+ memio::reset(&dec.label);
const label = strings::sub(line,
len(begin), len(line) - len(suffix));
- strio::concat(&dec.label, label)!;
+ memio::concat(&dec.label, label)!;
- return (strio::string(&dec.label), pemdecoder {
+ return (memio::string(&dec.label)!, pemdecoder {
stream = &pemdecoder_vt,
in = &dec.in,
b64_in = b64stream {
diff --git a/fmt/fmt.ha b/fmt/fmt.ha
@@ -6,10 +6,10 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
use ascii;
-use bufio;
use encoding::utf8;
use io;
use math;
+use memio;
use os;
use strconv;
use strings;
@@ -44,16 +44,16 @@ export fn errorfln(fmt: str, args: field...) (size | io::error) =
// 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: field...) str = {
- let buf = bufio::dynamic(io::mode::WRITE);
+ let buf = memio::dynamic();
assert(fprintf(&buf, fmt, args...) is size);
- return strings::fromutf8_unsafe(bufio::buffer(&buf));
+ return strings::fromutf8_unsafe(memio::buffer(&buf));
};
// Formats text for printing and writes it into a caller supplied buffer. The
// returned string is borrowed from this buffer. Aborts if the buffer isn't
// large enough to hold the formatted text.
export fn bsprintf(buf: []u8, fmt: str, args: field...) str = {
- let sink = bufio::fixed(buf, io::mode::WRITE);
+ let sink = memio::fixed(buf);
let l = fprintf(&sink, fmt, args...)!;
return strings::fromutf8_unsafe(buf[..l]);
};
@@ -107,9 +107,9 @@ export fn errorln(args: formattable...) (size | io::error) =
// 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(io::mode::WRITE);
+ let buf = memio::dynamic();
assert(fprint(&buf, args...) is size);
- return strings::fromutf8_unsafe(bufio::buffer(&buf));
+ return strings::fromutf8_unsafe(memio::buffer(&buf));
};
// Formats values for printing using the default format modifiers and writes
@@ -117,7 +117,7 @@ export fn asprint(args: formattable...) str = {
// is borrowed from this buffer. Aborts if the buffer isn't large enough to hold
// the formatted text.
export fn bsprint(buf: []u8, args: formattable...) str = {
- let sink = bufio::fixed(buf, io::mode::WRITE);
+ let sink = memio::fixed(buf);
let l = fprint(&sink, args...)!;
return strings::fromutf8_unsafe(buf[..l]);
};
diff --git a/format/ini/+test.ha b/format/ini/+test.ha
@@ -1,18 +1,18 @@
// License: MPL-2.0
// (c) 2021-2022 Alexey Yerin <yyp@disroot.org>
-use bufio;
use io;
+use memio;
use strings;
@test fn simple() void = {
- const buf = bufio::fixed(strings::toutf8(
+ const buf = memio::fixed(strings::toutf8(
"# This is a comment
[sourcehut.org]
name=Sourcehut
description=The hacker's forge
[harelang.org]
name=Hare
-description=The Hare programming language"), io::mode::READ);
+description=The Hare programming language"));
const sc = scan(&buf);
defer finish(&sc);
@@ -28,13 +28,13 @@ description=The Hare programming language"), io::mode::READ);
@test fn extended() void = {
// TODO: expand?
- const buf = bufio::fixed(strings::toutf8(
+ const buf = memio::fixed(strings::toutf8(
"# Equal sign in the value
exec=env VARIABLE=value binary
# Unicode
trademark=™
-"), io::mode::READ);
+"));
const sc = scan(&buf);
defer finish(&sc);
@@ -46,14 +46,14 @@ trademark=™
@test fn invalid() void = {
// Missing equal sign
- const buf = bufio::fixed(strings::toutf8("novalue\n"), io::mode::READ);
+ const buf = memio::fixed(strings::toutf8("novalue\n"));
const sc = scan(&buf);
defer finish(&sc);
assert(next(&sc) as error is syntaxerr); // TODO: test line numbering?
// Unterminated section header
- const buf = bufio::fixed(strings::toutf8("[dangling\n"), io::mode::READ);
+ const buf = memio::fixed(strings::toutf8("[dangling\n"));
const sc = scan(&buf);
defer finish(&sc);
diff --git a/format/tar/reader.ha b/format/tar/reader.ha
@@ -1,12 +1,11 @@
// License: MPL-2.0
// (c) 2022 Drew DeVault <sir@cmpwn.com>
-use bufio;
use bytes;
use endian;
use errors;
use io;
+use memio;
use strconv;
-use strio;
use types::c;
export type reader = struct {
@@ -58,7 +57,7 @@ export fn next(rd: *reader) (entry | error | io::EOF) = {
return io::EOF;
};
- const reader = bufio::fixed(buf, io::mode::READ);
+ const reader = memio::fixed(buf);
const name = readstr(&reader, 100);
const mode = readoct(&reader, 8)?;
const uid = readoct(&reader, 8)?;
@@ -100,9 +99,9 @@ export fn next(rd: *reader) (entry | error | io::EOF) = {
ent.devmajor = readoct(&reader, 8)?;
ent.devminor = readoct(&reader, 8)?;
const prefix = readstr(&reader, 155);
- let writer = strio::fixed(rd.name);
- strio::join(&writer, prefix, name)!;
- ent.name = strio::string(&writer);
+ let writer = memio::fixed(rd.name);
+ memio::join(&writer, prefix, name)!;
+ ent.name = memio::string(&writer)!;
return ent;
};
@@ -199,8 +198,8 @@ fn file_seek(
return new;
};
-fn readstr(rd: *bufio::memstream, ln: size) str = {
- const buf = match (bufio::borrowedread(rd, ln)) {
+fn readstr(rd: *memio::stream, ln: size) str = {
+ const buf = match (memio::borrowedread(rd, ln)) {
case let buf: []u8 =>
assert(len(buf) == ln);
yield buf;
@@ -210,7 +209,7 @@ fn readstr(rd: *bufio::memstream, ln: size) str = {
return c::tostr(buf: *[*]u8: *const c::char)!;
};
-fn readoct(rd: *bufio::memstream, ln: size) (uint | invalid) = {
+fn readoct(rd: *memio::stream, ln: size) (uint | invalid) = {
const string = readstr(rd, ln);
match (strconv::stoub(string, strconv::base::OCT)) {
case let u: uint =>
@@ -220,7 +219,7 @@ fn readoct(rd: *bufio::memstream, ln: size) (uint | invalid) = {
};
};
-fn readsize(rd: *bufio::memstream, ln: size) (size | invalid) = {
+fn readsize(rd: *memio::stream, ln: size) (size | invalid) = {
const string = readstr(rd, ln);
match (strconv::stozb(string, strconv::base::OCT)) {
case let z: size =>
diff --git a/glob/glob.ha b/glob/glob.ha
@@ -3,10 +3,10 @@
use fnmatch;
use fs;
use io;
+use memio;
use os;
use sort;
use strings;
-use strio;
// Flags used to control the behavior of [[next]].
export type flag = enum uint {
@@ -33,15 +33,15 @@ export type generator = struct {
};
export type strstack = struct {
- bufv: []strio::stream,
+ bufv: []memio::stream,
bufc: size,
};
export type pattern = struct {
// TODO: look into working with a couple of string iterators instead
- dir: strio::stream,
- pat: strio::stream,
- rem: strio::stream,
+ dir: memio::stream,
+ pat: memio::stream,
+ rem: memio::stream,
};
// Information about an unsuccessful search.
@@ -56,7 +56,7 @@ export type failure = !struct {
// freed using [[finish]].
export fn glob(pattern: str, flags: flag...) generator = {
let ss = strstack_init();
- strio::concat(strstack_push(&ss), pattern)!;
+ memio::concat(strstack_push(&ss), pattern)!;
let bs = flag::NONE;
for (let i = 0z; i < len(flags); i += 1) {
bs |= flags[i];
@@ -81,9 +81,9 @@ export fn finish(gen: *generator) void = {
// [[next]] can be repeatedly called until void is returned.
export fn next(gen: *generator) (str | void | failure) = {
const init = strstack_size(&gen.pats) == 1
- && len(strio::string(&gen.tmpp.dir)) == 0
- && len(strio::string(&gen.tmpp.pat)) == 0
- && len(strio::string(&gen.tmpp.rem)) == 0;
+ && len(memio::string(&gen.tmpp.dir)!) == 0
+ && len(memio::string(&gen.tmpp.pat)!) == 0
+ && len(memio::string(&gen.tmpp.rem)!) == 0;
match (next_match(os::cwd, gen)) {
case let s: str =>
return s;
@@ -92,7 +92,7 @@ export fn next(gen: *generator) (str | void | failure) = {
case void => void;
};
if (init && gen.flgs & flag::NOCHECK != 0) {
- return strio::string(&gen.pats.bufv[0]);
+ return memio::string(&gen.pats.bufv[0])!;
};
};
@@ -145,10 +145,10 @@ fn next_match(fs: *fs::fs, gen: *generator) (str | void | failure) = {
let b = strstack_push(&gen.pats);
if (len(rem) > 0) {
- strio::concat(b, dir, de.name, "/", rem)!;
+ memio::concat(b, dir, de.name, "/", rem)!;
continue;
};
- strio::concat(b, dir, de.name)!;
+ memio::concat(b, dir, de.name)!;
if (patm || gen.flgs & flag::MARK != 0) {
let m = fs::isdir(de.ftype);
// POSIX does not specify the behavior when a pathname
@@ -156,7 +156,7 @@ fn next_match(fs: *fs::fs, gen: *generator) (str | void | failure) = {
// directory. But in major implementation a slash
// character is appended in this case.
if (fs::islink(de.ftype)) {
- match (fs::realpath(fs, strio::string(b))) {
+ match (fs::realpath(fs, memio::string(b)!)) {
case let r: str =>
match (fs::stat(fs, r)) {
case let s: fs::filestat =>
@@ -167,7 +167,7 @@ fn next_match(fs: *fs::fs, gen: *generator) (str | void | failure) = {
};
};
if (m) {
- strio::concat(b, "/")!;
+ memio::concat(b, "/")!;
} else if (patm) {
strstack_pop(&gen.pats);
continue;
@@ -183,9 +183,9 @@ fn next_match(fs: *fs::fs, gen: *generator) (str | void | failure) = {
};
fn pattern_init() pattern = pattern {
- dir = strio::dynamic(),
- pat = strio::dynamic(),
- rem = strio::dynamic(),
+ dir = memio::dynamic(),
+ pat = memio::dynamic(),
+ rem = memio::dynamic(),
};
fn pattern_free(p: *pattern) void = {
@@ -195,16 +195,16 @@ fn pattern_free(p: *pattern) void = {
};
fn pattern_reset(p: *pattern) void = {
- strio::reset(&p.dir);
- strio::reset(&p.pat);
- strio::reset(&p.rem);
+ memio::reset(&p.dir);
+ memio::reset(&p.pat);
+ memio::reset(&p.rem);
};
-fn pattern_dir(p: *pattern) str = strio::string(&p.dir);
+fn pattern_dir(p: *pattern) str = memio::string(&p.dir)!;
-fn pattern_pat(p: *pattern) str = strio::string(&p.pat);
+fn pattern_pat(p: *pattern) str = memio::string(&p.pat)!;
-fn pattern_rem(p: *pattern) str = strio::string(&p.rem);
+fn pattern_rem(p: *pattern) str = memio::string(&p.rem)!;
fn pattern_parse(p: *pattern, pstr: str, noesc: bool) void = {
pattern_reset(p);
@@ -239,10 +239,10 @@ fn pattern_parse(p: *pattern, pstr: str, noesc: bool) void = {
case => void;
};
- strio::appendrune(&p.pat, r)!;
+ memio::appendrune(&p.pat, r)!;
if (r == '/') {
- strio::concat(&p.dir, strio::string(&p.pat))!;
- strio::reset(&p.pat);
+ memio::concat(&p.dir, memio::string(&p.pat)!)!;
+ memio::reset(&p.pat);
itpat = itdir;
};
esc = false;
@@ -250,7 +250,7 @@ fn pattern_parse(p: *pattern, pstr: str, noesc: bool) void = {
// p.pat is the first path component which contains special
// characters.
- strio::reset(&p.pat);
+ memio::reset(&p.pat);
for (let esc = false; true) {
const r = match (strings::next(&itpat)) {
case void =>
@@ -265,16 +265,16 @@ fn pattern_parse(p: *pattern, pstr: str, noesc: bool) void = {
};
if (esc && r != '/') {
- strio::appendrune(&p.pat, '\\')!;
+ memio::appendrune(&p.pat, '\\')!;
};
- strio::appendrune(&p.pat, r)!;
+ memio::appendrune(&p.pat, r)!;
if (r == '/') {
break;
};
esc = false;
};
- strio::concat(&p.rem, strings::iterstr(&itpat))!;
+ memio::concat(&p.rem, strings::iterstr(&itpat))!;
};
fn strstack_init() strstack = strstack {
@@ -291,12 +291,12 @@ fn strstack_free(ss: *strstack) void = {
fn strstack_size(ss: *strstack) size = ss.bufc;
-fn strstack_push(ss: *strstack) *strio::stream = {
+fn strstack_push(ss: *strstack) *memio::stream = {
if (ss.bufc == len(ss.bufv)) {
- append(ss.bufv, strio::dynamic());
+ append(ss.bufv, memio::dynamic());
};
let b = &ss.bufv[ss.bufc];
- strio::reset(b);
+ memio::reset(b);
ss.bufc += 1;
return b;
};
@@ -306,7 +306,7 @@ fn strstack_pop(ss: *strstack) (str | void) = {
return;
};
ss.bufc -= 1;
- return strio::string(&ss.bufv[ss.bufc]);
+ return memio::string(&ss.bufv[ss.bufc])!;
};
fn strstack_sort(ss: *strstack, pos: size) void = {
@@ -314,11 +314,11 @@ fn strstack_sort(ss: *strstack, pos: size) void = {
return;
};
let s = ss.bufv[pos..ss.bufc];
- sort::sort(s, size(strio::stream), &bufcmp);
+ sort::sort(s, size(memio::stream), &bufcmp);
};
fn bufcmp(a: const *void, b: const *void) int =
strings::compare(
- strio::string(b: *strio::stream),
- strio::string(a: *strio::stream),
+ memio::string(b: *memio::stream)!,
+ memio::string(a: *memio::stream)!,
);
diff --git a/hare/lex/+test.ha b/hare/lex/+test.ha
@@ -5,14 +5,14 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
// (c) 2021 Sudipto Mallick <smlckz@disroot.org>
-use bufio;
use fmt;
use io;
use io::{mode};
+use memio;
use strings;
@test fn unget() void = {
- let buf = bufio::fixed(strings::toutf8("z"), mode::READ);
+ let buf = memio::fixed(strings::toutf8("z"));
let lexer = init(&buf, "<test>");
unget(&lexer, ('x', location { path = "<test>", line = 1, col = 2 }));
unget(&lexer, ('y', location { path = "<test>", line = 1, col = 3 }));
@@ -60,7 +60,7 @@ fn vassert(expected: value, actual: value) void = {
};
fn lextest(in: str, expected: []token) void = {
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = init(&buf, "<test>");
for (let i = 0z; i < len(expected); i += 1) {
let etok = expected[i];
@@ -188,7 +188,7 @@ fn loc(line: uint, col: uint) location = location {
@test fn keywords() void = {
let keywords = bmap[..ltok::LAST_KEYWORD+1];
for (let i = 0z; i < len(keywords); i += 1) {
- let buf = bufio::fixed(strings::toutf8(keywords[i]), mode::READ);
+ let buf = memio::fixed(strings::toutf8(keywords[i]));
let lexer = init(&buf, "<test>");
let tok = lex(&lexer) as token;
assert(tok.0 == i: ltok);
@@ -205,7 +205,7 @@ fn loc(line: uint, col: uint) location = location {
lextest(in, expected);
let in = "// foo\n// bar\nhello world// baz\n\n// bad\ntest";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = init(&buf, "<input>", flag::COMMENTS);
assert(lex(&lexer) is token);
assert(comment(&lexer) == " foo\n bar\n");
@@ -307,7 +307,7 @@ fn loc(line: uint, col: uint) location = location {
// empty string
const in = ['1': u8, 0x80];
- let buf = bufio::fixed(in, mode::READ);
+ let buf = memio::fixed(in);
let lexer = init(&buf, "<test>");
const s = lex(&lexer) as error as syntax;
@@ -317,7 +317,7 @@ fn loc(line: uint, col: uint) location = location {
// a crash in nextw
const in = [0x80: u8];
- let buf = bufio::fixed(in, mode::READ);
+ let buf = memio::fixed(in);
let lexer = init(&buf, "<test>");
const s = lex(&lexer) as error as syntax;
@@ -327,7 +327,7 @@ fn loc(line: uint, col: uint) location = location {
// crash
const in = ['"': u8, '\\': u8, '^': u8, '"': u8];
- let buf = bufio::fixed(in, mode::READ);
+ let buf = memio::fixed(in);
let lexer = init(&buf, "<test>");
const s = lex(&lexer) as error as syntax;
@@ -336,7 +336,7 @@ fn loc(line: uint, col: uint) location = location {
// Regression: <X>e followed by another token used to cause a crash
const in = ['0': u8, 'e': u8, ')': u8];
- let buf = bufio::fixed(in, mode::READ);
+ let buf = memio::fixed(in);
let lexer = init(&buf, "<test>");
const s = lex(&lexer) as error as syntax;
@@ -358,7 +358,7 @@ type op = enum {
@test fn loc() void = {
const src = "h ello: my name is Inigo Montoya";
- let buf = bufio::fixed(strings::toutf8(src), mode::READ);
+ let buf = memio::fixed(strings::toutf8(src));
let lexer = init(&buf, "<test>");
const ops: [_]op = [
op::NEXT,
diff --git a/hare/lex/lex.ha b/hare/lex/lex.ha
@@ -10,12 +10,12 @@ use bufio;
use encoding::utf8;
use fmt;
use io;
+use memio;
use os;
use path;
use sort;
use strconv;
use strings;
-use strio;
use types;
export type lexer = struct {
@@ -232,7 +232,7 @@ fn lex_rune(lex: *lexer, loc: location) (rune | error) = {
fn lex_string(lex: *lexer, loc: location, delim: rune) (token | error) = {
let ret: token = (ltok::LIT_STR, "", loc);
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
for (true) match (next(lex)?) {
case io::EOF =>
return syntaxerr(loc, "unexpected EOF scanning string literal");
@@ -241,9 +241,9 @@ fn lex_string(lex: *lexer, loc: location, delim: rune) (token | error) = {
else if (delim == '"') {
unget(lex, r);
let r = lex_rune(lex, loc)?;
- strio::appendrune(&buf, r)?;
+ memio::appendrune(&buf, r)?;
} else {
- strio::appendrune(&buf, r.0)?;
+ memio::appendrune(&buf, r.0)?;
};
};
for (true) match (nextw(lex)?) {
@@ -254,7 +254,7 @@ fn lex_string(lex: *lexer, loc: location, delim: rune) (token | error) = {
case '"', '`' =>
const tok = lex_string(lex, loc, r.0)?;
const next = tok.1 as str;
- strio::concat(&buf, next)!;
+ memio::concat(&buf, next)!;
free(next);
break;
case '/' =>
@@ -276,7 +276,7 @@ fn lex_string(lex: *lexer, loc: location, delim: rune) (token | error) = {
break;
};
};
- return (ltok::LIT_STR, strio::string(&buf), loc);
+ return (ltok::LIT_STR, memio::string(&buf)!, loc);
};
fn lex_rn_str(lex: *lexer) (token | error) = {
@@ -310,11 +310,11 @@ fn lex_rn_str(lex: *lexer) (token | error) = {
};
fn lex_name(lex: *lexer, loc: location) (token | error) = {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
match (next(lex)) {
case let r: (rune, location) =>
assert(is_name(r.0, false));
- strio::appendrune(&buf, r.0)!;
+ memio::appendrune(&buf, r.0)!;
case (io::EOF | io::error) =>
abort();
};
@@ -326,12 +326,12 @@ fn lex_name(lex: *lexer, loc: location) (token | error) = {
unget(lex, r);
break;
};
- strio::appendrune(&buf, r.0)?;
+ memio::appendrune(&buf, r.0)?;
};
line_comment(lex)?;
- let n = strio::string(&buf);
+ let n = memio::string(&buf)!;
match (sort::searchstrings(bmap[..ltok::LAST_KEYWORD+1], n)) {
case void =>
@@ -383,19 +383,19 @@ fn lex_comment(lexr: *lexer) (void | error) = {
return;
};
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
defer io::close(&buf)!;
for (true) match (next(lexr)?) {
case io::EOF =>
break;
case let r: (rune, location) =>
- strio::appendrune(&buf, r.0)!;
+ memio::appendrune(&buf, r.0)!;
if (r.0 == '\n') {
break;
};
};
let bytes = strings::toutf8(lexr.comment);
- append(bytes, strings::toutf8(strio::string(&buf))...);
+ append(bytes, strings::toutf8(memio::string(&buf)!)...);
lexr.comment = strings::fromutf8(bytes)!;
};
diff --git a/hare/module/context.ha b/hare/module/context.ha
@@ -7,10 +7,10 @@ use fmt;
use fs;
use glob;
use hare::ast;
+use memio;
use os;
use path;
use strings;
-use strio;
export type context = struct {
// Filesystem to use for the cache and source files.
@@ -112,13 +112,13 @@ export fn identpath(name: ast::ident) str = {
//
// This is used for module names in environment variables and some file names.
export fn identuscore(ident: ast::ident) str = {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
for (let i = 0z; i < len(ident); i += 1) {
fmt::fprintf(&buf, "{}{}", ident[i],
if (i + 1 < len(ident)) "_"
else "") as size;
};
- return strio::string(&buf);
+ return memio::string(&buf)!;
};
@test fn identuscore() void = {
diff --git a/hare/module/manifest.ha b/hare/module/manifest.ha
@@ -72,7 +72,7 @@ export fn manifest_load(ctx: *context, ident: ast::ident) (manifest | error) = {
let inputs: []input = [], versions: []version = [];
let buf: [4096]u8 = [0...];
- let file = bufio::buffered(truefile, buf, []);
+ let file = bufio::init(truefile, buf, []);
for (true) {
let line = match (bufio::scanline(&file)) {
case io::EOF =>
@@ -324,7 +324,7 @@ export fn manifest_write(ctx: *context, man: *manifest) (void | error) = {
let (truefile, name) = temp::named(ctx.fs, cachedir, io::mode::WRITE, 0o644)?;
let wbuf: [os::BUFSIZ]u8 = [0...];
- let file = &bufio::buffered(truefile, [], wbuf);
+ let file = &bufio::init(truefile, [], wbuf);
defer {
bufio::flush(file)!;
fs::remove(ctx.fs, name): void;
diff --git a/hare/module/scan.ha b/hare/module/scan.ha
@@ -13,10 +13,10 @@ use hare::lex;
use hare::parse;
use hash;
use io;
+use memio;
use path;
use sort;
use strings;
-use strio;
use bufio;
use os;
@@ -358,7 +358,7 @@ fn scan_file(
let truef = fs::open(ctx.fs, path)?;
defer io::close(truef)!;
let rbuf: [os::BUFSIZ]u8 = [0...];
- let f = &bufio::buffered(truef, rbuf, []);
+ let f = &bufio::init(truef, rbuf, []);
let sha = sha256::sha256();
hash::write(&sha, strings::toutf8(path));
hash::write(&sha, [ABI_VERSION]);
@@ -431,19 +431,19 @@ export fn parsetags(in: str) ([]tag | void) = {
case '-' =>
yield tag_mode::EXCLUSIVE;
};
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
for (true) match (strings::next(&iter)) {
case void =>
break;
case let r: rune =>
if (ascii::isalnum(r) || r == '_') {
- strio::appendrune(&buf, r)!;
+ memio::appendrune(&buf, r)!;
} else {
strings::prev(&iter);
break;
};
};
- t.name = strio::string(&buf);
+ t.name = memio::string(&buf)!;
append(tags, t);
};
return tags;
diff --git a/hare/parse/+test/ident_test.ha b/hare/parse/+test/ident_test.ha
@@ -1,17 +1,17 @@
// License: MPL-2.0
// (c) 2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
-use bufio;
use hare::ast;
use hare::lex;
use io;
use io::{mode};
+use memio;
use strings;
@test fn ident() void = {
{
const in = ";";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
ident(&lexer) as error: void;
@@ -21,7 +21,7 @@ use strings;
{
const in = "foo";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let ident = ident(&lexer) as ast::ident;
@@ -34,7 +34,7 @@ use strings;
{
const in = "foo::bar";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let ident = ident(&lexer) as ast::ident;
@@ -47,7 +47,7 @@ use strings;
{
const in = "foo::bar::baz";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let ident = ident(&lexer) as ast::ident;
@@ -61,7 +61,7 @@ use strings;
{
const in = "foo::bar;";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let ident = ident(&lexer) as ast::ident;
diff --git a/hare/parse/+test/loc.ha b/hare/parse/+test/loc.ha
@@ -2,17 +2,17 @@
// (c) 2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use bufio;
use encoding::utf8;
use fmt;
use hare::ast;
use hare::lex;
use io;
use io::{mode};
+use memio;
use strings;
fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
- let buf = bufio::fixed(strings::toutf8(srcs[i]), mode::READ);
+ let buf = memio::fixed(strings::toutf8(srcs[i]));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let exp = match (expr(&lexer)) {
@@ -77,7 +77,7 @@ fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
// We want to check the location of nested expressions, so this can't
// use expr_testloc
- let buf = bufio::fixed(strings::toutf8("foo: bar: baz"), mode::READ);
+ let buf = memio::fixed(strings::toutf8("foo: bar: baz"));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let exp = match (expr(&lexer)) {
@@ -101,7 +101,7 @@ fn expr_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
};
fn type_testloc(srcs: str...) void = for (let i = 0z; i < len(srcs); i += 1) {
- let buf = bufio::fixed(strings::toutf8(srcs[i]), mode::READ);
+ let buf = memio::fixed(strings::toutf8(srcs[i]));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let typ = match (_type(&lexer)) {
diff --git a/hare/parse/+test/roundtrip.ha b/hare/parse/+test/roundtrip.ha
@@ -3,15 +3,14 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
// (c) 2022 Sebastian <sebastian@sebsite.pw>
-use bufio;
use fmt;
use hare::ast;
use hare::lex;
use hare::unparse;
use io::{mode};
use io;
+use memio;
use strings;
-use strio;
fn roundtrip(src: str) void = {
let unsrc = _roundtrip(src);
@@ -30,7 +29,7 @@ fn roundtrip_reparse(src: str) void = {
};
fn _roundtrip(src: str) str = {
- let buf = bufio::fixed(strings::toutf8(src), mode::READ);
+ let buf = memio::fixed(strings::toutf8(src));
let lexer = lex::init(&buf, "<test>", lex::flag::COMMENTS);
defer lex::finish(&lexer);
let u = ast::subunit {
@@ -44,9 +43,9 @@ fn _roundtrip(src: str) str = {
},
};
defer ast::subunit_finish(u);
- let out = strio::dynamic();
+ let out = memio::dynamic();
let z = unparse::subunit(&out, u) as size;
- let unsrc = strio::string(&out);
+ let unsrc = memio::string(&out)!;
assert(z == len(unsrc));
return unsrc;
};
diff --git a/hare/parse/+test/unit_test.ha b/hare/parse/+test/unit_test.ha
@@ -4,10 +4,10 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
// (c) 2022 Sebastian <sebastian@sebsite.pw>
-use bufio;
use hare::ast;
use hare::lex;
use io::{mode};
+use memio;
use strings;
fn import_eq(i1: ast::import, i2: ast::import) bool = {
@@ -75,7 +75,7 @@ fn tup_to_import(tup: import_tuple) ast::import = ast::import {
"use modalias = quux::{alias = grault, alias2 = garply};\n"
"export fn main() void = void;";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
let mods = imports(&lexer)!;
@@ -116,7 +116,7 @@ fn tup_to_import(tup: import_tuple) ast::import = ast::import {
assert(tok.0 == lex::ltok::EXPORT);
const in = "use a::{b = c = d};\n";
- let buf = bufio::fixed(strings::toutf8(in), mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lexer = lex::init(&buf, "<test>");
defer lex::finish(&lexer);
assert(imports(&lexer) is error);
diff --git a/hare/parse/ident.ha b/hare/parse/ident.ha
@@ -2,11 +2,10 @@
// (c) 2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use bufio;
use hare::ast;
use hare::lex::{ltok};
use hare::lex;
-use io;
+use memio;
use strings;
fn ident_trailing(lexer: *lex::lexer) ((ast::ident, bool) | error) = {
@@ -48,7 +47,7 @@ export fn ident(lexer: *lex::lexer) (ast::ident | error) = {
// A convenience function which parses an identifier from a string, so the
// caller needn't provide a lexer instance.
export fn identstr(in: str) (ast::ident | error) = {
- const buf = bufio::fixed(strings::toutf8(in), io::mode::READ);
+ const buf = memio::fixed(strings::toutf8(in));
const lexer = lex::init(&buf, "<string>");
defer lex::finish(&lexer);
let ret = ident(&lexer);
diff --git a/hare/parse/parse.ha b/hare/parse/parse.ha
@@ -7,7 +7,7 @@ use fmt;
use hare::lex::{ltok};
use hare::lex;
use io;
-use strio;
+use memio;
// All possible error types.
export type error = !lex::error;
@@ -37,7 +37,7 @@ fn want(lexer: *lex::lexer, want: lex::ltok...) (lex::token | error) = {
};
};
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
defer io::close(&buf)!;
for (let i = 0z; i < len(want); i += 1) {
const tstr = if (want[i] == ltok::NAME) "name"
@@ -49,7 +49,7 @@ fn want(lexer: *lex::lexer, want: lex::ltok...) (lex::token | error) = {
};
lex::unlex(lexer, tok);
return syntaxerr(lex::mkloc(lexer), "Unexpected '{}', was expecting {}",
- lex::tokstr(tok), strio::string(&buf));
+ lex::tokstr(tok), memio::string(&buf)!);
};
// Looks for a matching ltok from the lexer, and if not present, unlexes the
diff --git a/hare/types/+test.ha b/hare/types/+test.ha
@@ -4,17 +4,17 @@
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
// (c) 2022 Sebastian <sebastian@sebsite.pw>
-use bufio;
use errors;
+use fmt;
use hare::ast;
use hare::lex;
use hare::parse;
use io;
+use memio;
use strings;
-use fmt;
fn parse_type(in: str) ast::_type = {
- let buf = bufio::fixed(strings::toutf8(in), io::mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
let lex = lex::init(&buf, "<test>");
defer lex::finish(&lex);
return parse::_type(&lex)!;
diff --git a/hare/unit/+test.ha b/hare/unit/+test.ha
@@ -1,16 +1,16 @@
// License: MPL-2.0
// (c) 2021-2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
-use bufio;
use hare::ast;
use hare::lex;
use hare::parse;
use hare::types;
use io;
+use memio;
use strings;
fn parse_expr(src: str) *ast::expr = {
- const stream = bufio::fixed(strings::toutf8(src), io::mode::READ);
+ const stream = memio::fixed(strings::toutf8(src));
const lexer = lex::init(&stream, "<test>");
defer lex::finish(&lexer);
return alloc(parse::expr(&lexer)!);
diff --git a/hare/unparse/decl.ha b/hare/unparse/decl.ha
@@ -7,8 +7,8 @@ use io;
use fmt;
use hare::ast;
use hare::lex;
+use memio;
use strings;
-use strio;
// Unparses a [[hare::ast::decl]].
export fn decl(out: io::handle, d: ast::decl) (size | io::error) = {
@@ -124,9 +124,9 @@ fn comment(out: io::handle, s: str, indent: size) (size | io::error) = {
};
fn decl_test(d: ast::decl, expected: str) bool = {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
decl(&buf, d) as size;
- let s = strio::string(&buf);
+ let s = memio::string(&buf)!;
defer free(s);
return s == expected;
};
diff --git a/hare/unparse/ident.ha b/hare/unparse/ident.ha
@@ -5,7 +5,7 @@
use fmt;
use hare::ast;
use io;
-use strio;
+use memio;
// Unparses an identifier.
export fn ident(out: io::handle, id: ast::ident) (size | io::error) = {
@@ -20,9 +20,9 @@ export fn ident(out: io::handle, id: ast::ident) (size | io::error) = {
// Unparses an identifier into a string. The caller must free the return value.
export fn identstr(id: ast::ident) str = {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
ident(&buf, id)!;
- return strio::string(&buf);
+ return memio::string(&buf)!;
};
@test fn ident() void = {
diff --git a/hare/unparse/import.ha b/hare/unparse/import.ha
@@ -5,7 +5,7 @@
use fmt;
use io;
use hare::ast;
-use strio;
+use memio;
// Unparses a [[hare::ast::import]].
export fn import(out: io::handle, import: ast::import) (size | io::error) = {
@@ -81,9 +81,9 @@ export fn import(out: io::handle, import: ast::import) (size | io::error) = {
}, "use quux = foo::{alias1 = bar, alias2 = baz};"),
];
for (let i = 0z; i < len(tests); i += 1) {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
import(&buf, tests[i].0) as size;
- let s = strio::string(&buf);
+ let s = memio::string(&buf)!;
assert(s == tests[i].1);
free(s);
};
diff --git a/hare/unparse/type.ha b/hare/unparse/type.ha
@@ -7,8 +7,8 @@ use io;
use hare::ast;
use hare::ast::{variadism};
use hare::lex;
+use memio;
use strings;
-use strio;
// Returns a builtin type as a string.
export fn builtin_type(b: ast::builtin_type) str = switch (b) {
@@ -77,22 +77,22 @@ export fn prototype(
// estimate length of prototype to determine if it should span multiple
// lines
const linelen = if (len(t.params) == 0) {
- let strm = strio::dynamic();
+ let strm = memio::dynamic();
defer io::close(&strm)!;
_type(&strm, indent, *t.result)?;
- retname = strings::dup(strio::string(&strm));
+ retname = strings::dup(memio::string(&strm)!);
yield 0z; // only use one line if there's no parameters
} else {
- let strm = strio::dynamic();
+ let strm = memio::dynamic();
defer io::close(&strm)!;
let linelen = indent * 8 + 5;
linelen += if (len(t.params) != 0) len(t.params) * 3 - 1 else 0;
for (let i = 0z; i < len(t.params); i += 1) {
const param = t.params[i];
linelen += _type(&strm, indent, *param._type)?;
- typenames[i] = strings::dup(strio::string(&strm));
+ typenames[i] = strings::dup(memio::string(&strm)!);
linelen += if (param.name == "") -2 else len(param.name);
- strio::reset(&strm);
+ memio::reset(&strm);
};
switch (t.variadism) {
case variadism::NONE => void;
@@ -102,7 +102,7 @@ export fn prototype(
linelen += 5;
};
linelen += _type(&strm, indent, *t.result)?;
- retname = strings::dup(strio::string(&strm));
+ retname = strings::dup(memio::string(&strm)!);
yield linelen;
};
@@ -355,9 +355,9 @@ export fn _type(
};
fn type_test(t: ast::_type, expected: str) void = {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
_type(&buf, 0, t) as size;
- let s = strio::string(&buf);
+ let s = memio::string(&buf)!;
defer free(s);
if (s != expected) {
fmt::errorfln("=== wanted\n{}", expected)!;
diff --git a/hash/siphash/+test.ha b/hash/siphash/+test.ha
@@ -2,7 +2,6 @@ use endian;
use fmt;
use hash;
use io;
-use strio;
use strings;
@test fn siphash() void = {
diff --git a/memio/README b/memio/README
@@ -0,0 +1,11 @@
+memio provides implementations of [[io::stream]] which can read from or write to
+byte slices. [[fixed]] uses a caller-supplied buffer for storage, while
+[[dynamic]] uses a dynamically allocated buffer which will grow instead of
+erroring when writing past the end of the buffer. All memio streams are
+seekable; the read-write head works the same way as an operating system file.
+You can access the contents of the buffer via [[buffer]] and [[string]].
+
+Additionally, memio provides string-related I/O operations. Each of the utility
+functions (e.g. [[appendrune]]) work correctly with any [[io::handle]], but
+for efficiency reasons it is recommended that they are either a memio or
+[[bufio]] stream.
diff --git a/memio/ops.ha b/memio/ops.ha
@@ -0,0 +1,135 @@
+// License: MPL-2.0
+// (c) 2022 Alexey Yerin <yyp@disroot.org>
+// (c) 2021 Drew DeVault <sir@cmpwn.com>
+// (c) 2022 Yasumasa Tada <ytada@spartan.dev>
+use encoding::utf8;
+use io;
+use strings;
+
+// Appends zero or more strings to an [[io::handle]]. The output needn't be a
+// memio stream, but it's generally more efficient if it is. Returns the number
+// of bytes written, or an error.
+export fn concat(out: io::handle, strs: str...) (size | io::error) =
+ join(out, "", strs...);
+
+@test fn concat() void = {
+ let st = dynamic();
+ defer io::close(&st)!;
+ let tests: [_]([]str, str) = [
+ ([], ""),
+ ([""], ""),
+ (["", ""], ""),
+ (["hello"], "hello"),
+ (["hello", " ", "world"], "hello world"),
+ (["", "hello", " ", "world"], "hello world"),
+ (["hello", " ", "world", ""], "hello world"),
+ (["hello", "", " ", "world"], "hello world")
+ ];
+ for (let i = 0z; i < len(tests); i += 1) {
+ let ln = concat(&st, tests[i].0...) as size;
+ assert(ln == len(tests[i].1) && string(&st)! == tests[i].1);
+ reset(&st);
+ };
+};
+
+// Joins several strings together by a delimiter and writes them to a handle.
+// The output needn't be a memio stream, but it's generally more efficient if it
+// is. Returns the number of bytes written, or an error.
+export fn join(out: io::handle, delim: str, strs: str...) (size | io::error) = {
+ let n = 0z;
+ let delim = strings::toutf8(delim);
+ for (let i = 0z; i < len(strs); i += 1) {
+ n += io::writeall(out, strings::toutf8(strs[i]))?;
+ if (len(delim) != 0 && i + 1 < len(strs)) {
+ n += io::writeall(out, delim)?;
+ };
+ };
+ return n;
+};
+
+@test fn join() void = {
+ let st = dynamic();
+ defer io::close(&st)!;
+ let tests: [_](str, []str, str) = [
+ ("::", [], ""),
+ ("::", [""], ""),
+ ("::", ["", ""], "::"),
+ ("::", ["", "", ""], "::::"),
+ ("::", ["hello"], "hello"),
+ ("::", ["hello", "world"], "hello::world"),
+ ("::", ["", "hello", "world"], "::hello::world"),
+ ("::", ["hello", "world", ""], "hello::world::"),
+ ("::", ["hello", "", "world"], "hello::::world"),
+ ];
+ for (let i = 0z; i < len(tests); i += 1) {
+ let ln = join(&st, tests[i].0, tests[i].1...) as size;
+ assert(ln == len(tests[i].2) && string(&st)! == tests[i].2);
+ reset(&st);
+ };
+};
+
+// Appends zero or more strings to an [[io::handle]], in reverse order. The
+// output needn't be a memio stream, but it's generally more efficient if it is.
+// Returns the number of bytes written, or an error.
+export fn rconcat(out: io::handle, strs: str...) (size | io::error) =
+ rjoin(out, "", strs...);
+
+@test fn rconcat() void = {
+ let st = dynamic();
+ defer io::close(&st)!;
+ let tests: [_]([]str, str) = [
+ ([], ""),
+ ([""], ""),
+ (["", ""], ""),
+ (["hello"], "hello"),
+ (["hello", " ", "world"], "world hello"),
+ (["", "hello", " ", "world"], "world hello"),
+ (["hello", " ", "world", ""], "world hello"),
+ (["hello", "", " ", "world"], "world hello")
+ ];
+ for (let i = 0z; i < len(tests); i += 1) {
+ let ln = rconcat(&st, tests[i].0...) as size;
+ assert(ln == len(tests[i].1) && string(&st)! == tests[i].1);
+ reset(&st);
+ };
+};
+
+// Joins several strings together by a delimiter and writes them to a handle, in
+// reverse order. The output needn't be a memio stream, but it's generally more
+// efficient if it is. Returns the number of bytes written, or an error.
+export fn rjoin(out: io::handle, delim: str, strs: str...) (size | io::error) = {
+ let n = 0z;
+ let delim = strings::toutf8(delim);
+ for (let i = len(strs); i > 0; i -= 1) {
+ n += io::writeall(out, strings::toutf8(strs[i - 1]))?;
+ if (len(delim) != 0 && i - 1 > 0) {
+ n += io::writeall(out, delim)?;
+ };
+ };
+ return n;
+};
+
+@test fn rjoin() void = {
+ let st = dynamic();
+ defer io::close(&st)!;
+ let tests: [_](str, []str, str) = [
+ ("::", [], ""),
+ ("::", [""], ""),
+ ("::", ["", ""], "::"),
+ ("::", ["", "", ""], "::::"),
+ ("::", ["hello"], "hello"),
+ ("::", ["hello", "world"], "world::hello"),
+ ("::", ["", "hello", "world"], "world::hello::"),
+ ("::", ["hello", "world", ""], "::world::hello"),
+ ("::", ["hello", "", "world"], "world::::hello"),
+ ];
+ for (let i = 0z; i < len(tests); i += 1) {
+ let ln = rjoin(&st, tests[i].0, tests[i].1...) as size;
+ assert(ln == len(tests[i].2) && string(&st)! == tests[i].2);
+ reset(&st);
+ };
+};
+
+// Appends a rune to a stream.
+export fn appendrune(out: io::handle, r: rune) (size | io::error) =
+ io::writeall(out, utf8::encoderune(r));
diff --git a/memio/stream.ha b/memio/stream.ha
@@ -0,0 +1,274 @@
+// License: MPL-2.0
+// (c) 2022 Alexey Yerin <yyp@disroot.org>
+// (c) 2021 Bor Grošelj Simić <bor.groseljsimic@telemach.net>
+// (c) 2021 Drew DeVault <sir@cmpwn.com>
+// (c) 2021 Ember Sawady <ecs@d2evs.net>
+use bytes;
+use encoding::utf8;
+use errors;
+use io;
+use strings;
+
+export type stream = struct {
+ stream: io::stream,
+ buf: []u8,
+ pos: size,
+};
+
+const fixed_vt: io::vtable = io::vtable {
+ seeker = &seek,
+ copier = ©,
+ reader = &read,
+ writer = &fixed_write,
+ ...
+};
+
+const dynamic_vt: io::vtable = io::vtable {
+ seeker = &seek,
+ copier = ©,
+ reader = &read,
+ writer = &dynamic_write,
+ closer = &dynamic_close,
+ ...
+};
+
+// Creates a stream for a fixed, caller-supplied buffer. Seeking a stream will
+// cause subsequent writes to overwrite existing contents of the buffer.
+// Writes return an error if they would exceed the buffer's capacity. The
+// stream doesn't have to be closed.
+export fn fixed(in: []u8) stream = stream {
+ stream = &fixed_vt,
+ buf = in,
+ pos = 0,
+};
+
+// Creates an [[io::stream]] which dynamically allocates a buffer to store
+// writes into. Seeking the stream and reading will read the written data.
+// Calling [[io::close]] on this stream will free the buffer. If a stream's
+// data is referenced via [[buffer]], the stream shouldn't be closed as
+// long as the data is used.
+export fn dynamic() stream = dynamic_from([]);
+
+// Like [[dynamic]], but takes an existing slice as input. Writes will
+// overwrite the buffer and reads consume bytes from the initial buffer.
+// Like [[dynamic]], calling [[io::close]] will free the buffer.
+export fn dynamic_from(in: []u8) stream = stream {
+ stream = &dynamic_vt,
+ buf = in,
+ pos = 0,
+};
+
+// Returns a stream's buffer, up to the current cursor position.
+// [[io::seek]] to the end first in order to return the entire buffer.
+// The return value is borrowed from the input.
+export fn buffer(in: *stream) []u8 = {
+ return in.buf[..in.pos];
+};
+
+// Returns a stream's buffer, up to the current cursor position, as a string.
+// [[io::seek]] to the end first in order to return the entire buffer.
+// The return value is borrowed from the input.
+export fn string(in: *stream) (str | utf8::invalid) = {
+ return strings::fromutf8(in.buf[..in.pos]);
+};
+
+// A convenience function that sets the read-write cursor to zero, so that
+// the buffer can be overwritten and reused.
+export fn reset(in: *stream) void = {
+ in.pos = 0;
+};
+
+// Reads data from a [[dynamic]] or [[fixed]] stream and returns a slice
+// borrowed from the internal buffer.
+export fn borrowedread(st: *stream, amt: size) ([]u8 | io::EOF) = {
+ if (len(st.buf) - st.pos < amt) {
+ return io::EOF;
+ };
+ let buf = st.buf[st.pos..st.pos + amt];
+ st.pos += len(buf);
+ return buf;
+};
+
+fn read(s: *io::stream, buf: []u8) (size | io::EOF | io::error) = {
+ let s = s: *stream;
+ if (len(s.buf) == s.pos && len(buf) != 0) {
+ return io::EOF;
+ };
+ const n = if (len(s.buf) - s.pos < len(buf)) {
+ yield len(s.buf) - s.pos;
+ } else {
+ yield len(buf);
+ };
+ assert(s.pos + n <= len(s.buf));
+ buf[..n] = s.buf[s.pos..s.pos + n];
+ s.pos += n;
+ return n;
+};
+
+fn seek(
+ s: *io::stream,
+ off: io::off,
+ w: io::whence
+) (io::off | io::error) = {
+ let s = s: *stream;
+ let start = switch (w) {
+ case io::whence::SET => yield 0z;
+ case io::whence::CUR => yield s.pos;
+ case io::whence::END => yield len(s.buf);
+ };
+ if (off < 0) {
+ if (start < (-off): size) return errors::invalid;
+ } else {
+ if (len(s.buf) - start < off: size) return errors::invalid;
+ };
+ s.pos = start + off: size;
+ return s.pos: io::off;
+};
+
+fn copy(dest: *io::stream, src: *io::stream) (size | io::error) = {
+ if (src.reader != &read || dest.writer == null) {
+ return errors::unsupported;
+ };
+ let src = src: *stream;
+ return (dest.writer: *io::writer)(dest, src.buf[src.pos..]);
+};
+
+fn fixed_write(s: *io::stream, buf: const []u8) (size | io::error) = {
+ if (len(buf) == 0) {
+ return 0z;
+ };
+ let s = s: *stream;
+ if (s.pos >= len(s.buf)) {
+ return errors::overflow;
+ };
+ const n = if (len(buf) > len(s.buf[s.pos..])) {
+ yield len(s.buf[s.pos..]);
+ } else {
+ yield len(buf);
+ };
+ s.buf[s.pos..s.pos+n] = buf[..n];
+ s.pos += n;
+ return n;
+};
+
+fn dynamic_write(s: *io::stream, buf: const []u8) (size | io::error) = {
+ let s = s: *stream;
+ let spare = len(s.buf) - s.pos;
+ let bufend = if (spare < len(buf)) spare else len(buf);
+ s.buf[s.pos..s.pos+bufend] = buf[..bufend];
+ s.pos += bufend;
+ if (bufend < len(buf)) {
+ append(s.buf, buf[bufend..]...);
+ s.pos += len(buf[bufend..]);
+ };
+ return len(buf);
+};
+
+fn dynamic_close(s: *io::stream) (void | io::error) = {
+ const s = s: *stream;
+ free(s.buf);
+ s.buf = [];
+ s.pos = 0;
+};
+
+@test fn fixed() void = {
+ let buf: [1024]u8 = [0...];
+ let stream = fixed(buf);
+ defer io::close(&stream)!;
+
+ let n = 0z;
+ n += io::writeall(&stream, strings::toutf8("hello ")) as size;
+ n += io::writeall(&stream, strings::toutf8("world")) as size;
+ assert(bytes::equal(buf[..n], strings::toutf8("hello world")));
+ assert(io::seek(&stream, 6, io::whence::SET) as io::off == 6: io::off);
+ io::writeall(&stream, strings::toutf8("asdf")) as size;
+ assert(bytes::equal(buf[..n], strings::toutf8("hello asdfd")));
+
+ let out: [2]u8 = [0...];
+ let s = fixed([1u8, 2u8]);
+ defer io::close(&s)!;
+ assert(io::read(&s, out[..1]) as size == 1 && out[0] == 1);
+ assert(io::seek(&s, 1, io::whence::CUR) as io::off == 2: io::off);
+ assert(io::read(&s, buf[..]) is io::EOF);
+ assert(io::writeall(&s, [1, 2]) as io::error is errors::overflow);
+
+ let in: [6]u8 = [0, 1, 2, 3, 4, 5];
+ let out: [6]u8 = [0...];
+ let source = fixed(in);
+ let sink = fixed(out);
+ io::copy(&sink, &source)!;
+ assert(bytes::equal(in, out));
+
+ assert(io::write(&sink, [])! == 0);
+
+ static let buf: [1024]u8 = [0...];
+ let stream = fixed(buf);
+ assert(string(&stream)! == "");
+ io::writeall(&stream, strings::toutf8("hello ")) as size;
+ assert(string(&stream)! == "hello ");
+ io::writeall(&stream, strings::toutf8("world")) as size;
+ assert(string(&stream)! == "hello world");
+};
+
+@test fn dynamic() void = {
+ let s = dynamic();
+ assert(io::writeall(&s, [1, 2, 3]) as size == 3);
+ assert(bytes::equal(buffer(&s), [1, 2, 3]));
+ assert(io::writeall(&s, [4, 5]) as size == 2);
+ assert(bytes::equal(buffer(&s), [1, 2, 3, 4, 5]));
+ let buf: [2]u8 = [0...];
+ assert(io::seek(&s, 0, io::whence::SET) as io::off == 0: io::off);
+ assert(io::read(&s, buf[..]) as size == 2 && bytes::equal(buf, [1, 2]));
+ assert(io::read(&s, buf[..]) as size == 2 && bytes::equal(buf, [3, 4]));
+ assert(io::read(&s, buf[..]) as size == 1 && buf[0] == 5);
+ assert(io::read(&s, buf[..]) is io::EOF);
+ assert(io::writeall(&s, [6, 7, 8]) as size == 3);
+ assert(bytes::equal(buffer(&s), [1, 2, 3, 4, 5, 6, 7, 8]));
+ reset(&s);
+ assert(len(buffer(&s)) == 0);
+ assert(io::writeall(&s, [1, 2, 3]) as size == 3);
+ assert(io::close(&s) is void);
+
+ let sl: []u8 = alloc([1, 2, 3]);
+ let s = dynamic_from(sl);
+ assert(io::writeall(&s, [0, 0]) as size == 2);
+ assert(io::seek(&s, 0, io::whence::END) as io::off == 3: io::off);
+ assert(io::writeall(&s, [4, 5, 6]) as size == 3);
+ assert(bytes::equal(buffer(&s), [0, 0, 3, 4, 5, 6]));
+ assert(io::read(&s, buf[..]) is io::EOF);
+ io::close(&s)!;
+
+ sl = alloc([1, 2]);
+ let s = dynamic_from(sl);
+ assert(io::read(&s, buf[..1]) as size == 1 && buf[0] == 1);
+ assert(io::seek(&s, 1, io::whence::CUR) as io::off == 2: io::off);
+ assert(io::read(&s, buf[..]) is io::EOF);
+ assert(io::writeall(&s, [3, 4]) as size == 2 && bytes::equal(buffer(&s), [1, 2, 3, 4]));
+ io::close(&s)!;
+ assert(io::writeall(&s, [5, 6]) as size == 2 && bytes::equal(buffer(&s), [5, 6]));
+ io::close(&s)!;
+
+ let in: [6]u8 = [0, 1, 2, 3, 4, 5];
+ let source = dynamic_from(in);
+ let sink = dynamic();
+ io::copy(&sink, &source)!;
+ assert(bytes::equal(in, buffer(&sink)));
+
+ let in: [6]u8 = [0, 1, 2, 3, 4, 5];
+ let source = dynamic_from(in);
+ const borrowed = borrowedread(&source, len(in)-1) as []u8;
+ assert(bytes::equal(borrowed, [0, 1, 2, 3, 4]));
+ let source = dynamic_from(in);
+ const borrowed = borrowedread(&source, len(in)) as []u8;
+ assert(bytes::equal(borrowed, [0, 1, 2, 3, 4, 5]));
+ let source = dynamic_from(in);
+ assert(borrowedread(&source, len(in)+1) is io::EOF);
+
+ let stream = dynamic();
+ defer io::close(&stream)!;
+ assert(string(&stream)! == "");
+ io::writeall(&stream, strings::toutf8("hello ")) as size;
+ assert(string(&stream)! == "hello ");
+ io::writeall(&stream, strings::toutf8("world")) as size;
+ assert(string(&stream)! == "hello world");
+};
diff --git a/mime/system.ha b/mime/system.ha
@@ -21,7 +21,7 @@ fn load_systemdb() (void | fs::error | io::error) = {
const file = os::open(SYSTEM_DB)?;
let buf: [os::BUFSIZ]u8 = [0...];
- const strm = bufio::buffered(file, buf, []);
+ const strm = bufio::init(file, buf, []);
for (true) {
const line = match (bufio::scanline(&strm)) {
diff --git a/net/ip/ip.ha b/net/ip/ip.ha
@@ -11,9 +11,9 @@ use bytes;
use endian;
use fmt;
use io;
+use memio;
use strconv;
use strings;
-use strio;
// An IPv4 address.
export type addr4 = [4]u8;
@@ -341,9 +341,9 @@ export fn fmt(s: io::handle, item: (...addr | subnet)) (size | io::error) = {
export fn string(item: (...addr | subnet)) str = {
// Maximum length of an IPv6 address plus its netmask in hexadecimal
static let buf: [64]u8 = [0...];
- let stream = strio::fixed(buf);
+ let stream = memio::fixed(buf);
fmt(&stream, item) as size;
- return strio::string(&stream);
+ return memio::string(&stream)!;
};
fn wanttoken(tok: *strings::tokenizer) (str | invalid) = {
diff --git a/net/uri/fmt.ha b/net/uri/fmt.ha
@@ -2,10 +2,10 @@ use ascii;
use encoding::utf8;
use fmt;
use io;
+use memio;
use net::ip;
use strconv;
use strings;
-use strio;
// Extract from RFC3986 ABNF
@@ -114,7 +114,7 @@ fn percent_encode(out: io::handle, src: str, allowed: str) (size | io::error) =
// Formats a [[uri]] into a string. The result must be freed by the caller.
export fn string(u: *const uri) str = {
- const st = strio::dynamic();
+ const st = memio::dynamic();
fmt(&st, u)!;
- return strio::string(&st);
+ return memio::string(&st)!;
};
diff --git a/net/uri/parse.ha b/net/uri/parse.ha
@@ -4,10 +4,10 @@
use ascii;
use encoding::utf8;
use io;
+use memio;
use net::ip;
use strconv;
use strings;
-use strio;
// The URI provided to [[parse]] is invalid.
export type invalid = !void;
@@ -132,7 +132,7 @@ fn parse_authority(
in: *strings::iterator,
) (((str | ip::addr6), u16, str) | invalid) = {
// Scan everything until '@' or ':' or '/', then decide what it is
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
defer io::close(&buf)!;
let host: (str | ip::addr6) = "";
let port = 0u16;
@@ -148,25 +148,25 @@ fn parse_authority(
};
if (r == '[') {
- if (len(strio::string(&buf)) > 0) {
+ if (len(memio::string(&buf)!) > 0) {
if (len(userinfo) > 0) {
return invalid;
} else {
userinfo = percent_decode(
- strio::string(&buf))?;
+ memio::string(&buf)!)?;
};
};
- strio::reset(&buf);
+ memio::reset(&buf);
for (true) {
const r = wantrune(in)?;
if (r == ']') {
break;
};
- strio::appendrune(&buf, r)!;
+ memio::appendrune(&buf, r)!;
};
- const addr = percent_decode(strio::string(&buf))?;
+ const addr = percent_decode(memio::string(&buf)!)?;
match (ip::parse(addr)) {
case let v6: ip::addr6 =>
host = v6;
@@ -180,24 +180,24 @@ fn parse_authority(
return invalid;
};
// This was userinfo+host[+port]
- userinfo = percent_decode(strio::string(&buf))?;
- strio::reset(&buf);
+ userinfo = percent_decode(memio::string(&buf)!)?;
+ memio::reset(&buf);
has_userinfo = true;
case '/' =>
// This was just host
strings::prev(in);
- host = percent_decode(strio::string(&buf))?;
+ host = percent_decode(memio::string(&buf)!)?;
break;
case ':' =>
// This was host+port
- host = percent_decode(strio::string(&buf))?;
+ host = percent_decode(memio::string(&buf)!)?;
port = parse_port(in)?;
break;
case =>
return invalid;
};
} else {
- strio::appendrune(&buf, r)!;
+ memio::appendrune(&buf, r)!;
};
};
@@ -205,7 +205,7 @@ fn parse_authority(
case let s: str =>
// In end of string case
if (len(s) == 0) {
- host = percent_decode(strio::string(&buf))?;
+ host = percent_decode(memio::string(&buf)!)?;
};
case => yield;
};
@@ -327,27 +327,27 @@ fn parse_port(in: *strings::iterator) (u16 | invalid) = {
};
fn percent_decode(s: str) (str | invalid) = {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
percent_decode_static(&buf, s)?;
- return strio::string(&buf);
+ return memio::string(&buf)!;
};
fn percent_decode_static(out: io::handle, s: str) (void | invalid) = {
let iter = strings::iter(s);
- let tmp = strio::dynamic();
+ let tmp = memio::dynamic();
defer io::close(&tmp)!;
let percent_data: []u8 = [];
for (true) {
match (strings::next(&iter)) {
case let r: rune =>
if (r == '%') {
- strio::reset(&tmp);
+ memio::reset(&tmp);
for (let i = 0z; i < 2; i += 1) {
const r = wantrune(&iter)?;
- strio::appendrune(&tmp, r)!;
+ memio::appendrune(&tmp, r)!;
};
- match (strconv::stou8b(strio::string(&tmp),
+ match (strconv::stou8b(memio::string(&tmp)!,
strconv::base::HEX)) {
case let ord: u8 =>
append(percent_data, ord);
@@ -358,7 +358,7 @@ fn percent_decode_static(out: io::handle, s: str) (void | invalid) = {
if(len(percent_data) > 0) {
match(strings::fromutf8(percent_data)) {
case let stro: str =>
- strio::concat(out, stro)!;
+ memio::concat(out, stro)!;
case utf8::invalid =>
return invalid;
};
@@ -366,13 +366,13 @@ fn percent_decode_static(out: io::handle, s: str) (void | invalid) = {
percent_data = [];
};
- strio::appendrune(out, r)!;
+ memio::appendrune(out, r)!;
};
case void =>
if(len(percent_data) > 0) {
match(strings::fromutf8(percent_data)) {
case let stro: str =>
- strio::concat(out, stro)!;
+ memio::concat(out, stro)!;
case utf8::invalid =>
return invalid;
};
diff --git a/net/uri/query.ha b/net/uri/query.ha
@@ -1,17 +1,17 @@
use io;
+use memio;
use strings;
-use strio;
export type query_decoder = struct {
tokenizer: strings::tokenizer,
- bufs: (strio::stream, strio::stream),
+ bufs: (memio::stream, memio::stream),
};
// Initializes a decoder for a query string. Use [[query_next]] to walk it. The
// caller must call [[query_finish]] once they're done using it.
export fn decodequery(q: const str) query_decoder = query_decoder {
tokenizer = strings::tokenize(q, "&"),
- bufs = (strio::dynamic(), strio::dynamic()),
+ bufs = (memio::dynamic(), memio::dynamic()),
};
// Frees resources associated with the [[query_decoder]].
@@ -31,33 +31,33 @@ export fn query_next(dec: *query_decoder) ((str, str) | invalid | void) = {
};
const raw = strings::cut(tok, "=");
- strio::reset(&dec.bufs.0);
+ memio::reset(&dec.bufs.0);
percent_decode_static(&dec.bufs.0, raw.0)?;
- strio::reset(&dec.bufs.1);
+ memio::reset(&dec.bufs.1);
percent_decode_static(&dec.bufs.1, raw.1)?;
return (
- strio::string(&dec.bufs.0),
- strio::string(&dec.bufs.1),
+ memio::string(&dec.bufs.0)!,
+ memio::string(&dec.bufs.1)!,
);
};
// Encodes (key, value) pairs into a URI query string. The result must be
// freed by the caller.
export fn encodequery(pairs: [](str, str)) str = {
- const buf = strio::dynamic();
+ const buf = memio::dynamic();
for (let i = 0z; i < len(pairs); i += 1) {
const pair = pairs[i];
- if (i > 0) strio::appendrune(&buf, '&')!;
+ if (i > 0) memio::appendrune(&buf, '&')!;
assert(len(pair.0) > 0);
percent_encode(&buf, pair.0, unres_query_frag)!;
if (len(pair.1) > 0) {
- strio::appendrune(&buf, '=')!;
+ memio::appendrune(&buf, '=')!;
percent_encode(&buf, pair.1, unres_query_frag)!;
};
};
- return strio::string(&buf);
+ return memio::string(&buf)!;
};
@test fn decodequery() void = {
diff --git a/os/+freebsd/stdfd.ha b/os/+freebsd/stdfd.ha
@@ -5,14 +5,14 @@ use bufio;
use io;
use rt;
-let stdin_bufio: bufio::bufstream = bufio::bufstream {
+let stdin_bufio: bufio::stream = bufio::stream {
// Will be overwritten, but must be initialized
stream = null: io::stream,
source = 0,
...
};
-let stdout_bufio: bufio::bufstream = bufio::bufstream {
+let stdout_bufio: bufio::stream = bufio::stream {
// Will be overwritten, but must be initialized
stream = null: io::stream,
source = 1,
@@ -42,11 +42,11 @@ export def BUFSIZ: size = 4096; // 4 KiB
@init fn init_stdfd() void = {
static let stdinbuf: [BUFSIZ]u8 = [0...];
- stdin_bufio = bufio::buffered(stdin_file, stdinbuf, []);
+ stdin_bufio = bufio::init(stdin_file, stdinbuf, []);
stdin = &stdin_bufio;
static let stdoutbuf: [BUFSIZ]u8 = [0...];
- stdout_bufio = bufio::buffered(stdout_file, [], stdoutbuf);
+ stdout_bufio = bufio::init(stdout_file, [], stdoutbuf);
stdout = &stdout_bufio;
};
diff --git a/os/+linux/stdfd.ha b/os/+linux/stdfd.ha
@@ -5,14 +5,14 @@ use bufio;
use io;
use rt;
-let stdin_bufio: bufio::bufstream = bufio::bufstream {
+let stdin_bufio: bufio::stream = bufio::stream {
// Will be overwritten, but must be initialized
stream = null: io::stream,
source = 0,
...
};
-let stdout_bufio: bufio::bufstream = bufio::bufstream {
+let stdout_bufio: bufio::stream = bufio::stream {
// Will be overwritten, but must be initialized
stream = null: io::stream,
source = 1,
@@ -42,11 +42,11 @@ export def BUFSIZ: size = 4096; // 4 KiB
@init fn init_stdfd() void = {
static let stdinbuf: [BUFSIZ]u8 = [0...];
- stdin_bufio = bufio::buffered(stdin_file, stdinbuf, []);
+ stdin_bufio = bufio::init(stdin_file, stdinbuf, []);
stdin = &stdin_bufio;
static let stdoutbuf: [BUFSIZ]u8 = [0...];
- stdout_bufio = bufio::buffered(stdout_file, [], stdoutbuf);
+ stdout_bufio = bufio::init(stdout_file, [], stdoutbuf);
stdout = &stdout_bufio;
};
diff --git a/regex/regex.ha b/regex/regex.ha
@@ -5,6 +5,7 @@ use bufio;
use encoding::utf8;
use errors;
use io;
+use memio;
use strconv;
use strings;
use types;
@@ -773,7 +774,7 @@ fn search(
// Returns whether or not a [[regex]] matches any part of a given string.
export fn test(re: *regex, string: str) bool = {
- let strm = bufio::fixed(strings::toutf8(string), io::mode::READ);
+ let strm = memio::fixed(strings::toutf8(string));
return search(re, string, &strm, false) is []capture;
};
@@ -782,7 +783,7 @@ export fn test(re: *regex, string: str) bool = {
// leftmost match as a [[result]]. The caller must free the return value with
// [[result_free]].
export fn find(re: *regex, string: str) result = {
- let strm = bufio::fixed(strings::toutf8(string), io::mode::READ);
+ let strm = memio::fixed(strings::toutf8(string));
match (search(re, string, &strm, true)) {
case let m: []capture =>
return m;
@@ -798,7 +799,7 @@ export fn findall(re: *regex, string: str) []result = {
let res: [][]capture = [];
let str_idx = 0z, str_bytesize = 0z;
let substring = string;
- let strm = bufio::fixed(strings::toutf8(string), io::mode::READ);
+ let strm = memio::fixed(strings::toutf8(string));
const str_bytes = strings::toutf8(string);
for (true) {
match (search(re, substring, &strm, true)) {
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -161,7 +161,7 @@ test() {
else
gen_srcs test common.ha +test.ha fail+test.ha
gen_ssa test bufio encoding::hex encoding::utf8 fmt fnmatch io \
- os rt strings strio time unix::signal
+ os rt strings memio time unix::signal
fi
}
@@ -174,11 +174,19 @@ ascii() {
}
bufio() {
- gen_srcs bufio \
- buffered.ha \
- memstream.ha \
- scanner.ha
- gen_ssa bufio io bytes strings encoding::utf8 errors types
+ if [ $testing -eq 0 ]; then
+ gen_srcs bufio \
+ stream.ha \
+ scanner.ha
+ gen_ssa bufio bytes encoding::utf8 errors io strings types
+ else
+ gen_srcs bufio \
+ stream.ha \
+ scanner.ha \
+ stream_test+test.ha \
+ scanner_test+test.ha
+ gen_ssa bufio bytes encoding::utf8 errors io memio strings types
+ fi
}
bytes() {
@@ -200,15 +208,15 @@ crypto() {
gen_srcs crypto \
authenc.ha \
keyderiv.ha
- gen_ssa crypto bufio bytes crypto::argon2 crypto::chachapoly \
- crypto::math endian errors io
+ gen_ssa crypto bytes crypto::argon2 crypto::chachapoly \
+ crypto::math endian errors io memio
else
gen_srcs crypto \
authenc.ha \
keyderiv.ha \
+test/authenc_test.ha
- gen_ssa crypto bufio bytes crypto::argon2 crypto::chachapoly \
- crypto::math endian errors io
+ gen_ssa crypto bytes crypto::argon2 crypto::chachapoly \
+ crypto::math endian errors io memio
fi
}
@@ -233,8 +241,8 @@ crypto_aes() {
ctr+test.ha \
rt+test.ha \
+test/gcm.ha
- gen_ssa crypto::aes bufio bytes crypto::cipher crypto::math \
- endian errors io rt
+ gen_ssa crypto::aes bytes crypto::cipher crypto::math \
+ endian errors io memio rt
fi
}
@@ -252,13 +260,13 @@ crypto_argon2() {
if [ $testing -eq 0 ]
then
gen_srcs crypto::argon2 argon2.ha
- gen_ssa crypto::argon2 bufio bytes crypto::blake2b \
- crypto::math endian errors hash io rt types
+ gen_ssa crypto::argon2 bytes crypto::blake2b \
+ crypto::math endian errors hash io memio rt types
else
gen_srcs crypto::argon2 argon2.ha +test.ha
- gen_ssa crypto::argon2 bufio bytes crypto::blake2b \
- crypto::math encoding::hex endian errors hash io rt \
- strings types
+ gen_ssa crypto::argon2 bytes crypto::blake2b \
+ crypto::math encoding::hex endian errors hash io memio \
+ rt strings types
fi
}
@@ -269,9 +277,9 @@ crypto_bcrypt() {
else
gen_srcs crypto::bcrypt bcrypt.ha base64.ha +test.ha
fi
- gen_ssa crypto::bcrypt crypto::blowfish encoding::base64 bufio io \
- crypto crypto::random errors crypto::cipher strings fmt bytes \
- strconv
+ gen_ssa crypto::bcrypt bytes crypto crypto::blowfish \
+ crypto::cipher crypto::random encoding::base64 errors \
+ fmt io memio strconv strings
}
gensrcs_crypto_blake2b() {
@@ -288,7 +296,7 @@ crypto_blake2b() {
else
gensrcs_crypto_blake2b +test.ha vectors+test.ha
gen_ssa crypto::blake2b encoding::hex fmt hash io strings \
- strio crypto::math endian bytes
+ memio crypto::math endian bytes
fi
}
@@ -335,7 +343,7 @@ crypto_chacha() {
else
gen_srcs crypto::chacha chacha20.ha +test.ha
gen_ssa crypto::chacha bytes crypto::cipher crypto::math \
- endian io bufio
+ endian io memio
fi
}
@@ -438,7 +446,7 @@ gensrcs_crypto_rsa() {
genssa_crypto_rsa() {
gen_ssa crypto::rsa bufio bytes crypto::bigint crypto::math \
crypto::sha1 crypto::sha256 crypto::sha512 endian errors hash \
- io types $*
+ io memio types $*
}
crypto_rsa() {
@@ -461,8 +469,8 @@ crypto_salsa() {
io
else
gen_srcs crypto::salsa salsa20.ha +test.ha
- gen_ssa crypto::salsa bytes bufio crypto::cipher crypto::math \
- endian types io
+ gen_ssa crypto::salsa bytes crypto::cipher crypto::math \
+ endian io memio types
fi
}
@@ -544,6 +552,41 @@ crypto_x25519() {
fi
}
+datetime() {
+ gen_srcs -plinux datetime \
+ arithmetic.ha \
+ chronology.ha \
+ errors.ha \
+ date.ha \
+ datetime.ha \
+ duration.ha \
+ format.ha \
+ parse.ha \
+ period.ha \
+ reckon.ha \
+ time.ha \
+ timezone.ha \
+ virtual.ha
+ gen_ssa -plinux datetime ascii errors fmt io strconv strings memio \
+ time time::chrono
+ gen_srcs -pfreebsd datetime \
+ arithmetic.ha \
+ chronology.ha \
+ errors.ha \
+ date.ha \
+ datetime.ha \
+ duration.ha \
+ format.ha \
+ parse.ha \
+ period.ha \
+ reckon.ha \
+ time.ha \
+ timezone.ha \
+ virtual.ha
+ gen_ssa -pfreebsd datetime ascii errors fmt io strconv strings memio \
+ time time::chrono
+}
+
dirs() {
gen_srcs dirs \
xdg.ha
@@ -553,19 +596,19 @@ dirs() {
encoding_base64() {
gen_srcs encoding::base64 \
base64.ha
- gen_ssa encoding::base64 ascii bufio bytes errors io os strings
+ gen_ssa encoding::base64 ascii bytes errors io os strings memio
}
encoding_base32() {
gen_srcs encoding::base32 \
base32.ha
- gen_ssa encoding::base32 ascii bufio bytes errors io strings os
+ gen_ssa encoding::base32 ascii bytes errors io strings os memio
}
encoding_hex() {
gen_srcs encoding::hex \
hex.ha
- gen_ssa encoding::hex ascii bufio bytes errors fmt io strconv strio \
+ gen_ssa encoding::hex ascii bytes errors fmt io strconv memio \
strings
}
@@ -574,13 +617,13 @@ encoding_pem() {
then
gen_srcs encoding::pem \
pem.ha
- gen_ssa encoding::pem strings bufio strio io errors \
+ gen_ssa encoding::pem strings memio io errors \
encoding::base64 ascii os fmt
else
gen_srcs encoding::pem \
pem.ha \
+test.ha
- gen_ssa encoding::pem strings bufio strio io errors \
+ gen_ssa encoding::pem strings memio io errors \
encoding::base64 ascii os fmt bytes
fi
}
@@ -616,7 +659,7 @@ errors() {
fmt() {
gen_srcs fmt \
fmt.ha
- gen_ssa fmt ascii bufio encoding::utf8 io os strconv strings types
+ gen_ssa fmt ascii encoding::utf8 io memio os strconv strings types
}
fnmatch() {
@@ -651,14 +694,14 @@ format_ini() {
else
gensrcs_format_ini +test.ha
fi
- gen_ssa format::ini bufio encoding::utf8 fmt io strings
+ gen_ssa format::ini encoding::utf8 fmt io memio strings
}
format_tar() {
gen_srcs format::tar \
types.ha \
reader.ha
- gen_ssa format::tar bufio bytes endian errors io strconv strio types::c
+ gen_ssa format::tar bytes endian errors io strconv memio types::c
}
fs() {
@@ -682,7 +725,7 @@ glob() {
else
gen_srcs glob glob.ha +test.ha
fi
- gen_ssa glob fnmatch fs io os sort strings strio
+ gen_ssa glob fnmatch fs io os sort strings memio
}
hare_ast() {
@@ -696,6 +739,69 @@ hare_ast() {
gen_ssa hare::ast hare::lex strings
}
+gensrcs_hare_lex() {
+ gen_srcs hare::lex \
+ token.ha \
+ lex.ha \
+ $*
+}
+
+hare_lex() {
+ if [ $testing -eq 0 ]
+ then
+ gensrcs_hare_lex
+ else
+ gensrcs_hare_lex \
+ +test.ha
+ fi
+ gen_ssa hare::lex ascii io encoding::utf8 fmt memio sort \
+ strconv strings path
+}
+
+hare_module() {
+ gen_srcs hare::module \
+ types.ha \
+ context.ha \
+ scan.ha \
+ manifest.ha \
+ walk.ha
+ gen_ssa hare::module \
+ hare::ast hare::lex hare::parse hare::unparse memio fs io strings hash \
+ crypto::sha256 dirs bytes encoding::utf8 ascii fmt time bufio \
+ strconv os encoding::hex sort errors temp path
+}
+
+gensrcs_hare_parse() {
+ gen_srcs hare::parse \
+ decl.ha \
+ expr.ha \
+ ident.ha \
+ import.ha \
+ parse.ha \
+ type.ha \
+ unit.ha \
+ $*
+}
+
+hare_parse() {
+ if [ $testing -eq 0 ]
+ then
+ gensrcs_hare_parse
+ gen_ssa hare::parse ascii hare::ast hare::lex fmt types \
+ strings math
+ else
+ gensrcs_hare_parse \
+ +test/expr_test.ha \
+ +test/ident_test.ha \
+ +test/loc.ha \
+ +test/roundtrip.ha \
+ +test/types.ha \
+ +test/unit_test.ha
+ gen_ssa hare::parse ascii memio hare::ast hare::lex \
+ hare::unparse io fmt types strings math encoding::utf8
+ fi
+}
+
gensrcs_hare_types() {
gen_srcs hare::types \
'+$(ARCH)/writesize.ha' \
@@ -714,11 +820,11 @@ hare_types() {
then
gensrcs_hare_types +test.ha
gen_ssa hare::types hare::ast hash hash::fnv endian strings \
- errors sort fmt bufio hare::lex hare::parse io
+ errors sort fmt hare::lex hare::parse io
else
gensrcs_hare_types
gen_ssa hare::types hare::ast hash hash::fnv endian strings \
- errors sort fmt
+ errors memio sort fmt
fi
}
@@ -740,11 +846,11 @@ hare_unit() {
then
gensrcs_hare_unit +test.ha
gen_ssa hare::unit hare::ast hare::types hash hash::fnv \
- strings hare::lex bufio hare::parse
+ strings hare::lex hare::parse memio
else
gensrcs_hare_unit
gen_ssa hare::unit hare::ast hare::types hash hash::fnv \
- strings hare::lex
+ strings hare::lex memio
fi
}
@@ -757,71 +863,7 @@ hare_unparse() {
type.ha \
unit.ha \
util.ha
- gen_ssa hare::unparse fmt io strings strio hare::ast hare::lex
-}
-
-gensrcs_hare_lex() {
- gen_srcs hare::lex \
- token.ha \
- lex.ha \
- $*
-}
-
-hare_lex() {
- if [ $testing -eq 0 ]
- then
- gensrcs_hare_lex
- else
- gensrcs_hare_lex \
- +test.ha
- fi
- gen_ssa hare::lex ascii io bufio encoding::utf8 strings fmt sort strio \
- strconv path
-}
-
-hare_module() {
- gen_srcs hare::module \
- types.ha \
- context.ha \
- scan.ha \
- manifest.ha \
- walk.ha
- gen_ssa hare::module \
- hare::ast hare::lex hare::parse hare::unparse strio fs io strings hash \
- crypto::sha256 dirs bytes encoding::utf8 ascii fmt time bufio \
- strconv os encoding::hex sort errors temp path
-}
-
-gensrcs_hare_parse() {
- gen_srcs hare::parse \
- decl.ha \
- expr.ha \
- ident.ha \
- import.ha \
- parse.ha \
- type.ha \
- unit.ha \
- $*
-}
-
-hare_parse() {
- if [ $testing -eq 0 ]
- then
- gensrcs_hare_parse
- gen_ssa hare::parse ascii hare::ast hare::lex fmt types \
- strings math
- else
- gensrcs_hare_parse \
- +test/expr_test.ha \
- +test/ident_test.ha \
- +test/loc.ha \
- +test/roundtrip.ha \
- +test/types.ha \
- +test/unit_test.ha
- gen_ssa hare::parse ascii bufio hare::ast hare::lex \
- hare::unparse io strio fmt types strings math \
- encoding::utf8
- fi
+ gen_ssa hare::unparse fmt io strings memio hare::ast hare::lex
}
hash() {
@@ -869,7 +911,7 @@ hash_siphash() {
else
gen_srcs hash::siphash siphash.ha +test.ha
gen_ssa hash::siphash hash io endian crypto::math \
- fmt strio strings
+ fmt memio strings
fi
}
@@ -1064,8 +1106,8 @@ net_ip() {
gensrcs_net_ip \
test+test.ha
fi
- gen_ssa -plinux net::ip bytes endian io strconv strings strio fmt
- gen_ssa -pfreebsd net::ip bytes endian io strconv strings strio fmt
+ gen_ssa -plinux net::ip bytes endian io strconv strings memio fmt
+ gen_ssa -pfreebsd net::ip bytes endian io strconv strings memio fmt
}
net_tcp() {
@@ -1136,7 +1178,7 @@ net_uri() {
+test.ha
fi
gen_ssa net::uri \
- ascii encoding::utf8 fmt io net::ip strconv strings strio
+ ascii encoding::utf8 fmt io net::ip strconv strings memio
}
gensrcs_math_complex() {
@@ -1231,11 +1273,11 @@ regex() {
if [ $testing -eq 0 ]; then
gen_srcs regex regex.ha
gen_ssa regex ascii bufio encoding::utf8 errors io strconv \
- strings bufio types
+ strings bufio types memio
else
gen_srcs regex regex.ha +test.ha
gen_ssa regex encoding::utf8 errors strconv strings fmt io os \
- bufio types
+ bufio types memio
fi
}
@@ -1268,7 +1310,7 @@ shlex() {
gensrcs_shlex \
+test.ha
fi
- gen_ssa shlex ascii encoding::utf8 io strings strio
+ gen_ssa shlex ascii encoding::utf8 io strings memio
}
gensrcs_sort() {
@@ -1325,24 +1367,24 @@ strings() {
strings_template() {
gen_srcs strings::template \
template.ha
- gen_ssa strings::template ascii errors fmt io strings strio
+ gen_ssa strings::template ascii errors fmt io strings memio
}
-strio() {
- gen_srcs strio \
+memio() {
+ gen_srcs memio \
stream.ha \
ops.ha
- gen_ssa strio errors io strings encoding::utf8
+ gen_ssa memio errors io strings encoding::utf8
}
temp() {
gen_srcs -plinux temp +linux.ha
gen_ssa -plinux temp \
- crypto::random encoding::hex errors fs io os path strio fmt
+ crypto::random encoding::hex errors fs io os path memio fmt
gen_srcs -pfreebsd temp +freebsd.ha
gen_ssa -pfreebsd temp \
- crypto::random encoding::hex errors fs io os path strio fmt
+ crypto::random encoding::hex errors fs io os path memio fmt
}
time() {
@@ -1404,7 +1446,7 @@ time_date() {
tarithm.ha \
virtual.ha
gen_ssa -plinux time::date \
- ascii errors fmt io strconv strings strio time time::chrono
+ ascii errors fmt io strconv strings memio time time::chrono
gen_srcs -pfreebsd time::date \
date.ha \
daydate.ha \
@@ -1420,7 +1462,7 @@ time_date() {
tarithm.ha \
virtual.ha
gen_ssa -pfreebsd time::date \
- ascii errors fmt io strconv strings strio time time::chrono
+ ascii errors fmt io strconv strings memio time time::chrono
}
types() {
@@ -1468,27 +1510,27 @@ unix_hosts() {
+linux.ha \
hosts.ha
gen_ssa -plinux unix::hosts bufio encoding::utf8 fs io \
- net::ip os strings
+ net::ip os strings memio
gen_srcs -pfreebsd unix::hosts \
+freebsd.ha \
hosts.ha
gen_ssa -pfreebsd unix::hosts bufio encoding::utf8 fs io \
- net::ip os strings
+ net::ip os strings memio
else
gen_srcs -plinux unix::hosts \
+linux.ha \
test+test.ha \
hosts.ha
gen_ssa -plinux unix::hosts bufio encoding::utf8 fs io \
- net::ip os strings
+ net::ip os strings memio
gen_srcs -pfreebsd unix::hosts \
+freebsd.ha \
test+test.ha \
hosts.ha
gen_ssa -pfreebsd unix::hosts bufio encoding::utf8 fs io \
- net::ip os strings
+ net::ip os strings memio
fi
}
@@ -1497,7 +1539,7 @@ unix_passwd() {
group.ha \
passwd.ha \
types.ha
- gen_ssa unix::passwd bufio io os strconv strings
+ gen_ssa unix::passwd bufio io os strconv strings memio
}
unix_poll() {
@@ -1512,12 +1554,12 @@ unix_resolvconf() {
gen_srcs -plinux unix::resolvconf \
+linux.ha \
load.ha
- gen_ssa -plinux unix::resolvconf os io bufio net::ip strings
+ gen_ssa -plinux unix::resolvconf os io bufio memio net::ip strings
gen_srcs -pfreebsd unix::resolvconf \
+freebsd.ha \
load.ha
- gen_ssa -pfreebsd unix::resolvconf os io bufio net::ip strings
+ gen_ssa -pfreebsd unix::resolvconf os io bufio memio net::ip strings
}
unix_signal() {
@@ -1557,7 +1599,7 @@ unix_tty() {
uuid() {
gen_srcs uuid \
uuid.ha
- gen_ssa uuid crypto::random strio fmt endian io bytes bufio strings strconv
+ gen_ssa uuid crypto::random fmt endian io bytes memio strings strconv
}
# List of modules and their supported platforms. Place a tab between the module
@@ -1631,6 +1673,7 @@ math
math::checked
math::complex
math::random
+memio
net linux freebsd
net::dial
net::dns
@@ -1648,7 +1691,6 @@ sort
strconv
strings
strings::template
-strio
temp linux freebsd
test
time linux freebsd
diff --git a/scripts/install-mods b/scripts/install-mods
@@ -19,6 +19,7 @@ io
linux
log
math
+memio
mime
net
os
@@ -29,7 +30,6 @@ shlex
sort
strconv
strings
-strio
temp
test
time
diff --git a/shlex/+test.ha b/shlex/+test.ha
@@ -2,8 +2,8 @@
// (c) 2021 Alexey Yerin <yyp@disroot.org>
// (c) 2022 Drew DeVault <sir@cmpwn.com>
use io;
+use memio;
use strings;
-use strio;
@test fn split() void = {
const s = split(`hello\ world`)!;
@@ -64,14 +64,14 @@ use strio;
assert(split(`unterminated\ backslash \`) is syntaxerr);
};
-fn testquote(sink: *strio::stream, s: str, expected: str) void = {
+fn testquote(sink: *memio::stream, s: str, expected: str) void = {
assert(quote(sink, s)! == len(expected));
- assert(strio::string(sink) == expected);
- strio::reset(sink);
+ assert(memio::string(sink)! == expected);
+ memio::reset(sink);
};
@test fn quote() void = {
- const sink = strio::dynamic();
+ const sink = memio::dynamic();
defer io::close(&sink)!;
testquote(&sink, `hello`, `hello`);
testquote(&sink, `hello world`, `'hello world'`);
diff --git a/shlex/escape.ha b/shlex/escape.ha
@@ -4,8 +4,8 @@
use ascii;
use encoding::utf8;
use io;
+use memio;
use strings;
-use strio;
fn is_safe(s: str) bool = {
const iter = strings::iter(s);
@@ -64,7 +64,7 @@ export fn quote(sink: io::handle, s: str) (size | io::error) = {
// Quotes a shell string and returns a new string. The caller must free the
// return value.
export fn quotestr(s: str) str = {
- const sink = strio::dynamic();
+ const sink = memio::dynamic();
quote(&sink, s)!;
- return strio::string(&sink);
+ return memio::string(&sink)!;
};
diff --git a/shlex/split.ha b/shlex/split.ha
@@ -2,8 +2,8 @@
// (c) 2021-2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
use io;
+use memio;
use strings;
-use strio;
// Invalid shell syntax.
export type syntaxerr = !void;
@@ -13,7 +13,7 @@ export type syntaxerr = !void;
export fn split(in: const str) ([]str | syntaxerr) = {
let iter = strings::iter(in);
- let s = strio::dynamic();
+ let s = memio::dynamic();
let slice: []str = [];
let first = true;
let dirty = false;
@@ -39,8 +39,8 @@ export fn split(in: const str) ([]str | syntaxerr) = {
break;
};
if (!first) {
- append(slice, strio::string(&s));
- s = strio::dynamic();
+ append(slice, memio::string(&s)!);
+ s = memio::dynamic();
};
dirty = false;
case '\\' =>
@@ -50,7 +50,7 @@ export fn split(in: const str) ([]str | syntaxerr) = {
case '\'' =>
scan_single(&s, &iter)?;
case =>
- strio::appendrune(&s, r)!;
+ memio::appendrune(&s, r)!;
};
if (first) {
@@ -59,7 +59,7 @@ export fn split(in: const str) ([]str | syntaxerr) = {
};
if (dirty) {
- append(slice, strio::string(&s));
+ append(slice, memio::string(&s)!);
};
return slice;
@@ -81,7 +81,7 @@ fn scan_backslash(out: io::handle, in: *strings::iterator) (void | syntaxerr) =
return;
};
- strio::appendrune(out, r)!;
+ memio::appendrune(out, r)!;
};
fn scan_double(out: io::handle, in: *strings::iterator) (void | syntaxerr) = {
@@ -99,7 +99,7 @@ fn scan_double(out: io::handle, in: *strings::iterator) (void | syntaxerr) = {
case '\\' =>
scan_backslash(out, in)?;
case =>
- strio::appendrune(out, r)!;
+ memio::appendrune(out, r)!;
};
};
};
@@ -116,6 +116,6 @@ fn scan_single(out: io::handle, in: *strings::iterator) (void | syntaxerr) = {
if (r == '\'') {
break;
};
- strio::appendrune(out, r)!;
+ memio::appendrune(out, r)!;
};
};
diff --git a/stdlib.mk b/stdlib.mk
@@ -610,6 +610,13 @@ stdlib_deps_any += $(stdlib_math_random_any)
stdlib_math_random_linux = $(stdlib_math_random_any)
stdlib_math_random_freebsd = $(stdlib_math_random_any)
+# gen_lib memio (any)
+stdlib_memio_any = $(HARECACHE)/memio/memio-any.o
+stdlib_env += HARE_TD_memio=$(HARECACHE)/memio/memio.td
+stdlib_deps_any += $(stdlib_memio_any)
+stdlib_memio_linux = $(stdlib_memio_any)
+stdlib_memio_freebsd = $(stdlib_memio_any)
+
# gen_lib net (linux)
stdlib_net_linux = $(HARECACHE)/net/net-linux.o
stdlib_env += HARE_TD_net=$(HARECACHE)/net/net.td
@@ -750,13 +757,6 @@ stdlib_deps_any += $(stdlib_strings_template_any)
stdlib_strings_template_linux = $(stdlib_strings_template_any)
stdlib_strings_template_freebsd = $(stdlib_strings_template_any)
-# gen_lib strio (any)
-stdlib_strio_any = $(HARECACHE)/strio/strio-any.o
-stdlib_env += HARE_TD_strio=$(HARECACHE)/strio/strio.td
-stdlib_deps_any += $(stdlib_strio_any)
-stdlib_strio_linux = $(stdlib_strio_any)
-stdlib_strio_freebsd = $(stdlib_strio_any)
-
# gen_lib temp (linux)
stdlib_temp_linux = $(HARECACHE)/temp/temp-linux.o
stdlib_env += HARE_TD_temp=$(HARECACHE)/temp/temp.td
@@ -906,11 +906,10 @@ $(HARECACHE)/ascii/ascii-any.ssa: $(stdlib_ascii_any_srcs) $(stdlib_rt) $(stdlib
# bufio (+any)
stdlib_bufio_any_srcs = \
- $(STDLIB)/bufio/buffered.ha \
- $(STDLIB)/bufio/memstream.ha \
+ $(STDLIB)/bufio/stream.ha \
$(STDLIB)/bufio/scanner.ha
-$(HARECACHE)/bufio/bufio-any.ssa: $(stdlib_bufio_any_srcs) $(stdlib_rt) $(stdlib_io_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
+$(HARECACHE)/bufio/bufio-any.ssa: $(stdlib_bufio_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/bufio
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nbufio \
@@ -938,7 +937,7 @@ stdlib_crypto_any_srcs = \
$(STDLIB)/crypto/authenc.ha \
$(STDLIB)/crypto/keyderiv.ha
-$(HARECACHE)/crypto/crypto-any.ssa: $(stdlib_crypto_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_crypto_argon2_$(PLATFORM)) $(stdlib_crypto_chachapoly_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM))
+$(HARECACHE)/crypto/crypto-any.ssa: $(stdlib_crypto_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_crypto_argon2_$(PLATFORM)) $(stdlib_crypto_chachapoly_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto \
@@ -970,7 +969,7 @@ $(HARECACHE)/crypto/aes/xts/crypto_aes_xts-any.ssa: $(stdlib_crypto_aes_xts_any_
stdlib_crypto_argon2_any_srcs = \
$(STDLIB)/crypto/argon2/argon2.ha
-$(HARECACHE)/crypto/argon2/crypto_argon2-any.ssa: $(stdlib_crypto_argon2_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_crypto_blake2b_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_rt_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
+$(HARECACHE)/crypto/argon2/crypto_argon2-any.ssa: $(stdlib_crypto_argon2_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_crypto_blake2b_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_rt_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto/argon2
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::argon2 \
@@ -981,7 +980,7 @@ stdlib_crypto_bcrypt_any_srcs = \
$(STDLIB)/crypto/bcrypt/bcrypt.ha \
$(STDLIB)/crypto/bcrypt/base64.ha
-$(HARECACHE)/crypto/bcrypt/crypto_bcrypt-any.ssa: $(stdlib_crypto_bcrypt_any_srcs) $(stdlib_rt) $(stdlib_crypto_blowfish_$(PLATFORM)) $(stdlib_encoding_base64_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_crypto_$(PLATFORM)) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_crypto_cipher_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM))
+$(HARECACHE)/crypto/bcrypt/crypto_bcrypt-any.ssa: $(stdlib_crypto_bcrypt_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_crypto_$(PLATFORM)) $(stdlib_crypto_blowfish_$(PLATFORM)) $(stdlib_crypto_cipher_$(PLATFORM)) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_encoding_base64_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto/bcrypt
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::bcrypt \
@@ -1130,7 +1129,7 @@ stdlib_crypto_rsa_any_srcs = \
$(STDLIB)/crypto/rsa/keys.ha \
$(STDLIB)/crypto/rsa/pkcs1.ha
-$(HARECACHE)/crypto/rsa/crypto_rsa-any.ssa: $(stdlib_crypto_rsa_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_crypto_bigint_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_crypto_sha1_$(PLATFORM)) $(stdlib_crypto_sha256_$(PLATFORM)) $(stdlib_crypto_sha512_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
+$(HARECACHE)/crypto/rsa/crypto_rsa-any.ssa: $(stdlib_crypto_rsa_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_crypto_bigint_$(PLATFORM)) $(stdlib_crypto_math_$(PLATFORM)) $(stdlib_crypto_sha1_$(PLATFORM)) $(stdlib_crypto_sha256_$(PLATFORM)) $(stdlib_crypto_sha512_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/crypto/rsa
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ncrypto::rsa \
@@ -1231,7 +1230,7 @@ $(HARECACHE)/dirs/dirs-any.ssa: $(stdlib_dirs_any_srcs) $(stdlib_rt) $(stdlib_er
stdlib_encoding_base64_any_srcs = \
$(STDLIB)/encoding/base64/base64.ha
-$(HARECACHE)/encoding/base64/encoding_base64-any.ssa: $(stdlib_encoding_base64_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/encoding/base64/encoding_base64-any.ssa: $(stdlib_encoding_base64_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/encoding/base64
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nencoding::base64 \
@@ -1241,7 +1240,7 @@ $(HARECACHE)/encoding/base64/encoding_base64-any.ssa: $(stdlib_encoding_base64_a
stdlib_encoding_base32_any_srcs = \
$(STDLIB)/encoding/base32/base32.ha
-$(HARECACHE)/encoding/base32/encoding_base32-any.ssa: $(stdlib_encoding_base32_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_os_$(PLATFORM))
+$(HARECACHE)/encoding/base32/encoding_base32-any.ssa: $(stdlib_encoding_base32_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/encoding/base32
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nencoding::base32 \
@@ -1251,7 +1250,7 @@ $(HARECACHE)/encoding/base32/encoding_base32-any.ssa: $(stdlib_encoding_base32_a
stdlib_encoding_hex_any_srcs = \
$(STDLIB)/encoding/hex/hex.ha
-$(HARECACHE)/encoding/hex/encoding_hex-any.ssa: $(stdlib_encoding_hex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/encoding/hex/encoding_hex-any.ssa: $(stdlib_encoding_hex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/encoding/hex
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nencoding::hex \
@@ -1261,7 +1260,7 @@ $(HARECACHE)/encoding/hex/encoding_hex-any.ssa: $(stdlib_encoding_hex_any_srcs)
stdlib_encoding_pem_any_srcs = \
$(STDLIB)/encoding/pem/pem.ha
-$(HARECACHE)/encoding/pem/encoding_pem-any.ssa: $(stdlib_encoding_pem_any_srcs) $(stdlib_rt) $(stdlib_strings_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_encoding_base64_$(PLATFORM)) $(stdlib_ascii_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
+$(HARECACHE)/encoding/pem/encoding_pem-any.ssa: $(stdlib_encoding_pem_any_srcs) $(stdlib_rt) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_encoding_base64_$(PLATFORM)) $(stdlib_ascii_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/encoding/pem
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nencoding::pem \
@@ -1311,7 +1310,7 @@ $(HARECACHE)/errors/errors-any.ssa: $(stdlib_errors_any_srcs) $(stdlib_rt) $(std
stdlib_fmt_any_srcs = \
$(STDLIB)/fmt/fmt.ha
-$(HARECACHE)/fmt/fmt-any.ssa: $(stdlib_fmt_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
+$(HARECACHE)/fmt/fmt-any.ssa: $(stdlib_fmt_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/fmt
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nfmt \
@@ -1344,7 +1343,7 @@ stdlib_format_ini_any_srcs = \
$(STDLIB)/format/ini/scan.ha \
$(STDLIB)/format/ini/types.ha
-$(HARECACHE)/format/ini/format_ini-any.ssa: $(stdlib_format_ini_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/format/ini/format_ini-any.ssa: $(stdlib_format_ini_any_srcs) $(stdlib_rt) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/format/ini
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nformat::ini \
@@ -1355,7 +1354,7 @@ stdlib_format_tar_any_srcs = \
$(STDLIB)/format/tar/types.ha \
$(STDLIB)/format/tar/reader.ha
-$(HARECACHE)/format/tar/format_tar-any.ssa: $(stdlib_format_tar_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_types_c_$(PLATFORM))
+$(HARECACHE)/format/tar/format_tar-any.ssa: $(stdlib_format_tar_any_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_types_c_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/format/tar
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nformat::tar \
@@ -1387,7 +1386,7 @@ $(HARECACHE)/getopt/getopt-any.ssa: $(stdlib_getopt_any_srcs) $(stdlib_rt) $(std
stdlib_glob_any_srcs = \
$(STDLIB)/glob/glob.ha
-$(HARECACHE)/glob/glob-any.ssa: $(stdlib_glob_any_srcs) $(stdlib_rt) $(stdlib_fnmatch_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM))
+$(HARECACHE)/glob/glob-any.ssa: $(stdlib_glob_any_srcs) $(stdlib_rt) $(stdlib_fnmatch_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/glob
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nglob \
@@ -1413,7 +1412,7 @@ stdlib_hare_lex_any_srcs = \
$(STDLIB)/hare/lex/token.ha \
$(STDLIB)/hare/lex/lex.ha
-$(HARECACHE)/hare/lex/hare_lex-any.ssa: $(stdlib_hare_lex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_path_$(PLATFORM))
+$(HARECACHE)/hare/lex/hare_lex-any.ssa: $(stdlib_hare_lex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_path_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/lex
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::lex \
@@ -1427,7 +1426,7 @@ stdlib_hare_module_any_srcs = \
$(STDLIB)/hare/module/manifest.ha \
$(STDLIB)/hare/module/walk.ha
-$(HARECACHE)/hare/module/hare_module-any.ssa: $(stdlib_hare_module_any_srcs) $(stdlib_rt) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM)) $(stdlib_hare_parse_$(PLATFORM)) $(stdlib_hare_unparse_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_crypto_sha256_$(PLATFORM)) $(stdlib_dirs_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_ascii_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_temp_$(PLATFORM)) $(stdlib_path_$(PLATFORM))
+$(HARECACHE)/hare/module/hare_module-any.ssa: $(stdlib_hare_module_any_srcs) $(stdlib_rt) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM)) $(stdlib_hare_parse_$(PLATFORM)) $(stdlib_hare_unparse_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_crypto_sha256_$(PLATFORM)) $(stdlib_dirs_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_ascii_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_temp_$(PLATFORM)) $(stdlib_path_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/module
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::module \
@@ -1460,7 +1459,7 @@ stdlib_hare_types_any_srcs = \
$(STDLIB)/hare/types/store.ha \
$(STDLIB)/hare/types/types.ha
-$(HARECACHE)/hare/types/hare_types-any.ssa: $(stdlib_hare_types_any_srcs) $(stdlib_rt) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_hash_fnv_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
+$(HARECACHE)/hare/types/hare_types-any.ssa: $(stdlib_hare_types_any_srcs) $(stdlib_rt) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_hash_fnv_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_sort_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/types
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::types \
@@ -1477,7 +1476,7 @@ stdlib_hare_unit_any_srcs = \
$(STDLIB)/hare/unit/scope.ha \
$(STDLIB)/hare/unit/unit.ha
-$(HARECACHE)/hare/unit/hare_unit-any.ssa: $(stdlib_hare_unit_any_srcs) $(stdlib_rt) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_types_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_hash_fnv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM))
+$(HARECACHE)/hare/unit/hare_unit-any.ssa: $(stdlib_hare_unit_any_srcs) $(stdlib_rt) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_types_$(PLATFORM)) $(stdlib_hash_$(PLATFORM)) $(stdlib_hash_fnv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/unit
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::unit \
@@ -1493,7 +1492,7 @@ stdlib_hare_unparse_any_srcs = \
$(STDLIB)/hare/unparse/unit.ha \
$(STDLIB)/hare/unparse/util.ha
-$(HARECACHE)/hare/unparse/hare_unparse-any.ssa: $(stdlib_hare_unparse_any_srcs) $(stdlib_rt) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM))
+$(HARECACHE)/hare/unparse/hare_unparse-any.ssa: $(stdlib_hare_unparse_any_srcs) $(stdlib_rt) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_hare_ast_$(PLATFORM)) $(stdlib_hare_lex_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/hare/unparse
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nhare::unparse \
@@ -1732,6 +1731,17 @@ $(HARECACHE)/math/random/math_random-any.ssa: $(stdlib_math_random_any_srcs) $(s
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nmath::random \
-t$(HARECACHE)/math/random/math_random.td $(stdlib_math_random_any_srcs)
+# memio (+any)
+stdlib_memio_any_srcs = \
+ $(STDLIB)/memio/stream.ha \
+ $(STDLIB)/memio/ops.ha
+
+$(HARECACHE)/memio/memio-any.ssa: $(stdlib_memio_any_srcs) $(stdlib_rt) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM))
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(HARECACHE)/memio
+ @$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nmemio \
+ -t$(HARECACHE)/memio/memio.td $(stdlib_memio_any_srcs)
+
# net (+linux)
stdlib_net_linux_srcs = \
$(STDLIB)/net/+linux.ha \
@@ -1796,13 +1806,13 @@ stdlib_net_ip_freebsd_srcs = \
$(STDLIB)/net/ip/+freebsd.ha \
$(STDLIB)/net/ip/ip.ha
-$(HARECACHE)/net/ip/net_ip-linux.ssa: $(stdlib_net_ip_linux_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
+$(HARECACHE)/net/ip/net_ip-linux.ssa: $(stdlib_net_ip_linux_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/net/ip
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nnet::ip \
-t$(HARECACHE)/net/ip/net_ip.td $(stdlib_net_ip_linux_srcs)
-$(HARECACHE)/net/ip/net_ip-freebsd.ssa: $(stdlib_net_ip_freebsd_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
+$(HARECACHE)/net/ip/net_ip-freebsd.ssa: $(stdlib_net_ip_freebsd_srcs) $(stdlib_rt) $(stdlib_bytes_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/net/ip
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nnet::ip \
@@ -1893,7 +1903,7 @@ stdlib_net_uri_any_srcs = \
$(STDLIB)/net/uri/query.ha \
$(STDLIB)/net/uri/uri.ha
-$(HARECACHE)/net/uri/net_uri-any.ssa: $(stdlib_net_uri_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM))
+$(HARECACHE)/net/uri/net_uri-any.ssa: $(stdlib_net_uri_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/net/uri
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nnet::uri \
@@ -1981,7 +1991,7 @@ $(HARECACHE)/path/path-any.ssa: $(stdlib_path_any_srcs) $(stdlib_rt) $(stdlib_st
stdlib_regex_any_srcs = \
$(STDLIB)/regex/regex.ha
-$(HARECACHE)/regex/regex-any.ssa: $(stdlib_regex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_types_$(PLATFORM))
+$(HARECACHE)/regex/regex-any.ssa: $(stdlib_regex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_types_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/regex
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nregex \
@@ -1992,7 +2002,7 @@ stdlib_shlex_any_srcs = \
$(STDLIB)/shlex/escape.ha \
$(STDLIB)/shlex/split.ha
-$(HARECACHE)/shlex/shlex-any.ssa: $(stdlib_shlex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM))
+$(HARECACHE)/shlex/shlex-any.ssa: $(stdlib_shlex_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/shlex
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nshlex \
@@ -2056,28 +2066,17 @@ $(HARECACHE)/strings/strings-any.ssa: $(stdlib_strings_any_srcs) $(stdlib_rt) $(
stdlib_strings_template_any_srcs = \
$(STDLIB)/strings/template/template.ha
-$(HARECACHE)/strings/template/strings_template-any.ssa: $(stdlib_strings_template_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM))
+$(HARECACHE)/strings/template/strings_template-any.ssa: $(stdlib_strings_template_any_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/strings/template
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nstrings::template \
-t$(HARECACHE)/strings/template/strings_template.td $(stdlib_strings_template_any_srcs)
-# strio (+any)
-stdlib_strio_any_srcs = \
- $(STDLIB)/strio/stream.ha \
- $(STDLIB)/strio/ops.ha
-
-$(HARECACHE)/strio/strio-any.ssa: $(stdlib_strio_any_srcs) $(stdlib_rt) $(stdlib_errors_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM))
- @printf 'HAREC \t$@\n'
- @mkdir -p $(HARECACHE)/strio
- @$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nstrio \
- -t$(HARECACHE)/strio/strio.td $(stdlib_strio_any_srcs)
-
# temp (+linux)
stdlib_temp_linux_srcs = \
$(STDLIB)/temp/+linux.ha
-$(HARECACHE)/temp/temp-linux.ssa: $(stdlib_temp_linux_srcs) $(stdlib_rt) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_path_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
+$(HARECACHE)/temp/temp-linux.ssa: $(stdlib_temp_linux_srcs) $(stdlib_rt) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_path_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/temp
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ntemp \
@@ -2087,7 +2086,7 @@ $(HARECACHE)/temp/temp-linux.ssa: $(stdlib_temp_linux_srcs) $(stdlib_rt) $(stdli
stdlib_temp_freebsd_srcs = \
$(STDLIB)/temp/+freebsd.ha
-$(HARECACHE)/temp/temp-freebsd.ssa: $(stdlib_temp_freebsd_srcs) $(stdlib_rt) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_path_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
+$(HARECACHE)/temp/temp-freebsd.ssa: $(stdlib_temp_freebsd_srcs) $(stdlib_rt) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_encoding_hex_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_path_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/temp
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ntemp \
@@ -2180,7 +2179,7 @@ stdlib_time_date_linux_srcs = \
$(STDLIB)/time/date/tarithm.ha \
$(STDLIB)/time/date/virtual.ha
-$(HARECACHE)/time/date/time_date-linux.ssa: $(stdlib_time_date_linux_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_time_chrono_$(PLATFORM))
+$(HARECACHE)/time/date/time_date-linux.ssa: $(stdlib_time_date_linux_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_time_chrono_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/time/date
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ntime::date \
@@ -2202,7 +2201,7 @@ stdlib_time_date_freebsd_srcs = \
$(STDLIB)/time/date/tarithm.ha \
$(STDLIB)/time/date/virtual.ha
-$(HARECACHE)/time/date/time_date-freebsd.ssa: $(stdlib_time_date_freebsd_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_time_chrono_$(PLATFORM))
+$(HARECACHE)/time/date/time_date-freebsd.ssa: $(stdlib_time_date_freebsd_srcs) $(stdlib_rt) $(stdlib_ascii_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_time_$(PLATFORM)) $(stdlib_time_chrono_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/time/date
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Ntime::date \
@@ -2267,7 +2266,7 @@ stdlib_unix_hosts_linux_srcs = \
$(STDLIB)/unix/hosts/+linux.ha \
$(STDLIB)/unix/hosts/hosts.ha
-$(HARECACHE)/unix/hosts/unix_hosts-linux.ssa: $(stdlib_unix_hosts_linux_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/unix/hosts/unix_hosts-linux.ssa: $(stdlib_unix_hosts_linux_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/unix/hosts
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nunix::hosts \
@@ -2278,7 +2277,7 @@ stdlib_unix_hosts_freebsd_srcs = \
$(STDLIB)/unix/hosts/+freebsd.ha \
$(STDLIB)/unix/hosts/hosts.ha
-$(HARECACHE)/unix/hosts/unix_hosts-freebsd.ssa: $(stdlib_unix_hosts_freebsd_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/unix/hosts/unix_hosts-freebsd.ssa: $(stdlib_unix_hosts_freebsd_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_fs_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/unix/hosts
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nunix::hosts \
@@ -2290,7 +2289,7 @@ stdlib_unix_passwd_any_srcs = \
$(STDLIB)/unix/passwd/passwd.ha \
$(STDLIB)/unix/passwd/types.ha
-$(HARECACHE)/unix/passwd/unix_passwd-any.ssa: $(stdlib_unix_passwd_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/unix/passwd/unix_passwd-any.ssa: $(stdlib_unix_passwd_any_srcs) $(stdlib_rt) $(stdlib_bufio_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_os_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/unix/passwd
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nunix::passwd \
@@ -2323,7 +2322,7 @@ stdlib_unix_resolvconf_linux_srcs = \
$(STDLIB)/unix/resolvconf/+linux.ha \
$(STDLIB)/unix/resolvconf/load.ha
-$(HARECACHE)/unix/resolvconf/unix_resolvconf-linux.ssa: $(stdlib_unix_resolvconf_linux_srcs) $(stdlib_rt) $(stdlib_os_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/unix/resolvconf/unix_resolvconf-linux.ssa: $(stdlib_unix_resolvconf_linux_srcs) $(stdlib_rt) $(stdlib_os_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/unix/resolvconf
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nunix::resolvconf \
@@ -2334,7 +2333,7 @@ stdlib_unix_resolvconf_freebsd_srcs = \
$(STDLIB)/unix/resolvconf/+freebsd.ha \
$(STDLIB)/unix/resolvconf/load.ha
-$(HARECACHE)/unix/resolvconf/unix_resolvconf-freebsd.ssa: $(stdlib_unix_resolvconf_freebsd_srcs) $(stdlib_rt) $(stdlib_os_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
+$(HARECACHE)/unix/resolvconf/unix_resolvconf-freebsd.ssa: $(stdlib_unix_resolvconf_freebsd_srcs) $(stdlib_rt) $(stdlib_os_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_net_ip_$(PLATFORM)) $(stdlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/unix/resolvconf
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nunix::resolvconf \
@@ -2397,7 +2396,7 @@ $(HARECACHE)/unix/tty/unix_tty-freebsd.ssa: $(stdlib_unix_tty_freebsd_srcs) $(st
stdlib_uuid_any_srcs = \
$(STDLIB)/uuid/uuid.ha
-$(HARECACHE)/uuid/uuid-any.ssa: $(stdlib_uuid_any_srcs) $(stdlib_rt) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_strio_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_bufio_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM))
+$(HARECACHE)/uuid/uuid-any.ssa: $(stdlib_uuid_any_srcs) $(stdlib_rt) $(stdlib_crypto_random_$(PLATFORM)) $(stdlib_fmt_$(PLATFORM)) $(stdlib_endian_$(PLATFORM)) $(stdlib_io_$(PLATFORM)) $(stdlib_bytes_$(PLATFORM)) $(stdlib_memio_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_strconv_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(HARECACHE)/uuid
@$(stdlib_env) $(HAREC) $(HAREFLAGS) -o $@ -Nuuid \
@@ -3014,6 +3013,13 @@ testlib_deps_any += $(testlib_math_random_any)
testlib_math_random_linux = $(testlib_math_random_any)
testlib_math_random_freebsd = $(testlib_math_random_any)
+# gen_lib memio (any)
+testlib_memio_any = $(TESTCACHE)/memio/memio-any.o
+testlib_env += HARE_TD_memio=$(TESTCACHE)/memio/memio.td
+testlib_deps_any += $(testlib_memio_any)
+testlib_memio_linux = $(testlib_memio_any)
+testlib_memio_freebsd = $(testlib_memio_any)
+
# gen_lib net (linux)
testlib_net_linux = $(TESTCACHE)/net/net-linux.o
testlib_env += HARE_TD_net=$(TESTCACHE)/net/net.td
@@ -3154,13 +3160,6 @@ testlib_deps_any += $(testlib_strings_template_any)
testlib_strings_template_linux = $(testlib_strings_template_any)
testlib_strings_template_freebsd = $(testlib_strings_template_any)
-# gen_lib strio (any)
-testlib_strio_any = $(TESTCACHE)/strio/strio-any.o
-testlib_env += HARE_TD_strio=$(TESTCACHE)/strio/strio.td
-testlib_deps_any += $(testlib_strio_any)
-testlib_strio_linux = $(testlib_strio_any)
-testlib_strio_freebsd = $(testlib_strio_any)
-
# gen_lib temp (linux)
testlib_temp_linux = $(TESTCACHE)/temp/temp-linux.o
testlib_env += HARE_TD_temp=$(TESTCACHE)/temp/temp.td
@@ -3310,11 +3309,12 @@ $(TESTCACHE)/ascii/ascii-any.ssa: $(testlib_ascii_any_srcs) $(testlib_rt) $(test
# bufio (+any)
testlib_bufio_any_srcs = \
- $(STDLIB)/bufio/buffered.ha \
- $(STDLIB)/bufio/memstream.ha \
- $(STDLIB)/bufio/scanner.ha
+ $(STDLIB)/bufio/stream.ha \
+ $(STDLIB)/bufio/scanner.ha \
+ $(STDLIB)/bufio/stream_test+test.ha \
+ $(STDLIB)/bufio/scanner_test+test.ha
-$(TESTCACHE)/bufio/bufio-any.ssa: $(testlib_bufio_any_srcs) $(testlib_rt) $(testlib_io_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_types_$(PLATFORM))
+$(TESTCACHE)/bufio/bufio-any.ssa: $(testlib_bufio_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/bufio
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nbufio \
@@ -3343,7 +3343,7 @@ testlib_crypto_any_srcs = \
$(STDLIB)/crypto/keyderiv.ha \
$(STDLIB)/crypto/+test/authenc_test.ha
-$(TESTCACHE)/crypto/crypto-any.ssa: $(testlib_crypto_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_argon2_$(PLATFORM)) $(testlib_crypto_chachapoly_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM))
+$(TESTCACHE)/crypto/crypto-any.ssa: $(testlib_crypto_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_argon2_$(PLATFORM)) $(testlib_crypto_chachapoly_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto \
@@ -3360,7 +3360,7 @@ testlib_crypto_aes_any_srcs = \
$(STDLIB)/crypto/aes/rt+test.ha \
$(STDLIB)/crypto/aes/+test/gcm.ha
-$(TESTCACHE)/crypto/aes/crypto_aes-any.ssa: $(testlib_crypto_aes_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_rt_$(PLATFORM))
+$(TESTCACHE)/crypto/aes/crypto_aes-any.ssa: $(testlib_crypto_aes_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_rt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/aes
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::aes \
@@ -3382,7 +3382,7 @@ testlib_crypto_argon2_any_srcs = \
$(STDLIB)/crypto/argon2/argon2.ha \
$(STDLIB)/crypto/argon2/+test.ha
-$(TESTCACHE)/crypto/argon2/crypto_argon2-any.ssa: $(testlib_crypto_argon2_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_blake2b_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_rt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_types_$(PLATFORM))
+$(TESTCACHE)/crypto/argon2/crypto_argon2-any.ssa: $(testlib_crypto_argon2_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_blake2b_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_rt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/argon2
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::argon2 \
@@ -3394,7 +3394,7 @@ testlib_crypto_bcrypt_any_srcs = \
$(STDLIB)/crypto/bcrypt/base64.ha \
$(STDLIB)/crypto/bcrypt/+test.ha
-$(TESTCACHE)/crypto/bcrypt/crypto_bcrypt-any.ssa: $(testlib_crypto_bcrypt_any_srcs) $(testlib_rt) $(testlib_crypto_blowfish_$(PLATFORM)) $(testlib_encoding_base64_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_crypto_$(PLATFORM)) $(testlib_crypto_random_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_strconv_$(PLATFORM))
+$(TESTCACHE)/crypto/bcrypt/crypto_bcrypt-any.ssa: $(testlib_crypto_bcrypt_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_$(PLATFORM)) $(testlib_crypto_blowfish_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_crypto_random_$(PLATFORM)) $(testlib_encoding_base64_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/bcrypt
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::bcrypt \
@@ -3406,7 +3406,7 @@ testlib_crypto_blake2b_any_srcs = \
$(STDLIB)/crypto/blake2b/+test.ha \
$(STDLIB)/crypto/blake2b/vectors+test.ha
-$(TESTCACHE)/crypto/blake2b/crypto_blake2b-any.ssa: $(testlib_crypto_blake2b_any_srcs) $(testlib_rt) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_bytes_$(PLATFORM))
+$(TESTCACHE)/crypto/blake2b/crypto_blake2b-any.ssa: $(testlib_crypto_blake2b_any_srcs) $(testlib_rt) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_bytes_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/blake2b
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::blake2b \
@@ -3447,7 +3447,7 @@ testlib_crypto_chacha_any_srcs = \
$(STDLIB)/crypto/chacha/chacha20.ha \
$(STDLIB)/crypto/chacha/+test.ha
-$(TESTCACHE)/crypto/chacha/crypto_chacha-any.ssa: $(testlib_crypto_chacha_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bufio_$(PLATFORM))
+$(TESTCACHE)/crypto/chacha/crypto_chacha-any.ssa: $(testlib_crypto_chacha_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/chacha
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::chacha \
@@ -3557,7 +3557,7 @@ testlib_crypto_rsa_any_srcs = \
$(STDLIB)/crypto/rsa/+test/keys_test.ha \
$(STDLIB)/crypto/rsa/+test/pkcs1_test.ha
-$(TESTCACHE)/crypto/rsa/crypto_rsa-any.ssa: $(testlib_crypto_rsa_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_bigint_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_crypto_sha1_$(PLATFORM)) $(testlib_crypto_sha256_$(PLATFORM)) $(testlib_crypto_sha512_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_types_$(PLATFORM))
+$(TESTCACHE)/crypto/rsa/crypto_rsa-any.ssa: $(testlib_crypto_rsa_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_bigint_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_crypto_sha1_$(PLATFORM)) $(testlib_crypto_sha256_$(PLATFORM)) $(testlib_crypto_sha512_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/rsa
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::rsa \
@@ -3579,7 +3579,7 @@ testlib_crypto_salsa_any_srcs = \
$(STDLIB)/crypto/salsa/salsa20.ha \
$(STDLIB)/crypto/salsa/+test.ha
-$(TESTCACHE)/crypto/salsa/crypto_salsa-any.ssa: $(testlib_crypto_salsa_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_types_$(PLATFORM)) $(testlib_io_$(PLATFORM))
+$(TESTCACHE)/crypto/salsa/crypto_salsa-any.ssa: $(testlib_crypto_salsa_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_crypto_cipher_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/crypto/salsa
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ncrypto::salsa \
@@ -3666,7 +3666,7 @@ $(TESTCACHE)/dirs/dirs-any.ssa: $(testlib_dirs_any_srcs) $(testlib_rt) $(testlib
testlib_encoding_base64_any_srcs = \
$(STDLIB)/encoding/base64/base64.ha
-$(TESTCACHE)/encoding/base64/encoding_base64-any.ssa: $(testlib_encoding_base64_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/encoding/base64/encoding_base64-any.ssa: $(testlib_encoding_base64_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/encoding/base64
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nencoding::base64 \
@@ -3676,7 +3676,7 @@ $(TESTCACHE)/encoding/base64/encoding_base64-any.ssa: $(testlib_encoding_base64_
testlib_encoding_base32_any_srcs = \
$(STDLIB)/encoding/base32/base32.ha
-$(TESTCACHE)/encoding/base32/encoding_base32-any.ssa: $(testlib_encoding_base32_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_os_$(PLATFORM))
+$(TESTCACHE)/encoding/base32/encoding_base32-any.ssa: $(testlib_encoding_base32_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/encoding/base32
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nencoding::base32 \
@@ -3686,7 +3686,7 @@ $(TESTCACHE)/encoding/base32/encoding_base32-any.ssa: $(testlib_encoding_base32_
testlib_encoding_hex_any_srcs = \
$(STDLIB)/encoding/hex/hex.ha
-$(TESTCACHE)/encoding/hex/encoding_hex-any.ssa: $(testlib_encoding_hex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/encoding/hex/encoding_hex-any.ssa: $(testlib_encoding_hex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/encoding/hex
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nencoding::hex \
@@ -3697,7 +3697,7 @@ testlib_encoding_pem_any_srcs = \
$(STDLIB)/encoding/pem/pem.ha \
$(STDLIB)/encoding/pem/+test.ha
-$(TESTCACHE)/encoding/pem/encoding_pem-any.ssa: $(testlib_encoding_pem_any_srcs) $(testlib_rt) $(testlib_strings_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_encoding_base64_$(PLATFORM)) $(testlib_ascii_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_bytes_$(PLATFORM))
+$(TESTCACHE)/encoding/pem/encoding_pem-any.ssa: $(testlib_encoding_pem_any_srcs) $(testlib_rt) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_encoding_base64_$(PLATFORM)) $(testlib_ascii_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_bytes_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/encoding/pem
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nencoding::pem \
@@ -3747,7 +3747,7 @@ $(TESTCACHE)/errors/errors-any.ssa: $(testlib_errors_any_srcs) $(testlib_rt) $(t
testlib_fmt_any_srcs = \
$(STDLIB)/fmt/fmt.ha
-$(TESTCACHE)/fmt/fmt-any.ssa: $(testlib_fmt_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_types_$(PLATFORM))
+$(TESTCACHE)/fmt/fmt-any.ssa: $(testlib_fmt_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_types_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/fmt
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nfmt \
@@ -3782,7 +3782,7 @@ testlib_format_ini_any_srcs = \
$(STDLIB)/format/ini/types.ha \
$(STDLIB)/format/ini/+test.ha
-$(TESTCACHE)/format/ini/format_ini-any.ssa: $(testlib_format_ini_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/format/ini/format_ini-any.ssa: $(testlib_format_ini_any_srcs) $(testlib_rt) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/format/ini
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nformat::ini \
@@ -3793,7 +3793,7 @@ testlib_format_tar_any_srcs = \
$(STDLIB)/format/tar/types.ha \
$(STDLIB)/format/tar/reader.ha
-$(TESTCACHE)/format/tar/format_tar-any.ssa: $(testlib_format_tar_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_types_c_$(PLATFORM))
+$(TESTCACHE)/format/tar/format_tar-any.ssa: $(testlib_format_tar_any_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_types_c_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/format/tar
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nformat::tar \
@@ -3826,7 +3826,7 @@ testlib_glob_any_srcs = \
$(STDLIB)/glob/glob.ha \
$(STDLIB)/glob/+test.ha
-$(TESTCACHE)/glob/glob-any.ssa: $(testlib_glob_any_srcs) $(testlib_rt) $(testlib_fnmatch_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM))
+$(TESTCACHE)/glob/glob-any.ssa: $(testlib_glob_any_srcs) $(testlib_rt) $(testlib_fnmatch_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/glob
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nglob \
@@ -3853,7 +3853,7 @@ testlib_hare_lex_any_srcs = \
$(STDLIB)/hare/lex/lex.ha \
$(STDLIB)/hare/lex/+test.ha
-$(TESTCACHE)/hare/lex/hare_lex-any.ssa: $(testlib_hare_lex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_path_$(PLATFORM))
+$(TESTCACHE)/hare/lex/hare_lex-any.ssa: $(testlib_hare_lex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_path_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/lex
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::lex \
@@ -3867,7 +3867,7 @@ testlib_hare_module_any_srcs = \
$(STDLIB)/hare/module/manifest.ha \
$(STDLIB)/hare/module/walk.ha
-$(TESTCACHE)/hare/module/hare_module-any.ssa: $(testlib_hare_module_any_srcs) $(testlib_rt) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM)) $(testlib_hare_unparse_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_crypto_sha256_$(PLATFORM)) $(testlib_dirs_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_ascii_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_temp_$(PLATFORM)) $(testlib_path_$(PLATFORM))
+$(TESTCACHE)/hare/module/hare_module-any.ssa: $(testlib_hare_module_any_srcs) $(testlib_rt) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM)) $(testlib_hare_unparse_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_crypto_sha256_$(PLATFORM)) $(testlib_dirs_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_ascii_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_temp_$(PLATFORM)) $(testlib_path_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/module
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::module \
@@ -3889,7 +3889,7 @@ testlib_hare_parse_any_srcs = \
$(STDLIB)/hare/parse/+test/types.ha \
$(STDLIB)/hare/parse/+test/unit_test.ha
-$(TESTCACHE)/hare/parse/hare_parse-any.ssa: $(testlib_hare_parse_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_unparse_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_types_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_math_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM))
+$(TESTCACHE)/hare/parse/hare_parse-any.ssa: $(testlib_hare_parse_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_unparse_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_types_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_math_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/parse
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::parse \
@@ -3907,7 +3907,7 @@ testlib_hare_types_any_srcs = \
$(STDLIB)/hare/types/types.ha \
$(STDLIB)/hare/types/+test.ha
-$(TESTCACHE)/hare/types/hare_types-any.ssa: $(testlib_hare_types_any_srcs) $(testlib_rt) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_hash_fnv_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM)) $(testlib_io_$(PLATFORM))
+$(TESTCACHE)/hare/types/hare_types-any.ssa: $(testlib_hare_types_any_srcs) $(testlib_rt) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_hash_fnv_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_sort_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM)) $(testlib_io_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/types
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::types \
@@ -3925,7 +3925,7 @@ testlib_hare_unit_any_srcs = \
$(STDLIB)/hare/unit/unit.ha \
$(STDLIB)/hare/unit/+test.ha
-$(TESTCACHE)/hare/unit/hare_unit-any.ssa: $(testlib_hare_unit_any_srcs) $(testlib_rt) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_types_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_hash_fnv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM))
+$(TESTCACHE)/hare/unit/hare_unit-any.ssa: $(testlib_hare_unit_any_srcs) $(testlib_rt) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_types_$(PLATFORM)) $(testlib_hash_$(PLATFORM)) $(testlib_hash_fnv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM)) $(testlib_hare_parse_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/unit
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::unit \
@@ -3941,7 +3941,7 @@ testlib_hare_unparse_any_srcs = \
$(STDLIB)/hare/unparse/unit.ha \
$(STDLIB)/hare/unparse/util.ha
-$(TESTCACHE)/hare/unparse/hare_unparse-any.ssa: $(testlib_hare_unparse_any_srcs) $(testlib_rt) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM))
+$(TESTCACHE)/hare/unparse/hare_unparse-any.ssa: $(testlib_hare_unparse_any_srcs) $(testlib_rt) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_hare_ast_$(PLATFORM)) $(testlib_hare_lex_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hare/unparse
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhare::unparse \
@@ -4013,7 +4013,7 @@ testlib_hash_siphash_any_srcs = \
$(STDLIB)/hash/siphash/siphash.ha \
$(STDLIB)/hash/siphash/+test.ha
-$(TESTCACHE)/hash/siphash/hash_siphash-any.ssa: $(testlib_hash_siphash_any_srcs) $(testlib_rt) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/hash/siphash/hash_siphash-any.ssa: $(testlib_hash_siphash_any_srcs) $(testlib_rt) $(testlib_hash_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_crypto_math_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/hash/siphash
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nhash::siphash \
@@ -4190,6 +4190,17 @@ $(TESTCACHE)/math/random/math_random-any.ssa: $(testlib_math_random_any_srcs) $(
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nmath::random \
-t$(TESTCACHE)/math/random/math_random.td $(testlib_math_random_any_srcs)
+# memio (+any)
+testlib_memio_any_srcs = \
+ $(STDLIB)/memio/stream.ha \
+ $(STDLIB)/memio/ops.ha
+
+$(TESTCACHE)/memio/memio-any.ssa: $(testlib_memio_any_srcs) $(testlib_rt) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM))
+ @printf 'HAREC \t$@\n'
+ @mkdir -p $(TESTCACHE)/memio
+ @$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nmemio \
+ -t$(TESTCACHE)/memio/memio.td $(testlib_memio_any_srcs)
+
# net (+linux)
testlib_net_linux_srcs = \
$(STDLIB)/net/+linux.ha \
@@ -4256,13 +4267,13 @@ testlib_net_ip_freebsd_srcs = \
$(STDLIB)/net/ip/ip.ha \
$(STDLIB)/net/ip/test+test.ha
-$(TESTCACHE)/net/ip/net_ip-linux.ssa: $(testlib_net_ip_linux_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
+$(TESTCACHE)/net/ip/net_ip-linux.ssa: $(testlib_net_ip_linux_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/net/ip
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nnet::ip \
-t$(TESTCACHE)/net/ip/net_ip.td $(testlib_net_ip_linux_srcs)
-$(TESTCACHE)/net/ip/net_ip-freebsd.ssa: $(testlib_net_ip_freebsd_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
+$(TESTCACHE)/net/ip/net_ip-freebsd.ssa: $(testlib_net_ip_freebsd_srcs) $(testlib_rt) $(testlib_bytes_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/net/ip
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nnet::ip \
@@ -4354,7 +4365,7 @@ testlib_net_uri_any_srcs = \
$(STDLIB)/net/uri/uri.ha \
$(STDLIB)/net/uri/+test.ha
-$(TESTCACHE)/net/uri/net_uri-any.ssa: $(testlib_net_uri_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM))
+$(TESTCACHE)/net/uri/net_uri-any.ssa: $(testlib_net_uri_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/net/uri
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nnet::uri \
@@ -4443,7 +4454,7 @@ testlib_regex_any_srcs = \
$(STDLIB)/regex/regex.ha \
$(STDLIB)/regex/+test.ha
-$(TESTCACHE)/regex/regex-any.ssa: $(testlib_regex_any_srcs) $(testlib_rt) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_types_$(PLATFORM))
+$(TESTCACHE)/regex/regex-any.ssa: $(testlib_regex_any_srcs) $(testlib_rt) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_types_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/regex
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nregex \
@@ -4455,7 +4466,7 @@ testlib_shlex_any_srcs = \
$(STDLIB)/shlex/split.ha \
$(STDLIB)/shlex/+test.ha
-$(TESTCACHE)/shlex/shlex-any.ssa: $(testlib_shlex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM))
+$(TESTCACHE)/shlex/shlex-any.ssa: $(testlib_shlex_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/shlex
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nshlex \
@@ -4522,28 +4533,17 @@ $(TESTCACHE)/strings/strings-any.ssa: $(testlib_strings_any_srcs) $(testlib_rt)
testlib_strings_template_any_srcs = \
$(STDLIB)/strings/template/template.ha
-$(TESTCACHE)/strings/template/strings_template-any.ssa: $(testlib_strings_template_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM))
+$(TESTCACHE)/strings/template/strings_template-any.ssa: $(testlib_strings_template_any_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/strings/template
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nstrings::template \
-t$(TESTCACHE)/strings/template/strings_template.td $(testlib_strings_template_any_srcs)
-# strio (+any)
-testlib_strio_any_srcs = \
- $(STDLIB)/strio/stream.ha \
- $(STDLIB)/strio/ops.ha
-
-$(TESTCACHE)/strio/strio-any.ssa: $(testlib_strio_any_srcs) $(testlib_rt) $(testlib_errors_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM))
- @printf 'HAREC \t$@\n'
- @mkdir -p $(TESTCACHE)/strio
- @$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nstrio \
- -t$(TESTCACHE)/strio/strio.td $(testlib_strio_any_srcs)
-
# temp (+linux)
testlib_temp_linux_srcs = \
$(STDLIB)/temp/+linux.ha
-$(TESTCACHE)/temp/temp-linux.ssa: $(testlib_temp_linux_srcs) $(testlib_rt) $(testlib_crypto_random_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_path_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
+$(TESTCACHE)/temp/temp-linux.ssa: $(testlib_temp_linux_srcs) $(testlib_rt) $(testlib_crypto_random_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_path_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/temp
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ntemp \
@@ -4553,7 +4553,7 @@ $(TESTCACHE)/temp/temp-linux.ssa: $(testlib_temp_linux_srcs) $(testlib_rt) $(tes
testlib_temp_freebsd_srcs = \
$(STDLIB)/temp/+freebsd.ha
-$(TESTCACHE)/temp/temp-freebsd.ssa: $(testlib_temp_freebsd_srcs) $(testlib_rt) $(testlib_crypto_random_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_path_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
+$(TESTCACHE)/temp/temp-freebsd.ssa: $(testlib_temp_freebsd_srcs) $(testlib_rt) $(testlib_crypto_random_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_path_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/temp
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ntemp \
@@ -4565,7 +4565,7 @@ testlib_test_any_srcs = \
$(STDLIB)/test/+test.ha \
$(STDLIB)/test/fail+test.ha
-$(TESTCACHE)/test/test-any.ssa: $(testlib_test_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_fnmatch_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_rt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_unix_signal_$(PLATFORM))
+$(TESTCACHE)/test/test-any.ssa: $(testlib_test_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_hex_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_fnmatch_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_rt_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_unix_signal_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/test
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ntest \
@@ -4648,7 +4648,7 @@ testlib_time_date_linux_srcs = \
$(STDLIB)/time/date/tarithm.ha \
$(STDLIB)/time/date/virtual.ha
-$(TESTCACHE)/time/date/time_date-linux.ssa: $(testlib_time_date_linux_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_time_chrono_$(PLATFORM))
+$(TESTCACHE)/time/date/time_date-linux.ssa: $(testlib_time_date_linux_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_time_chrono_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/time/date
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ntime::date \
@@ -4670,7 +4670,7 @@ testlib_time_date_freebsd_srcs = \
$(STDLIB)/time/date/tarithm.ha \
$(STDLIB)/time/date/virtual.ha
-$(TESTCACHE)/time/date/time_date-freebsd.ssa: $(testlib_time_date_freebsd_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_time_chrono_$(PLATFORM))
+$(TESTCACHE)/time/date/time_date-freebsd.ssa: $(testlib_time_date_freebsd_srcs) $(testlib_rt) $(testlib_ascii_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_time_$(PLATFORM)) $(testlib_time_chrono_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/time/date
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Ntime::date \
@@ -4737,7 +4737,7 @@ testlib_unix_hosts_linux_srcs = \
$(STDLIB)/unix/hosts/test+test.ha \
$(STDLIB)/unix/hosts/hosts.ha
-$(TESTCACHE)/unix/hosts/unix_hosts-linux.ssa: $(testlib_unix_hosts_linux_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/unix/hosts/unix_hosts-linux.ssa: $(testlib_unix_hosts_linux_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/unix/hosts
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nunix::hosts \
@@ -4749,7 +4749,7 @@ testlib_unix_hosts_freebsd_srcs = \
$(STDLIB)/unix/hosts/test+test.ha \
$(STDLIB)/unix/hosts/hosts.ha
-$(TESTCACHE)/unix/hosts/unix_hosts-freebsd.ssa: $(testlib_unix_hosts_freebsd_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/unix/hosts/unix_hosts-freebsd.ssa: $(testlib_unix_hosts_freebsd_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_fs_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/unix/hosts
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nunix::hosts \
@@ -4761,7 +4761,7 @@ testlib_unix_passwd_any_srcs = \
$(STDLIB)/unix/passwd/passwd.ha \
$(STDLIB)/unix/passwd/types.ha
-$(TESTCACHE)/unix/passwd/unix_passwd-any.ssa: $(testlib_unix_passwd_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/unix/passwd/unix_passwd-any.ssa: $(testlib_unix_passwd_any_srcs) $(testlib_rt) $(testlib_bufio_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_os_$(PLATFORM)) $(testlib_strconv_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_memio_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/unix/passwd
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nunix::passwd \
@@ -4794,7 +4794,7 @@ testlib_unix_resolvconf_linux_srcs = \
$(STDLIB)/unix/resolvconf/+linux.ha \
$(STDLIB)/unix/resolvconf/load.ha
-$(TESTCACHE)/unix/resolvconf/unix_resolvconf-linux.ssa: $(testlib_unix_resolvconf_linux_srcs) $(testlib_rt) $(testlib_os_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/unix/resolvconf/unix_resolvconf-linux.ssa: $(testlib_unix_resolvconf_linux_srcs) $(testlib_rt) $(testlib_os_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/unix/resolvconf
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nunix::resolvconf \
@@ -4805,7 +4805,7 @@ testlib_unix_resolvconf_freebsd_srcs = \
$(STDLIB)/unix/resolvconf/+freebsd.ha \
$(STDLIB)/unix/resolvconf/load.ha
-$(TESTCACHE)/unix/resolvconf/unix_resolvconf-freebsd.ssa: $(testlib_unix_resolvconf_freebsd_srcs) $(testlib_rt) $(testlib_os_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
+$(TESTCACHE)/unix/resolvconf/unix_resolvconf-freebsd.ssa: $(testlib_unix_resolvconf_freebsd_srcs) $(testlib_rt) $(testlib_os_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_net_ip_$(PLATFORM)) $(testlib_strings_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/unix/resolvconf
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nunix::resolvconf \
@@ -4868,7 +4868,7 @@ $(TESTCACHE)/unix/tty/unix_tty-freebsd.ssa: $(testlib_unix_tty_freebsd_srcs) $(t
testlib_uuid_any_srcs = \
$(STDLIB)/uuid/uuid.ha
-$(TESTCACHE)/uuid/uuid-any.ssa: $(testlib_uuid_any_srcs) $(testlib_rt) $(testlib_crypto_random_$(PLATFORM)) $(testlib_strio_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_bufio_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strconv_$(PLATFORM))
+$(TESTCACHE)/uuid/uuid-any.ssa: $(testlib_uuid_any_srcs) $(testlib_rt) $(testlib_crypto_random_$(PLATFORM)) $(testlib_fmt_$(PLATFORM)) $(testlib_endian_$(PLATFORM)) $(testlib_io_$(PLATFORM)) $(testlib_bytes_$(PLATFORM)) $(testlib_memio_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_strconv_$(PLATFORM))
@printf 'HAREC \t$@\n'
@mkdir -p $(TESTCACHE)/uuid
@$(testlib_env) $(HAREC) $(TESTHAREFLAGS) -o $@ -Nuuid \
diff --git a/strings/template/template.ha b/strings/template/template.ha
@@ -4,8 +4,8 @@ use ascii;
use errors;
use fmt;
use io;
+use memio;
use strings;
-use strio;
export type literal = str;
export type variable = str;
@@ -19,7 +19,7 @@ export type param = (str, fmt::formattable);
// Compiles a template string. The return value must be freed with [[finish]]
// after use.
export fn compile(input: str) (template | errors::invalid) = {
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
defer io::close(&buf)!;
let instrs: []instruction = [];
@@ -36,12 +36,12 @@ export fn compile(input: str) (template | errors::invalid) = {
match (strings::next(&iter)) {
case let next_rn: rune =>
if (next_rn == '$') {
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
} else {
strings::prev(&iter);
- const lit = strio::string(&buf);
+ const lit = memio::string(&buf)!;
append(instrs, strings::dup(lit): literal);
- strio::reset(&buf);
+ memio::reset(&buf);
parse_variable(&instrs, &iter, &buf)?;
};
@@ -49,12 +49,12 @@ export fn compile(input: str) (template | errors::invalid) = {
return errors::invalid;
};
} else {
- strio::appendrune(&buf, rn)!;
+ memio::appendrune(&buf, rn)!;
};
};
- if (len(strio::string(&buf)) != 0) {
- const lit = strio::string(&buf);
+ if (len(memio::string(&buf)!) != 0) {
+ const lit = memio::string(&buf)!;
append(instrs, strings::dup(lit): literal);
};
@@ -109,7 +109,7 @@ fn get_param(name: str, params: param...) fmt::formattable = {
fn parse_variable(
instrs: *[]instruction,
iter: *strings::iterator,
- buf: *strio::stream,
+ buf: *memio::stream,
) (void | errors::invalid) = {
let brace = false;
match (strings::next(iter)) {
@@ -135,13 +135,13 @@ fn parse_variable(
if (rn == '{') {
return errors::invalid;
} else if (rn != '}') {
- strio::appendrune(buf, rn)!;
+ memio::appendrune(buf, rn)!;
} else {
break;
};
} else {
if (ascii::isalnum(rn)) {
- strio::appendrune(buf, rn)!;
+ memio::appendrune(buf, rn)!;
} else {
strings::prev(iter);
break;
@@ -149,9 +149,9 @@ fn parse_variable(
};
};
- const var = strio::string(buf);
+ const var = memio::string(buf)!;
append(instrs, strings::dup(var): variable);
- strio::reset(buf);
+ memio::reset(buf);
};
def test_input: str = `Dear ${recipient},
@@ -170,7 +170,7 @@ foreign bank account balance of $1,000,000 to you.`;
const tmpl = compile(test_input)!;
defer finish(&tmpl);
- let buf = strio::dynamic();
+ let buf = memio::dynamic();
defer io::close(&buf)!;
execute(&tmpl, &buf,
@@ -179,5 +179,5 @@ foreign bank account balance of $1,000,000 to you.`;
("brother", "Elon Musk"),
)!;
- assert(strio::string(&buf) == test_output);
+ assert(memio::string(&buf)! == test_output);
};
diff --git a/strio/README b/strio/README
@@ -1,5 +0,0 @@
-strio provides string-related I/O operations, specifically to make efficient use
-of memory while building strings incrementally. The main entry points to strio
-are [[dynamic]] and [[fixed]]. Each of the utility functions (e.g.
-[[appendrune]]) work correctly with any [[io::handle]], but for efficiency
-reasons it is recommended that they are either a strio or [[bufio]] stream.
diff --git a/strio/ops.ha b/strio/ops.ha
@@ -1,135 +0,0 @@
-// License: MPL-2.0
-// (c) 2022 Alexey Yerin <yyp@disroot.org>
-// (c) 2021 Drew DeVault <sir@cmpwn.com>
-// (c) 2022 Yasumasa Tada <ytada@spartan.dev>
-use encoding::utf8;
-use io;
-use strings;
-
-// Appends zero or more strings to an [[io::handle]]. The output needn't be a
-// strio stream, but it's generally more efficient if it is. Returns the number
-// of bytes written, or an error.
-export fn concat(out: io::handle, strs: str...) (size | io::error) =
- join(out, "", strs...);
-
-@test fn concat() void = {
- let st = dynamic();
- defer io::close(&st)!;
- let tests: [_]([]str, str) = [
- ([], ""),
- ([""], ""),
- (["", ""], ""),
- (["hello"], "hello"),
- (["hello", " ", "world"], "hello world"),
- (["", "hello", " ", "world"], "hello world"),
- (["hello", " ", "world", ""], "hello world"),
- (["hello", "", " ", "world"], "hello world")
- ];
- for (let i = 0z; i < len(tests); i += 1) {
- let ln = concat(&st, tests[i].0...) as size;
- assert(ln == len(tests[i].1) && string(&st) == tests[i].1);
- truncate(&st);
- };
-};
-
-// Joins several strings together by a delimiter and writes them to a handle.
-// The output needn't be a strio stream, but it's generally more efficient if it
-// is. Returns the number of bytes written, or an error.
-export fn join(out: io::handle, delim: str, strs: str...) (size | io::error) = {
- let n = 0z;
- let delim = strings::toutf8(delim);
- for (let i = 0z; i < len(strs); i += 1) {
- n += io::writeall(out, strings::toutf8(strs[i]))?;
- if (len(delim) != 0 && i + 1 < len(strs)) {
- n += io::writeall(out, delim)?;
- };
- };
- return n;
-};
-
-@test fn join() void = {
- let st = dynamic();
- defer io::close(&st)!;
- let tests: [_](str, []str, str) = [
- ("::", [], ""),
- ("::", [""], ""),
- ("::", ["", ""], "::"),
- ("::", ["", "", ""], "::::"),
- ("::", ["hello"], "hello"),
- ("::", ["hello", "world"], "hello::world"),
- ("::", ["", "hello", "world"], "::hello::world"),
- ("::", ["hello", "world", ""], "hello::world::"),
- ("::", ["hello", "", "world"], "hello::::world"),
- ];
- for (let i = 0z; i < len(tests); i += 1) {
- let ln = join(&st, tests[i].0, tests[i].1...) as size;
- assert(ln == len(tests[i].2) && string(&st) == tests[i].2);
- truncate(&st);
- };
-};
-
-// Appends zero or more strings to an [[io::handle]], in reverse order. The
-// output needn't be a strio stream, but it's generally more efficient if it is.
-// Returns the number of bytes written, or an error.
-export fn rconcat(out: io::handle, strs: str...) (size | io::error) =
- rjoin(out, "", strs...);
-
-@test fn rconcat() void = {
- let st = dynamic();
- defer io::close(&st)!;
- let tests: [_]([]str, str) = [
- ([], ""),
- ([""], ""),
- (["", ""], ""),
- (["hello"], "hello"),
- (["hello", " ", "world"], "world hello"),
- (["", "hello", " ", "world"], "world hello"),
- (["hello", " ", "world", ""], "world hello"),
- (["hello", "", " ", "world"], "world hello")
- ];
- for (let i = 0z; i < len(tests); i += 1) {
- let ln = rconcat(&st, tests[i].0...) as size;
- assert(ln == len(tests[i].1) && string(&st) == tests[i].1);
- truncate(&st);
- };
-};
-
-// Joins several strings together by a delimiter and writes them to a handle, in
-// reverse order. The output needn't be a strio stream, but it's generally more
-// efficient if it is. Returns the number of bytes written, or an error.
-export fn rjoin(out: io::handle, delim: str, strs: str...) (size | io::error) = {
- let n = 0z;
- let delim = strings::toutf8(delim);
- for (let i = len(strs); i > 0; i -= 1) {
- n += io::writeall(out, strings::toutf8(strs[i - 1]))?;
- if (len(delim) != 0 && i - 1 > 0) {
- n += io::writeall(out, delim)?;
- };
- };
- return n;
-};
-
-@test fn rjoin() void = {
- let st = dynamic();
- defer io::close(&st)!;
- let tests: [_](str, []str, str) = [
- ("::", [], ""),
- ("::", [""], ""),
- ("::", ["", ""], "::"),
- ("::", ["", "", ""], "::::"),
- ("::", ["hello"], "hello"),
- ("::", ["hello", "world"], "world::hello"),
- ("::", ["", "hello", "world"], "world::hello::"),
- ("::", ["hello", "world", ""], "::world::hello"),
- ("::", ["hello", "", "world"], "world::::hello"),
- ];
- for (let i = 0z; i < len(tests); i += 1) {
- let ln = rjoin(&st, tests[i].0, tests[i].1...) as size;
- assert(ln == len(tests[i].2) && string(&st) == tests[i].2);
- truncate(&st);
- };
-};
-
-// Appends a rune to a stream.
-export fn appendrune(out: io::handle, r: rune) (size | io::error) =
- io::writeall(out, utf8::encoderune(r));
diff --git a/strio/stream.ha b/strio/stream.ha
@@ -1,104 +0,0 @@
-// License: MPL-2.0
-// (c) 2022 Alexey Yerin <yyp@disroot.org>
-// (c) 2021 Drew DeVault <sir@cmpwn.com>
-use errors;
-use io;
-use strings;
-
-const fixed_vtable: io::vtable = io::vtable {
- writer = &fixed_write,
- ...
-};
-
-export type stream = struct {
- stream: io::stream,
- buf: []u8,
-};
-
-// Returns the current contents of the buffer as a string. Aborts the program if
-// invalid UTF-8 has been written to the buffer. The return value is borrowed
-// from the stream, and will be freed when the stream is closed. Use
-// [[strings::dup]] to extend its lifetime.
-export fn string(in: *stream) str = {
- return strings::fromutf8(in.buf)!;
-};
-
-// Resets the buffer's length to zero, but does not attempt to deallocate its
-// backing memory. Suitable for use both with fixed and dynamic streams.
-export fn reset(in: *stream) void = {
- in.buf = in.buf[..0];
-};
-
-// Creates a write-only string stream using the provided buffer for storage.
-// The writes will return an error if they would exceed the buffer's capacity.
-// The stream doesn't need to be closed.
-export fn fixed(in: []u8) stream = {
- return stream {
- stream = &fixed_vtable,
- buf = in[..0],
- };
-};
-
-fn fixed_write(s: *io::stream, buf: const []u8) (size | io::error) = {
- let s = s: *stream;
- if (cap(s.buf) == len(s.buf)) return errors::overflow;
- let n = if (cap(s.buf) - len(s.buf) < len(buf)) {
- yield cap(s.buf) - len(s.buf);
- } else len(buf);
- static append(s.buf, buf[..n]...);
- return n;
-};
-
-@test fn fixed() void = {
- static let buf: [1024]u8 = [0...];
- let stream = fixed(buf);
- assert(string(&stream) == "");
- io::writeall(&stream, strings::toutf8("hello ")) as size;
- assert(string(&stream) == "hello ");
- io::writeall(&stream, strings::toutf8("world")) as size;
- assert(string(&stream) == "hello world");
-};
-
-const dynamic_vtable: io::vtable = io::vtable {
- writer = &dynamic_write,
- closer = &dynamic_close,
- ...
-};
-
-// Creates a write-only string stream using an allocated buffer for storage, for
-// efficiently building strings.
-//
-// Calling [[io::close]] on this stream will free the buffer.
-export fn dynamic() stream = {
- return stream {
- stream = &dynamic_vtable,
- buf = [],
- };
-};
-
-// Truncates the buffer, freeing memory associated with it and setting its
-// length to zero.
-export fn truncate(in: *stream) void = {
- delete(in.buf[..]);
-};
-
-fn dynamic_write(s: *io::stream, buf: const []u8) (size | io::error) = {
- let s = s: *stream;
- append(s.buf, buf...);
- return len(buf);
-};
-
-fn dynamic_close(s: *io::stream) (void | io::error) = {
- const s = s: *stream;
- free(s.buf);
-};
-
-@test fn dynamic() void = {
- let stream = dynamic();
- defer io::close(&stream)!;
- assert(string(&stream) == "");
- io::writeall(&stream, strings::toutf8("hello ")) as size;
- assert(string(&stream) == "hello ");
- io::writeall(&stream, strings::toutf8("world")) as size;
- assert(string(&stream) == "hello world");
-};
diff --git a/temp/+freebsd.ha b/temp/+freebsd.ha
@@ -9,9 +9,9 @@ use errors;
use fmt;
use fs;
use io;
+use memio;
use os;
use path;
-use strio;
fn get_tmpdir() str = os::tryenv("TMPDIR", "/tmp");
@@ -82,10 +82,10 @@ export fn dir() str = {
let buf: [8]u8 = [0...], name: [16]u8 = [0...];
random::buffer(buf[..]);
- let sink = strio::fixed(name);
+ let sink = memio::fixed(name);
const enc = hex::newencoder(&sink);
io::write(&enc, buf)!;
- let name = strio::string(&sink);
+ let name = memio::string(&sink)!;
static let buf = path::buffer { ... };
path::set(&buf, get_tmpdir(), name)!;
diff --git a/temp/+linux.ha b/temp/+linux.ha
@@ -9,9 +9,9 @@ use errors;
use fmt;
use fs;
use io;
+use memio;
use os;
use path;
-use strio;
fn get_tmpdir() str = os::tryenv("TMPDIR", "/tmp");
@@ -94,10 +94,10 @@ export fn dir() str = {
const buf: [8]u8 = [0...], name: [16]u8 = [0...];
random::buffer(buf[..]);
- const sink = strio::fixed(name);
+ const sink = memio::fixed(name);
let enc = hex::newencoder(&sink);
io::write(&enc, buf) as size;
- const name = strio::string(&sink);
+ const name = memio::string(&sink)!;
static let buf = path::buffer { ... };
path::set(&buf, get_tmpdir(), name)!;
diff --git a/test/+test.ha b/test/+test.ha
@@ -4,10 +4,10 @@ use encoding::utf8;
use fmt;
use fnmatch;
use io;
+use memio;
use os;
use rt;
use strings;
-use strio;
use time;
use unix::signal;
@@ -33,8 +33,8 @@ fn finish_output(output: *output) void = {
};
type context = struct {
- stdout: bufio::memstream,
- stderr: bufio::memstream,
+ stdout: memio::stream,
+ stderr: memio::stream,
failures: []failure,
output: []output,
maxname: size,
@@ -81,8 +81,8 @@ export @symbol("__test_main") fn main() size = {
};
let ctx = context {
- stdout = bufio::dynamic(io::mode::WRITE),
- stderr = bufio::dynamic(io::mode::WRITE),
+ stdout = memio::dynamic(),
+ stderr = memio::dynamic(),
maxname = maxname,
default_round = rt::fegetround(),
...
@@ -143,8 +143,8 @@ export @symbol("__test_main") fn main() size = {
fn do_test(ctx: *context, test: test) void = {
signal::handle(signal::sig::SEGV, &handle_segv, signal::flag::NODEFER);
- bufio::reset(&ctx.stdout);
- bufio::reset(&ctx.stderr);
+ memio::reset(&ctx.stdout);
+ memio::reset(&ctx.stderr);
const start_time = time::now(time::clock::MONOTONIC);
@@ -164,23 +164,23 @@ fn do_test(ctx: *context, test: test) void = {
time_diff / 1000000000,
time_diff % 1000000000)!;
- const stdout = bufio::buffer(&ctx.stdout);
+ const stdout = memio::buffer(&ctx.stdout);
const stdout = match (strings::fromutf8(stdout)) {
case let s: str =>
yield strings::dup(s);
case utf8::invalid =>
- let s = strio::dynamic();
+ let s = memio::dynamic();
hex::dump(&s, stdout)!;
- yield strio::string(&s);
+ yield memio::string(&s)!;
};
- const stderr = bufio::buffer(&ctx.stderr);
+ const stderr = memio::buffer(&ctx.stderr);
const stderr = match (strings::fromutf8(stderr)) {
case let s: str =>
yield strings::dup(s);
case utf8::invalid =>
- let s = strio::dynamic();
+ let s = memio::dynamic();
hex::dump(&s, stderr)!;
- yield strio::string(&s);
+ yield memio::string(&s)!;
};
if (failed && (stdout != "" || stderr != "")) {
append(ctx.output, output {
diff --git a/time/chrono/timezone.ha b/time/chrono/timezone.ha
@@ -240,7 +240,7 @@ let TZ_LOCAL: timezone = timezone {
};
static let buf: [os::BUFSIZ]u8 = [0...];
- const file = bufio::buffered(file, buf, []);
+ const file = bufio::init(file, buf, []);
load_tzif(&file, &TZ_LOCAL): void;
};
};
diff --git a/time/chrono/tzdb.ha b/time/chrono/tzdb.ha
@@ -31,7 +31,7 @@ export fn tz(name: str) (locality | tzdberror) = {
const file = os::open(fpath)?;
static let buf: [os::BUFSIZ]u8 = [0...];
- const bufstrm = bufio::buffered(file, buf, []);
+ const bufstrm = bufio::init(file, buf, []);
let loc = alloc(timezone {
name = strings::dup(name),
diff --git a/time/date/format.ha b/time/date/format.ha
@@ -6,8 +6,8 @@ use ascii;
use errors;
use fmt;
use io;
+use memio;
use strings;
-use strio;
use time;
use time::chrono;
@@ -86,17 +86,17 @@ export fn bsformat(
layout: str,
d: *date,
) (str | io::error) = {
- let sink = strio::fixed(buf);
+ let sink = memio::fixed(buf);
format(&sink, layout, d)?;
- return strio::string(&sink);
+ return memio::string(&sink)!;
};
// Formats a [[date]] and writes it into a heap-allocated string.
// The caller must free the return value.
export fn asformat(layout: str, d: *date) (str | io::error) = {
- let sink = strio::dynamic();
+ let sink = memio::dynamic();
format(&sink, layout, d)?;
- return strio::string(&sink);
+ return memio::string(&sink)!;
};
fn fmtout(out: io::handle, r: rune, d: *date) (size | io::error) = {
@@ -227,7 +227,7 @@ export fn format(
if (r == '%') {
escaped = true;
} else {
- strio::appendrune(h, r)?;
+ memio::appendrune(h, r)?;
};
};
};
diff --git a/time/date/parse.ha b/time/date/parse.ha
@@ -7,7 +7,6 @@ use errors;
use io;
use strconv;
use strings;
-use strio;
use time;
use time::chrono;
diff --git a/unix/hosts/hosts.ha b/unix/hosts/hosts.ha
@@ -7,6 +7,7 @@ use bufio;
use encoding::utf8;
use fs;
use io;
+use memio;
use net::ip;
use os;
use strings;
@@ -64,7 +65,7 @@ export fn next(it: *iterator) (host | void | error) = for (true) {
continue;
};
- const scanner = bufio::fixed(line, io::mode::READ);
+ const scanner = memio::fixed(line);
const tok = match (bufio::scantok(&scanner, ' ', '\t')?) {
case io::EOF =>
return void;
diff --git a/unix/hosts/test+test.ha b/unix/hosts/test+test.ha
@@ -1,7 +1,7 @@
// License: MPL-2.0
// (c) 2023 Dmitry Matveyev <public@greenfork.me>
-use bufio;
use io;
+use memio;
use net::ip;
use strings;
@@ -16,7 +16,7 @@ def HOSTS_FILE = `
`;
@test fn next() void = {
- let buf = bufio::fixed(strings::toutf8(HOSTS_FILE), io::mode::READ);
+ let buf = memio::fixed(strings::toutf8(HOSTS_FILE));
let it = iter(&buf);
const h = next(&it) as host;
@@ -52,15 +52,15 @@ def HOSTS_FILE = `
@test fn errors() void = {
const s = "127";
- assert(next(&iter(&bufio::fixed(strings::toutf8(s), io::mode::READ)))
+ assert(next(&iter(&memio::fixed(strings::toutf8(s))))
is ip::invalid);
const s = "127.0.0.1";
- assert(next(&iter(&bufio::fixed(strings::toutf8(s), io::mode::READ)))
+ assert(next(&iter(&memio::fixed(strings::toutf8(s))))
is invalid);
};
@test fn lookup() void = {
- let buf = bufio::fixed(strings::toutf8(HOSTS_FILE), io::mode::READ);
+ let buf = memio::fixed(strings::toutf8(HOSTS_FILE));
let it = iter(&buf);
const addrs = iter_lookup(&it, "other.localdomain") as []ip::addr;
assert(len(addrs) == 2);
diff --git a/unix/passwd/group.ha b/unix/passwd/group.ha
@@ -4,6 +4,7 @@
// (c) 2021 Ember Sawady <ecs@d2evs.net>
use bufio;
use io;
+use memio;
use os;
use strconv;
use strings;
@@ -128,10 +129,10 @@ export fn getgid(gid: uint) (grent | void) = {
};
@test fn nextgr() void = {
- let buf = bufio::fixed(strings::toutf8(
+ let buf = memio::fixed(strings::toutf8(
"root:x:0:root\n"
"mail:x:12:\n"
- "video:x:986:alex,wmuser"), io::mode::READ);
+ "video:x:986:alex,wmuser"));
let ent = nextgr(&buf) as grent;
defer grent_finish(&ent);
diff --git a/unix/passwd/passwd.ha b/unix/passwd/passwd.ha
@@ -4,6 +4,7 @@
// (c) 2021 Ember Sawady <ecs@d2evs.net>
use bufio;
use io;
+use memio;
use os;
use strconv;
use strings;
@@ -150,9 +151,9 @@ export fn getuid(uid: uint) (pwent | void) = {
};
@test fn nextpw() void = {
- let buf = bufio::fixed(strings::toutf8(
+ let buf = memio::fixed(strings::toutf8(
"sircmpwn:x:1000:1000:sircmpwn's comment:/home/sircmpwn:/bin/mrsh\n"
- "alex:x:1001:1001::/home/alex:/bin/zsh"), io::mode::READ);
+ "alex:x:1001:1001::/home/alex:/bin/zsh"));
let ent = nextpw(&buf) as pwent;
defer pwent_finish(&ent);
diff --git a/unix/resolvconf/load.ha b/unix/resolvconf/load.ha
@@ -4,6 +4,7 @@
// (c) 2021 Ember Sawady <ecs@d2evs.net>
use bufio;
use io;
+use memio;
use net::ip;
use os;
use strings;
@@ -38,7 +39,7 @@ export fn load() []ip::addr = {
continue;
};
- const scanner = bufio::fixed(line, io::mode::READ);
+ const scanner = memio::fixed(line);
const tok = match (bufio::scantok(&scanner, ' ', '\t')!) {
case io::EOF =>
break;
diff --git a/uuid/uuid.ha b/uuid/uuid.ha
@@ -2,15 +2,14 @@
// (c) 2022 Alexey Yerin <yyp@disroot.org>
// (c) 2021 Drew DeVault <sir@cmpwn.com>
// (c) 2021 Ember Sawady <ecs@d2evs.net>
-use bufio;
use bytes;
use crypto::random;
use endian;
use fmt;
use io;
+use memio;
use strconv;
use strings;
-use strio;
// A UUID.
export type uuid = [16]u8;
@@ -85,18 +84,18 @@ export fn uri(out: io::handle, in: uuid) (size | io::error) = {
// caller must use [[strings::dup]] to extend its lifetime.
export fn encodestr(in: uuid) str = {
static let buf: [UUID_STRLEN]u8 = [0...];
- let sink = strio::fixed(buf);
+ let sink = memio::fixed(buf);
encode(&sink, in) as size;
- return strio::string(&sink);
+ return memio::string(&sink)!;
};
// Encodes a UUID as a string. The return value is statically allocated, the
// caller must use [[strings::dup]] to extend its lifetime.
export fn encodeuri(in: uuid) str = {
static let buf: [UUID_URILEN]u8 = [0...];
- let sink = strio::fixed(buf);
+ let sink = memio::fixed(buf);
uri(&sink, in) as size;
- return strio::string(&sink);
+ return memio::string(&sink)!;
};
@test fn encode() void = {
@@ -146,7 +145,7 @@ export fn decode(in: io::handle) (uuid | invalid | io::error) = {
// Decodes a UUID from a string.
export fn decodestr(in: str) (uuid | invalid) = {
- let buf = bufio::fixed(strings::toutf8(in), io::mode::READ);
+ let buf = memio::fixed(strings::toutf8(in));
match (decode(&buf)) {
case let err: io::error =>
abort();