commit 9346336ffe19f9216b9148763daf22e739ecec91
parent 6a5dbe35b0ea90dbb6edeba87ac852267b0edb1e
Author: Autumn! <autumnull@posteo.net>
Date: Sun, 7 May 2023 01:43:28 +0000
path: use custom error types and strerror
Signed-off-by: Autumn! <autumnull@posteo.net>
Diffstat:
6 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/path/README b/path/README
@@ -17,7 +17,9 @@ Assuming that [[PATHSEP]] is '/', "/usr//bin/../bin/./hare/" becomes
The buffer object includes an array of length [[PATH_MAX]], which can be
somewhat large; on Linux it's 4096 bytes. You can allocate this on the stack in
-most cases, but you may prefer to allocate it elsewhere depending on your needs.
+most cases, but you may prefer to allocate it elsewhere depending on your
+needs. Functions in this module return [[too_long]] if the buffer's capacity
+would be exceeded.
// Stack allocated
let buf = path::init()!;
diff --git a/path/buffer.ha b/path/buffer.ha
@@ -2,7 +2,6 @@
// (c) 2022 Drew DeVault <sir@cmpwn.com>
// (c) 2022 Humm <hummsmith42@gmail.com>
use bytes;
-use errors;
use strings;
export type buffer = struct {
@@ -11,7 +10,7 @@ export type buffer = struct {
};
// Initializes a new path buffer.
-export fn init(items: str...) (buffer | errors::overflow) = {
+export fn init(items: str...) (buffer | error) = {
let buf = buffer { ... };
push(&buf, items...)?;
return buf;
@@ -19,7 +18,7 @@ export fn init(items: str...) (buffer | errors::overflow) = {
// Sets the value of a path buffer to a list of components, overwriting any
// previous value. Returns the new string value of the path.
-export fn set(buf: *buffer, items: str...) (str | errors::overflow) = {
+export fn set(buf: *buffer, items: str...) (str | error) = {
buf.end = 0;
return push(buf, items...);
};
diff --git a/path/error.ha b/path/error.ha
@@ -0,0 +1,12 @@
+// Returned when adding an extension if the path is root, or the final path
+// segment consists entirely of dots.
+export type cant_extend = !void;
+// Returned when a path buffer would have overflowed.
+export type too_long = !void;
+export type error = !(cant_extend | too_long);
+
+// Convert an [[error]] into a descriptive string.
+export fn strerror(e: error) str = match (e) {
+case cant_extend => return "Can't add extension (filename is root or all dots)";
+case too_long => return "Path buffer overflow";
+};
diff --git a/path/stack.ha b/path/stack.ha
@@ -1,12 +1,11 @@
// License: MPL-2.0
// (c) 2021-2022 Drew DeVault <sir@cmpwn.com>
use bytes;
-use errors;
use strings;
// Appends path elements onto the end of a path buffer.
// Returns the new string value of the path.
-export fn push(buf: *buffer, items: str...) (str | errors::overflow) = {
+export fn push(buf: *buffer, items: str...) (str | error) = {
for (let i = 0z; i < len(items); i += 1) {
let elem = strings::toutf8(items[i]);
for (true) match (bytes::index(elem, PATHSEP)) {
@@ -39,7 +38,7 @@ const dotdot: []u8 = ['.', '.'];
// x/.. + .. => x/../..
// x/y + .. => x
// x + y => x/y
-fn appendnorm(buf: *buffer, seg: []u8) (size | errors::overflow) = {
+fn appendnorm(buf: *buffer, seg: []u8) (size | error) = {
if (len(seg) == 0 || bytes::equal(dot, seg)) return buf.end;
if (bytes::equal(dotdot, seg)) {
if (isroot(buf)) return buf.end;
@@ -59,12 +58,12 @@ fn appendnorm(buf: *buffer, seg: []u8) (size | errors::overflow) = {
// append a segment to a buffer, *without* preserving normalization.
// returns the new end of the buffer
-fn appendlit(buf: *buffer, bs: []u8) (size | errors::overflow) = {
+fn appendlit(buf: *buffer, bs: []u8) (size | error) = {
let newend = buf.end;
if (buf.end == 0 || isroot(buf)) {
- if (PATH_MAX < buf.end + len(bs)) return errors::overflow;
+ if (PATH_MAX < buf.end + len(bs)) return too_long;
} else {
- if (PATH_MAX < buf.end + len(bs) + 1) return errors::overflow;
+ if (PATH_MAX < buf.end + len(bs) + 1) return too_long;
buf.buf[buf.end] = PATHSEP;
newend += 1;
};
@@ -187,7 +186,7 @@ export fn join(items: str...) str = {
// If the path is the root directory, the root directory is returned. The value
// is either borrowed from the input or statically allocated; use
// [[strings::dup]] to extend its lifetime or modify it.
-export fn parent(buf: *const buffer) (str | errors::overflow) = {
+export fn parent(buf: *const buffer) (str | error) = {
const newend = appendnorm(buf, dotdot)?;
if (newend == 0) return ".";
return strings::fromutf8_unsafe(buf.buf[..newend]);
diff --git a/scripts/gen-stdlib b/scripts/gen-stdlib
@@ -1203,6 +1203,7 @@ path() {
gen_srcs path \
'+$(PLATFORM).ha' \
buffer.ha \
+ error.ha \
util.ha \
stack.ha \
names.ha \
diff --git a/stdlib.mk b/stdlib.mk
@@ -1836,6 +1836,7 @@ $(HARECACHE)/os/exec/os_exec-freebsd.ssa: $(stdlib_os_exec_freebsd_srcs) $(stdli
stdlib_path_any_srcs = \
$(STDLIB)/path/+$(PLATFORM).ha \
$(STDLIB)/path/buffer.ha \
+ $(STDLIB)/path/error.ha \
$(STDLIB)/path/util.ha \
$(STDLIB)/path/stack.ha \
$(STDLIB)/path/names.ha \
@@ -4110,6 +4111,7 @@ $(TESTCACHE)/os/exec/os_exec-freebsd.ssa: $(testlib_os_exec_freebsd_srcs) $(test
testlib_path_any_srcs = \
$(STDLIB)/path/+$(PLATFORM).ha \
$(STDLIB)/path/buffer.ha \
+ $(STDLIB)/path/error.ha \
$(STDLIB)/path/util.ha \
$(STDLIB)/path/stack.ha \
$(STDLIB)/path/names.ha \