commit 95d6615246f3516dba5aa034be42d5f60eb52517
parent 6cfd76c32af6a597c60254b460bc2878cbf86b99
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 12 Nov 2021 10:11:53 +0100
io: add readitem, readitems
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
5 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/hare/module/scan.ha b/hare/module/scan.ha
@@ -14,7 +14,7 @@ use sort;
use strings;
use strio;
-def ABI_VERSION: u8 = 0;
+def ABI_VERSION: u8 = 1;
// Scans the files in a directory for eligible build inputs and returns a
// [[version]] which includes all applicable files and their dependencies.
diff --git a/io/types.ha b/io/types.ha
@@ -1,13 +1,24 @@
use errors;
+// Returned by [[readitem]] and [[readitems]] if the I/O handle returned [[EOF]]
+// prior to completely reading an item.
+export type underread = !void;
+
// Any error which may be returned from an I/O function.
-export type error = !errors::error;
+export type error = !(errors::error | underread);
// Indicates an end-of-file condition.
export type EOF = void;
// Converts an I/O [[error]] into a user-friendly string.
-export fn strerror(err: error) str = errors::strerror(err);
+export fn strerror(err: error) str = {
+ match (err) {
+ case underread =>
+ return "Insufficient data to read entire item";
+ case err: errors::error =>
+ return errors::strerror(err);
+ };
+};
// Used to indicate if a stream should be used for reading, or writing, or both.
export type mode = enum u8 {
diff --git a/io/util.ha b/io/util.ha
@@ -0,0 +1,27 @@
+// Reads an entire "item", i.e. one Hare object, from an I/O handle. This
+// function may use multiple reads, but if [[EOF]] is encountered before the
+// entire object is read, an [[underread]] error is returned. Otherwise, the
+// return value is the total number of bytes read (which shall be equal to
+// itemsz).
+export fn readitem(in: handle, item: *void, itemsz: size) (size | error) = {
+ let buf = item: *[*]u8;
+ let i = 0z;
+ for (i < itemsz) {
+ match (io::read(in, buf[..(itemsz - i)])) {
+ case io::EOF =>
+ return underread;
+ case z: size =>
+ i += z;
+ };
+ };
+ return i;
+};
+
+// Reads several "items", i.e. Hare objects, from an I/O handle. If [[EOF]] is
+// returned prior to reading all of the items completely, an [[underread]] error
+// is returned. Otherwise, the return value is the number of items read.
+export fn readitems(in: handle, items: []void, itemsz: size) (size | error) = {
+ let buf = items: *[*]u8;
+ readitem(in, buf, len(items) * itemsz)?;
+ return len(items);
+};
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -606,6 +606,7 @@ gensrcs_io() {
stream.ha \
tee.ha \
types.ha \
+ util.ha \
$*
gen_srcs -pfreebsd io \
'arch+$(ARCH).ha' \
@@ -621,6 +622,7 @@ gensrcs_io() {
stream.ha \
tee.ha \
types.ha \
+ util.ha \
$*
}
diff --git a/stdlib.mk b/stdlib.mk
@@ -1067,7 +1067,8 @@ stdlib_io_linux_srcs= \
$(STDLIB)/io/limit.ha \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
- $(STDLIB)/io/types.ha
+ $(STDLIB)/io/types.ha \
+ $(STDLIB)/io/util.ha
# io (+freebsd)
stdlib_io_freebsd_srcs= \
@@ -1083,7 +1084,8 @@ stdlib_io_freebsd_srcs= \
$(STDLIB)/io/limit.ha \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
- $(STDLIB)/io/types.ha
+ $(STDLIB)/io/types.ha \
+ $(STDLIB)/io/util.ha
$(HARECACHE)/io/io-linux.ssa: $(stdlib_io_linux_srcs) $(stdlib_rt) $(stdlib_strings_$(PLATFORM)) $(stdlib_errors_$(PLATFORM))
@printf 'HAREC \t$@\n'
@@ -2755,6 +2757,7 @@ testlib_io_linux_srcs= \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
$(STDLIB)/io/types.ha \
+ $(STDLIB)/io/util.ha \
$(STDLIB)/io/+test/copy.ha \
$(STDLIB)/io/+test/limit.ha \
$(STDLIB)/io/+test/stream.ha
@@ -2774,6 +2777,7 @@ testlib_io_freebsd_srcs= \
$(STDLIB)/io/stream.ha \
$(STDLIB)/io/tee.ha \
$(STDLIB)/io/types.ha \
+ $(STDLIB)/io/util.ha \
$(STDLIB)/io/+test/copy.ha \
$(STDLIB)/io/+test/limit.ha \
$(STDLIB)/io/+test/stream.ha