aboutsummaryrefslogtreecommitdiff
path: root/src/format.c
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-11-18 17:02:20 +0100
committerFederico Angelilli <code@fedang.net>2024-11-18 17:02:20 +0100
commitaa19580474f96c9aacf5e85008013891ad2a7045 (patch)
treea3323b6ca6ebed38799477ebba7df61ad1218240 /src/format.c
parente07263e6f1c777241f9512fbbb266e89d1364f08 (diff)
Start working on advanced formatting
Diffstat (limited to 'src/format.c')
-rw-r--r--src/format.c119
1 files changed, 119 insertions, 0 deletions
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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#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);
+}