Some checks failed
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=OFF (push) Failing after 13s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=OFF (push) Failing after 16s
CMake / ubuntu-latest - shared=OFF, pthread=OFF, posix=ON (push) Failing after 12s
CMake / ubuntu-latest - shared=ON, pthread=OFF, posix=ON (push) Failing after 14s
CMake / ubuntu-latest - shared=OFF, pthread=ON, posix=ON (push) Failing after 16s
CMake / ubuntu-latest - shared=ON, pthread=ON, posix=ON (push) Failing after 13s
Signed-off-by: Slendi <slendi@socopon.com>
144 lines
2.9 KiB
C
144 lines
2.9 KiB
C
#include <dcfg.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
typedef enum {
|
|
T_FIELD,
|
|
T_INDEX,
|
|
} TokenType;
|
|
|
|
typedef struct {
|
|
TokenType type;
|
|
union {
|
|
dcfg_StringView field;
|
|
size_t index;
|
|
} v;
|
|
} Token;
|
|
|
|
#define MAX_TOKENS 256
|
|
|
|
static size_t tokenize(char const *query, Token *out)
|
|
{
|
|
size_t count = 0;
|
|
size_t i = 0;
|
|
if (query[i] == '.')
|
|
i++;
|
|
while (query[i] && count < MAX_TOKENS) {
|
|
if (query[i] == '.') {
|
|
i++;
|
|
size_t start = i;
|
|
while (query[i] && query[i] != '.' && query[i] != '[')
|
|
i++;
|
|
out[count].type = T_FIELD;
|
|
out[count].v.field.data = query + start;
|
|
out[count].v.field.size = i - start;
|
|
count++;
|
|
} else if (query[i] == '[') {
|
|
i++;
|
|
char *end;
|
|
size_t idx = strtoul(query + i, &end, 10);
|
|
if (*end != ']') {
|
|
fprintf(stderr, "invalid index\n");
|
|
exit(1);
|
|
}
|
|
i = (size_t)(end - query) + 1;
|
|
out[count].type = T_INDEX;
|
|
out[count].v.index = idx;
|
|
count++;
|
|
} else {
|
|
size_t start = i;
|
|
while (query[i] && query[i] != '.' && query[i] != '[')
|
|
i++;
|
|
out[count].type = T_FIELD;
|
|
out[count].v.field.data = query + start;
|
|
out[count].v.field.size = i - start;
|
|
count++;
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static void print_value(dcfg_Value *v)
|
|
{
|
|
dcfg_StringView sv;
|
|
if (dcfg_serialize_value(v, &sv)) {
|
|
fwrite(sv.data, 1, sv.size, stdout);
|
|
free((void *)sv.data);
|
|
putchar('\n');
|
|
} else {
|
|
puts("null");
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (argc < 3) {
|
|
fprintf(stderr, "usage: %s <query> <file>\n", argv[0]);
|
|
return 1;
|
|
}
|
|
char const *query = argv[1];
|
|
char const *file = argv[2];
|
|
|
|
dcfg_Instance *inst = dcfg_make_instance(&(dcfg_InstanceCreateInfo) { 0 });
|
|
if (!inst) {
|
|
fprintf(stderr, "failed to create instance\n");
|
|
return 1;
|
|
}
|
|
dcfg_Value *root = dcfg_parse(inst, dcfg_SV(file));
|
|
if (!root) {
|
|
fprintf(stderr, "parse error: %s\n", dcfg_last_error(inst));
|
|
dcfg_destroy_instance(inst);
|
|
return 1;
|
|
}
|
|
|
|
Token toks[MAX_TOKENS];
|
|
size_t n = tokenize(query, toks);
|
|
|
|
dcfg_Value *evaled;
|
|
if (!dcfg_Value_evaluate_toplevel(root, &evaled, NULL, NULL, 0)) {
|
|
fprintf(stderr, "evaluation error: %s\n", dcfg_last_error(inst));
|
|
dcfg_destroy(root);
|
|
dcfg_destroy_instance(inst);
|
|
return 1;
|
|
}
|
|
|
|
dcfg_Value *cur = evaled;
|
|
for (size_t i = 0; i < n; i++) {
|
|
Token *t = &toks[i];
|
|
dcfg_Value *next = NULL;
|
|
|
|
if (t->type == T_FIELD) {
|
|
if (!dcfg_Value_get_object_field_ex(cur, t->v.field, &next, true)) {
|
|
fprintf(stderr, "no such field\n");
|
|
dcfg_destroy(evaled);
|
|
dcfg_destroy(root);
|
|
dcfg_destroy_instance(inst);
|
|
return 1;
|
|
}
|
|
} else {
|
|
if (!dcfg_Value_get_array_item_ex(cur, t->v.index, &next, true)) {
|
|
fprintf(stderr, "index out of bounds\n");
|
|
dcfg_destroy(evaled);
|
|
dcfg_destroy(root);
|
|
dcfg_destroy_instance(inst);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (cur != evaled)
|
|
dcfg_destroy(cur);
|
|
|
|
cur = next;
|
|
}
|
|
print_value(cur);
|
|
if (cur != evaled)
|
|
dcfg_destroy(cur);
|
|
|
|
dcfg_destroy(evaled);
|
|
dcfg_destroy(root);
|
|
dcfg_destroy_instance(inst);
|
|
return 0;
|
|
}
|