diff options
author | Florian Dold <florian.dold@gmail.com> | 2020-08-20 23:08:13 +0530 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2020-08-20 23:08:13 +0530 |
commit | 0a5308e71e7f65a9921d74e8d55b389654defca6 (patch) | |
tree | 5c5fef0b2fff39580fec0accb452ec688aa49c05 /src/mustach/mustach-jansson.c | |
parent | 9ed4a331019dab10c8bd37094e3dcde2efdac2e6 (diff) | |
download | merchant-0a5308e71e7f65a9921d74e8d55b389654defca6.tar.gz merchant-0a5308e71e7f65a9921d74e8d55b389654defca6.tar.bz2 merchant-0a5308e71e7f65a9921d74e8d55b389654defca6.zip |
jansson adapter for mustache templates
Diffstat (limited to 'src/mustach/mustach-jansson.c')
-rw-r--r-- | src/mustach/mustach-jansson.c | 308 |
1 files changed, 308 insertions, 0 deletions
diff --git a/src/mustach/mustach-jansson.c b/src/mustach/mustach-jansson.c new file mode 100644 index 00000000..afb8f823 --- /dev/null +++ b/src/mustach/mustach-jansson.c @@ -0,0 +1,308 @@ +/* + Copyright (C) 2020 Taler Systems SA + + Original license: + Author: José Bollo <jobol@nonadev.net> + Author: José Bollo <jose.bollo@iot.bzh> + + https://gitlab.com/jobol/mustach + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "platform.h" +#include "mustach-jansson.h" + +struct Context +{ + /** + * Context object. + */ + json_t *cont; + + /** + * Current object. + */ + json_t *obj; + + /** + * Opaque object iterator. + */ + void *iter; + + /** + * Current index when iterating over an array. + */ + unsigned int index; + + /** + * Count when iterating over an array. + */ + unsigned int count; + + bool is_objiter; +}; + +struct JanssonClosure +{ + json_t *root; + mustach_jansson_write_cb writecb; + int depth; + + /** + * Did the last find(..) call result in an iterable? + */ + struct Context stack[MUSTACH_MAX_DEPTH]; + + /** + * The last object we found should be iterated over. + */ + bool found_iter; +}; + +static json_t * +find (struct JanssonClosure *e, const char *name) +{ + json_t *obj = e->stack[e->depth].obj; + char *nd = GNUNET_strdup (name); + char *p = nd; + char *saveptr = NULL; + + while (true) + { + char *tok = strtok_r (p, ".", &saveptr); + if (tok == NULL) + break; + obj = json_object_get (obj, tok); + if (obj == NULL) + break; + p = NULL; + } + + GNUNET_free (nd); + + return obj; +} + + +static int +start(void *closure) +{ + struct JanssonClosure *e = closure; + e->depth = 0; + 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 +emituw (void *closure, const char *buffer, size_t size, int escape, FILE *file) +{ + struct JanssonClosure *e = closure; + if (!escape) + e->writecb (file, buffer, size); + else + do + { + switch (*buffer) + { + case '<': + e->writecb (file, "<", 4); + break; + case '>': + e->writecb (file, ">", 4); + break; + case '&': + e->writecb (file, "&", 5); + break; + default: + e->writecb (file, buffer, 1); + break; + } + buffer++; + } + while(--size); + return MUSTACH_OK; +} + + +static const char * +item (struct JanssonClosure *e, const char *name) +{ + json_t *obj; + + if ( (0 == strcmp (name, "*") ) && + (e->stack[e->depth].is_objiter ) ) + return json_object_iter_key (e->stack[e->depth].iter); + obj = find (e, name); + if (NULL != obj) + return json_string_value (obj); + return NULL; +} + + +static int +enter(void *closure, const char *name) +{ + struct JanssonClosure *e = closure; + json_t *o = find(e, name); + if (++e->depth >= MUSTACH_MAX_DEPTH) + return MUSTACH_ERROR_TOO_DEEP; + + if (json_is_object (o)) + { + if (e->found_iter) + { + void *iter = json_object_iter (o); + if (NULL == iter) + { + e->depth--; + return 0; + } + e->stack[e->depth].is_objiter = 1; + e->stack[e->depth].iter = iter; + e->stack[e->depth].obj = json_object_iter_value (iter); + e->stack[e->depth].cont = o; + } + else + { + e->stack[e->depth].is_objiter = 0; + e->stack[e->depth].obj = o; + e->stack[e->depth].cont = o; + } + return 1; + } + + if (json_is_array (o)) + { + unsigned int size = json_array_size (o); + if (size == 0) + { + e->depth--; + return 0; + } + e->stack[e->depth].count = size; + e->stack[e->depth].cont = o; + e->stack[e->depth].obj = json_array_get (o, 0); + e->stack[e->depth].index = 0; + e->stack[e->depth].is_objiter = 0; + return 1; + } + + e->depth--; + return 0; +} + + +static int +next (void *closure) +{ + struct JanssonClosure *e = closure; + struct Context *ctx; + if (e->depth <= 0) + return MUSTACH_ERROR_CLOSING; + ctx = &e->stack[e->depth]; + if (ctx->is_objiter) + { + ctx->iter = json_object_iter_next (ctx->obj, ctx->iter); + if (NULL == ctx->iter) + return 0; + ctx->obj = json_object_iter_value (ctx->iter); + return 1; + } + ctx->index++; + if (ctx->index >= ctx->count) + return 0; + ctx->obj = json_array_get (ctx->cont, ctx->index); + return 1; +} + +static int leave (void *closure) +{ + struct JanssonClosure *e = closure; + if (e->depth <= 0) + return MUSTACH_ERROR_CLOSING; + e->depth--; + return 0; +} + +static int get (void *closure, const char *name, struct mustach_sbuf *sbuf) +{ + struct JanssonClosure *e = closure; + const char *s; + + s = item (e, name); + if (s) + sbuf->value = s; + else + sbuf->value = ""; + return MUSTACH_OK; +} + +static struct mustach_itf itf = { + .start = start, + .put = NULL, + .enter = enter, + .next = next, + .leave = leave, + .partial =NULL, + .get = get, + .emit = NULL, + .stop = NULL +}; + +static struct mustach_itf itfuw = { + .start = start, + .put = NULL, + .enter = enter, + .next = next, + .leave = leave, + .partial = NULL, + .get = get, + .emit = emituw, + .stop = NULL +}; + +int fmustach_jansson (const char *template, json_t *root, FILE *file) +{ + struct JanssonClosure e = { 0 }; + e.root = root; + return fmustach(template, &itf, &e, file); +} + +int fdmustach_jansson (const char *template, json_t *root, int fd) +{ + struct JanssonClosure e = { 0 }; + e.root = root; + return fdmustach(template, &itf, &e, fd); +} + +int mustach_jansson (const char *template, json_t *root, char **result, size_t *size) +{ + struct JanssonClosure e = { 0 }; + e.root = root; + e.writecb = NULL; + return mustach(template, &itf, &e, result, size); +} + +int umustach_jansson (const char *template, json_t *root, mustach_jansson_write_cb writecb, void *closure) +{ + struct JanssonClosure e = { 0 }; + e.root = root; + e.writecb = writecb; + return fmustach(template, &itfuw, &e, closure); +} + |