skip to content
==> src/catalog_toml.c <==
1/* Line probes of program.toml, one per grep/sed of build-programs.sh. */
2#include "mesh/catalog_toml.h"
3
4#include <stdint.h>
5#include <string.h>
6
7/* Calls f on each line (without its newline) until it returns true. */
8static bool each_line(const char *t, bool (*f)(const char *l, size_t n, void *u), void *u) {
9    while (*t) {
10        const char *e = strchr(t, '\n');
11        size_t n = e ? (size_t)(e - t) : strlen(t);
12        if (f(t, n, u)) return true;
13        if (!e) break;
14        t = e + 1;
15    }
16    return false;
17}
18
19static size_t skip_spaces(const char *l, size_t i, size_t n) {
20    while (i < n && l[i] == ' ') i++;
21    return i;
22}
23
24typedef struct {
25    char *out;
26    size_t cap;
27} name_q;
28
29static bool name_line(const char *l, size_t n, void *u) {
30    name_q *q = u;
31    if (n < 4 || memcmp(l, "name", 4) != 0) return false;
32    size_t i = skip_spaces(l, 4, n);
33    if (i >= n || l[i] != '=') return false;
34    i = skip_spaces(l, i + 1, n);
35    if (i >= n || l[i] != '"') return false;
36    /* sed's greedy .* up to the last '"' of the line, which must end it. */
37    if (l[n - 1] != '"' || n - 1 <= i) return false;
38    size_t len = n - 1 - (i + 1);
39    if (len + 1 > q->cap) return false;
40    memcpy(q->out, l + i + 1, len);
41    q->out[len] = 0;
42    return true;
43}
44
45bool mesh_catalog_toml_name(const char *text, char *out, size_t cap) {
46    name_q q = {out, cap};
47    return each_line(text, name_line, &q);
48}
49
50static bool starts(const char *l, size_t n, const char *p) {
51    size_t k = strlen(p);
52    return n >= k && memcmp(l, p, k) == 0;
53}
54
55static bool backends_line(const char *l, size_t n, void *u) {
56    (void)u;
57    return starts(l, n, "backends");
58}
59bool mesh_catalog_toml_has_backends(const char *text) { return each_line(text, backends_line, NULL); }
60
61/* '^backends *= *\[ *"native" *\]' (the line may go on after the ']'). */
62static bool native_line(const char *l, size_t n, void *u) {
63    (void)u;
64    if (!starts(l, n, "backends")) return false;
65    size_t i = skip_spaces(l, 8, n);
66    if (i >= n || l[i] != '=') return false;
67    i = skip_spaces(l, i + 1, n);
68    if (i >= n || l[i] != '[') return false;
69    i = skip_spaces(l, i + 1, n);
70    if (n - i < 8 || memcmp(l + i, "\"native\"", 8) != 0) return false;
71    i = skip_spaces(l, i + 8, n);
72    return i < n && l[i] == ']';
73}
74bool mesh_catalog_toml_native(const char *text) { return each_line(text, native_line, NULL); }
75
76static bool backend_line(const char *l, size_t n, void *u) {
77    const char *want = u;
78    if (!starts(l, n, "backends")) return false;
79    size_t i = skip_spaces(l, 8, n);
80    if (i >= n || l[i] != '=') return false;
81    size_t k = strlen(want);
82    for (size_t j = i + 1; j + k + 2 <= n; j++)
83        if (l[j] == '"' && memcmp(l + j + 1, want, k) == 0 && l[j + 1 + k] == '"') return true;
84    return false;
85}
86bool mesh_catalog_toml_backend(const char *text, const char *b) { return each_line(text, backend_line, (void *)(uintptr_t)b); }
87
88typedef struct {
89    const char *key;
90    char *out;
91    size_t cap, len;
92    bool found;
93} comment_q;
94
95static bool comment_line(const char *l, size_t n, void *u) {
96    comment_q *q = u;
97    size_t k = strlen(q->key);
98    if (n < 4 + k || l[0] != '#' || l[1] != ' ' || memcmp(l + 2, q->key, k) != 0 || l[2 + k] != ':') return false;
99    size_t i = skip_spaces(l, 3 + k, n);
100    size_t len = n - i;
101    if (q->found && q->len + 1 < q->cap) q->out[q->len++] = '\n';
102    if (q->len + len + 1 > q->cap) len = q->cap - q->len - 1;
103    memcpy(q->out + q->len, l + i, len);
104    q->len += len;
105    q->out[q->len] = 0;
106    q->found = true;
107    return false;
108}
109
110bool mesh_catalog_toml_comment(const char *text, const char *key, char *out, size_t cap) {
111    if (cap == 0) return false;
112    comment_q q = {key, out, cap, 0, false};
113    out[0] = 0;
114    each_line(text, comment_line, &q);
115    return q.found;
116}