diff options
Diffstat (limited to 'src/mustach/mustach-json-c.c')
-rw-r--r-- | src/mustach/mustach-json-c.c | 526 |
1 files changed, 0 insertions, 526 deletions
diff --git a/src/mustach/mustach-json-c.c b/src/mustach/mustach-json-c.c deleted file mode 100644 index df901dcd..00000000 --- a/src/mustach/mustach-json-c.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - Author: José Bollo <jobol@nonadev.net> - Author: José Bollo <jose.bollo@iot.bzh> - - https://gitlab.com/jobol/mustach - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#define _GNU_SOURCE - -#include <stdio.h> -#include <string.h> -#ifdef _WIN32 -#include <malloc.h> -#endif -#ifdef __sun -# include <alloca.h> -#endif - -#include "mustach.h" -#include "mustach-json-c.h" - -#if defined(NO_EXTENSION_FOR_MUSTACH) -# undef NO_SINGLE_DOT_EXTENSION_FOR_MUSTACH -# define NO_SINGLE_DOT_EXTENSION_FOR_MUSTACH -# undef NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH -# define NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH -# undef NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH -# define NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH -# undef NO_JSON_POINTER_EXTENSION_FOR_MUSTACH -# define NO_JSON_POINTER_EXTENSION_FOR_MUSTACH -# undef NO_OBJECT_ITERATION_FOR_MUSTACH -# define NO_OBJECT_ITERATION_FOR_MUSTACH -# undef NO_INCLUDE_PARTIAL_FALLBACK -# define NO_INCLUDE_PARTIAL_FALLBACK -#endif - -#if !defined(NO_INCLUDE_PARTIAL_FALLBACK) \ - && !defined(INCLUDE_PARTIAL_EXTENSION) -# define INCLUDE_PARTIAL_EXTENSION ".mustache" -#endif - -#if !defined(NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH) -# undef NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH -#endif - -struct expl { - struct json_object *root; - mustach_json_c_write_cb writecb; - int depth; -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - int found_objiter; -#endif - struct { - struct json_object *cont; - struct json_object *obj; -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - struct json_object_iterator biter, eiter; - int is_objiter; -#endif - int index, count; - } stack[MUSTACH_MAX_DEPTH]; -}; - -enum comp { - C_no = 0, - C_eq = 1, - C_lt = 5, - C_le = 6, - C_gt = 9, - C_ge = 10 -}; - -#if !defined(NO_EQUAL_VALUE_EXTENSION_FOR_MUSTACH) -static enum comp getcomp(char *head) -{ - return head[0] == '=' ? C_eq -#if !defined(NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH) - : head[0] == '<' ? (head[1] == '=' ? C_le : C_lt) - : head[0] == '>' ? (head[1] == '=' ? C_ge : C_gt) -#endif - : C_no; -} - -static char *keyval(char *head, int isptr, enum comp *comp) -{ - char *w, c, s; - enum comp k; - - k = C_no; -#if !defined(NO_USE_VALUE_ESCAPE_FIRST_EXTENSION_FOR_MUSTACH) - s = getcomp(head) != C_no; -#else - s = 0; -#endif - c = *(w = head); - while (c && (s || (k = getcomp(head)) == C_no)) { - if (s) - s = 0; - else - s = (isptr ? c == '~' : c == '\\') - && (getcomp(head + 1) != C_no); - if (!s) - *w++ = c; - c = *++head; - } - *w = 0; - *comp = k; - return k == C_no ? NULL : &head[k & 3]; -} - -static int compare(struct json_object *o, const char *value) -{ - switch (json_object_get_type(o)) { - case json_type_double: - return json_object_get_double(o) - atof(value); - case json_type_int: - return json_object_get_int64(o) - (int64_t)atoll(value); - default: - return strcmp(json_object_get_string(o), value); - } -} - -static int evalcomp(struct json_object *o, char *value, enum comp k) -{ - int r, c; - - c = compare(o, value); - switch (k) { - case C_eq: r = c == 0; break; -#if !defined(NO_COMPARE_VALUE_EXTENSION_FOR_MUSTACH) - case C_lt: r = c < 0; break; - case C_le: r = c <= 0; break; - case C_gt: r = c > 0; break; - case C_ge: r = c >= 0; break; -#endif - default: r = 0; break; - } - return r; -} -#else -static inline char *keyval(char *head, int isptr, enum comp *comp) -{ - *comp = C_no; - return NULL; -} -static inline int compare(struct json_object *o, char *value, enum comp k) -{ - return 0; -} -#endif - -static char *key(char **head, int isptr) -{ - char *r, *i, *w, c; - - c = *(i = *head); - if (!c) - r = NULL; - else { - r = w = i; -#if !defined(NO_JSON_POINTER_EXTENSION_FOR_MUSTACH) - if (isptr) - while (c && c != '/') { - if (c == '~') - switch (i[1]) { - case '1': c = '/'; /*@fallthrough@*/ - case '0': i++; - } - *w++ = c; - c = *++i; - } - else -#endif - while (c && c != '.') { - if (c == '\\' && (i[1] == '.' || i[1] == '\\')) - c = *++i; - *w++ = c; - c = *++i; - } - *w = 0; - *head = i + !!c; - } - return r; -} - -static struct json_object *find(struct expl *e, const char *name) -{ - int i, isptr; - struct json_object *o, *no; - char *n, *c, *v; - enum comp k; - - n = alloca(1 + strlen(name)); - strcpy(n, name); - isptr = 0; -#if !defined(NO_JSON_POINTER_EXTENSION_FOR_MUSTACH) - isptr = n[0] == '/'; - n += isptr; -#endif - - v = keyval(n, isptr, &k); -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - e->found_objiter = 0; -#endif -#if !defined(NO_SINGLE_DOT_EXTENSION_FOR_MUSTACH) - if (n[0] == '.' && !n[1]) { - /* case of . alone */ - o = e->stack[e->depth].obj; - } else -#endif - { - c = key(&n, isptr); - if (c == NULL) - return NULL; - o = NULL; - i = e->depth; - while (i >= 0 && !json_object_object_get_ex(e->stack[i].obj, c, &o)) - i--; - if (i < 0) { -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - o = e->stack[e->depth].obj; - if (c[0] == '*' && !c[1] && !v && !key(&n, isptr) && json_object_is_type(o, json_type_object)) { - e->found_objiter = 1; - return o; - } -#endif - return NULL; - } - c = key(&n, isptr); - while(c) { - if (!json_object_object_get_ex(o, c, &no)) { -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - if (c[0] == '*' && !c[1] && !v && !key(&n, isptr) && json_object_is_type(o, json_type_object)) { - e->found_objiter = 1; - return o; - } -#endif - return NULL; - } - o = no; - c = key(&n, isptr); - } - } - if (v) { - i = v[0] == '!'; - if (i == evalcomp(o, &v[i], k)) - o = NULL; - } - return o; -} - -static int start(void *closure) -{ - struct expl *e = closure; - e->depth = 0; - e->stack[0].cont = NULL; - e->stack[0].obj = e->root; - e->stack[0].index = 0; - e->stack[0].count = 1; - return MUSTACH_OK; -} - -static int write(struct expl *e, const char *buffer, size_t size, FILE *file) -{ - return e->writecb(file, buffer, size); -} - -static int emituw(void *closure, const char *buffer, size_t size, int escape, FILE *file) -{ - struct expl *e = closure; - if (!escape) - write(e, buffer, size, file); - else - do { - switch(*buffer) { - case '<': write(e, "<", 4, file); break; - case '>': write(e, ">", 4, file); break; - case '&': write(e, "&", 5, file); break; - default: write(e, buffer, 1, file); break; - } - buffer++; - } while(--size); - return MUSTACH_OK; -} - -static const char *item(struct expl *e, const char *name) -{ - struct json_object *o; - const char *s; - -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - if (name[0] == '*' && !name[1] && e->stack[e->depth].is_objiter) - s = json_object_iter_peek_name(&e->stack[e->depth].biter); - else - s = (o = find(e, name)) && !e->found_objiter ? json_object_get_string(o) : NULL; -#else - s = (o = find(e, name)) ? json_object_get_string(o) : NULL; -#endif - return s; -} - -static int enter(void *closure, const char *name) -{ - struct expl *e = closure; - struct json_object *o = find(e, name); - if (++e->depth >= MUSTACH_MAX_DEPTH) - return MUSTACH_ERROR_TOO_DEEP; - if (json_object_is_type(o, json_type_array)) { - e->stack[e->depth].count = json_object_array_length(o); - if (e->stack[e->depth].count == 0) { - e->depth--; - return 0; - } - e->stack[e->depth].cont = o; - e->stack[e->depth].obj = json_object_array_get_idx(o, 0); - e->stack[e->depth].index = 0; -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - e->stack[e->depth].is_objiter = 0; - } else if (json_object_is_type(o, json_type_object) && e->found_objiter) { - e->stack[e->depth].biter = json_object_iter_begin(o); - e->stack[e->depth].eiter = json_object_iter_end(o); - if (json_object_iter_equal(&e->stack[e->depth].biter, &e->stack[e->depth].eiter)) { - e->depth--; - return 0; - } - e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].biter); - e->stack[e->depth].cont = o; - e->stack[e->depth].is_objiter = 1; -#endif - } else if (json_object_is_type(o, json_type_object) || json_object_get_boolean(o)) { - e->stack[e->depth].count = 1; - e->stack[e->depth].cont = NULL; - e->stack[e->depth].obj = o; - e->stack[e->depth].index = 0; -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - e->stack[e->depth].is_objiter = 0; -#endif - } else { - e->depth--; - return 0; - } - return 1; -} - -static int next(void *closure) -{ - struct expl *e = closure; - if (e->depth <= 0) - return MUSTACH_ERROR_CLOSING; -#if !defined(NO_OBJECT_ITERATION_FOR_MUSTACH) - if (e->stack[e->depth].is_objiter) { - json_object_iter_next(&e->stack[e->depth].biter); - if (json_object_iter_equal(&e->stack[e->depth].biter, &e->stack[e->depth].eiter)) - return 0; - e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].biter); - return 1; - } -#endif - e->stack[e->depth].index++; - if (e->stack[e->depth].index >= e->stack[e->depth].count) - return 0; - e->stack[e->depth].obj = json_object_array_get_idx(e->stack[e->depth].cont, e->stack[e->depth].index); - return 1; -} - -static int leave(void *closure) -{ - struct expl *e = closure; - if (e->depth <= 0) - return MUSTACH_ERROR_CLOSING; - e->depth--; - return 0; -} - -#if !defined(NO_INCLUDE_PARTIAL_FALLBACK) -static int get_partial_from_file(const char *name, struct mustach_sbuf *sbuf) -{ - static char extension[] = INCLUDE_PARTIAL_EXTENSION; - size_t s; - long pos; - FILE *file; - char *path, *buffer; - - /* allocate path */ - s = strlen(name); - path = malloc(s + sizeof extension); - if (path == NULL) - return MUSTACH_ERROR_SYSTEM; - - /* try without extension first */ - memcpy(path, name, s + 1); - file = fopen(path, "r"); - if (file == NULL) { - memcpy(&path[s], extension, sizeof extension); - file = fopen(path, "r"); - } - free(path); - - /* if file opened */ - if (file != NULL) { - /* compute file size */ - if (fseek(file, 0, SEEK_END) >= 0 - && (pos = ftell(file)) >= 0 - && fseek(file, 0, SEEK_SET) >= 0) { - /* allocate value */ - s = (size_t)pos; - buffer = malloc(s + 1); - if (buffer != NULL) { - /* read value */ - if (1 == fread(buffer, s, 1, file)) { - /* force zero at end */ - sbuf->value = buffer; - buffer[s] = 0; - sbuf->freecb = free; - fclose(file); - return MUSTACH_OK; - } - free(buffer); - } - } - fclose(file); - } - return MUSTACH_ERROR_SYSTEM; -} - -static int partial(void *closure, const char *name, struct mustach_sbuf *sbuf) -{ - struct expl *e = closure; - const char *s; - - s = item(e, name); - if (s) - sbuf->value = s; - else if (get_partial_from_file(name, sbuf) < 0) - sbuf->value = ""; - return MUSTACH_OK; -} -#endif - -static int get(void *closure, const char *name, struct mustach_sbuf *sbuf) -{ - struct expl *e = closure; - const char *s; - - s = item(e, name); - if (s) - sbuf->value = s; - else - sbuf->value = ""; - return MUSTACH_OK; -} - -static struct mustach_itf itf = { - .start = start, - .put = NULL, - .enter = enter, - .next = next, - .leave = leave, -#if !defined(NO_INCLUDE_PARTIAL_FALLBACK) - .partial = partial, -#else - .partial =NULL, -#endif - .get = get, - .emit = NULL, - .stop = NULL -}; - -static struct mustach_itf itfuw = { - .start = start, - .put = NULL, - .enter = enter, - .next = next, - .leave = leave, -#if !defined(NO_INCLUDE_PARTIAL_FALLBACK) - .partial = partial, -#else - .partial =NULL, -#endif - .get = get, - .emit = emituw, - .stop = NULL -}; - -int fmustach_json_c(const char *template, struct json_object *root, FILE *file) -{ - struct expl e; - e.root = root; - return fmustach(template, &itf, &e, file); -} - -int fdmustach_json_c(const char *template, struct json_object *root, int fd) -{ - struct expl e; - e.root = root; - return fdmustach(template, &itf, &e, fd); -} - -int mustach_json_c(const char *template, struct json_object *root, char **result, size_t *size) -{ - struct expl e; - e.root = root; - e.writecb = NULL; - return mustach(template, &itf, &e, result, size); -} - -int umustach_json_c(const char *template, struct json_object *root, mustach_json_c_write_cb writecb, void *closure) -{ - struct expl e; - e.root = root; - e.writecb = writecb; - return fmustach(template, &itfuw, &e, closure); -} - |