aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-08-20 23:08:13 +0530
committerFlorian Dold <florian.dold@gmail.com>2020-08-20 23:08:13 +0530
commit0a5308e71e7f65a9921d74e8d55b389654defca6 (patch)
tree5c5fef0b2fff39580fec0accb452ec688aa49c05
parent9ed4a331019dab10c8bd37094e3dcde2efdac2e6 (diff)
jansson adapter for mustache templates
-rw-r--r--src/mustach/.gitignore1
-rw-r--r--src/mustach/Makefile.am12
-rw-r--r--src/mustach/mustach-jansson.c308
-rw-r--r--src/mustach/mustach-jansson.h (renamed from src/mustach/mustach-json-c.h)28
-rw-r--r--src/mustach/mustach-json-c.c526
-rw-r--r--src/mustach/test_mustach_jansson.c80
6 files changed, 416 insertions, 539 deletions
diff --git a/src/mustach/.gitignore b/src/mustach/.gitignore
new file mode 100644
index 00000000..b2bf6ef9
--- /dev/null
+++ b/src/mustach/.gitignore
@@ -0,0 +1 @@
+test_mustach_jansson
diff --git a/src/mustach/Makefile.am b/src/mustach/Makefile.am
index a39a28d0..ac9f2842 100644
--- a/src/mustach/Makefile.am
+++ b/src/mustach/Makefile.am
@@ -11,7 +11,17 @@ lib_LIBRARIES = \
libmustach.a
libmustach_a_SOURCES = \
- mustach.c mustach.h
+ mustach.c mustach.h \
+ mustach-jansson.c mustach-jansson.h
+
+test_mustach_jansson_SOURCES = \
+ test_mustach_jansson.c
+test_mustach_jansson_LDADD = \
+ -lgnunetutil \
+ libmustach.a
+
+check_PROGRAMS = \
+ test_mustach_jansson
check_SCRIPTS = \
run-original-tests.sh
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, "&lt;", 4);
+ break;
+ case '>':
+ e->writecb (file, "&gt;", 4);
+ break;
+ case '&':
+ e->writecb (file, "&amp;", 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);
+}
+
diff --git a/src/mustach/mustach-json-c.h b/src/mustach/mustach-jansson.h
index 3dfa228b..f1a1b761 100644
--- a/src/mustach/mustach-json-c.h
+++ b/src/mustach/mustach-jansson.h
@@ -1,4 +1,7 @@
/*
+ Copyright (C) 2020 Taler Systems SA
+
+ Original license:
Author: José Bollo <jose.bollo@iot.bzh>
Author: José Bollo <jobol@nonadev.net>
@@ -17,13 +20,14 @@
limitations under the License.
*/
-#ifndef _mustach_json_c_h_included_
-#define _mustach_json_c_h_included_
+#ifndef _mustach_jansson_h_included_
+#define _mustach_jansson_h_included_
-#include <json-c/json.h>
+#include <taler/taler_json_lib.h>
+#include "mustach.h"
/**
- * fmustach_json_c - Renders the mustache 'template' in 'file' for 'root'.
+ * fmustach_jansson - Renders the mustache 'template' in 'file' for 'root'.
*
* @template: the template string to instanciate
* @root: the root json object to render
@@ -32,10 +36,10 @@
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
-extern int fmustach_json_c(const char *template, struct json_object *root, FILE *file);
+extern int fmustach_jansson(const char *template, json_t *root, FILE *file);
/**
- * fmustach_json_c - Renders the mustache 'template' in 'fd' for 'root'.
+ * fmustach_jansson - Renders the mustache 'template' in 'fd' for 'root'.
*
* @template: the template string to instanciate
* @root: the root json object to render
@@ -44,11 +48,11 @@ extern int fmustach_json_c(const char *template, struct json_object *root, FILE
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
-extern int fdmustach_json_c(const char *template, struct json_object *root, int fd);
+extern int fdmustach_jansson(const char *template, json_t *root, int fd);
/**
- * fmustach_json_c - Renders the mustache 'template' in 'result' for 'root'.
+ * fmustach_jansson - Renders the mustache 'template' in 'result' for 'root'.
*
* @template: the template string to instanciate
* @root: the root json object to render
@@ -58,10 +62,10 @@ extern int fdmustach_json_c(const char *template, struct json_object *root, int
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
-extern int mustach_json_c(const char *template, struct json_object *root, char **result, size_t *size);
+extern int mustach_jansson(const char *template, json_t *root, char **result, size_t *size);
/**
- * umustach_json_c - Renders the mustache 'template' for 'root' to custom writer 'writecb' with 'closure'.
+ * umustach_jansson - Renders the mustache 'template' for 'root' to custom writer 'writecb' with 'closure'.
*
* @template: the template string to instanciate
* @root: the root json object to render
@@ -71,8 +75,8 @@ extern int mustach_json_c(const char *template, struct json_object *root, char *
* Returns 0 in case of success, -1 with errno set in case of system error
* a other negative value in case of error.
*/
-typedef int (*mustach_json_c_write_cb)(void*closure, const char*buffer, size_t size);
-extern int umustach_json_c(const char *template, struct json_object *root, mustach_json_c_write_cb writecb, void *closure);
+typedef int (*mustach_jansson_write_cb)(void *closure, const char *buffer, size_t size);
+extern int umustach_jansson(const char *template, json_t *root, mustach_jansson_write_cb writecb, void *closure);
#endif
diff --git a/src/mustach/mustach-json-c.c b/src/mustach/mustach-json-c.c
deleted file mode 100644
index df901dcd..00000000
--- a/src/mustach/mustach-json-c.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- 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.
-*/
-
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <string.h>
-#ifdef _WIN32
-#include <malloc.h>
-#endif
-#ifdef __sun
-# include <alloca.h>
-#endif
-
-#include "mustach.h"
-#include "mustach-json-c.h"
-
-#if defined(NO_EXTENSION_FOR_MUSTACH)
-# undef NO_SINGLE_DOT_EXTENSION_FOR_MUSTACH
-# define NO_SINGLE_DOT_EXTENSION_FOR_MUSTACH
-# undef NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH
-# define NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH
-# undef NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH
-# define NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH
-# undef NO_JSON_POINTER_EXTENSION_FOR_MUSTACH
-# define NO_JSON_POINTER_EXTENSION_FOR_MUSTACH
-# undef NO_OBJECT_ITERATION_FOR_MUSTACH
-# define NO_OBJECT_ITERATION_FOR_MUSTACH
-# undef NO_INCLUDE_PARTIAL_FALLBACK
-# define NO_INCLUDE_PARTIAL_FALLBACK
-#endif
-
-#if !defined(NO_INCLUDE_PARTIAL_FALLBACK) \
- && !defined(INCLUDE_PARTIAL_EXTENSION)
-# define INCLUDE_PARTIAL_EXTENSION ".mustache"
-#endif
-
-#if !defined(NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH)
-# undef NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH
-#endif
-
-struct expl {
- struct json_object *root;
- mustach_json_c_write_cb writecb;
- int depth;
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- int found_objiter;
-#endif
- struct {
- struct json_object *cont;
- struct json_object *obj;
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- struct json_object_iterator biter, eiter;
- int is_objiter;
-#endif
- int index, count;
- } stack[MUSTACH_MAX_DEPTH];
-};
-
-enum comp {
- C_no = 0,
- C_eq = 1,
- C_lt = 5,
- C_le = 6,
- C_gt = 9,
- C_ge = 10
-};
-
-#if !defined(NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH)
-static enum comp getcomp(char *head)
-{
- return head[0] == '=' ? C_eq
-#if !defined(NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH)
- : head[0] == '<' ? (head[1] == '=' ? C_le : C_lt)
- : head[0] == '>' ? (head[1] == '=' ? C_ge : C_gt)
-#endif
- : C_no;
-}
-
-static char *keyval(char *head, int isptr, enum comp *comp)
-{
- char *w, c, s;
- enum comp k;
-
- k = C_no;
-#if !defined(NO_USE_VALUE_ESCAPE_FIRST_EXTENSION_FOR_MUSTACH)
- s = getcomp(head) != C_no;
-#else
- s = 0;
-#endif
- c = *(w = head);
- while (c && (s || (k = getcomp(head)) == C_no)) {
- if (s)
- s = 0;
- else
- s = (isptr ? c == '~' : c == '\\')
- && (getcomp(head + 1) != C_no);
- if (!s)
- *w++ = c;
- c = *++head;
- }
- *w = 0;
- *comp = k;
- return k == C_no ? NULL : &head[k & 3];
-}
-
-static int compare(struct json_object *o, const char *value)
-{
- switch (json_object_get_type(o)) {
- case json_type_double:
- return json_object_get_double(o) - atof(value);
- case json_type_int:
- return json_object_get_int64(o) - (int64_t)atoll(value);
- default:
- return strcmp(json_object_get_string(o), value);
- }
-}
-
-static int evalcomp(struct json_object *o, char *value, enum comp k)
-{
- int r, c;
-
- c = compare(o, value);
- switch (k) {
- case C_eq: r = c == 0; break;
-#if !defined(NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH)
- case C_lt: r = c < 0; break;
- case C_le: r = c <= 0; break;
- case C_gt: r = c > 0; break;
- case C_ge: r = c >= 0; break;
-#endif
- default: r = 0; break;
- }
- return r;
-}
-#else
-static inline char *keyval(char *head, int isptr, enum comp *comp)
-{
- *comp = C_no;
- return NULL;
-}
-static inline int compare(struct json_object *o, char *value, enum comp k)
-{
- return 0;
-}
-#endif
-
-static char *key(char **head, int isptr)
-{
- char *r, *i, *w, c;
-
- c = *(i = *head);
- if (!c)
- r = NULL;
- else {
- r = w = i;
-#if !defined(NO_JSON_POINTER_EXTENSION_FOR_MUSTACH)
- if (isptr)
- while (c && c != '/') {
- if (c == '~')
- switch (i[1]) {
- case '1': c = '/'; /*@fallthrough@*/
- case '0': i++;
- }
- *w++ = c;
- c = *++i;
- }
- else
-#endif
- while (c && c != '.') {
- if (c == '\\' && (i[1] == '.' || i[1] == '\\'))
- c = *++i;
- *w++ = c;
- c = *++i;
- }
- *w = 0;
- *head = i + !!c;
- }
- return r;
-}
-
-static struct json_object *find(struct expl *e, const char *name)
-{
- int i, isptr;
- struct json_object *o, *no;
- char *n, *c, *v;
- enum comp k;
-
- n = alloca(1 + strlen(name));
- strcpy(n, name);
- isptr = 0;
-#if !defined(NO_JSON_POINTER_EXTENSION_FOR_MUSTACH)
- isptr = n[0] == '/';
- n += isptr;
-#endif
-
- v = keyval(n, isptr, &k);
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- e->found_objiter = 0;
-#endif
-#if !defined(NO_SINGLE_DOT_EXTENSION_FOR_MUSTACH)
- if (n[0] == '.' && !n[1]) {
- /* case of . alone */
- o = e->stack[e->depth].obj;
- } else
-#endif
- {
- c = key(&n, isptr);
- if (c == NULL)
- return NULL;
- o = NULL;
- i = e->depth;
- while (i >= 0 && !json_object_object_get_ex(e->stack[i].obj, c, &o))
- i--;
- if (i < 0) {
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- o = e->stack[e->depth].obj;
- if (c[0] == '*' && !c[1] && !v && !key(&n, isptr) && json_object_is_type(o, json_type_object)) {
- e->found_objiter = 1;
- return o;
- }
-#endif
- return NULL;
- }
- c = key(&n, isptr);
- while(c) {
- if (!json_object_object_get_ex(o, c, &no)) {
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- if (c[0] == '*' && !c[1] && !v && !key(&n, isptr) && json_object_is_type(o, json_type_object)) {
- e->found_objiter = 1;
- return o;
- }
-#endif
- return NULL;
- }
- o = no;
- c = key(&n, isptr);
- }
- }
- if (v) {
- i = v[0] == '!';
- if (i == evalcomp(o, &v[i], k))
- o = NULL;
- }
- return o;
-}
-
-static int start(void *closure)
-{
- struct expl *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 write(struct expl *e, const char *buffer, size_t size, FILE *file)
-{
- return e->writecb(file, buffer, size);
-}
-
-static int emituw(void *closure, const char *buffer, size_t size, int escape, FILE *file)
-{
- struct expl *e = closure;
- if (!escape)
- write(e, buffer, size, file);
- else
- do {
- switch(*buffer) {
- case '<': write(e, "&lt;", 4, file); break;
- case '>': write(e, "&gt;", 4, file); break;
- case '&': write(e, "&amp;", 5, file); break;
- default: write(e, buffer, 1, file); break;
- }
- buffer++;
- } while(--size);
- return MUSTACH_OK;
-}
-
-static const char *item(struct expl *e, const char *name)
-{
- struct json_object *o;
- const char *s;
-
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- if (name[0] == '*' && !name[1] && e->stack[e->depth].is_objiter)
- s = json_object_iter_peek_name(&e->stack[e->depth].biter);
- else
- s = (o = find(e, name)) && !e->found_objiter ? json_object_get_string(o) : NULL;
-#else
- s = (o = find(e, name)) ? json_object_get_string(o) : NULL;
-#endif
- return s;
-}
-
-static int enter(void *closure, const char *name)
-{
- struct expl *e = closure;
- struct json_object *o = find(e, name);
- if (++e->depth >= MUSTACH_MAX_DEPTH)
- return MUSTACH_ERROR_TOO_DEEP;
- 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) {
- e->depth--;
- return 0;
- }
- e->stack[e->depth].cont = o;
- e->stack[e->depth].obj = json_object_array_get_idx(o, 0);
- e->stack[e->depth].index = 0;
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- e->stack[e->depth].is_objiter = 0;
- } else if (json_object_is_type(o, json_type_object) && e->found_objiter) {
- e->stack[e->depth].biter = json_object_iter_begin(o);
- e->stack[e->depth].eiter = json_object_iter_end(o);
- if (json_object_iter_equal(&e->stack[e->depth].biter, &e->stack[e->depth].eiter)) {
- e->depth--;
- return 0;
- }
- e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].biter);
- e->stack[e->depth].cont = o;
- e->stack[e->depth].is_objiter = 1;
-#endif
- } 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;
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- e->stack[e->depth].is_objiter = 0;
-#endif
- } else {
- e->depth--;
- return 0;
- }
- return 1;
-}
-
-static int next(void *closure)
-{
- struct expl *e = closure;
- if (e->depth <= 0)
- return MUSTACH_ERROR_CLOSING;
-#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH)
- if (e->stack[e->depth].is_objiter) {
- json_object_iter_next(&e->stack[e->depth].biter);
- if (json_object_iter_equal(&e->stack[e->depth].biter, &e->stack[e->depth].eiter))
- return 0;
- e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].biter);
- return 1;
- }
-#endif
- 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;
-}
-
-#if !defined(NO_INCLUDE_PARTIAL_FALLBACK)
-static int get_partial_from_file(const char *name, struct mustach_sbuf *sbuf)
-{
- static char extension[] = INCLUDE_PARTIAL_EXTENSION;
- size_t s;
- long pos;
- FILE *file;
- char *path, *buffer;
-
- /* allocate path */
- s = strlen(name);
- path = malloc(s + sizeof extension);
- if (path == NULL)
- return MUSTACH_ERROR_SYSTEM;
-
- /* try without extension first */
- memcpy(path, name, s + 1);
- file = fopen(path, "r");
- if (file == NULL) {
- memcpy(&path[s], extension, sizeof extension);
- file = fopen(path, "r");
- }
- free(path);
-
- /* if file opened */
- if (file != NULL) {
- /* compute file size */
- if (fseek(file, 0, SEEK_END) >= 0
- && (pos = ftell(file)) >= 0
- && fseek(file, 0, SEEK_SET) >= 0) {
- /* allocate value */
- s = (size_t)pos;
- buffer = malloc(s + 1);
- if (buffer != NULL) {
- /* read value */
- if (1 == fread(buffer, s, 1, file)) {
- /* force zero at end */
- sbuf->value = buffer;
- buffer[s] = 0;
- sbuf->freecb = free;
- fclose(file);
- return MUSTACH_OK;
- }
- free(buffer);
- }
- }
- fclose(file);
- }
- return MUSTACH_ERROR_SYSTEM;
-}
-
-static int partial(void *closure, const char *name, struct mustach_sbuf *sbuf)
-{
- struct expl *e = closure;
- const char *s;
-
- s = item(e, name);
- if (s)
- sbuf->value = s;
- else if (get_partial_from_file(name, sbuf) < 0)
- sbuf->value = "";
- return MUSTACH_OK;
-}
-#endif
-
-static int get(void *closure, const char *name, struct mustach_sbuf *sbuf)
-{
- struct expl *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,
-#if !defined(NO_INCLUDE_PARTIAL_FALLBACK)
- .partial = partial,
-#else
- .partial =NULL,
-#endif
- .get = get,
- .emit = NULL,
- .stop = NULL
-};
-
-static struct mustach_itf itfuw = {
- .start = start,
- .put = NULL,
- .enter = enter,
- .next = next,
- .leave = leave,
-#if !defined(NO_INCLUDE_PARTIAL_FALLBACK)
- .partial = partial,
-#else
- .partial =NULL,
-#endif
- .get = get,
- .emit = emituw,
- .stop = NULL
-};
-
-int fmustach_json_c(const char *template, struct json_object *root, FILE *file)
-{
- struct expl e;
- e.root = root;
- return fmustach(template, &itf, &e, file);
-}
-
-int fdmustach_json_c(const char *template, struct json_object *root, int fd)
-{
- struct expl e;
- e.root = root;
- return fdmustach(template, &itf, &e, fd);
-}
-
-int mustach_json_c(const char *template, struct json_object *root, char **result, size_t *size)
-{
- struct expl e;
- e.root = root;
- e.writecb = NULL;
- return mustach(template, &itf, &e, result, size);
-}
-
-int umustach_json_c(const char *template, struct json_object *root, mustach_json_c_write_cb writecb, void *closure)
-{
- struct expl e;
- e.root = root;
- e.writecb = writecb;
- return fmustach(template, &itfuw, &e, closure);
-}
-
diff --git a/src/mustach/test_mustach_jansson.c b/src/mustach/test_mustach_jansson.c
new file mode 100644
index 00000000..8f1e37b6
--- /dev/null
+++ b/src/mustach/test_mustach_jansson.c
@@ -0,0 +1,80 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or
+ (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with TALER; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file mustac/test_mustach_jansson.c
+ * @brief testcase to test the mustach/jansson integration
+ * @author Florian Dold
+ */
+#include "platform.h"
+#include "mustach-jansson.h"
+
+void
+assert_template (const char *template, json_t *root, const char *expected)
+{
+ char *r;
+ size_t sz;
+
+ GNUNET_assert (0 == mustach_jansson (template, root, &r, &sz));
+ GNUNET_assert (0 == strcmp (r, expected));
+ GNUNET_free (r);
+}
+
+int
+main (int argc,
+ char *const *argv)
+{
+ json_t *root = json_object ();
+ json_t *arr = json_array ();
+ json_t *obj = json_object();
+ /* test 1 */
+ char *t1 = "hello world";
+ char *x1 = "hello world";
+ /* test 2 */
+ char *t2 = "hello {{ v1 }}";
+ char *x2 = "hello world";
+ /* test 3 */
+ char *t3 = "hello {{ v3.x }}";
+ char *x3 = "hello baz";
+ /* test 4 */
+ char *t4 = "hello {{# v2 }}{{ . }}{{/ v2 }}";
+ char *x4 = "hello foobar";
+ /* test 5 */
+ char *t5 = "hello {{# v3 }}{{ y }}/{{ x }}{{ z }}{{/ v3 }}";
+ char *x5 = "hello quux/baz";
+
+ json_object_set_new (root, "v1", json_string ("world"));
+ json_array_append_new (arr, json_string ("foo"));
+ json_array_append_new (arr, json_string ("bar"));
+ json_object_set_new (root, "v2", arr);
+ json_object_set_new (root, "v3", obj);
+ json_object_set_new (obj, "x", json_string ("baz"));
+ json_object_set_new (obj, "y", json_string ("quux"));
+
+ assert_template (t1, root, x1);
+ assert_template (t2, root, x2);
+ assert_template (t3, root, x3);
+ assert_template (t4, root, x4);
+ assert_template (t5, root, x5);
+
+ json_decref (root);
+
+ return 0;
+}
+