diff options
author | Christian Grothoff <christian@grothoff.org> | 2023-05-11 01:16:53 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2023-05-11 01:16:53 +0200 |
commit | ec8ad2e3b3f1298a49ab9592babc0a15c2053e54 (patch) | |
tree | 30b92aa8bfcaba32d9626614ff3516b59d5b8723 /src/templating/mustach-json-c.c | |
parent | 0dd0fff17d0802f48bfab0bac498968abc8a59cf (diff) | |
download | exchange-ec8ad2e3b3f1298a49ab9592babc0a15c2053e54.tar.xz |
update mustach library
Diffstat (limited to 'src/templating/mustach-json-c.c')
-rw-r--r-- | src/templating/mustach-json-c.c | 267 |
1 files changed, 267 insertions, 0 deletions
diff --git a/src/templating/mustach-json-c.c b/src/templating/mustach-json-c.c new file mode 100644 index 000000000..a21a113fb --- /dev/null +++ b/src/templating/mustach-json-c.c @@ -0,0 +1,267 @@ +/* + Author: José Bollo <jobol@nonadev.net> + + https://gitlab.com/jobol/mustach + + SPDX-License-Identifier: ISC +*/ + +#define _GNU_SOURCE + +#include <stdio.h> +#include <string.h> + +#include "mustach.h" +#include "mustach-wrap.h" +#include "mustach-json-c.h" + +struct expl { + struct json_object *root; + struct json_object *selection; + int depth; + struct { + struct json_object *cont; + struct json_object *obj; + struct json_object_iterator iter; + struct json_object_iterator enditer; + int is_objiter; + int index, count; + } stack[MUSTACH_MAX_DEPTH]; +}; + +static int start(void *closure) +{ + struct expl *e = closure; + e->depth = 0; + e->selection = NULL; + e->stack[0].cont = NULL; + e->stack[0].obj = e->root; + e->stack[0].index = 0; + e->stack[0].count = 1; + return MUSTACH_OK; +} + +static int compare(void *closure, const char *value) +{ + struct expl *e = closure; + struct json_object *o = e->selection; + double d; + int64_t i; + + switch (json_object_get_type(o)) { + case json_type_double: + d = json_object_get_double(o) - atof(value); + return d < 0 ? -1 : d > 0 ? 1 : 0; + case json_type_int: + i = json_object_get_int64(o) - (int64_t)atoll(value); + return i < 0 ? -1 : i > 0 ? 1 : 0; + default: + return strcmp(json_object_get_string(o), value); + } +} + +static int sel(void *closure, const char *name) +{ + struct expl *e = closure; + struct json_object *o; + int i, r; + + if (name == NULL) { + o = e->stack[e->depth].obj; + r = 1; + } else { + i = e->depth; + while (i >= 0 && !json_object_object_get_ex(e->stack[i].obj, name, &o)) + i--; + if (i >= 0) + r = 1; + else { + o = NULL; + r = 0; + } + } + e->selection = o; + return r; +} + +static int subsel(void *closure, const char *name) +{ + struct expl *e = closure; + struct json_object *o; + int r; + + r = json_object_object_get_ex(e->selection, name, &o); + if (r) + e->selection = o; + return r; +} + +static int enter(void *closure, int objiter) +{ + struct expl *e = closure; + struct json_object *o; + + if (++e->depth >= MUSTACH_MAX_DEPTH) + return MUSTACH_ERROR_TOO_DEEP; + + o = e->selection; + e->stack[e->depth].is_objiter = 0; + if (objiter) { + if (!json_object_is_type(o, json_type_object)) + goto not_entering; + + e->stack[e->depth].iter = json_object_iter_begin(o); + e->stack[e->depth].enditer = json_object_iter_end(o); + if (json_object_iter_equal(&e->stack[e->depth].iter, &e->stack[e->depth].enditer)) + goto not_entering; + e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].iter); + e->stack[e->depth].cont = o; + e->stack[e->depth].is_objiter = 1; + } else if (json_object_is_type(o, json_type_array)) { + e->stack[e->depth].count = json_object_array_length(o); + if (e->stack[e->depth].count == 0) + goto not_entering; + e->stack[e->depth].cont = o; + e->stack[e->depth].obj = json_object_array_get_idx(o, 0); + e->stack[e->depth].index = 0; + } else if (json_object_is_type(o, json_type_object) || json_object_get_boolean(o)) { + e->stack[e->depth].count = 1; + e->stack[e->depth].cont = NULL; + e->stack[e->depth].obj = o; + e->stack[e->depth].index = 0; + } else + goto not_entering; + return 1; + +not_entering: + e->depth--; + return 0; +} + +static int next(void *closure) +{ + struct expl *e = closure; + + if (e->depth <= 0) + return MUSTACH_ERROR_CLOSING; + + if (e->stack[e->depth].is_objiter) { + json_object_iter_next(&e->stack[e->depth].iter); + if (json_object_iter_equal(&e->stack[e->depth].iter, &e->stack[e->depth].enditer)) + return 0; + e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].iter); + return 1; + } + + e->stack[e->depth].index++; + if (e->stack[e->depth].index >= e->stack[e->depth].count) + return 0; + + e->stack[e->depth].obj = json_object_array_get_idx(e->stack[e->depth].cont, e->stack[e->depth].index); + return 1; +} + +static int leave(void *closure) +{ + struct expl *e = closure; + + if (e->depth <= 0) + return MUSTACH_ERROR_CLOSING; + + e->depth--; + return 0; +} + +static int get(void *closure, struct mustach_sbuf *sbuf, int key) +{ + struct expl *e = closure; + const char *s; + + if (key) + s = e->stack[e->depth].is_objiter + ? json_object_iter_peek_name(&e->stack[e->depth].iter) + : ""; + else + switch (json_object_get_type(e->selection)) { + case json_type_string: + s = json_object_get_string(e->selection); + break; + case json_type_null: + s = ""; + break; + default: + s = json_object_to_json_string_ext(e->selection, 0); + break; + } + sbuf->value = s; + return 1; +} + +const struct mustach_wrap_itf mustach_json_c_wrap_itf = { + .start = start, + .stop = NULL, + .compare = compare, + .sel = sel, + .subsel = subsel, + .enter = enter, + .next = next, + .leave = leave, + .get = get +}; + +int mustach_json_c_file(const char *template, size_t length, struct json_object *root, int flags, FILE *file) +{ + struct expl e; + e.root = root; + return mustach_wrap_file(template, length, &mustach_json_c_wrap_itf, &e, flags, file); +} + +int mustach_json_c_fd(const char *template, size_t length, struct json_object *root, int flags, int fd) +{ + struct expl e; + e.root = root; + return mustach_wrap_fd(template, length, &mustach_json_c_wrap_itf, &e, flags, fd); +} + +int mustach_json_c_mem(const char *template, size_t length, struct json_object *root, int flags, char **result, size_t *size) +{ + struct expl e; + e.root = root; + return mustach_wrap_mem(template, length, &mustach_json_c_wrap_itf, &e, flags, result, size); +} + +int mustach_json_c_write(const char *template, size_t length, struct json_object *root, int flags, mustach_write_cb_t *writecb, void *closure) +{ + struct expl e; + e.root = root; + return mustach_wrap_write(template, length, &mustach_json_c_wrap_itf, &e, flags, writecb, closure); +} + +int mustach_json_c_emit(const char *template, size_t length, struct json_object *root, int flags, mustach_emit_cb_t *emitcb, void *closure) +{ + struct expl e; + e.root = root; + return mustach_wrap_emit(template, length, &mustach_json_c_wrap_itf, &e, flags, emitcb, closure); +} + +int fmustach_json_c(const char *template, struct json_object *root, FILE *file) +{ + return mustach_json_c_file(template, 0, root, -1, file); +} + +int fdmustach_json_c(const char *template, struct json_object *root, int fd) +{ + return mustach_json_c_fd(template, 0, root, -1, fd); +} + +int mustach_json_c(const char *template, struct json_object *root, char **result, size_t *size) +{ + return mustach_json_c_mem(template, 0, root, -1, result, size); +} + +int umustach_json_c(const char *template, struct json_object *root, mustach_write_cb_t *writecb, void *closure) +{ + return mustach_json_c_write(template, 0, root, -1, writecb, closure); +} + + |