From 6086b2dbda874d5538e878101c7ee98a10fdeddb Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Tue, 18 Mar 2025 17:00:30 -0400 Subject: Expose PathType as a proper enum --- stdlib/datatypes.h | 7 ++++- stdlib/paths.c | 86 ++++++++++++++++++++++++++++++++---------------------- stdlib/paths.h | 1 + 3 files changed, 58 insertions(+), 36 deletions(-) (limited to 'stdlib') diff --git a/stdlib/datatypes.h b/stdlib/datatypes.h index dc121c82..b81ff741 100644 --- a/stdlib/datatypes.h +++ b/stdlib/datatypes.h @@ -97,7 +97,12 @@ typedef struct Text_s { #define OptionalPattern_t Text_t typedef struct { - enum { PATH_NONE, PATH_RELATIVE, PATH_ABSOLUTE, PATH_HOME } type; + enum { PATH_NONE, PATH_RELATIVE, PATH_ABSOLUTE, PATH_HOME } $tag; +} PathType_t; +#define OptionalPathType_t PathType_t + +typedef struct { + PathType_t type; Array_t components; } Path_t; #define OptionalPath_t Path_t diff --git a/stdlib/paths.c b/stdlib/paths.c index bac37b27..ba98e9fb 100644 --- a/stdlib/paths.c +++ b/stdlib/paths.c @@ -17,11 +17,13 @@ #include #include "arrays.h" +#include "enums.h" #include "files.h" #include "integers.h" #include "optionals.h" #include "paths.h" #include "patterns.h" +#include "structs.h" #include "text.h" #include "types.h" #include "util.h" @@ -30,7 +32,9 @@ #include "siphash.h" #include "siphash-internals.h" -static const Path_t HOME_PATH = {.type=PATH_HOME}, ROOT_PATH = {.type=PATH_ABSOLUTE}, CURDIR_PATH = {.type=PATH_RELATIVE}; +static const Path_t HOME_PATH = {.type.$tag=PATH_HOME}, + ROOT_PATH = {.type.$tag=PATH_ABSOLUTE}, + CURDIR_PATH = {.type.$tag=PATH_RELATIVE}; static void clean_components(Array_t *components) { @@ -60,16 +64,16 @@ public Path_t Path$from_str(const char *str) Path_t result = {.components={}}; if (str[0] == '/') { - result.type = PATH_ABSOLUTE; + result.type.$tag = PATH_ABSOLUTE; str += 1; } else if (str[0] == '~' && str[1] == '/') { - result.type = PATH_HOME; + result.type.$tag = PATH_HOME; str += 2; } else if (str[0] == '.' && str[1] == '/') { - result.type = PATH_RELATIVE; + result.type.$tag = PATH_RELATIVE; str += 2; } else { - result.type = PATH_RELATIVE; + result.type.$tag = PATH_RELATIVE; } while (str && *str) { @@ -100,12 +104,12 @@ public Path_t Path$from_text(Text_t text) public Path_t Path$expand_home(Path_t path) { - if (path.type == PATH_HOME) { + if (path.type.$tag == PATH_HOME) { Path_t pwd = Path$from_str(getenv("HOME")); Array_t components = Array$concat(pwd.components, path.components, sizeof(Text_t)); assert(components.length == path.components.length + pwd.components.length); clean_components(&components); - path = (Path_t){.type=PATH_ABSOLUTE, .components=components}; + path = (Path_t){.type.$tag=PATH_ABSOLUTE, .components=components}; } return path; } @@ -116,7 +120,7 @@ public Path_t Path$_concat(int n, Path_t items[n]) Path_t result = items[0]; ARRAY_INCREF(result.components); for (int i = 1; i < n; i++) { - if (items[i].type != PATH_RELATIVE) + if (items[i].type.$tag != PATH_RELATIVE) fail("Cannot concatenate an absolute or home-based path onto another path: (%s)\n", Path$as_c_string(items[i])); Array$insert_all(&result.components, items[i].components, I(0), sizeof(Text_t)); @@ -127,8 +131,8 @@ public Path_t Path$_concat(int n, Path_t items[n]) public Path_t Path$resolved(Path_t path, Path_t relative_to) { - if (path.type == PATH_RELATIVE && !(relative_to.type == PATH_RELATIVE && relative_to.components.length == 0)) { - Path_t result = {.type=relative_to.type}; + if (path.type.$tag == PATH_RELATIVE && !(relative_to.type.$tag == PATH_RELATIVE && relative_to.components.length == 0)) { + Path_t result = {.type.$tag=relative_to.type.$tag}; result.components = relative_to.components; ARRAY_INCREF(result.components); Array$insert_all(&result.components, path.components, I(0), sizeof(Text_t)); @@ -140,11 +144,11 @@ public Path_t Path$resolved(Path_t path, Path_t relative_to) public Path_t Path$relative_to(Path_t path, Path_t relative_to) { - if (path.type != relative_to.type) + if (path.type.$tag != relative_to.type.$tag) fail("Cannot create a path relative to a different path with a mismatching type: (%k) relative to (%k)", (Text_t[1]){Path$as_text(&path, false, &Path$info)}, (Text_t[1]){Path$as_text(&relative_to, false, &Path$info)}); - Path_t result = {.type=PATH_RELATIVE}; + Path_t result = {.type.$tag=PATH_RELATIVE}; int64_t shared = 0; for (; shared < path.components.length && shared < relative_to.components.length; shared++) { Text_t *p = (Text_t*)(path.components.data + shared*path.components.stride); @@ -532,13 +536,13 @@ public Path_t Path$write_unique(Path_t path, Text_t text) public Path_t Path$parent(Path_t path) { - if (path.type == PATH_ABSOLUTE && path.components.length == 0) { + if (path.type.$tag == PATH_ABSOLUTE && path.components.length == 0) { return path; } else if (path.components.length > 0 && !Text$equal_values(*(Text_t*)(path.components.data + path.components.stride*(path.components.length-1)), Text(".."))) { - return (Path_t){.type=path.type, .components=Array$slice(path.components, I(1), I(-2))}; + return (Path_t){.type.$tag=path.type.$tag, .components=Array$slice(path.components, I(1), I(-2))}; } else { - Path_t result = {.type=path.type, .components=path.components}; + Path_t result = {.type.$tag=path.type.$tag, .components=path.components}; ARRAY_INCREF(result.components); Array$insert_value(&result.components, Text(".."), I(0), sizeof(Text_t)); return result; @@ -549,9 +553,9 @@ public PUREFUNC Text_t Path$base_name(Path_t path) { if (path.components.length >= 1) return *(Text_t*)(path.components.data + path.components.stride*(path.components.length-1)); - else if (path.type == PATH_HOME) + else if (path.type.$tag == PATH_HOME) return Text("~"); - else if (path.type == PATH_RELATIVE) + else if (path.type.$tag == PATH_RELATIVE) return Text("."); else return EMPTY_TEXT; @@ -573,7 +577,7 @@ public Text_t Path$extension(Path_t path, bool full) public Path_t Path$with_component(Path_t path, Text_t component) { Path_t result = { - .type=path.type, + .type.$tag=path.type.$tag, .components=path.components, }; ARRAY_INCREF(result.components); @@ -588,7 +592,7 @@ public Path_t Path$with_extension(Path_t path, Text_t extension, bool replace) fail("A path with no components can't have an extension!"); Path_t result = { - .type=path.type, + .type.$tag=path.type.$tag, .components=path.components, }; ARRAY_INCREF(result.components); @@ -675,7 +679,7 @@ public PUREFUNC uint64_t Path$hash(const void *obj, const TypeInfo_t *type) (void)type; Path_t *path = (Path_t*)obj; siphash sh; - siphashinit(&sh, (uint64_t)path->type); + siphashinit(&sh, (uint64_t)path->type.$tag); for (int64_t i = 0; i < path->components.length; i++) { uint64_t item_hash = Text$hash(path->components.data + i*path->components.stride, &Text$info); siphashadd64bits(&sh, item_hash); @@ -687,7 +691,7 @@ public PUREFUNC int32_t Path$compare(const void *va, const void *vb, const TypeI { (void)type; Path_t *a = (Path_t*)va, *b = (Path_t*)vb; - int diff = ((int)a->type - (int)b->type); + int diff = ((int)a->type.$tag - (int)b->type.$tag); if (diff != 0) return diff; return Array$compare(&a->components, &b->components, Array$info(&Text$info)); } @@ -696,32 +700,32 @@ public PUREFUNC bool Path$equal(const void *va, const void *vb, const TypeInfo_t { (void)type; Path_t *a = (Path_t*)va, *b = (Path_t*)vb; - if (a->type != b->type) return false; + if (a->type.$tag != b->type.$tag) return false; return Array$equal(&a->components, &b->components, Array$info(&Text$info)); } public PUREFUNC bool Path$equal_values(Path_t a, Path_t b) { - if (a.type != b.type) return false; + if (a.type.$tag != b.type.$tag) return false; return Array$equal(&a.components, &b.components, Array$info(&Text$info)); } public const char *Path$as_c_string(Path_t path) { if (path.components.length == 0) { - if (path.type == PATH_ABSOLUTE) return "/"; - else if (path.type == PATH_RELATIVE) return "."; - else if (path.type == PATH_HOME) return "~"; + if (path.type.$tag == PATH_ABSOLUTE) return "/"; + else if (path.type.$tag == PATH_RELATIVE) return "."; + else if (path.type.$tag == PATH_HOME) return "~"; } size_t len = 0, capacity = 16; char *buf = GC_MALLOC_ATOMIC(capacity); - if (path.type == PATH_ABSOLUTE) { + if (path.type.$tag == PATH_ABSOLUTE) { buf[len++] = '/'; - } else if (path.type == PATH_HOME) { + } else if (path.type.$tag == PATH_HOME) { buf[len++] = '~'; buf[len++] = '/'; - } else if (path.type == PATH_RELATIVE) { + } else if (path.type.$tag == PATH_RELATIVE) { if (!Text$equal_values(*(Text_t*)path.components.data, Text(".."))) { buf[len++] = '.'; buf[len++] = '/'; @@ -750,11 +754,11 @@ public Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type) if (!obj) return Text("Path"); Path_t *path = (Path_t*)obj; Text_t text = Text$join(Text("/"), path->components); - if (path->type == PATH_HOME) + if (path->type.$tag == PATH_HOME) text = Text$concat(path->components.length > 0 ? Text("~/") : Text("~"), text); - else if (path->type == PATH_ABSOLUTE) + else if (path->type.$tag == PATH_ABSOLUTE) text = Text$concat(Text("/"), text); - else if (path->type == PATH_RELATIVE && (path->components.length == 0 || !Text$equal_values(*(Text_t*)(path->components.data), Text("..")))) + else if (path->type.$tag == PATH_RELATIVE && (path->components.length == 0 || !Text$equal_values(*(Text_t*)(path->components.data), Text("..")))) text = Text$concat(path->components.length > 0 ? Text("./") : Text("."), text); if (color) @@ -766,14 +770,14 @@ public Text_t Path$as_text(const void *obj, bool color, const TypeInfo_t *type) public CONSTFUNC bool Path$is_none(const void *obj, const TypeInfo_t *type) { (void)type; - return ((Path_t*)obj)->type == PATH_NONE; + return ((Path_t*)obj)->type.$tag == PATH_NONE; } public void Path$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) { (void)type; Path_t *path = (Path_t*)obj; - fputc((int)path->type, out); + fputc((int)path->type.$tag, out); Array$serialize(&path->components, out, pointers, Array$info(&Text$info)); } @@ -781,7 +785,7 @@ public void Path$deserialize(FILE *in, void *obj, Array_t *pointers, const TypeI { (void)type; Path_t path = {}; - path.type = fgetc(in); + path.type.$tag = fgetc(in); Array$deserialize(in, &path.components, pointers, Array$info(&Text$info)); *(Path_t*)obj = path; } @@ -801,4 +805,16 @@ public const TypeInfo_t Path$info = { } }; +public const TypeInfo_t PathType$info = { + .size=sizeof(PathType_t), + .align=__alignof__(PathType_t), + .metamethods=PackedDataEnum$metamethods, + .tag=EnumInfo, + .EnumInfo={ + .name="PathType", + .num_tags=3, + .tags=((NamedType_t[3]){{.name="Relative"}, {.name="Absolute"}, {.name="Home"}}), + }, +}; + // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 diff --git a/stdlib/paths.h b/stdlib/paths.h index f65bd3ca..6c6cebd3 100644 --- a/stdlib/paths.h +++ b/stdlib/paths.h @@ -65,6 +65,7 @@ void Path$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInf void Path$deserialize(FILE *in, void *obj, Array_t *pointers, const TypeInfo_t *type); extern const TypeInfo_t Path$info; +extern const TypeInfo_t PathType$info; // vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0 -- cgit v1.2.3