From aa19580474f96c9aacf5e85008013891ad2a7045 Mon Sep 17 00:00:00 2001 From: Federico Angelilli Date: Mon, 18 Nov 2024 17:02:20 +0100 Subject: Start working on advanced formatting --- src/format.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/format.c (limited to 'src/format.c') diff --git a/src/format.c b/src/format.c new file mode 100644 index 0000000..a7bad77 --- /dev/null +++ b/src/format.c @@ -0,0 +1,119 @@ +#include +#include +#include + +#include "format.h" +#include "any_log.h" +#include "util.h" + +format_status_t format_init(format_t *format, const char *string, char delim, const format_pair_t *pairs) +{ + format_status_t status = FORMAT_SUCCESS; + + char **parts = NULL; + size_t length = 0, n = 0; + size_t start = 0, end = 0; + + size_t i = 0; + while (string[i] != '\0') { + if (string[i] == delim) { + // TODO + //if (string[i + 1] == delim) { + //} + + if (string[i + 1] == '{') { + if (start != end) { + parts = realloc(parts, ++length * sizeof(char **)); + parts[n++] = strslice(string, start, end); + } + + start = end = i + 2; + while (string[end] != '}') { + if (string[end] == '\0') { + status = FORMAT_UNTERMINATED; + goto clean; + } + if (string[end] == '$' && string[end + 1] == '{') { + status = FORMAT_NESTED; + goto clean; + } + end++; + } + + size_t l = end - start; + size_t next = --end; + + while (start <= end && isspace(string[start])) start++, l--; + while (start <= end && isspace(string[end])) end--, l--; + + log_info("%c'", string[end]); + log_info("'%.*s'", (int)l, string + start); + + for (size_t p = 0; pairs[p].action != FORMAT_NONE; p++) { + if (pairs[p].key == NULL || + (strlen(pairs[p].key) == l && !strncmp(string + start, pairs[p].key, l))) { + + parts = realloc(parts, ++length * sizeof(char **)); + switch (pairs[p].action) { + case FORMAT_STRING: + parts[n++] = strcopy(pairs[p].value); + break; + + case FORMAT_BYTE: + parts[n++] = (char *)(uintptr_t)pairs[p].byte; + break; + + case FORMAT_FUNCTION: + if (pairs[p].key == NULL) { + char *key = strslice(string, start, l + start); + parts[n++] = pairs[p].fn(key); + free(key); + } else + parts[n++] = pairs[p].fn(pairs[p].key); + break; + + default: + unreachable(); + } + + start = i = ++next; + goto next; + } + } + + status = FORMAT_UNKNOWN; + goto clean; + } + + } + + end = i++; +next: + } + + if (string[end] != '\0') { + while (string[end] != '\0') end++; + parts = realloc(parts, ++length * sizeof(char **)); + parts[n++] = strslice(string, start, end); + } + + format->parts = parts; + format->length = n; + + return status; + +clean: + for (size_t i = 0; i < length; i++) { + // XXX: Ugly and probably will explode + if ((uintptr_t)parts[i] > UINT8_MAX) + free(parts[i]); + } + free(parts); + + return status; +} + +void format_free(format_t *format) +{ + free(format->parts); +} -- cgit v1.2.3