hare

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

commit 1a3f57236188e16e05467a829da25c9f5e3000d5
parent 172bf36d3834b36349e16f6c50f74e99368edbbc
Author: Bor Grošelj Simić <bgs@turminal.net>
Date:   Tue, 19 Apr 2022 21:13:48 +0200

merge strio/fixed.ha and strio/dynamic.ha

Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>

Diffstat:
Mscripts/gen-stdlib | 3+--
Mstdlib.mk | 6++----
Dstrio/dynamic.ha | 59-----------------------------------------------------------
Dstrio/fixed.ha | 45---------------------------------------------
Astrio/stream.ha | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 100 insertions(+), 110 deletions(-)

diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib @@ -1124,8 +1124,7 @@ strings() { strio() { gen_srcs strio \ - dynamic.ha \ - fixed.ha \ + stream.ha \ ops.ha gen_ssa strio io strings slices encoding::utf8 errors } diff --git a/stdlib.mk b/stdlib.mk @@ -1706,8 +1706,7 @@ $(HARECACHE)/strings/strings-any.ssa: $(stdlib_strings_any_srcs) $(stdlib_rt) $( # strio (+any) stdlib_strio_any_srcs= \ - $(STDLIB)/strio/dynamic.ha \ - $(STDLIB)/strio/fixed.ha \ + $(STDLIB)/strio/stream.ha \ $(STDLIB)/strio/ops.ha $(HARECACHE)/strio/strio-any.ssa: $(stdlib_strio_any_srcs) $(stdlib_rt) $(stdlib_io_$(PLATFORM)) $(stdlib_strings_$(PLATFORM)) $(stdlib_slices_$(PLATFORM)) $(stdlib_encoding_utf8_$(PLATFORM)) $(stdlib_errors_$(PLATFORM)) @@ -3699,8 +3698,7 @@ $(TESTCACHE)/strings/strings-any.ssa: $(testlib_strings_any_srcs) $(testlib_rt) # strio (+any) testlib_strio_any_srcs= \ - $(STDLIB)/strio/dynamic.ha \ - $(STDLIB)/strio/fixed.ha \ + $(STDLIB)/strio/stream.ha \ $(STDLIB)/strio/ops.ha $(TESTCACHE)/strio/strio-any.ssa: $(testlib_strio_any_srcs) $(testlib_rt) $(testlib_io_$(PLATFORM)) $(testlib_strings_$(PLATFORM)) $(testlib_slices_$(PLATFORM)) $(testlib_encoding_utf8_$(PLATFORM)) $(testlib_errors_$(PLATFORM)) diff --git a/strio/dynamic.ha b/strio/dynamic.ha @@ -1,59 +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; - -export type stream = struct { - stream: io::stream, - buf: []u8, -}; - -// 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. If stream's data -// is transfered via [[string]], it shouldn't be closed as long if the data is -// freed. -export fn dynamic() stream = { - return stream { - stream = io::stream { - writer = &dynamic_write, - closer = &dynamic_close, - ... - }, - buf = [], - }; -}; - -// Resets the buffer's length to zero, but keeps the allocated memory around for -// future writes. -export fn reset(in: *stream) void = { - in.buf = in.buf[..0]; -}; - -// 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 = { - const s = s: *stream; - free(s.buf); -}; - -@test fn dynamic() void = { - let stream = dynamic(); - defer io::close(&stream); - io::write(&stream, strings::toutf8("hello ")) as size; - io::write(&stream, strings::toutf8("world")) as size; - assert(string(&stream) == "hello world"); -}; diff --git a/strio/fixed.ha b/strio/fixed.ha @@ -1,45 +0,0 @@ -// License: MPL-2.0 -// (c) 2022 Alexey Yerin <yyp@disroot.org> -// (c) 2021 Drew DeVault <sir@cmpwn.com> -use io; -use slices; -use strings; - -// Creates a write-only string stream using the provided buffer for storage. -// The program aborts if writes would exceed the buffer's capacity. The stream -// doesn't need to be closed. -export fn fixed(in: []u8) stream = { - return stream { - stream = io::stream { - writer = &fixed_write, - ... - }, - buf = in[..0], - }; -}; - -// Returns the current contents of the buffer as a string. Aborts the program if -// invalid UTF-8 has been written to the buffer. -export fn string(in: *stream) str = { - let in = in: *stream; - return strings::fromutf8(in.buf); -}; - -fn fixed_write(s: *io::stream, buf: const []u8) (size | io::error) = { - let s = s: *stream; - let cap = slices::cap(s.buf); - if (cap == len(s.buf)) { - abort("strio::fixed buffer exceeded"); - }; - let n = if (cap - len(s.buf) < len(buf)) cap - 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); - io::write(&stream, strings::toutf8("hello ")) as size; - io::write(&stream, strings::toutf8("world")) as size; - assert(string(&stream) == "hello world"); -}; diff --git a/strio/stream.ha b/strio/stream.ha @@ -0,0 +1,97 @@ +// License: MPL-2.0 +// (c) 2022 Alexey Yerin <yyp@disroot.org> +// (c) 2021 Drew DeVault <sir@cmpwn.com> +use io; +use slices; +use strings; + +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. +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 program aborts if writes would exceed the buffer's capacity. The stream +// doesn't need to be closed. +export fn fixed(in: []u8) stream = { + return stream { + stream = io::stream { + writer = &fixed_write, + ... + }, + buf = in[..0], + }; +}; + +fn fixed_write(s: *io::stream, buf: const []u8) (size | io::error) = { + let s = s: *stream; + let cap = slices::cap(s.buf); + if (cap == len(s.buf)) { + abort("strio::fixed buffer exceeded"); + }; + let n = if (cap - len(s.buf) < len(buf)) cap - 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); + io::write(&stream, strings::toutf8("hello ")) as size; + io::write(&stream, strings::toutf8("world")) as size; + assert(string(&stream) == "hello world"); +}; + +// 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. If stream's data +// is transfered via [[string]], it shouldn't be closed as long if the data is +// freed. +export fn dynamic() stream = { + return stream { + stream = io::stream { + writer = &dynamic_write, + closer = &dynamic_close, + ... + }, + 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 = { + const s = s: *stream; + free(s.buf); +}; + +@test fn dynamic() void = { + let stream = dynamic(); + defer io::close(&stream); + io::write(&stream, strings::toutf8("hello ")) as size; + io::write(&stream, strings::toutf8("world")) as size; + assert(string(&stream) == "hello world"); +};