aboutsummaryrefslogtreecommitdiff
path: root/src/format.c
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-11-19 01:13:47 +0100
committerFederico Angelilli <code@fedang.net>2024-11-19 01:13:47 +0100
commit0d088e48b5e4480fe2421bb90d601131bed35c8a (patch)
treed60c348cfa44fae7796e46a7e29492764a475fc8 /src/format.c
parent7a33c4e201783acb7d5bdd07bbccf921940b332c (diff)
Update format
Diffstat (limited to 'src/format.c')
-rw-r--r--src/format.c93
1 files changed, 60 insertions, 33 deletions
diff --git a/src/format.c b/src/format.c
index 49d5d35..2a2ee03 100644
--- a/src/format.c
+++ b/src/format.c
@@ -11,18 +11,14 @@
do { \
if (n + 1 >= length) { \
length += (need); \
- parts = realloc(parts, length * sizeof(char *)); \
+ parts = realloc(parts, length * sizeof(format_pair_t)); \
assert(parts != NULL); \
- marks = realloc(marks, length * sizeof(uint8_t)); \
- assert(marks != NULL); \
} \
} while (0)
bool format_init(format_t *format, const char *string, char delim)
{
- char **parts = NULL;
- uint8_t *marks = NULL;
-
+ format_pair_t *parts = NULL;
size_t length = 0, n = 0;
size_t start = 0, end = 0;
@@ -34,19 +30,16 @@ bool format_init(format_t *format, const char *string, char delim)
format_grow(2);
if (start != end) {
- parts[n] = strslice(string, start, end);
- marks[n] = false;
+ parts[n].string = strslice(string, start, end);
+ parts[n].mark = 0;
n++;
}
start = end += 2;
while (string[end] != '}') {
if (string[end] == '\0' || (string[end] == '$' && string[end + 1] == '{')) {
- for (size_t k = 0; k < n; k++)
- free(parts[k]);
-
- free(parts);
- free(marks);
+ format->parts = parts, format->length = length;
+ format_free(format);
return false;
}
end++;
@@ -58,8 +51,8 @@ bool format_init(format_t *format, const char *string, char delim)
while (start <= end && isspace(string[start])) start++, l--;
while (start <= end && isspace(string[end])) end--, l--;
- parts[n] = strslice(string, start, start + l);
- marks[n] = true;
+ parts[n].string = strslice(string, start, start + l);
+ parts[n].mark = 1;
n++;
start = end = ++next;
@@ -75,35 +68,70 @@ next:
while (string[end] != '\0') end++;
format_grow(1);
- parts[n] = strslice(string, start, end);
- marks[n] = false;
+ parts[n].string = strslice(string, start, end);
+ parts[n].mark = 0;
n++;
}
format->parts = parts;
- format->marks = marks;
format->length = n;
return true;
}
-int format_remark(format_t *format, const char *label, const format_pair_t *pairs)
+static size_t format_option_cmp(const char *a, const char *b)
{
- int errors = 0, marked = 0;
+ size_t i = 0;
+ while (b[i] != '\0') {
+ if (a[i] != b[i]) return 0;
+ i++;
+ }
+ return i;
+}
+static bool format_option_match(format_pair_t *part, const format_option_t *option)
+{
+ format_mark_t mark = 0;
+ size_t off = 0;
+
+ for (format_pair_t *ps = option->prefixes; ps != NULL && ps->string != NULL; ps++) {
+ off = format_option_cmp(part->string, ps->string);
+ if (off != 0) {
+ mark |= ps->mark;
+ break;
+ }
+ }
+
+ size_t tmp = format_option_cmp(part->string + off, option->option.string);
+ if (tmp == 0) return false;
+ off += tmp;
+ mark |= option->option.mark;
+
+ for (format_pair_t *ss = option->suffixes; ss != NULL && ss->string != NULL; ss++) {
+ tmp = format_option_cmp(part->string + off, ss->string);
+ if (tmp != 0) {
+ mark |= ss->mark;
+ break;
+ }
+ }
+
+ if (part->string[tmp] != '\0')
+ return false;
+
+ part->mark = mark;
+ return true;
+}
+
+int format_remark(format_t *format, const char *label, const format_option_t *options)
+{
+ int errors = 0, marked = 0;
for (size_t i = 0; i < format->length; i++) {
- // Skip regular strings
- if (!format->marks[i]) continue;
- size_t l = strlen(format->parts[i]);
- for (size_t j = 0; pairs[j].key != NULL; j++) {
- size_t kl = strlen(pairs[j].key);
+ // Skip regular strings
+ if (!format->parts[i].mark) continue;
- if ((pairs[j].prefix && !strncmp(pairs[j].key, format->parts[i], kl)) ||
- (pairs[j].postfix && l > kl && !strncmp(pairs[j].key, format->parts[i] + (l - kl), kl)) ||
- !strcmp(pairs[j].key, format->parts[i]))
- {
- format->marks[i] = pairs[j].mark;
+ for (size_t j = 0; !iszero(&options[j], sizeof(format_option_t)); j++) {
+ if (format_option_match(&format->parts[i], &options[j])) {
marked++;
goto next;
}
@@ -111,7 +139,7 @@ int format_remark(format_t *format, const char *label, const format_pair_t *pair
errors++;
if (label != NULL)
- log_error("Unknown format option '%s' for block '%s'", format->parts[i], label);
+ log_error("Unknown format option '%s' for block '%s'", format->parts[i].string, label);
next:
}
@@ -121,8 +149,7 @@ next:
void format_free(format_t *format)
{
for (size_t i = 0; i < format->length; i++)
- free(format->parts[i]);
+ free(format->parts[i].string);
free(format->parts);
- free(format->marks);
}