Get something working
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
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>
This commit is contained in:
143
programs/dcfgq.c
Normal file
143
programs/dcfgq.c
Normal file
@@ -0,0 +1,143 @@
|
||||
#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;
|
||||
}
|
Reference in New Issue
Block a user