diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-08-16 14:06:46 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-08-16 14:06:46 +0200 |
commit | c1d0a7d2e64fd7c6bd041a5259cf212b3aabd414 (patch) | |
tree | 8b5c4d05187336048f13c1e500501f6e6bbda727 | |
parent | 19010a2f6d658e78ded8abb02995d9154d22bbf3 (diff) |
-move templating logic to libtalertemplating of exchange
59 files changed, 44 insertions, 3538 deletions
diff --git a/configure.ac b/configure.ac index 79130ef5..7286e277 100644 --- a/configure.ac +++ b/configure.ac @@ -395,7 +395,6 @@ src/backenddb/Makefile src/include/Makefile src/lib/Makefile src/merchant-tools/Makefile -src/mustach/Makefile src/testing/Makefile ]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index cb071d95..984c780f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,3 +1,3 @@ # This Makefile is in the public domain AM_CPPFLAGS = -I$(top_srcdir)/src/include -SUBDIRS = include mustach backenddb backend lib testing merchant-tools +SUBDIRS = include backenddb backend lib testing merchant-tools diff --git a/src/backend/Makefile.am b/src/backend/Makefile.am index 073fff5e..2bd25251 100644 --- a/src/backend/Makefile.am +++ b/src/backend/Makefile.am @@ -107,12 +107,11 @@ taler_merchant_httpd_SOURCES = \ taler-merchant-httpd_spa.c \ taler-merchant-httpd_spa.h \ taler-merchant-httpd_statics.c \ - taler-merchant-httpd_statics.h \ - taler-merchant-httpd_templating.c \ - taler-merchant-httpd_templating.h + taler-merchant-httpd_statics.h taler_merchant_httpd_LDADD = \ $(top_builddir)/src/backenddb/libtalermerchantdb.la \ -ltalerexchange \ + -ltalertemplating \ -ltalermhd \ -ltalerbank \ -ltalerjson \ @@ -123,7 +122,6 @@ taler_merchant_httpd_LDADD = \ -lgnunetcurl \ -lgnunetjson \ -lgnunetutil \ - $(top_builddir)/src/mustach/libmustach.a \ @QR_LIBS@ \ $(XLIB) taler_merchant_httpd_CFLAGS = \ diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index d5bc19d6..d95dafdc 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -25,6 +25,7 @@ #include <taler/taler_dbevents.h> #include <taler/taler_bank_service.h> #include <taler/taler_mhd_lib.h> +#include <taler/taler_templating_lib.h> #include <taler/taler_exchange_service.h> #include "taler-merchant-httpd_auditors.h" #include "taler-merchant-httpd_config.h" @@ -70,7 +71,7 @@ #include "taler-merchant-httpd_reserves.h" #include "taler-merchant-httpd_spa.h" #include "taler-merchant-httpd_statics.h" -#include "taler-merchant-httpd_templating.h" + /** * Fixme: document. @@ -306,6 +307,7 @@ do_shutdown (void *cls) GNUNET_CONTAINER_multihashmap_destroy (TMH_by_id_map); TMH_by_id_map = NULL; } + TALER_TEMPLATING_done (); } @@ -1140,7 +1142,7 @@ url_handler (void *cls, MHD_HTTP_METHOD_HEAD)) method = MHD_HTTP_METHOD_GET; /* MHD will deal with the rest */ - + /* Find out the merchant backend instance for the request. * If there is an instance, remove the instance specification * from the beginning of the request URL. */ @@ -1443,12 +1445,12 @@ url_handler (void *cls, &hc->instance->auth.auth_salt, &hc->instance->auth.auth_hash)); else /* Are the credentials provided OK for CLI override? */ - auth_ok |= ( use_default && - (NULL != TMH_default_auth) && - (NULL != auth) && - (! auth_malformed) && - (0 == strcmp (auth, - TMH_default_auth)) ); + auth_ok |= (use_default && + (NULL != TMH_default_auth) && + (NULL != auth) && + (! auth_malformed) && + (0 == strcmp (auth, + TMH_default_auth)) ); if (! auth_ok) { if (auth_malformed) @@ -1778,7 +1780,7 @@ run (void *cls, "merchant", "FORCE_AUDIT")) TMH_force_audit = GNUNET_YES; - TMH_templating_init (); + TALER_TEMPLATING_init ("merchant"); if (GNUNET_OK != TMH_spa_init ()) { diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c index 53260f67..5d229fc2 100644 --- a/src/backend/taler-merchant-httpd_get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_get-orders-ID.c @@ -25,12 +25,12 @@ #include <taler/taler_signatures.h> #include <taler/taler_dbevents.h> #include <taler/taler_json_lib.h> +#include <taler/taler_templating_lib.h> #include <taler/taler_exchange_service.h> #include "taler-merchant-httpd_exchanges.h" #include "taler-merchant-httpd_get-orders-ID.h" #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_qr.h" -#include "taler-merchant-httpd_templating.h" /** * How often do we retry DB transactions on serialization failures? @@ -691,12 +691,12 @@ send_pay_request (struct GetOrderData *god, qr), GNUNET_JSON_pack_string ("order_summary", get_order_summary (god))); - res = TMH_return_from_template (god->sc.con, - MHD_HTTP_PAYMENT_REQUIRED, - "request_payment", - god->hc->instance->settings.id, - taler_pay_uri, - context); + res = TALER_TEMPLATING_reply (god->sc.con, + MHD_HTTP_PAYMENT_REQUIRED, + "request_payment", + god->hc->instance->settings.id, + taler_pay_uri, + context); if (GNUNET_SYSERR == res) { GNUNET_break (0); @@ -1460,12 +1460,12 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, uri), GNUNET_JSON_pack_string ("taler_refund_qrcode_svg", qr)); - res = TMH_return_from_template (god->sc.con, - MHD_HTTP_OK, - "offer_refund", - hc->instance->settings.id, - uri, - context); + res = TALER_TEMPLATING_reply (god->sc.con, + MHD_HTTP_OK, + "offer_refund", + hc->instance->settings.id, + uri, + context); json_decref (context); } GNUNET_free (uri); @@ -1484,12 +1484,12 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh, &god->refund_amount), TALER_JSON_pack_amount ("refund_taken", &god->refund_taken)); - res = TMH_return_from_template (god->sc.con, - MHD_HTTP_OK, - "show_order_details", - hc->instance->settings.id, - NULL, - context); + res = TALER_TEMPLATING_reply (god->sc.con, + MHD_HTTP_OK, + "show_order_details", + hc->instance->settings.id, + NULL, + context); json_decref (context); } if (GNUNET_SYSERR == res) diff --git a/src/backend/taler-merchant-httpd_get-tips-ID.c b/src/backend/taler-merchant-httpd_get-tips-ID.c index f427b168..0486de3e 100644 --- a/src/backend/taler-merchant-httpd_get-tips-ID.c +++ b/src/backend/taler-merchant-httpd_get-tips-ID.c @@ -23,10 +23,11 @@ #include <jansson.h> #include <taler/taler_signatures.h> #include <taler/taler_json_lib.h> +#include <taler/taler_templating_lib.h> #include "taler-merchant-httpd_get-tips-ID.h" #include "taler-merchant-httpd_mhd.h" #include "taler-merchant-httpd_qr.h" -#include "taler-merchant-httpd_templating.h" + char * TMH_make_taler_tip_uri (struct MHD_Connection *con, @@ -249,18 +250,18 @@ TMH_get_tips_ID (const struct TMH_RequestHandler *rh, uri), GNUNET_JSON_pack_string ("taler_tip_qrcode_svg", qr)); - ret = TMH_return_from_template (connection, - ( (0 == remaining.value) && - (0 == remaining.fraction) ) + ret = TALER_TEMPLATING_reply (connection, + ( (0 == remaining.value) && + (0 == remaining.fraction) ) ? MHD_HTTP_GONE : MHD_HTTP_OK, - ( (0 == remaining.value) && - (0 == remaining.fraction) ) + ( (0 == remaining.value) && + (0 == remaining.fraction) ) ? "depleted_tip" : "offer_tip", - hc->instance->settings.id, - uri, - context); + hc->instance->settings.id, + uri, + context); json_decref (context); } GNUNET_free (tip_status_url); diff --git a/src/backend/taler-merchant-httpd_statics.c b/src/backend/taler-merchant-httpd_statics.c index 69331087..0cf54713 100644 --- a/src/backend/taler-merchant-httpd_statics.c +++ b/src/backend/taler-merchant-httpd_statics.c @@ -22,8 +22,8 @@ #include <gnunet/gnunet_util_lib.h> #include <taler/taler_util.h> #include <taler/taler_mhd_lib.h> +#include <taler/taler_templating_lib.h> #include "taler-merchant-httpd_statics.h" -#include "../mustach/mustach.h" #include <gnunet/gnunet_mhd_compat.h> diff --git a/src/backend/taler-merchant-httpd_templating.c b/src/backend/taler-merchant-httpd_templating.c deleted file mode 100644 index 9d7766b9..00000000 --- a/src/backend/taler-merchant-httpd_templating.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 taler-merchant-httpd_templating.c - * @brief logic to load and complete HTML templates - * @author Christian Grothoff - */ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <taler/taler_util.h> -#include <taler/taler_mhd_lib.h> -#include "taler-merchant-httpd_templating.h" -#include "../mustach/mustach.h" -#include "../mustach/mustach-jansson.h" -#include <gnunet/gnunet_mhd_compat.h> - - -/** - * Entry in a key-value array we use to cache templates. - */ -struct TVE -{ - /** - * A name, used as the key. NULL for the last entry. - */ - char *name; - - /** - * Language the template is in. - */ - char *lang; - - /** - * 0-terminated (!) file data to return for @e name and @e lang. - */ - char *value; - -}; - - -/** - * Array of templates loaded into RAM. - */ -static struct TVE *loaded; - -/** - * Length of the #loaded array. - */ -static unsigned int loaded_length; - - -/** - * Load Mustach template into memory. Note that we intentionally cache - * failures, that is if we ever failed to load a template, we will never try - * again. - * - * @param connection the connection we act upon - * @param name name of the template file to load - * (MUST be a 'static' string in memory!) - * @return NULL on error, otherwise the template - */ -static const char * -lookup_template (struct MHD_Connection *connection, - const char *name) -{ - struct TVE *best = NULL; - const char *lang; - - lang = MHD_lookup_connection_value (connection, - MHD_HEADER_KIND, - MHD_HTTP_HEADER_ACCEPT_LANGUAGE); - if (NULL == lang) - lang = "en"; - /* find best match by language */ - for (unsigned int i = 0; i<loaded_length; i++) - { - if (0 != strcmp (loaded[i].name, - name)) - continue; /* does not match by name */ - if ( (NULL == best) || - (TALER_language_matches (lang, - loaded[i].lang) > - TALER_language_matches (lang, - best->lang) ) ) - best = &loaded[i]; - } - if (NULL == best) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No templates found in `%s'\n", - name); - return NULL; - } - return best->value; -} - -/** - * Get the base URL for static resources. - * - * @param con the MHD connection - * @param instance_id the instance ID - * @returns the static files base URL, guaranteed - * to have a trailing slash. - */ -static char * -make_static_url (struct MHD_Connection *con, - const char *instance_id) -{ - const char *host; - const char *forwarded_host; - const char *uri_path; - struct GNUNET_Buffer buf = { 0 }; - - host = MHD_lookup_connection_value (con, - MHD_HEADER_KIND, - "Host"); - forwarded_host = MHD_lookup_connection_value (con, - MHD_HEADER_KIND, - "X-Forwarded-Host"); - - uri_path = MHD_lookup_connection_value (con, - MHD_HEADER_KIND, - "X-Forwarded-Prefix"); - if (NULL != forwarded_host) - host = forwarded_host; - - if (NULL == host) - { - GNUNET_break (0); - return NULL; - } - - GNUNET_assert (NULL != instance_id); - - if (GNUNET_NO == TALER_mhd_is_https (con)) - GNUNET_buffer_write_str (&buf, - "http://"); - else - GNUNET_buffer_write_str (&buf, - "https://"); - GNUNET_buffer_write_str (&buf, - host); - if (NULL != uri_path) - GNUNET_buffer_write_path (&buf, - uri_path); - if (0 != strcmp ("default", - instance_id)) - { - GNUNET_buffer_write_path (&buf, - "instances"); - GNUNET_buffer_write_path (&buf, - instance_id); - } - GNUNET_buffer_write_path (&buf, - "static/"); - return GNUNET_buffer_reap_str (&buf); -} - - - - -/** - * Load a @a template and substitute using @a root, returning - * the result to the @a connection with the given - * @a http_status code. - * - * @param connection the connection we act upon - * @param http_status code to use on success - * @param template basename of the template to load - * @param instance_id instance ID, used to compute static files URL - * @param taler_uri value for "Taler:" header to set, or NULL - * @param root JSON object to pass as the root context - * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, - * #GNUNET_SYSERR on failure (to queue an error) - */ -enum GNUNET_GenericReturnValue -TMH_return_from_template (struct MHD_Connection *connection, - unsigned int http_status, - const char *template, - const char *instance_id, - const char *taler_uri, - json_t *root) -{ - struct MHD_Response *reply; - char *body; - size_t body_size; - - { - const char *tmpl; - int eno; - - tmpl = lookup_template (connection, - template); - if (NULL == tmpl) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Failed to load template `%s'\n", - template); - if (MHD_YES != - TALER_MHD_reply_with_error (connection, - MHD_HTTP_NOT_ACCEPTABLE, - TALER_EC_MERCHANT_GENERIC_FAILED_TO_LOAD_TEMPLATE, - template)) - return GNUNET_SYSERR; - return GNUNET_NO; - } - /* Add default values to the context */ - { - char *static_url = make_static_url (connection, - instance_id); - json_object_set (root, - "static_url", - json_string (static_url)); - GNUNET_free (static_url); - } - if (0 != - (eno = mustach_jansson (tmpl, - root, - &body, - &body_size))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "mustach failed on template `%s' with error %d\n", - template, - eno); - if (MHD_YES != - TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_MERCHANT_GENERIC_FAILED_TO_EXPAND_TEMPLATE, - template)) - return GNUNET_SYSERR; - return GNUNET_NO; - } - } - - /* try to compress reply if client allows it */ - { - bool compressed = false; - - if (MHD_YES == - TALER_MHD_can_compress (connection)) - { - compressed = TALER_MHD_body_compress ((void **) &body, - &body_size); - } - reply = MHD_create_response_from_buffer (body_size, - body, - MHD_RESPMEM_MUST_FREE); - if (NULL == reply) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (compressed) - { - if (MHD_NO == - MHD_add_response_header (reply, - MHD_HTTP_HEADER_CONTENT_ENCODING, - "deflate")) - { - GNUNET_break (0); - MHD_destroy_response (reply); - return GNUNET_SYSERR; - } - } - } - - /* Add standard headers */ - if (NULL != taler_uri) - GNUNET_break (MHD_NO != - MHD_add_response_header (reply, - "Taler", - taler_uri)); - GNUNET_break (MHD_NO != - MHD_add_response_header (reply, - MHD_HTTP_HEADER_CONTENT_TYPE, - "text/html")); - - /* Actually return reply */ - { - MHD_RESULT ret; - - ret = MHD_queue_response (connection, - http_status, - reply); - MHD_destroy_response (reply); - if (MHD_NO == ret) - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Function called with a template's filename. - * - * @param cls closure - * @param filename complete filename (absolute path) - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -static int -load_template (void *cls, - const char *filename) -{ - char *lang; - char *end; - int fd; - struct stat sb; - char *map; - const char *name; - - if ('.' == filename[0]) - return GNUNET_OK; - - name = strrchr (filename, - '/'); - if (NULL == name) - name = filename; - else - name++; - lang = strchr (name, - '.'); - if (NULL == lang) - return GNUNET_OK; /* name must include .$LANG */ - lang++; - end = strchr (lang, - '.'); - if ( (NULL == end) || - (0 != strcmp (end, - ".must")) ) - return GNUNET_OK; /* name must end with '.must' */ - - /* finally open template */ - fd = open (filename, - O_RDONLY); - if (-1 == fd) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - filename); - - return GNUNET_SYSERR; - } - if (0 != - fstat (fd, - &sb)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "open", - filename); - GNUNET_break (0 == close (fd)); - return GNUNET_OK; - } - map = GNUNET_malloc_large (sb.st_size + 1); - if (NULL == map) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, - "malloc"); - GNUNET_break (0 == close (fd)); - return GNUNET_SYSERR; - } - if (sb.st_size != - read (fd, - map, - sb.st_size)) - { - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, - "read", - filename); - GNUNET_break (0 == close (fd)); - return GNUNET_OK; - } - GNUNET_break (0 == close (fd)); - GNUNET_array_grow (loaded, - loaded_length, - loaded_length + 1); - loaded[loaded_length - 1].name = GNUNET_strndup (name, - (lang - 1) - name); - loaded[loaded_length - 1].lang = GNUNET_strndup (lang, - end - lang); - loaded[loaded_length - 1].value = map; - return GNUNET_OK; -} - - -/** - * Preload templates. - */ -int -TMH_templating_init () -{ - char *dn; - int ret; - - { - char *path; - - path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR); - if (NULL == path) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - GNUNET_asprintf (&dn, - "%s/merchant/templates/", - path); - GNUNET_free (path); - } - ret = GNUNET_DISK_directory_scan (dn, - &load_template, - NULL); - GNUNET_free (dn); - if (-1 == ret) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Nicely shut down. - */ -void __attribute__ ((destructor)) -templating_fini () -{ - for (unsigned int i = 0; i<loaded_length; i++) - { - GNUNET_free (loaded[i].name); - GNUNET_free (loaded[i].lang); - GNUNET_free (loaded[i].value); - } - GNUNET_array_grow (loaded, - loaded_length, - 0); -} diff --git a/src/backend/taler-merchant-httpd_templating.h b/src/backend/taler-merchant-httpd_templating.h deleted file mode 100644 index a1c2e05a..00000000 --- a/src/backend/taler-merchant-httpd_templating.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 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 taler-merchant-httpd_templating.h - * @brief logic to load and complete HTML templates - * @author Christian Grothoff - */ -#ifndef TALER_MERCHANT_HTTPD_TEMPLATING_H -#define TALER_MERCHANT_HTTPD_TEMPLATING_H - -#include <microhttpd.h> - - -/** - * Load a @a template and substitute using @a root, returning - * the result to the @a connection with the given - * @a http_status code. - * - * @param connection the connection we act upon - * @param http_status code to use on success - * @param template basename of the template to load - * @param instance_id instance ID, used to compute static files URL - * @param taler_uri value for "Taler:" header to set, or NULL - * @param root JSON object to pass as the root context - * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, - * #GNUNET_SYSERR on failure (to queue an error) - */ -enum GNUNET_GenericReturnValue -TMH_return_from_template (struct MHD_Connection *connection, - unsigned int http_status, - const char *template, - const char *instance_id, - const char *taler_uri, - json_t *root); - -/** - * Preload templates. - */ -int -TMH_templating_init (void); - - -#endif diff --git a/src/mustach/.gitignore b/src/mustach/.gitignore deleted file mode 100644 index b2bf6ef9..00000000 --- a/src/mustach/.gitignore +++ /dev/null @@ -1 +0,0 @@ -test_mustach_jansson diff --git a/src/mustach/AUTHORS b/src/mustach/AUTHORS deleted file mode 100644 index 2fcc6043..00000000 --- a/src/mustach/AUTHORS +++ /dev/null @@ -1,23 +0,0 @@ -Main author: - José Bollo <jobol@nonadev.net> - -Contributors: - Abhishek Mishra - Atlas - Harold L Marzan - Lailton Fernando Mariano - Sami Kerola - Sijmen J. Mulder - Tomasz Sieprawski - -Packagers: - pkgsrc: Sijmen J. Mulder - alpine linux: Lucas Ramage - -Thanks to issue submitters: - Dante Torres - @fabbe - Johann Oskarsson - Mark Bucciarelli - Paul Wisehart - Thierry Fournier diff --git a/src/mustach/LICENSE-2.0.txt b/src/mustach/LICENSE-2.0.txt deleted file mode 100644 index d6456956..00000000 --- a/src/mustach/LICENSE-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/src/mustach/Makefile.am b/src/mustach/Makefile.am deleted file mode 100644 index d4cbb2d9..00000000 --- a/src/mustach/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -# This Makefile.am is in the public domain -AM_CPPFLAGS = -I$(top_srcdir)/src/include $(LIBGCRYPT_CFLAGS) - -if USE_COVERAGE - AM_CFLAGS = --coverage -O0 - XLIB = -lgcov -endif - - -lib_LIBRARIES = \ - libmustach.a - -libmustach_a_SOURCES = \ - 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 \ - $(XLIB) - -check_PROGRAMS = \ - test_mustach_jansson - -check_SCRIPTS = \ - run-original-tests.sh - -TESTS = $(check_SCRIPTS) $(check_PROGRAMS) - -EXTRA_DIST = \ - $(check_SCRIPTS) diff --git a/src/mustach/ORIGIN b/src/mustach/ORIGIN deleted file mode 100644 index fafb0ae7..00000000 --- a/src/mustach/ORIGIN +++ /dev/null @@ -1,9 +0,0 @@ -Cloned originally from https://gitlab.com/jobol/mustach/ - -Changes: -======== - -Renamed original Makefile to Makefile.orig and wrote Makefile.am for us. - -Added run-original-tests.sh shell script as a wrapper around Makefile.org -to us the original build process for the test suite. diff --git a/src/mustach/README.md b/src/mustach/README.md deleted file mode 100644 index a6df19f6..00000000 --- a/src/mustach/README.md +++ /dev/null @@ -1,214 +0,0 @@ -# Introduction to Mustach 0.99 - -`mustach` is a C implementation of the [mustache](http://mustache.github.io "main site for mustache") -template specification. - -The main site for `mustach` is on [gitlab](https://gitlab.com/jobol/mustach). - -The best way to use mustach is to copy the files **mustach.h** and **mustach.c** -directly into your project and use it. - -Alternatively, make and meson files are provided for building `mustach` and -`libmustach.so` shared library. - -## Distributions offering mustach package - -### Alpine Linux - -```sh -apk add mustach -apk add mustach-lib -apk add mustach-dev -``` - -### NetBSD - -```sh -cd devel/mustach -make -``` - -See http://pkgsrc.se/devel/mustach - -## Using Mustach from sources - -The file **mustach.h** is the main documentation. Look at it. - -The current source files are: - -- **mustach.c** core implementation of mustache in C -- **mustach.h** header file for core definitions -- **mustach-json-c.c** tiny json wrapper of mustach using [json-c](https://github.com/json-c/json-c) -- **mustach-json-c.h** header file for using the tiny JSON wrapper -- **mustach-tool.c** simple tool for applying template files to a JSON file - -The file **mustach-json-c.c** is the main example of use of **mustach** core -and it is also a practical implementation that can be used. It uses the library -json-c. (NOTE for Mac OS: available through homebrew). - -HELP REQUESTED TO GIVE EXAMPLE BASED ON OTHER LIBRARIES (ex: janson, ...). - -The tool **mustach** is build using `make`, its usage is: - - mustach json template [template]... - -It then outputs the result of applying the templates files to the JSON file. - -### Portability - -Some system does not provide *open_memstream*. In that case, tell your -preferred compiler to declare the preprocessor symbol **NO_OPEN_MEMSTREAM**. -Example: - - gcc -DNO_OPEN_MEMSTREAM - -### Integration - -The file **mustach.h** is the main documentation. Look at it. - -The file **mustach-json-c.c** provides a good example of integration. - -If you intend to use basic HTML/XML escaping and standard C FILE, the callbacks -of the interface **mustach_itf** that you have to implement are: -`enter`, `next`, `leave`, `get`. - -If you intend to use specific escaping and/or specific output, the callbacks -of the interface **mustach_itf** that you have to implement are: -`enter`, `next`, `leave`, `get` and `emit`. - -### Extensions - -By default, the current implementation provides the following extensions: - -#### Explicit Substitution - -This is a core extension implemented in file **mustach.c**. - -In somecases the name of the key used for substitution begins with a -character reserved for mustach: one of `#`, `^`, `/`, `&`, `{`, `>` and `=`. -This extension introduces the special character `:` to explicitly -tell mustach to just substitute the value. So `:` becomes a new special -character. - -#### Value Testing and Comparing - -This are a tool extension implemented in file **mustach-json-c.c**. - -These extensions allows you to test the value of the selected key. -They allow to write `key=value` (matching test) or `key=!value` -(not matching test) in any query. - -The specific comparison extension also allows to compare if greater, -lesser, etc.. than a value. It allows to write `key>value`. - -It the comparator sign appears in the first column it is ignored -as if it was escaped. - -#### Access to current value - -The value of the current field can be accessed using single dot like -in `{{#key}}{{.}}{{/key}}` that applied to `{"key":3.14}` produces `3.14` -and `{{#array}} {{.}}{{/array}}` applied to `{"array":[1,2]}` produces -` 1 2`. - -#### Iteration on objects - -Using the pattern `{{#X.*}}...{{/X.*}}` it is possible to iterate on -fields of `X`. Example: `{{s.*}} {{*}}:{{.}}{{/s.*}}` applied on -`{"s":{"a":1,"b":true}}` produces ` a:1 b:true`. Here the single star -`{{*}}` is replaced by the iterated key and the single dot `{{.}}` is -replaced by its value. - -### Removing Extensions - -When compiling mustach.c or mustach-json-c.c, -extensions can be removed by defining macros -using option -D. - -The possible macros are of 3 categories, the global, -the mustach core specific and the mustach-json-c example -of implementation specific. - -#### Global macros - -- `NO_EXTENSION_FOR_MUSTACH` - - This macro disables any current or future - extensions for the core or the example. - -#### Macros for the core mustach engine (mustach.c) - -- `NO_COLON_EXTENSION_FOR_MUSTACH` - - This macro remove the ability to use colon (:) - as explicit command for variable substitution. - This extension allows to have name starting - with one of the mustach character `:#^/&{=>` - -- `NO_ALLOW_EMPTY_TAG` - - Generate the error MUSTACH_ERROR_EMPTY_TAG automatically - when an empty tag is encountered. - -#### Macros for the implementation example (mustach-json-c.c) - -- `NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH` - - This macro allows the program to check whether - the actual value is equal to an expected value. - This is useful in `{{#key=val}}` or `{{^key=val}}` - with the corresponding `{{/key=val}}`. - It can also be used in `{{key=val}}` but this - doesn't seem to be useful. - -- `NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH` - - This macro allows the program to compare the actual - value with an expected value. The comparison operators - are `=`, `>`, `<`, `>=`, `<=`. The meaning of the - comparison numeric or alphabetic depends on the type - of the inspected value. Also the result of the comparison - can be inverted if the value starts with `!`. - Example of use: `{{key>=val}}`, or `{{#key>=val}}` and - `{{^key>=val}}` with their matching `{{/key>=val}}`. - -- `NO_USE_VALUE_ESCAPE_FIRST_EXTENSION_FOR_MUSTACH` - - This macro fordids automatic escaping of coparison - sign appearing at first column. - -- `NO_JSON_POINTER_EXTENSION_FOR_MUSTACH` - - This macro removes the possible use of JSON pointers. - JSON pointers are defined in IETF RFC 6901. - If not set, any key starting with "/" is a JSON pointer. - This implies to use the colon to introduce keys. - So `NO_COLON_EXTENSION_FOR_MUSTACH` implies - `NO_JSON_POINTER_EXTENSION_FOR_MUSTACH`. - A special escaping is used for `=`, `<`, `>` signs when - values comparisons are enabled: `~=` gives `=` in the key. - -- `NO_OBJECT_ITERATION_FOR_MUSTACH` - - Disable the object iteration extension. That extension allows - to iterate over the keys of an object. The iteration on object - is selected by using the selector `{{#key.*}}`. In the context - of iterating over object keys, the single key `{{*}}` returns the - key and `{{.}}` returns the value. - -- `NO_SINGLE_DOT_EXTENSION_FOR_MUSTACH` - - Disable access to current object value using single dot - like in `{{.}}`. - -- `NO_INCLUDE_PARTIAL_FALLBACK` - - Disable include of file by partial pattern like `{{> name}}`. - By default if a such pattern is found, **mustach** search - for `name` in the current json context. This what is done - historically and when `NO_INCLUDE_PARTIAL_FALLBACK` is defined. - When `NO_INCLUDE_PARTIAL_FALLBACK` is defined, if the value is - found in the json context, the files `name` and `name.mustache` - are searched in that order and the first file found is used - as partial content. The macro `INCLUDE_PARTIAL_EXTENSION` can - be use for changing the extension added. diff --git a/src/mustach/meson.build b/src/mustach/meson.build deleted file mode 100644 index c7ecc8df..00000000 --- a/src/mustach/meson.build +++ /dev/null @@ -1,12 +0,0 @@ -project('mustach', 'c', - version: '1.0.0' -) - -mustach_inc = include_directories('.') -mustach_lib = shared_library('mustach', - 'mustach.c', - include_directories: mustach_inc -) - -mustach_dep = declare_dependency(link_with: mustach_lib, - include_directories: mustach_inc) diff --git a/src/mustach/mustach-jansson.c b/src/mustach/mustach-jansson.c deleted file mode 100644 index 2aed5829..00000000 --- a/src/mustach/mustach-jansson.c +++ /dev/null @@ -1,417 +0,0 @@ -/* - 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; -}; - -enum Bang -{ - BANG_NONE, - BANG_I18N, - BANG_STRINGIFY, - BANG_AMOUNT_CURRENCY, - BANG_AMOUNT_DECIMAL, -}; - -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; - - /** - * Last bang we found. - */ - enum Bang found_bang; - - /** - * Language for i18n lookups. - */ - const char *lang; -}; - - -static json_t * -walk (json_t *obj, const char *path) -{ - char *saveptr = NULL; - char *sp = GNUNET_strdup (path); - char *p = sp; - 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 (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 (path); - - 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; - e->lang = json_string_value (json_object_get (e->root, "$language")); - 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 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 void -freecb (void *v) -{ - free (v); -} - -static int -get (void *closure, const char *name, struct mustach_sbuf *sbuf) -{ - struct JanssonClosure *e = closure; - json_t *obj; - - 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; -} - -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-jansson.h b/src/mustach/mustach-jansson.h deleted file mode 100644 index 27dcdd64..00000000 --- a/src/mustach/mustach-jansson.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - Copyright (C) 2020 Taler Systems SA - - Original license: - Author: José Bollo <jose.bollo@iot.bzh> - Author: José Bollo <jobol@nonadev.net> - - 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. -*/ - -#ifndef _mustach_jansson_h_included_ -#define _mustach_jansson_h_included_ - -#include <taler/taler_json_lib.h> -#include "mustach.h" - -/** - * fmustach_jansson - Renders the mustache 'template' in 'file' for 'root'. - * - * @template: the template string to instantiate - * @root: the root json object to render - * \@file: the file where to write the result - * - * 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_jansson(const char *template, json_t *root, FILE *file); - -/** - * fmustach_jansson - Renders the mustache 'template' in 'fd' for 'root'. - * - * @template: the template string to instantiate - * @root: the root json object to render - * @fd: the file descriptor number where to write the result - * - * 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_jansson(const char *template, json_t *root, int fd); - - -/** - * fmustach_jansson - Renders the mustache 'template' in 'result' for 'root'. - * - * @template: the template string to instantiate - * @root: the root json object to render - * @result: the pointer receiving the result when 0 is returned - * @size: the size of the returned result - * - * 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_jansson(const char *template, json_t *root, char **result, size_t *size); - -/** - * umustach_jansson - Renders the mustache 'template' for 'root' to custom writer 'writecb' with 'closure'. - * - * @template: the template string to instantiate - * @root: the root json object to render - * @writecb: the function that write values - * @closure: the closure for the write function - * - * 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_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-tool.c b/src/mustach/mustach-tool.c deleted file mode 100644 index 364e34a8..00000000 --- a/src/mustach/mustach-tool.c +++ /dev/null @@ -1,155 +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 <stdlib.h> -#include <stdio.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <libgen.h> - -#include "mustach-json-c.h" - -static const size_t BLOCKSIZE = 8192; - -static const char *errors[] = { - "??? unreferenced ???", - "system", - "unexpected end", - "empty tag", - "tag too long", - "bad separators", - "too depth", - "closing", - "bad unescape tag", - "invalid interface", - "item not found", - "partial not found" -}; - -static void help(char *prog) -{ - printf("usage: %s json-file mustach-templates...\n", basename(prog)); - exit(0); -} - -static char *readfile(const char *filename) -{ - int f; - struct stat s; - char *result; - size_t size, pos; - ssize_t rc; - - result = NULL; - if (filename[0] == '-' && filename[1] == 0) - f = dup(0); - else - f = open(filename, O_RDONLY); - if (f < 0) { - fprintf(stderr, "Can't open file: %s\n", filename); - exit(1); - } - - fstat(f, &s); - switch (s.st_mode & S_IFMT) { - case S_IFREG: - size = s.st_size; - break; - case S_IFSOCK: - case S_IFIFO: - size = BLOCKSIZE; - break; - default: - fprintf(stderr, "Bad file: %s\n", filename); - exit(1); - } - - pos = 0; - result = malloc(size + 1); - do { - if (result == NULL) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - rc = read(f, &result[pos], (size - pos) + 1); - if (rc < 0) { - fprintf(stderr, "Error while reading %s\n", filename); - exit(1); - } - if (rc > 0) { - pos += (size_t)rc; - if (pos > size) { - size = pos + BLOCKSIZE; - result = realloc(result, size + 1); - } - } - } while(rc > 0); - - close(f); - result[pos] = 0; - return result; -} - -int main(int ac, char **av) -{ - struct json_object *o; - char *t; - char *prog = *av; - int s; - - (void)ac; /* unused */ - - if (*++av) { - if (!strcmp(*av, "-h") || !strcmp(*av, "--help")) - help(prog); - if (av[0][0] == '-' && !av[0][1]) - o = json_object_from_fd(0); - else - o = json_object_from_file(av[0]); -#if JSON_C_VERSION_NUM >= 0x000D00 - if (json_util_get_last_err() != NULL) { - fprintf(stderr, "Bad json: %s (file %s)\n", json_util_get_last_err(), av[0]); - exit(1); - } - else -#endif - if (o == NULL) { - fprintf(stderr, "Aborted: null json (file %s)\n", av[0]); - exit(1); - } - while(*++av) { - t = readfile(*av); - s = fmustach_json_c(t, o, stdout); - if (s != 0) { - s = -s; - if (s < 1 || s >= (int)(sizeof errors / sizeof * errors)) - s = 0; - fprintf(stderr, "Template error %s (file %s)\n", errors[s], *av); - } - free(t); - } - json_object_put(o); - } - return 0; -} - diff --git a/src/mustach/mustach.c b/src/mustach/mustach.c deleted file mode 100644 index caa80dcc..00000000 --- a/src/mustach/mustach.c +++ /dev/null @@ -1,472 +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 <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <errno.h> -#include <ctype.h> -#ifdef _WIN32 -#include <malloc.h> -#endif -#ifdef __sun -# include <alloca.h> -#endif - -#include "mustach.h" - -#if defined(NO_EXTENSION_FOR_MUSTACH) -# undef NO_COLON_EXTENSION_FOR_MUSTACH -# define NO_COLON_EXTENSION_FOR_MUSTACH -# undef NO_ALLOW_EMPTY_TAG -# define NO_ALLOW_EMPTY_TAG -#endif - -struct iwrap { - int (*emit)(void *closure, const char *buffer, size_t size, int escape, FILE *file); - void *closure; /* closure for: enter, next, leave, emit, get */ - int (*put)(void *closure, const char *name, int escape, FILE *file); - void *closure_put; /* closure for put */ - int (*enter)(void *closure, const char *name); - int (*next)(void *closure); - int (*leave)(void *closure); - int (*get)(void *closure, const char *name, struct mustach_sbuf *sbuf); - int (*partial)(void *closure, const char *name, struct mustach_sbuf *sbuf); - void *closure_partial; /* closure for partial */ -}; - -#if !defined(NO_OPEN_MEMSTREAM) -static FILE *memfile_open(char **buffer, size_t *size) -{ - return open_memstream(buffer, size); -} -static void memfile_abort(FILE *file, char **buffer, size_t *size) -{ - fclose(file); - free(*buffer); - *buffer = NULL; - *size = 0; -} -static int memfile_close(FILE *file, char **buffer, size_t *size) -{ - int rc; - - /* adds terminating null */ - rc = fputc(0, file) ? MUSTACH_ERROR_SYSTEM : 0; - fclose(file); - if (rc == 0) - /* removes terminating null of the length */ - (*size)--; - else { - free(*buffer); - *buffer = NULL; - *size = 0; - } - return rc; -} -#else -static FILE *memfile_open(char **buffer, size_t *size) -{ - /* - * We can't provide *buffer and *size as open_memstream does but - * at least clear them so the caller won't get bad data. - */ - *buffer = NULL; - *size = 0; - - return tmpfile(); -} -static void memfile_abort(FILE *file, char **buffer, size_t *size) -{ - fclose(file); - *buffer = NULL; - *size = 0; -} -static int memfile_close(FILE *file, char **buffer, size_t *size) -{ - int rc; - size_t s; - char *b; - - s = (size_t)ftell(file); - b = malloc(s + 1); - if (b == NULL) { - rc = MUSTACH_ERROR_SYSTEM; - errno = ENOMEM; - s = 0; - } else { - rewind(file); - if (1 == fread(b, s, 1, file)) { - rc = 0; - b[s] = 0; - } else { - rc = MUSTACH_ERROR_SYSTEM; - free(b); - b = NULL; - s = 0; - } - } - *buffer = b; - *size = s; - return rc; -} -#endif - -static inline void sbuf_reset(struct mustach_sbuf *sbuf) -{ - sbuf->value = NULL; - sbuf->freecb = NULL; - sbuf->closure = NULL; -} - -static inline void sbuf_release(struct mustach_sbuf *sbuf) -{ - if (sbuf->releasecb) - sbuf->releasecb(sbuf->value, sbuf->closure); -} - -static int iwrap_emit(void *closure, const char *buffer, size_t size, int escape, FILE *file) -{ - size_t i, j; - - (void)closure; /* unused */ - - if (!escape) - return fwrite(buffer, size, 1, file) != 1 ? MUSTACH_ERROR_SYSTEM : MUSTACH_OK; - - i = 0; - while (i < size) { - j = i; - while (j < size && buffer[j] != '<' && buffer[j] != '>' && buffer[j] != '&') - j++; - if (j != i && fwrite(&buffer[i], j - i, 1, file) != 1) - return MUSTACH_ERROR_SYSTEM; - if (j < size) { - switch(buffer[j++]) { - case '<': - if (fwrite("<", 4, 1, file) != 1) - return MUSTACH_ERROR_SYSTEM; - break; - case '>': - if (fwrite(">", 4, 1, file) != 1) - return MUSTACH_ERROR_SYSTEM; - break; - case '&': - if (fwrite("&", 5, 1, file) != 1) - return MUSTACH_ERROR_SYSTEM; - break; - default: break; - } - } - i = j; - } - return MUSTACH_OK; -} - -static int iwrap_put(void *closure, const char *name, int escape, FILE *file) -{ - struct iwrap *iwrap = closure; - int rc; - struct mustach_sbuf sbuf; - size_t length; - - sbuf_reset(&sbuf); - rc = iwrap->get(iwrap->closure, name, &sbuf); - if (rc >= 0) { - length = strlen(sbuf.value); - if (length) - rc = iwrap->emit(iwrap->closure, sbuf.value, length, escape, file); - sbuf_release(&sbuf); - } - return rc; -} - -static int iwrap_partial(void *closure, const char *name, struct mustach_sbuf *sbuf) -{ - struct iwrap *iwrap = closure; - int rc; - FILE *file; - size_t size; - char *result; - - result = NULL; - file = memfile_open(&result, &size); - if (file == NULL) - rc = MUSTACH_ERROR_SYSTEM; - else { - rc = iwrap->put(iwrap->closure_put, name, 0, file); - if (rc < 0) - memfile_abort(file, &result, &size); - else { - rc = memfile_close(file, &result, &size); - if (rc == 0) { - sbuf->value = result; - sbuf->freecb = free; - } - } - } - return rc; -} - -static int process(const char *template, struct iwrap *iwrap, FILE *file, const char *opstr, const char *clstr) -{ - struct mustach_sbuf sbuf; - char name[MUSTACH_MAX_LENGTH + 1], c, *tmp; - const char *beg, *term; - struct { const char *name, *again; size_t length; int enabled, entered; } stack[MUSTACH_MAX_DEPTH]; - size_t oplen, cllen, len, l; - int depth, rc, enabled; - - enabled = 1; - oplen = strlen(opstr); - cllen = strlen(clstr); - depth = 0; - for(;;) { - beg = strstr(template, opstr); - if (beg == NULL) { - /* no more mustach */ - if (enabled && template[0]) { - rc = iwrap->emit(iwrap->closure, template, strlen(template), 0, file); - if (rc < 0) - return rc; - } - return depth ? MUSTACH_ERROR_UNEXPECTED_END : MUSTACH_OK; - } - if (enabled && beg != template) { - rc = iwrap->emit(iwrap->closure, template, (size_t)(beg - template), 0, file); - if (rc < 0) - return rc; - } - beg += oplen; - term = strstr(beg, clstr); - if (term == NULL) - return MUSTACH_ERROR_UNEXPECTED_END; - template = term + cllen; - len = (size_t)(term - beg); - c = *beg; - switch(c) { - case '!': - case '=': - break; - case '{': - for (l = 0 ; clstr[l] == '}' ; l++); - if (clstr[l]) { - if (!len || beg[len-1] != '}') - return MUSTACH_ERROR_BAD_UNESCAPE_TAG; - len--; - } else { - if (term[l] != '}') - return MUSTACH_ERROR_BAD_UNESCAPE_TAG; - template++; - } - c = '&'; - /*@fallthrough@*/ - case '^': - case '#': - case '/': - case '&': - case '>': -#if !defined(NO_COLON_EXTENSION_FOR_MUSTACH) - case ':': -#endif - beg++; len--; - default: - while (len && isspace(beg[0])) { beg++; len--; } - while (len && isspace(beg[len-1])) len--; -#if !defined(NO_ALLOW_EMPTY_TAG) - if (len == 0) - return MUSTACH_ERROR_EMPTY_TAG; -#endif - if (len > MUSTACH_MAX_LENGTH) - return MUSTACH_ERROR_TAG_TOO_LONG; - memcpy(name, beg, len); - name[len] = 0; - break; - } - switch(c) { - case '!': - /* comment */ - /* nothing to do */ - break; - case '=': - /* defines separators */ - if (len < 5 || beg[len - 1] != '=') - return MUSTACH_ERROR_BAD_SEPARATORS; - beg++; - len -= 2; - for (l = 0; l < len && !isspace(beg[l]) ; l++); - if (l == len) - return MUSTACH_ERROR_BAD_SEPARATORS; - oplen = l; - tmp = alloca(oplen + 1); - memcpy(tmp, beg, oplen); - tmp[oplen] = 0; - opstr = tmp; - while (l < len && isspace(beg[l])) l++; - if (l == len) - return MUSTACH_ERROR_BAD_SEPARATORS; - cllen = len - l; - tmp = alloca(cllen + 1); - memcpy(tmp, beg + l, cllen); - tmp[cllen] = 0; - clstr = tmp; - break; - case '^': - case '#': - /* begin section */ - if (depth == MUSTACH_MAX_DEPTH) - return MUSTACH_ERROR_TOO_DEEP; - rc = enabled; - if (rc) { - rc = iwrap->enter(iwrap->closure, name); - if (rc < 0) - return rc; - } - stack[depth].name = beg; - stack[depth].again = template; - stack[depth].length = len; - stack[depth].enabled = enabled; - stack[depth].entered = rc; - if ((c == '#') == (rc == 0)) - enabled = 0; - depth++; - break; - case '/': - /* end section */ - if (depth-- == 0 || len != stack[depth].length || memcmp(stack[depth].name, name, len)) - return MUSTACH_ERROR_CLOSING; - rc = enabled && stack[depth].entered ? iwrap->next(iwrap->closure) : 0; - if (rc < 0) - return rc; - if (rc) { - template = stack[depth++].again; - } else { - enabled = stack[depth].enabled; - if (enabled && stack[depth].entered) - iwrap->leave(iwrap->closure); - } - break; - case '>': - /* partials */ - if (enabled) { - sbuf_reset(&sbuf); - rc = iwrap->partial(iwrap->closure_partial, name, &sbuf); - if (rc >= 0) { - rc = process(sbuf.value, iwrap, file, opstr, clstr); - sbuf_release(&sbuf); - } - if (rc < 0) - return rc; - } - break; - default: - /* replacement */ - if (enabled) { - rc = iwrap->put(iwrap->closure_put, name, c != '&', file); - if (rc < 0) - return rc; - } - break; - } - } -} - -int fmustach(const char *template, struct mustach_itf *itf, void *closure, FILE *file) -{ - int rc; - struct iwrap iwrap; - - /* check validity */ - if (!itf->enter || !itf->next || !itf->leave || (!itf->put && !itf->get)) - return MUSTACH_ERROR_INVALID_ITF; - - /* init wrap structure */ - iwrap.closure = closure; - if (itf->put) { - iwrap.put = itf->put; - iwrap.closure_put = closure; - } else { - iwrap.put = iwrap_put; - iwrap.closure_put = &iwrap; - } - if (itf->partial) { - iwrap.partial = itf->partial; - iwrap.closure_partial = closure; - } else if (itf->get) { - iwrap.partial = itf->get; - iwrap.closure_partial = closure; - } else { - iwrap.partial = iwrap_partial; - iwrap.closure_partial = &iwrap; - } - iwrap.emit = itf->emit ? itf->emit : iwrap_emit; - iwrap.enter = itf->enter; - iwrap.next = itf->next; - iwrap.leave = itf->leave; - iwrap.get = itf->get; - - /* process */ - rc = itf->start ? itf->start(closure) : 0; - if (rc == 0) - rc = process(template, &iwrap, file, "{{", "}}"); - if (itf->stop) - itf->stop(closure, rc); - return rc; -} - -int fdmustach(const char *template, struct mustach_itf *itf, void *closure, int fd) -{ - int rc; - FILE *file; - - file = fdopen(fd, "w"); - if (file == NULL) { - rc = MUSTACH_ERROR_SYSTEM; - errno = ENOMEM; - } else { - rc = fmustach(template, itf, closure, file); - fclose(file); - } - return rc; -} - -int mustach(const char *template, struct mustach_itf *itf, void *closure, char **result, size_t *size) -{ - int rc; - FILE *file; - size_t s; - - *result = NULL; - if (size == NULL) - size = &s; - file = memfile_open(result, size); - if (file == NULL) - rc = MUSTACH_ERROR_SYSTEM; - else { - rc = fmustach(template, itf, closure, file); - if (rc < 0) - memfile_abort(file, result, size); - else - rc = memfile_close(file, result, size); - } - return rc; -} - diff --git a/src/mustach/mustach.h b/src/mustach/mustach.h deleted file mode 100644 index ad952275..00000000 --- a/src/mustach/mustach.h +++ /dev/null @@ -1,241 +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. -*/ - -#ifndef _mustach_h_included_ -#define _mustach_h_included_ - -struct mustach_sbuf; /* see below */ - -/** - * Current version of mustach and its derivates - */ -#define MUSTACH_VERSION 99 -#define MUSTACH_VERSION_MAJOR (MUSTACH_VERSION / 100) -#define MUSTACH_VERSION_MINOR (MUSTACH_VERSION % 100) - -/** - * Maximum nested imbrications supported - */ -#define MUSTACH_MAX_DEPTH 256 - -/** - * Maximum length of tags in mustaches {{...}} - */ -#define MUSTACH_MAX_LENGTH 1024 - -/** - * mustach_itf - interface for callbacks - * - * All of this function should return a negative value to stop - * the mustache processing. The returned negative value will be - * then returned to the caller of mustach as is. - * - * The functions enter and next should return 0 or 1. - * - * All other functions should normally return MUSTACH_OK (zero). - * If it returns a negative value, it means an error that stop - * the process and that is reported to the caller. - * - * @start: If defined (can be NULL), starts the mustach processing - * of the closure, called at the very beginning before any - * mustach processing occurs. - * - * @put: If defined (can be NULL), writes the value of 'name' - * to 'file' with 'escape' or not. - * As an extension (see NO_ALLOW_EMPTY_TAG), the 'name' can be - * the empty string. In that later case an implementation can - * return MUSTACH_ERROR_EMPTY_TAG to refuse empty names. - * If NULL and 'get' NULL the error MUSTACH_ERROR_INVALID_ITF - * is returned. - * - * @enter: Enters the section of 'name' if possible. - * Musts return 1 if entered or 0 if not entered. - * When 1 is returned, the function 'leave' will always be called. - * Conversely 'leave' is never called when enter returns 0 or - * a negative value. - * When 1 is returned, the function must activate the first - * item of the section. - * - * @next: Activates the next item of the section if it exists. - * Musts return 1 when the next item is activated. - * Musts return 0 when there is no item to activate. - * - * @leave: Leaves the last entered section - * - * @partial: If defined (can be NULL), returns in 'sbuf' the content of the - * partial of 'name'. @see mustach_sbuf - * If NULL but 'get' not NULL, 'get' is used instead of partial. - * If NULL and 'get' NULL and 'put' not NULL, 'put' is called with - * a true FILE. - * - * @emit: If defined (can be NULL), writes the 'buffer' of 'size' with 'escape'. - * If NULL the standard function 'fwrite' is used with a true FILE. - * If not NULL that function is called instead of 'fwrite' to output - * text. - * It implies that if you define either 'partial' or 'get' callback, - * the meaning of 'FILE *file' is abstract for mustach's process and - * then you can use 'FILE*file' pass any kind of pointer (including NULL) - * to the function 'fmustach'. An example of a such behaviour is given by - * the implementation of 'umustach_json_c'. - * - * @get: If defined (can be NULL), returns in 'sbuf' the value of 'name'. - * As an extension (see NO_ALLOW_EMPTY_TAG), the 'name' can be - * the empty string. In that later case an implementation can - * return MUSTACH_ERROR_EMPTY_TAG to refuse empty names. - * If NULL and 'put' NULL the error MUSTACH_ERROR_INVALID_ITF - * is returned. - * - * @stop: If defined (can be NULL), stops the mustach processing - * of the closure, called at the very end after all mustach - * processing occurerd. The status returned by the processing - * is passed to the stop. - * - * The array below summarize status of callbacks: - * - * FULLY OPTIONAL: start partial - * MANDATORY: enter next leave - * COMBINATORIAL: put emit get - * - * Not definig a MANDATORY callback returns error MUSTACH_ERROR_INVALID_ITF. - * - * For COMBINATORIAL callbacks the array below summarize possible combinations: - * - * combination : put : emit : get : abstract FILE - * -------------+---------+---------+---------+----------------------- - * HISTORIC : defined : NULL : NULL : NO: standard FILE - * MINIMAL : NULL : NULL : defined : NO: standard FILE - * CUSTOM : NULL : defined : defined : YES: abstract FILE - * DUCK : defined : NULL : defined : NO: standard FILE - * DANGEROUS : defined : defined : any : YES or NO, depends on 'partial' - * INVALID : NULL : any : NULL : - - * - * The DUCK case runs on one leg. 'get' is not used if 'partial' is defined - * but is used for 'partial' if 'partial' is NULL. Thus for clarity, do not use - * it that way but define 'partial' and let 'get' NULL. - * - * The DANGEROUS case is special: it allows abstract FILE if 'partial' is defined - * but forbids abstract FILE when 'partial' is NULL. - * - * The INVALID case returns error MUSTACH_ERROR_INVALID_ITF. - */ -struct mustach_itf { - int (*start)(void *closure); - int (*put)(void *closure, const char *name, int escape, FILE *file); - int (*enter)(void *closure, const char *name); - int (*next)(void *closure); - int (*leave)(void *closure); - int (*partial)(void *closure, const char *name, struct mustach_sbuf *sbuf); - int (*emit)(void *closure, const char *buffer, size_t size, int escape, FILE *file); - int (*get)(void *closure, const char *name, struct mustach_sbuf *sbuf); - void (*stop)(void *closure, int status); -}; - -/** - * mustach_sbuf - Interface for handling zero terminated strings - * - * That structure is used for returning zero terminated strings -in 'value'- - * to mustach. The callee can provide a function for releasing the returned - * 'value'. Three methods for releasing the string are possible. - * - * 1. no release: set either 'freecb' or 'releasecb' with NULL (done by default) - * 2. release without closure: set 'freecb' to its expected value - * 3. release with closure: set 'releasecb' and 'closure' to their expected values - * - * @value: The value of the string. That value is not changed by mustach -const-. - * - * @freecb: The function to call for freeing the value without closure. - * For convenience, signature of that callback is compatible with 'free'. - * Can be NULL. - * - * @releasecb: The function to release with closure. - * Can be NULL. - * - * @closure: The closure to use for 'releasecb'. - */ -struct mustach_sbuf { - const char *value; - union { - void (*freecb)(void*); - void (*releasecb)(const char *value, void *closure); - }; - void *closure; -}; - -/* - * Definition of error codes returned by mustach - */ -#define MUSTACH_OK 0 -#define MUSTACH_ERROR_SYSTEM -1 -#define MUSTACH_ERROR_UNEXPECTED_END -2 -#define MUSTACH_ERROR_EMPTY_TAG -3 -#define MUSTACH_ERROR_TAG_TOO_LONG -4 -#define MUSTACH_ERROR_BAD_SEPARATORS -5 -#define MUSTACH_ERROR_TOO_DEEP -6 -#define MUSTACH_ERROR_CLOSING -7 -#define MUSTACH_ERROR_BAD_UNESCAPE_TAG -8 -#define MUSTACH_ERROR_INVALID_ITF -9 -#define MUSTACH_ERROR_ITEM_NOT_FOUND -10 -#define MUSTACH_ERROR_PARTIAL_NOT_FOUND -11 - -/* You can use definition below for user specific error */ -#define MUSTACH_ERROR_USER_BASE -100 -#define MUSTACH_ERROR_USER(x) (MUSTACH_ERROR_USER_BASE-(x)) - -/** - * fmustach - Renders the mustache 'template' in 'file' for 'itf' and 'closure'. - * - * @template: the template string to instantiate - * @itf: the interface to the functions that mustach calls - * @closure: the closure to pass to functions called - * \@file: the file where to write the result - * - * 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(const char *template, struct mustach_itf *itf, void *closure, FILE *file); - -/** - * fmustach - Renders the mustache 'template' in 'fd' for 'itf' and 'closure'. - * - * @template: the template string to instantiate - * @itf: the interface to the functions that mustach calls - * @closure: the closure to pass to functions called - * @fd: the file descriptor number where to write the result - * - * 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(const char *template, struct mustach_itf *itf, void *closure, int fd); - -/** - * fmustach - Renders the mustache 'template' in 'result' for 'itf' and 'closure'. - * - * @template: the template string to instantiate - * @itf: the interface to the functions that mustach calls - * @closure: the closure to pass to functions called - * @result: the pointer receiving the result when 0 is returned - * @size: the size of the returned result - * - * 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(const char *template, struct mustach_itf *itf, void *closure, char **result, size_t *size); - -#endif - diff --git a/src/mustach/run-original-tests.sh b/src/mustach/run-original-tests.sh deleted file mode 100755 index 9c7d34cd..00000000 --- a/src/mustach/run-original-tests.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -eu -# The build fails if libjson-c-dev is not installed. -# That's OK, we don't otherwise need it and don't -# even bother testing for it in configure.ac. -# However, in that case, skip the test suite. - -make -f Makefile.orig mustach || exit 77 -make -f Makefile.orig test -make -f Makefile.orig clean || true diff --git a/src/mustach/test1/.gitignore b/src/mustach/test1/.gitignore deleted file mode 100644 index 4d897daa..00000000 --- a/src/mustach/test1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -resu.last -vg.last diff --git a/src/mustach/test1/Makefile b/src/mustach/test1/Makefile deleted file mode 100644 index de53086b..00000000 --- a/src/mustach/test1/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -.PHONY: test clean - -test: ../mustach - @echo starting test - @valgrind ../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - -clean: - rm -f resu.last - diff --git a/src/mustach/test1/json b/src/mustach/test1/json deleted file mode 100644 index 5b2e3d83..00000000 --- a/src/mustach/test1/json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "Chris", - "value": 10000, - "taxed_value": 6000, - "in_ca": true, - "person": false, - "repo": [ - { "name": "resque", "who": [ { "committer": "joe" }, { "reviewer": "avrel" }, { "committer": "william" } ] }, - { "name": "hub", "who": [ { "committer": "jack" }, { "reviewer": "avrel" }, { "committer": "greg" } ] }, - { "name": "rip", "who": [ { "reviewer": "joe" }, { "reviewer": "jack" }, { "committer": "greg" } ] } - ], - "person?": { "name": "Jon" }, - "special": "----{{extra}}----", - "extra": 3.14159, - "#sharp": "#", - "!bang": "!", - "/slash": "/", - "^circ": "^", - "=equal": "=", - ":colon": ":", - ">greater": ">", - "~tilde": "~" -} diff --git a/src/mustach/test1/must b/src/mustach/test1/must deleted file mode 100644 index 723f966c..00000000 --- a/src/mustach/test1/must +++ /dev/null @@ -1,43 +0,0 @@ -Hello {{name}} -You have just won {{value}} dollars! -{{#in_ca}} -Well, {{taxed_value}} dollars, after taxes. -{{/in_ca}} -Shown. -{{#person}} - Never shown! -{{/person}} -{{^person}} - No person -{{/person}} - -{{#repo}} - <b>{{name}}</b> reviewers:{{#who}} {{reviewer}}{{/who}} committers:{{#who}} {{committer}}{{/who}} -{{/repo}} - -{{#person?}} - Hi {{name}}! -{{/person?}} - -{{=%(% %)%=}} -===================================== -%(%! gros commentaire %)% -%(%#repo%)% - <b>%(%name%)%</b> reviewers:%(%#who%)% %(%reviewer%)%%(%/who%)% committers:%(%#who%)% %(%committer%)%%(%/who%)% -%(%/repo%)% -===================================== -%(%={{ }}=%)% -ggggggggg -{{> special}} -jjjjjjjjj -end - -{{:#sharp}} -{{:!bang}} -{{:~tilde}} -{{:/~0tilde}} -{{:/~1slash}} see json pointers IETF RFC 6901 -{{:^circ}} -{{:\=equal}} -{{::colon}} -{{:>greater}} diff --git a/src/mustach/test1/resu.ref b/src/mustach/test1/resu.ref deleted file mode 100644 index 545e5857..00000000 --- a/src/mustach/test1/resu.ref +++ /dev/null @@ -1,49 +0,0 @@ -Hello Chris -You have just won 10000 dollars! - -Well, 6000 dollars, after taxes. - -Shown. - - - No person - - - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - - - - Hi Jon! - - - -===================================== - - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - -===================================== - -ggggggggg -----3.14159---- -jjjjjjjjj -end - -# -! -~ -~ -/ see json pointers IETF RFC 6901 -^ -= -: -> diff --git a/src/mustach/test2/.gitignore b/src/mustach/test2/.gitignore deleted file mode 100644 index 4d897daa..00000000 --- a/src/mustach/test2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -resu.last -vg.last diff --git a/src/mustach/test2/Makefile b/src/mustach/test2/Makefile deleted file mode 100644 index a493de60..00000000 --- a/src/mustach/test2/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -.PHONY: test clean - -test: ../mustach - @echo starting test - @valgrind ../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - -clean: - rm -f resu.last diff --git a/src/mustach/test2/json b/src/mustach/test2/json deleted file mode 100644 index 8c668b3b..00000000 --- a/src/mustach/test2/json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "header": "Colors", - "items": [ - {"name": "red", "first": true, "url": "#Red"}, - {"name": "green", "link": true, "url": "#Green"}, - {"name": "blue", "link": true, "url": "#Blue"} - ], - "empty": false -} diff --git a/src/mustach/test2/must b/src/mustach/test2/must deleted file mode 100644 index aa6da707..00000000 --- a/src/mustach/test2/must +++ /dev/null @@ -1,17 +0,0 @@ -<h1>{{header}}</h1> -{{#bug}} -{{/bug}} - -{{#items}} - {{#first}} - <li><strong>{{name}}</strong></li> - {{/first}} - {{#link}} - <li><a href="{{url}}">{{name}}</a></li> - {{/link}} -{{/items}} - -{{#empty}} - <p>The list is empty.</p> -{{/empty}} - diff --git a/src/mustach/test2/resu.ref b/src/mustach/test2/resu.ref deleted file mode 100644 index 67d1f547..00000000 --- a/src/mustach/test2/resu.ref +++ /dev/null @@ -1,22 +0,0 @@ -<h1>Colors</h1> - - - - - <li><strong>red</strong></li> - - - - - - <li><a href="#Green">green</a></li> - - - - - <li><a href="#Blue">blue</a></li> - - - - - diff --git a/src/mustach/test3/.gitignore b/src/mustach/test3/.gitignore deleted file mode 100644 index 4d897daa..00000000 --- a/src/mustach/test3/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -resu.last -vg.last diff --git a/src/mustach/test3/Makefile b/src/mustach/test3/Makefile deleted file mode 100644 index de53086b..00000000 --- a/src/mustach/test3/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -.PHONY: test clean - -test: ../mustach - @echo starting test - @valgrind ../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - -clean: - rm -f resu.last - diff --git a/src/mustach/test3/json b/src/mustach/test3/json deleted file mode 100644 index 79278817..00000000 --- a/src/mustach/test3/json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "Chris", - "company": "<b>GitHub & Co</b>", - "names": ["Chris", "Kross"], - "skills": ["JavaScript", "PHP", "Java"], - "age": 18 -} diff --git a/src/mustach/test3/must b/src/mustach/test3/must deleted file mode 100644 index 5c490469..00000000 --- a/src/mustach/test3/must +++ /dev/null @@ -1,15 +0,0 @@ -* {{name}} -* {{age}} -* {{company}} -* {{&company}} -* {{{company}}} -{{=<% %>=}} -* <%company%> -* <%&company%> -* <%{company}%> - -<%={{ }}=%> -* <ul>{{#names}}<li>{{.}}</li>{{/names}}</ul> -* skills: <ul>{{#skills}}<li>{{.}}</li>{{/skills}}</ul> -{{#age}}* age: {{.}}{{/age}} - diff --git a/src/mustach/test3/resu.ref b/src/mustach/test3/resu.ref deleted file mode 100644 index e89ce902..00000000 --- a/src/mustach/test3/resu.ref +++ /dev/null @@ -1,15 +0,0 @@ -* Chris -* 18 -* <b>GitHub & Co</b> -* <b>GitHub & Co</b> -* <b>GitHub & Co</b> - -* <b>GitHub & Co</b> -* <b>GitHub & Co</b> -* <b>GitHub & Co</b> - - -* <ul><li>Chris</li><li>Kross</li></ul> -* skills: <ul><li>JavaScript</li><li>PHP</li><li>Java</li></ul> -* age: 18 - diff --git a/src/mustach/test4/.gitignore b/src/mustach/test4/.gitignore deleted file mode 100644 index 4d897daa..00000000 --- a/src/mustach/test4/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -resu.last -vg.last diff --git a/src/mustach/test4/Makefile b/src/mustach/test4/Makefile deleted file mode 100644 index de53086b..00000000 --- a/src/mustach/test4/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -.PHONY: test clean - -test: ../mustach - @echo starting test - @valgrind ../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - -clean: - rm -f resu.last - diff --git a/src/mustach/test4/json b/src/mustach/test4/json deleted file mode 100644 index a1083607..00000000 --- a/src/mustach/test4/json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "person": { "name": "Jon", "age": 25 }, - "person.name": "Fred", - "person.name=Fred": "The other Fred.", - "persons": [ - { "name": "Jon", "age": 25, "lang": "en" }, - { "name": "Henry", "age": 27, "lang": "en" }, - { "name": "Amed", "age": 24, "lang": "fr" } ], - "fellows": { - "Jon": { "age": 25, "lang": "en" }, - "Henry": { "age": 27, "lang": "en" }, - "Amed": { "age": 24, "lang": "fr" } } -} diff --git a/src/mustach/test4/must b/src/mustach/test4/must deleted file mode 100644 index 003b9366..00000000 --- a/src/mustach/test4/must +++ /dev/null @@ -1,58 +0,0 @@ -This are extensions!! - -{{person.name}} -{{person.age}} - -{{person\.name}} -{{person\.name\=Fred}} - -{{#person.name=Jon}} -Hello Jon -{{/person.name=Jon}} - -{{^person.name=Jon}} -No Jon? Hey Jon... -{{/person.name=Jon}} - -{{^person.name=Harry}} -No Harry? Hey Calahan... -{{/person.name=Harry}} - -{{#person\.name=Fred}} -Hello Fred -{{/person\.name=Fred}} - -{{^person\.name=Fred}} -No Fred? Hey Fred... -{{/person\.name=Fred}} - -{{#person\.name\=Fred=The other Fred.}} -Hello Fred#2 -{{/person\.name\=Fred=The other Fred.}} - -{{^person\.name\=Fred=The other Fred.}} -No Fred#2? Hey Fred#2... -{{/person\.name\=Fred=The other Fred.}} - -{{#persons}} -{{#lang=!fr}}Hello {{name}}, {{age}} years{{/lang=!fr}} -{{#lang=fr}}Salut {{name}}, {{age}} ans{{/lang=fr}} -{{/persons}} - -{{#persons}} -{{name}}: {{age=24}}/{{age}}/{{age=!27}} -{{/persons}} - -{{#fellows.*}} -{{*}}: {{age=24}}/{{age}}/{{age=!27}} -{{/fellows.*}} - -{{#*}} - (1) {{*}}: {{.}} - {{#*}} - (2) {{*}}: {{.}} - {{#*}} - (3) {{*}}: {{.}} - {{/*}} - {{/*}} -{{/*}} diff --git a/src/mustach/test4/resu.ref b/src/mustach/test4/resu.ref deleted file mode 100644 index 2d48918a..00000000 --- a/src/mustach/test4/resu.ref +++ /dev/null @@ -1,100 +0,0 @@ -This are extensions!! - -Jon -25 - -Fred -The other Fred. - - -Hello Jon - - - - - -No Harry? Hey Calahan... - - - -Hello Fred - - - - - -Hello Fred#2 - - - - - -Hello Jon, 25 years - - -Hello Henry, 27 years - - - -Salut Amed, 24 ans - - - -Jon: /25/25 - -Henry: /27/ - -Amed: 24/24/24 - - - -Jon: /25/25 - -Henry: /27/ - -Amed: 24/24/24 - - - - (1) person: { "name": "Jon", "age": 25 } - - (2) name: Jon - - - (2) age: 25 - - - - (1) person.name: Fred - - - (1) person.name=Fred: The other Fred. - - - (1) persons: [ { "name": "Jon", "age": 25, "lang": "en" }, { "name": "Henry", "age": 27, "lang": "en" }, { "name": "Amed", "age": 24, "lang": "fr" } ] - - - (1) fellows: { "Jon": { "age": 25, "lang": "en" }, "Henry": { "age": 27, "lang": "en" }, "Amed": { "age": 24, "lang": "fr" } } - - (2) Jon: { "age": 25, "lang": "en" } - - (3) age: 25 - - (3) lang: en - - - (2) Henry: { "age": 27, "lang": "en" } - - (3) age: 27 - - (3) lang: en - - - (2) Amed: { "age": 24, "lang": "fr" } - - (3) age: 24 - - (3) lang: fr - - - diff --git a/src/mustach/test5/.gitignore b/src/mustach/test5/.gitignore deleted file mode 100644 index 4d897daa..00000000 --- a/src/mustach/test5/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -resu.last -vg.last diff --git a/src/mustach/test5/Makefile b/src/mustach/test5/Makefile deleted file mode 100644 index de53086b..00000000 --- a/src/mustach/test5/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -.PHONY: test clean - -test: ../mustach - @echo starting test - @valgrind ../mustach json must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - -clean: - rm -f resu.last - diff --git a/src/mustach/test5/json b/src/mustach/test5/json deleted file mode 100644 index 5b2e3d83..00000000 --- a/src/mustach/test5/json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "Chris", - "value": 10000, - "taxed_value": 6000, - "in_ca": true, - "person": false, - "repo": [ - { "name": "resque", "who": [ { "committer": "joe" }, { "reviewer": "avrel" }, { "committer": "william" } ] }, - { "name": "hub", "who": [ { "committer": "jack" }, { "reviewer": "avrel" }, { "committer": "greg" } ] }, - { "name": "rip", "who": [ { "reviewer": "joe" }, { "reviewer": "jack" }, { "committer": "greg" } ] } - ], - "person?": { "name": "Jon" }, - "special": "----{{extra}}----", - "extra": 3.14159, - "#sharp": "#", - "!bang": "!", - "/slash": "/", - "^circ": "^", - "=equal": "=", - ":colon": ":", - ">greater": ">", - "~tilde": "~" -} diff --git a/src/mustach/test5/must b/src/mustach/test5/must deleted file mode 100644 index 44305df2..00000000 --- a/src/mustach/test5/must +++ /dev/null @@ -1,23 +0,0 @@ -===================================== -from json -{{> special}} -===================================== -not found -{{> notfound}} -===================================== -without extension first -{{> must2 }} -===================================== -last with extension -{{> must3 }} -===================================== -Ensure must3 didn't change specials - -{{#person?}} - Hi {{name}}! -{{/person?}} - -%(%#person?%)% - Hi %(%name%)%! -%(%/person?%)% - diff --git a/src/mustach/test5/must2 b/src/mustach/test5/must2 deleted file mode 100644 index d4a1d378..00000000 --- a/src/mustach/test5/must2 +++ /dev/null @@ -1,14 +0,0 @@ -must2 == BEGIN -Hello {{name}} -You have just won {{value}} dollars! -{{#in_ca}} -Well, {{taxed_value}} dollars, after taxes. -{{/in_ca}} -Shown. -{{#person}} - Never shown! -{{/person}} -{{^person}} - No person -{{/person}} -must2 == END diff --git a/src/mustach/test5/must2.mustache b/src/mustach/test5/must2.mustache deleted file mode 100644 index 33f1ead3..00000000 --- a/src/mustach/test5/must2.mustache +++ /dev/null @@ -1 +0,0 @@ -must2.mustache ==SHOULD NOT BE SEEN== diff --git a/src/mustach/test5/must3.mustache b/src/mustach/test5/must3.mustache deleted file mode 100644 index 821aaac3..00000000 --- a/src/mustach/test5/must3.mustache +++ /dev/null @@ -1,17 +0,0 @@ -must3.mustache == BEGIN -{{#repo}} - <b>{{name}}</b> reviewers:{{#who}} {{reviewer}}{{/who}} committers:{{#who}} {{committer}}{{/who}} -{{/repo}} - -{{#person?}} - Hi {{name}}! -{{/person?}} - -{{=%(% %)%=}} -===================================== -%(%! big comment %)% -%(%#repo%)% - <b>%(%name%)%</b> reviewers:%(%#who%)% %(%reviewer%)%%(%/who%)% committers:%(%#who%)% %(%committer%)%%(%/who%)% -%(%/repo%)% -===================================== -must3.mustache == END diff --git a/src/mustach/test5/resu.ref b/src/mustach/test5/resu.ref deleted file mode 100644 index afc39659..00000000 --- a/src/mustach/test5/resu.ref +++ /dev/null @@ -1,60 +0,0 @@ -===================================== -from json -----3.14159---- -===================================== -not found - -===================================== -without extension first -must2 == BEGIN -Hello Chris -You have just won 10000 dollars! - -Well, 6000 dollars, after taxes. - -Shown. - - - No person - -must2 == END - -===================================== -last with extension -must3.mustache == BEGIN - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - - - - Hi Jon! - - - -===================================== - - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - -===================================== -must3.mustache == END - -===================================== -Ensure must3 didn't change specials - - - Hi Jon! - - -%(%#person?%)% - Hi %(%name%)%! -%(%/person?%)% - diff --git a/src/mustach/test5/special b/src/mustach/test5/special deleted file mode 100644 index 02d9975c..00000000 --- a/src/mustach/test5/special +++ /dev/null @@ -1 +0,0 @@ -special ==SHOULD NOT BE SEEN== diff --git a/src/mustach/test5/special.mustache b/src/mustach/test5/special.mustache deleted file mode 100644 index 70a771fd..00000000 --- a/src/mustach/test5/special.mustache +++ /dev/null @@ -1 +0,0 @@ -special.mustache ==SHOULD NOT BE SEEN== diff --git a/src/mustach/test6/.gitignore b/src/mustach/test6/.gitignore deleted file mode 100644 index 62f4d919..00000000 --- a/src/mustach/test6/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -resu.last -vg.last -test-custom-write -!test-custom-write.c diff --git a/src/mustach/test6/Makefile b/src/mustach/test6/Makefile deleted file mode 100644 index b8a63375..00000000 --- a/src/mustach/test6/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PHONY: test clean - -test-custom-write: test-custom-write.c ../mustach-json-c.h ../mustach-json-c.c ../mustach.h ../mustach.c - @echo building test-custom-write - $(CC) $(CFLAGS) -g -o test-custom-write test-custom-write.c ../mustach.c ../mustach-json-c.c -ljson-c - -test: test-custom-write - @echo starting test - @valgrind ./test-custom-write json -U must -l must -x must > resu.last 2> vg.last - @sed -i 's:^==[0-9]*== ::' vg.last - @diff resu.ref resu.last && echo "result ok" || echo "ERROR! Result differs" - -clean: - rm -f resu.last test-custom-write - diff --git a/src/mustach/test6/json b/src/mustach/test6/json deleted file mode 100644 index 5b2e3d83..00000000 --- a/src/mustach/test6/json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "Chris", - "value": 10000, - "taxed_value": 6000, - "in_ca": true, - "person": false, - "repo": [ - { "name": "resque", "who": [ { "committer": "joe" }, { "reviewer": "avrel" }, { "committer": "william" } ] }, - { "name": "hub", "who": [ { "committer": "jack" }, { "reviewer": "avrel" }, { "committer": "greg" } ] }, - { "name": "rip", "who": [ { "reviewer": "joe" }, { "reviewer": "jack" }, { "committer": "greg" } ] } - ], - "person?": { "name": "Jon" }, - "special": "----{{extra}}----", - "extra": 3.14159, - "#sharp": "#", - "!bang": "!", - "/slash": "/", - "^circ": "^", - "=equal": "=", - ":colon": ":", - ">greater": ">", - "~tilde": "~" -} diff --git a/src/mustach/test6/must b/src/mustach/test6/must deleted file mode 100644 index 723f966c..00000000 --- a/src/mustach/test6/must +++ /dev/null @@ -1,43 +0,0 @@ -Hello {{name}} -You have just won {{value}} dollars! -{{#in_ca}} -Well, {{taxed_value}} dollars, after taxes. -{{/in_ca}} -Shown. -{{#person}} - Never shown! -{{/person}} -{{^person}} - No person -{{/person}} - -{{#repo}} - <b>{{name}}</b> reviewers:{{#who}} {{reviewer}}{{/who}} committers:{{#who}} {{committer}}{{/who}} -{{/repo}} - -{{#person?}} - Hi {{name}}! -{{/person?}} - -{{=%(% %)%=}} -===================================== -%(%! gros commentaire %)% -%(%#repo%)% - <b>%(%name%)%</b> reviewers:%(%#who%)% %(%reviewer%)%%(%/who%)% committers:%(%#who%)% %(%committer%)%%(%/who%)% -%(%/repo%)% -===================================== -%(%={{ }}=%)% -ggggggggg -{{> special}} -jjjjjjjjj -end - -{{:#sharp}} -{{:!bang}} -{{:~tilde}} -{{:/~0tilde}} -{{:/~1slash}} see json pointers IETF RFC 6901 -{{:^circ}} -{{:\=equal}} -{{::colon}} -{{:>greater}} diff --git a/src/mustach/test6/resu.ref b/src/mustach/test6/resu.ref deleted file mode 100644 index 345d3aef..00000000 --- a/src/mustach/test6/resu.ref +++ /dev/null @@ -1,147 +0,0 @@ -HELLO CHRIS -YOU HAVE JUST WON 10000 DOLLARS! - -WELL, 6000 DOLLARS, AFTER TAXES. - -SHOWN. - - - NO PERSON - - - - <B>RESQUE</B> REVIEWERS: AVREL COMMITTERS: JOE WILLIAM - - <B>HUB</B> REVIEWERS: AVREL COMMITTERS: JACK GREG - - <B>RIP</B> REVIEWERS: JOE JACK COMMITTERS: GREG - - - - HI JON! - - - -===================================== - - - <B>RESQUE</B> REVIEWERS: AVREL COMMITTERS: JOE WILLIAM - - <B>HUB</B> REVIEWERS: AVREL COMMITTERS: JACK GREG - - <B>RIP</B> REVIEWERS: JOE JACK COMMITTERS: GREG - -===================================== - -GGGGGGGGG -----3.14159---- -JJJJJJJJJ -END - -# -! -~ -~ -/ SEE JSON POINTERS IETF RFC 6901 -^ -= -: -> -hello chris -you have just won 10000 dollars! - -well, 6000 dollars, after taxes. - -shown. - - - no person - - - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - - - - hi jon! - - - -===================================== - - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - -===================================== - -ggggggggg -----3.14159---- -jjjjjjjjj -end - -# -! -~ -~ -/ see json pointers ietf rfc 6901 -^ -= -: -> -Hello Chris -You have just won 10000 dollars! - -Well, 6000 dollars, after taxes. - -Shown. - - - No person - - - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - - - - Hi Jon! - - - -===================================== - - - <b>resque</b> reviewers: avrel committers: joe william - - <b>hub</b> reviewers: avrel committers: jack greg - - <b>rip</b> reviewers: joe jack committers: greg - -===================================== - -ggggggggg -----3.14159---- -jjjjjjjjj -end - -# -! -~ -~ -/ see json pointers IETF RFC 6901 -^ -= -: -> diff --git a/src/mustach/test6/test-custom-write.c b/src/mustach/test6/test-custom-write.c deleted file mode 100644 index cc50a47c..00000000 --- a/src/mustach/test6/test-custom-write.c +++ /dev/null @@ -1,145 +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 <stdlib.h> -#include <stdio.h> -#include <ctype.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <string.h> -#include <libgen.h> - -#include "../mustach-json-c.h" - -static const size_t BLOCKSIZE = 8192; - -static char *readfile(const char *filename) -{ - int f; - struct stat s; - char *result; - size_t size, pos; - ssize_t rc; - - result = NULL; - if (filename[0] == '-' && filename[1] == 0) - f = dup(0); - else - f = open(filename, O_RDONLY); - if (f < 0) { - fprintf(stderr, "Can't open file: %s\n", filename); - exit(1); - } - - fstat(f, &s); - switch (s.st_mode & S_IFMT) { - case S_IFREG: - size = s.st_size; - break; - case S_IFSOCK: - case S_IFIFO: - size = BLOCKSIZE; - break; - default: - fprintf(stderr, "Bad file: %s\n", filename); - exit(1); - } - - pos = 0; - result = malloc(size + 1); - do { - if (result == NULL) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - rc = read(f, &result[pos], (size - pos) + 1); - if (rc < 0) { - fprintf(stderr, "Error while reading %s\n", filename); - exit(1); - } - if (rc > 0) { - pos += (size_t)rc; - if (pos > size) { - size = pos + BLOCKSIZE; - result = realloc(result, size + 1); - } - } - } while(rc > 0); - - close(f); - result[pos] = 0; - return result; -} - -enum { None, Upper, Lower } mode = None; - -int uwrite(void *closure, const char *buffer, size_t size) -{ - switch(mode) { - case None: - fwrite(buffer, size, 1, stdout); - break; - case Upper: - while(size--) - fputc(toupper(*buffer++), stdout); - break; - case Lower: - while(size--) - fputc(tolower(*buffer++), stdout); - break; - } - return 0; -} - -int main(int ac, char **av) -{ - struct json_object *o; - char *t; - char *prog = *av; - int s; - - if (*++av) { - o = json_object_from_file(av[0]); - if (o == NULL) { - fprintf(stderr, "Aborted: null json (file %s)\n", av[0]); - exit(1); - } - while(*++av) { - if (!strcmp(*av, "-U")) - mode = Upper; - else if (!strcmp(*av, "-l")) - mode = Lower; - else if (!strcmp(*av, "-x")) - mode = None; - else { - t = readfile(*av); - s = umustach_json_c(t, o, uwrite, NULL); - if (s != 0) - fprintf(stderr, "Template error %d\n", s); - free(t); - } - } - json_object_put(o); - } - return 0; -} - diff --git a/src/mustach/test_mustach_jansson.c b/src/mustach/test_mustach_jansson.c deleted file mode 100644 index 11af86fa..00000000 --- a/src/mustach/test_mustach_jansson.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - 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 test_mustach_jansson.c - * @brief testcase to test the mustach/jansson integration - * @author Florian Dold - */ -#include "platform.h" -#include "mustach-jansson.h" - - -static 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 (); - json_t *contract; - /* test 1 */ - const char *t1 = "hello world"; - const char *x1 = "hello world"; - /* test 2 */ - const char *t2 = "hello {{ v1 }}"; - const char *x2 = "hello world"; - /* test 3 */ - const char *t3 = "hello {{ v3.x }}"; - const char *x3 = "hello baz"; - /* test 4 */ - const char *t4 = "hello {{# v2 }}{{ . }}{{/ v2 }}"; - const char *x4 = "hello foobar"; - /* test 5 */ - const char *t5 = "hello {{# v3 }}{{ y }}/{{ x }}{{ z }}{{/ v3 }}"; - const char *x5 = "hello quux/baz"; - /* test 6 */ - const char *t6 = "hello {{ v2!stringify }}"; - const char *x6 = "hello [\n \"foo\",\n \"bar\"\n]"; - /* test 7 */ - const char *t7 = "amount: {{ amt!amount_decimal }} {{ amt!amount_currency }}"; - const char *x7 = "amount: 123.00 EUR"; - /* test 8 */ - const char *t8 = "{{^ v4 }}fallback{{/ v4 }}"; - const char *x8 = "fallback"; - - /* contract test 8 (contract) */ - const char *tc = "summary: {{ summary!i18n }}"; - const char *xc_en = "summary: ENGLISH"; - const char *xc_de = "summary: DEUTSCH"; - const char *xc_fr = "summary: FRANCAISE"; - - GNUNET_assert (NULL != root); - GNUNET_assert (NULL != arr); - GNUNET_assert (NULL != obj); - GNUNET_assert (0 == - json_object_set_new (root, - "v1", - json_string ("world"))); - GNUNET_assert (0 == - json_object_set_new (root, - "v4", - json_array ())); - GNUNET_assert (0 == - json_array_append_new (arr, - json_string ("foo"))); - GNUNET_assert (0 == - json_array_append_new (arr, - json_string ("bar"))); - GNUNET_assert (0 == - json_object_set_new (root, - "v2", - arr)); - GNUNET_assert (0 == - json_object_set_new (root, - "v3", - obj)); - GNUNET_assert (0 == - json_object_set_new (root, - "amt", - json_string ("EUR:123.00"))); - GNUNET_assert (0 == - json_object_set_new (obj, - "x", - json_string ("baz"))); - GNUNET_assert (0 == - 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 (t8, root, x8); - assert_template (tc, contract, xc_en); - - GNUNET_assert (0 == - json_object_set_new (contract, - "$language", - json_string ("de"))); - assert_template (tc, contract, xc_de); - - GNUNET_assert (0 == - json_object_set_new (contract, - "$language", - json_string ("fr"))); - assert_template (tc, contract, xc_fr); - - GNUNET_assert (0 == - json_object_set_new (contract, - "$language", - json_string ("it"))); - assert_template (tc, contract, xc_en); - json_decref (root); - json_decref (contract); - return 0; -} |