about summary refs log tree commit diff
path: root/boot/common.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-07-22 19:29:21 +0200
committerMel <mel@rnrd.eu>2025-07-23 03:56:24 +0200
commitb0acce3b858715a04fba154a23c6ea5fac083a74 (patch)
treeba0695ef0b8ecad3993f49f803ac7060622ef2a0 /boot/common.c
parent52a6c142d7c85520b09e300283154b7ec9c6b9f3 (diff)
downloadcatskill-b0acce3b858715a04fba154a23c6ea5fac083a74.tar.zst
catskill-b0acce3b858715a04fba154a23c6ea5fac083a74.zip
Add option to test suite to auto-adjust expected output in definition
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/common.c')
-rw-r--r--boot/common.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/boot/common.c b/boot/common.c
index 7416696..6a95bb6 100644
--- a/boot/common.c
+++ b/boot/common.c
@@ -254,6 +254,78 @@ string_format(struct String s, const ascii* format, ...)
     va_end(args);
 }
 
+enum String_Concat_Arg
+{
+    ARG_END,
+    ARG_STRING,
+    ARG_ASCII,
+};
+
+#define MAX_STRING_CONCAT_LENGTH 2048
+
+struct String
+string_concatenate(enum String_Concat_Arg type1, ...)
+{
+    va_list args;
+    va_start(args, type1);
+    uint total_length = 0;
+    enum String_Concat_Arg type = type1;
+    while (type != ARG_END) {
+        switch (type) {
+        case ARG_STRING: {
+            struct String s = va_arg(args, struct String);
+            if (!string_is_empty(s)) total_length += s.length;
+            break;
+        }
+        case ARG_ASCII: {
+            ascii* str = va_arg(args, ascii*);
+            if (str) total_length += strlen(str);
+            break;
+        }
+        default:
+            break;
+        }
+        type = va_arg(args, enum String_Concat_Arg);
+    }
+    va_end(args);
+
+    if (total_length == 0) return string_empty();
+
+    check(total_length < MAX_STRING_CONCAT_LENGTH - 1, "string concatenation too long");
+    ascii buffer[MAX_STRING_CONCAT_LENGTH];
+
+    ascii* cursor = buffer;
+    va_start(args, type1);
+    type = type1;
+    while (type != ARG_END) {
+        switch (type) {
+        case ARG_STRING: {
+            struct String s = va_arg(args, struct String);
+            if (!string_is_empty(s)) {
+                memcpy(cursor, s.data, s.length);
+                cursor += s.length;
+            }
+            break;
+        }
+        case ARG_ASCII: {
+            ascii* str = va_arg(args, ascii*);
+            if (str) {
+                uint length = strlen(str);
+                memcpy(cursor, str, length);
+                cursor += length;
+            }
+            break;
+        }
+        default:
+            break;
+        }
+        type = va_arg(args, enum String_Concat_Arg);
+    }
+    va_end(args);
+
+    return string_new(buffer, total_length);
+}
+
 struct String_View
 string_substring(struct String s, uint start, uint end)
 {