hare

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

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:
Mbufio/README | 37++++++++++++-------------------------
Dbufio/buffered.ha | 346-------------------------------------------------------------------------------
Dbufio/memstream.ha | 299-------------------------------------------------------------------------------
Mbufio/scanner.ha | 118-------------------------------------------------------------------------------
Abufio/scanner_test+test.ha | 113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abufio/stream.ha | 233+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Abufio/stream_test+test.ha | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcmd/hare/schedule.ha | 1-
Mcmd/harec/context.ha | 4++--
Mcmd/harec/gen.ha | 8++++----
Mcmd/harec/main.ha | 2+-
Mcmd/haredoc/docstr.ha | 30+++++++++++++++---------------
Mcmd/haredoc/hare.ha | 1-
Mcmd/haredoc/html.ha | 25++++++++++++-------------
Mcmd/haredoc/main.ha | 4++--
Mcmd/haredoc/tty.ha | 14+++++++-------
Mcmd/haredoc/util.ha | 8++++----
Mcrypto/aes/+test/gcm.ha | 10+++++-----
Mcrypto/aes/ctr+test.ha | 24++++++++++++------------
Mcrypto/argon2/argon2.ha | 4++--
Mcrypto/authenc.ha | 8++++----
Mcrypto/bcrypt/base64.ha | 6+++---
Mcrypto/bcrypt/bcrypt.ha | 6+++---
Mcrypto/blake2b/+test.ha | 12++++++------
Mcrypto/chacha/+test.ha | 10+++++-----
Mcrypto/chachapoly/chachapoly.ha | 4++--
Mcrypto/chachapoly/encryption+test.ha | 22+++++++++++-----------
Mcrypto/rsa/keys.ha | 10+++++-----
Mcrypto/salsa/+test.ha | 10+++++-----
Mencoding/base32/base32.ha | 26+++++++++++++-------------
Mencoding/base64/base64.ha | 26+++++++++++++-------------
Mencoding/hex/hex.ha | 21++++++++++-----------
Mencoding/pem/+test.ha | 21++++++++++-----------
Mencoding/pem/pem.ha | 20++++++++++----------
Mfmt/fmt.ha | 14+++++++-------
Mformat/ini/+test.ha | 14+++++++-------
Mformat/tar/reader.ha | 19+++++++++----------
Mglob/glob.ha | 74+++++++++++++++++++++++++++++++++++++-------------------------------------
Mhare/lex/+test.ha | 20++++++++++----------
Mhare/lex/lex.ha | 26+++++++++++++-------------
Mhare/module/context.ha | 6+++---
Mhare/module/manifest.ha | 4++--
Mhare/module/scan.ha | 10+++++-----
Mhare/parse/+test/ident_test.ha | 12++++++------
Mhare/parse/+test/loc.ha | 8++++----
Mhare/parse/+test/roundtrip.ha | 9++++-----
Mhare/parse/+test/unit_test.ha | 6+++---
Mhare/parse/ident.ha | 5++---
Mhare/parse/parse.ha | 6+++---
Mhare/types/+test.ha | 6+++---
Mhare/unit/+test.ha | 4++--
Mhare/unparse/decl.ha | 6+++---
Mhare/unparse/ident.ha | 6+++---
Mhare/unparse/import.ha | 6+++---
Mhare/unparse/type.ha | 18+++++++++---------
Mhash/siphash/+test.ha | 1-
Amemio/README | 11+++++++++++
Amemio/ops.ha | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amemio/stream.ha | 274+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmime/system.ha | 2+-
Mnet/ip/ip.ha | 6+++---
Mnet/uri/fmt.ha | 6+++---
Mnet/uri/parse.ha | 44++++++++++++++++++++++----------------------
Mnet/uri/query.ha | 22+++++++++++-----------
Mos/+freebsd/stdfd.ha | 8++++----
Mos/+linux/stdfd.ha | 8++++----
Mregex/regex.ha | 7++++---
Mscripts/gen-stdlib | 296+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mscripts/install-mods | 2+-
Mshlex/+test.ha | 10+++++-----
Mshlex/escape.ha | 6+++---
Mshlex/split.ha | 18+++++++++---------
Mstdlib.mk | 232++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mstrings/template/template.ha | 30+++++++++++++++---------------
Dstrio/README | 5-----
Dstrio/ops.ha | 135-------------------------------------------------------------------------------
Dstrio/stream.ha | 104-------------------------------------------------------------------------------
Mtemp/+freebsd.ha | 6+++---
Mtemp/+linux.ha | 6+++---
Mtest/+test.ha | 26+++++++++++++-------------
Mtime/chrono/timezone.ha | 2+-
Mtime/chrono/tzdb.ha | 2+-
Mtime/date/format.ha | 12++++++------
Mtime/date/parse.ha | 1-
Munix/hosts/hosts.ha | 3++-
Munix/hosts/test+test.ha | 10+++++-----
Munix/passwd/group.ha | 5+++--
Munix/passwd/passwd.ha | 5+++--
Munix/resolvconf/load.ha | 3++-
Muuid/uuid.ha | 13++++++-------
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 = &copy, - reader = &read, - ... -}; - -const fixed_vt_w: io::vtable = io::vtable { - seeker = &seek, - copier = &copy, - writer = &fixed_write, - ... -}; - -const fixed_vt_rw: io::vtable = io::vtable { - seeker = &seek, - copier = &copy, - 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 = &copy, - writer = &dynamic_write, - closer = &dynamic_close, - ... -}; - -const dynamic_vt_rw: io::vtable = io::vtable { - seeker = &seek, - copier = &copy, - 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) == "&quot;hello world!&quot;"); + assert(memio::string(&sink)! == "&quot;hello world!&quot;"); - let sink = strio::dynamic(); + let sink = memio::dynamic(); defer io::close(&sink)!; html_escape(&sink, "<hello & 'world'!>")!; - assert(strio::string(&sink) == "&lt;hello &amp; &apos;world&apos;!&gt;"); + assert(memio::string(&sink)! == "&lt;hello &amp; &apos;world&apos;!&gt;"); }; // 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 = &copy, + reader = &read, + writer = &fixed_write, + ... +}; + +const dynamic_vt: io::vtable = io::vtable { + seeker = &seek, + copier = &copy, + 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();