summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-08-21 16:18:06 +0530
committerFlorian Dold <florian.dold@gmail.com>2020-08-21 16:18:06 +0530
commit87a93ed1607cdc5a5e3ec8e0e37d6c288d4cf5cc (patch)
tree35b1bbb708c7abb1fa7ea420a14802bf6e7de7c9 /src
parent1684fc64333b97aee8e6128e96ff4920e494e2e0 (diff)
downloadmerchant-87a93ed1607cdc5a5e3ec8e0e37d6c288d4cf5cc.tar.gz
merchant-87a93ed1607cdc5a5e3ec8e0e37d6c288d4cf5cc.tar.bz2
merchant-87a93ed1607cdc5a5e3ec8e0e37d6c288d4cf5cc.zip
template bangs
Diffstat (limited to 'src')
-rw-r--r--src/mustach/mustach-jansson.c167
-rw-r--r--src/mustach/test_mustach_jansson.c38
2 files changed, 176 insertions, 29 deletions
diff --git a/src/mustach/mustach-jansson.c b/src/mustach/mustach-jansson.c
index afb8f823..2aed5829 100644
--- a/src/mustach/mustach-jansson.c
+++ b/src/mustach/mustach-jansson.c
@@ -53,6 +53,15 @@ struct Context
bool is_objiter;
};
+enum Bang
+{
+ BANG_NONE,
+ BANG_I18N,
+ BANG_STRINGIFY,
+ BANG_AMOUNT_CURRENCY,
+ BANG_AMOUNT_DECIMAL,
+};
+
struct JanssonClosure
{
json_t *root;
@@ -68,16 +77,25 @@ struct JanssonClosure
* The last object we found should be iterated over.
*/
bool found_iter;
+
+ /**
+ * Last bang we found.
+ */
+ enum Bang found_bang;
+
+ /**
+ * Language for i18n lookups.
+ */
+ const char *lang;
};
+
static json_t *
-find (struct JanssonClosure *e, const char *name)
+walk (json_t *obj, const char *path)
{
- json_t *obj = e->stack[e->depth].obj;
- char *nd = GNUNET_strdup (name);
- char *p = nd;
char *saveptr = NULL;
-
+ char *sp = GNUNET_strdup (path);
+ char *p = sp;
while (true)
{
char *tok = strtok_r (p, ".", &saveptr);
@@ -88,8 +106,51 @@ find (struct JanssonClosure *e, const char *name)
break;
p = NULL;
}
+ GNUNET_free (sp);
+ return obj;
+}
+
+
+static json_t *
+find (struct JanssonClosure *e, const char *name)
+{
+ json_t *obj = NULL;
+ char *path = GNUNET_strdup (name);
+ char *bang;
+
+ bang = strchr (path, '!');
+
+ e->found_bang = BANG_NONE;
+
+ if (NULL != bang)
+ {
+ *bang = 0;
+ bang++;
+
+ if (0 == strcmp (bang, "i18n"))
+ e->found_bang = BANG_I18N;
+ else if (0 == strcmp(bang, "stringify"))
+ e->found_bang = BANG_STRINGIFY;
+ else if (0 == strcmp(bang, "amount_decimal"))
+ e->found_bang = BANG_AMOUNT_CURRENCY;
+ else if (0 == strcmp(bang, "amount_currency"))
+ e->found_bang = BANG_AMOUNT_DECIMAL;
+ }
+
+ if (BANG_I18N == e->found_bang && NULL != e->lang)
+ {
+ char *aug_path;
+ GNUNET_asprintf (&aug_path, "%s_i18n.%s", path, e->lang);
+ obj = walk (e->stack[e->depth].obj, aug_path);
+ GNUNET_free (aug_path);
+ }
+
+ if (NULL == obj)
+ {
+ obj = walk (e->stack[e->depth].obj, path);
+ }
- GNUNET_free (nd);
+ GNUNET_free (path);
return obj;
}
@@ -104,6 +165,7 @@ start(void *closure)
e->stack[0].obj = e->root;
e->stack[0].index = 0;
e->stack[0].count = 1;
+ e->lang = json_string_value (json_object_get (e->root, "$language"));
return MUSTACH_OK;
}
@@ -139,21 +201,6 @@ emituw (void *closure, const char *buffer, size_t size, int escape, FILE *file)
}
-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)
{
@@ -230,7 +277,8 @@ next (void *closure)
return 1;
}
-static int leave (void *closure)
+static int
+leave (void *closure)
{
struct JanssonClosure *e = closure;
if (e->depth <= 0)
@@ -239,16 +287,77 @@ static int leave (void *closure)
return 0;
}
-static int get (void *closure, const char *name, struct mustach_sbuf *sbuf)
+static void
+freecb (void *v)
+{
+ free (v);
+}
+
+static int
+get (void *closure, const char *name, struct mustach_sbuf *sbuf)
{
struct JanssonClosure *e = closure;
- const char *s;
+ json_t *obj;
- s = item (e, name);
- if (s)
- sbuf->value = s;
- else
- sbuf->value = "";
+ if ( (0 == strcmp (name, "*") ) &&
+ (e->stack[e->depth].is_objiter ) )
+ {
+ sbuf->value = json_object_iter_key (e->stack[e->depth].iter);
+ return MUSTACH_OK;
+ }
+ obj = find (e, name);
+ if (NULL != obj)
+ {
+ switch (e->found_bang)
+ {
+ case BANG_I18N:
+ case BANG_NONE:
+ {
+ const char *s = json_string_value (obj);
+ if (NULL != s)
+ {
+ sbuf->value = s;
+ return MUSTACH_OK;
+ }
+ }
+ break;
+ case BANG_STRINGIFY:
+ sbuf->value = json_dumps (obj, JSON_INDENT (2));
+ sbuf->freecb = freecb;
+ return MUSTACH_OK;
+ case BANG_AMOUNT_DECIMAL:
+ {
+ char *s;
+ char *c;
+ if (!json_is_string (obj))
+ break;
+ s = strdup (json_string_value (obj));
+ c = strchr (s, ':');
+ if (NULL != c)
+ *c = 0;
+ sbuf->value = s;
+ sbuf->freecb = freecb;
+ return MUSTACH_OK;
+ }
+ break;
+ case BANG_AMOUNT_CURRENCY:
+ {
+ const char *s;
+ if (!json_is_string (obj))
+ break;
+ s = json_string_value (obj);
+ s = strchr (s, ':');
+ if (NULL == s)
+ break;
+ sbuf->value = s + 1;
+ return MUSTACH_OK;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ sbuf->value = "";
return MUSTACH_OK;
}
diff --git a/src/mustach/test_mustach_jansson.c b/src/mustach/test_mustach_jansson.c
index 8f1e37b6..a211d87c 100644
--- a/src/mustach/test_mustach_jansson.c
+++ b/src/mustach/test_mustach_jansson.c
@@ -43,6 +43,7 @@ main (int argc,
json_t *root = json_object ();
json_t *arr = json_array ();
json_t *obj = json_object();
+ json_t *contract;
/* test 1 */
char *t1 = "hello world";
char *x1 = "hello world";
@@ -58,22 +59,59 @@ main (int argc,
/* test 5 */
char *t5 = "hello {{# v3 }}{{ y }}/{{ x }}{{ z }}{{/ v3 }}";
char *x5 = "hello quux/baz";
+ /* test 6 */
+ char *t6 = "hello {{ v2!stringify }}";
+ char *x6 = "hello [\n \"foo\",\n \"bar\"\n]";
+ /* test 7 */
+ char *t7 = "amount: {{ amt!amount_decimal }} {{ amt!amount_currency }}";
+ char *x7 = "amount: 123.00 EUR";
+
+ /* contract test 8 (contract) */
+ char *tc = "summary: {{ summary!i18n }}";
+ char *xc_en = "summary: ENGLISH";
+ char *xc_de = "summary: DEUTSCH";
+ char *xc_fr = "summary: FRANCAISE";
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 (root, "amt", json_string("EUR:123.00"));
json_object_set_new (obj, "x", json_string ("baz"));
json_object_set_new (obj, "y", json_string ("quux"));
+ contract = json_pack("{ s:s, s:{s:s, s:s}}",
+ "summary",
+ "ENGLISH",
+ "summary_i18n",
+ "de",
+ "DEUTSCH",
+ "fr",
+ "FRANCAISE");
+ GNUNET_assert (NULL != contract);
+
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);
+ assert_template (t6, root, x6);
+ assert_template (t7, root, x7);
+
+ assert_template (tc, contract, xc_en);
+
+ json_object_set_new (contract, "$language", json_string ("de"));
+ assert_template (tc, contract, xc_de);
+
+ json_object_set_new (contract, "$language", json_string ("fr"));
+ assert_template (tc, contract, xc_fr);
+
+ json_object_set_new (contract, "$language", json_string ("it"));
+ assert_template (tc, contract, xc_en);
json_decref (root);
+ json_decref (contract);
return 0;
}