exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

mustach-jansson.c (6192B)


      1 /*
      2  Author: José Bollo <jobol@nonadev.net>
      3 
      4  https://gitlab.com/jobol/mustach
      5 
      6  SPDX-License-Identifier: ISC
      7 */
      8 
      9 #ifndef _GNU_SOURCE
     10 #define _GNU_SOURCE
     11 #endif
     12 
     13 #include <stdio.h>
     14 #include <string.h>
     15 
     16 #include "mustach.h"
     17 #include "mustach-wrap.h"
     18 #include "mustach-jansson.h"
     19 
     20 struct expl {
     21 	json_t *root;
     22 	json_t *selection;
     23 	int depth;
     24 	struct {
     25 		json_t *cont;
     26 		json_t *obj;
     27 		void *iter;
     28 		int is_objiter;
     29 		size_t index, count;
     30 	} stack[MUSTACH_MAX_DEPTH];
     31 };
     32 
     33 static int start(void *closure)
     34 {
     35 	struct expl *e = closure;
     36 	e->depth = 0;
     37 	e->selection = json_null();
     38 	e->stack[0].cont = NULL;
     39 	e->stack[0].obj = e->root;
     40 	e->stack[0].index = 0;
     41 	e->stack[0].count = 1;
     42 	return MUSTACH_OK;
     43 }
     44 
     45 static int compare(void *closure, const char *value)
     46 {
     47 	struct expl *e = closure;
     48 	json_t *o = e->selection;
     49 	double d;
     50 	json_int_t i;
     51 
     52 	switch (json_typeof(o)) {
     53 	case JSON_REAL:
     54 		d = json_number_value(o) - atof(value);
     55 		return d < 0 ? -1 : d > 0 ? 1 : 0;
     56 	case JSON_INTEGER:
     57 		i = (json_int_t)json_integer_value(o) - (json_int_t)atoll(value);
     58 		return i < 0 ? -1 : i > 0 ? 1 : 0;
     59 	case JSON_STRING:
     60 		return strcmp(json_string_value(o), value);
     61 	case JSON_TRUE:
     62 		return strcmp("true", value);
     63 	case JSON_FALSE:
     64 		return strcmp("false", value);
     65 	case JSON_NULL:
     66 		return strcmp("null", value);
     67 	default:
     68 		return 1;
     69 	}
     70 }
     71 
     72 static int sel(void *closure, const char *name)
     73 {
     74 	struct expl *e = closure;
     75 	json_t *o;
     76 	int i, r;
     77 
     78 	if (name == NULL) {
     79 		o = e->stack[e->depth].obj;
     80 		r = 1;
     81 	} else {
     82 		i = e->depth;
     83 		while (i >= 0 && !(o = json_object_get(e->stack[i].obj, name)))
     84 			i--;
     85 		if (i >= 0)
     86 			r = 1;
     87 		else {
     88 			o = json_null();
     89 			r = 0;
     90 		}
     91 	}
     92 	e->selection = o;
     93 	return r;
     94 }
     95 
     96 static int subsel(void *closure, const char *name)
     97 {
     98 	struct expl *e = closure;
     99 	json_t *o = NULL;
    100 	int r = 0;
    101 
    102 	if (json_is_object(e->selection)) {
    103 		o = json_object_get(e->selection, name);
    104 		r = o != NULL;
    105 	}
    106 	else if (json_is_array(e->selection)) {
    107 		char *end;
    108 		size_t idx = (size_t)strtol(name, &end, 10);
    109 		if (!*end && idx < json_array_size(e->selection)) {
    110 			o = json_array_get(e->selection, idx);
    111 			r = 1;
    112 		}		
    113 	}
    114 	if (r)
    115 		e->selection = o;
    116 	return r;
    117 }
    118 
    119 static int enter(void *closure, int objiter)
    120 {
    121 	struct expl *e = closure;
    122 	json_t *o;
    123 
    124 	if (++e->depth >= MUSTACH_MAX_DEPTH)
    125 		return MUSTACH_ERROR_TOO_DEEP;
    126 
    127 	o = e->selection;
    128 	e->stack[e->depth].is_objiter = 0;
    129 	if (objiter) {
    130 		if (!json_is_object(o))
    131 			goto not_entering;
    132 		e->stack[e->depth].iter = json_object_iter(o);
    133 		if (e->stack[e->depth].iter == NULL)
    134 			goto not_entering;
    135 		e->stack[e->depth].obj = json_object_iter_value(e->stack[e->depth].iter);
    136 		e->stack[e->depth].cont = o;
    137 		e->stack[e->depth].is_objiter = 1;
    138 	} else if (json_is_array(o)) {
    139 		e->stack[e->depth].count = json_array_size(o);
    140 		if (e->stack[e->depth].count == 0)
    141 			goto not_entering;
    142 		e->stack[e->depth].cont = o;
    143 		e->stack[e->depth].obj = json_array_get(o, 0);
    144 		e->stack[e->depth].index = 0;
    145 	} else if ((json_is_object(o) && json_object_size(o))
    146                 || json_is_true(o)
    147 	        || (json_is_string(o) && json_string_length(o) > 0)
    148 	        || (json_is_integer(o) && json_integer_value(o) != 0)
    149 	        || (json_is_real(o) && json_real_value(o) != 0)) {
    150 		e->stack[e->depth].count = 1;
    151 		e->stack[e->depth].cont = NULL;
    152 		e->stack[e->depth].obj = o;
    153 		e->stack[e->depth].index = 0;
    154 	} else
    155 		goto not_entering;
    156 	return 1;
    157 
    158 not_entering:
    159 	e->depth--;
    160 	return 0;
    161 }
    162 
    163 static int next(void *closure)
    164 {
    165 	struct expl *e = closure;
    166 
    167 	if (e->depth <= 0)
    168 		return MUSTACH_ERROR_CLOSING;
    169 
    170 	if (e->stack[e->depth].is_objiter) {
    171 		e->stack[e->depth].iter = json_object_iter_next(e->stack[e->depth].cont, e->stack[e->depth].iter);
    172 		if (e->stack[e->depth].iter == NULL)
    173 			return 0;
    174 		e->stack[e->depth].obj = json_object_iter_value(e->stack[e->depth].iter);
    175 		return 1;
    176 	}
    177 
    178 	e->stack[e->depth].index++;
    179 	if (e->stack[e->depth].index >= e->stack[e->depth].count)
    180 		return 0;
    181 
    182 	e->stack[e->depth].obj = json_array_get(e->stack[e->depth].cont, e->stack[e->depth].index);
    183 	return 1;
    184 }
    185 
    186 static int leave(void *closure)
    187 {
    188 	struct expl *e = closure;
    189 
    190 	if (e->depth <= 0)
    191 		return MUSTACH_ERROR_CLOSING;
    192 
    193 	e->depth--;
    194 	return 0;
    195 }
    196 
    197 static int get(void *closure, struct mustach_sbuf *sbuf, int key)
    198 {
    199 	struct expl *e = closure;
    200 	const char *s;
    201 	int d;
    202 
    203 	if (key) {
    204 		s = "";
    205 		for (d = e->depth ; d >= 0 ; d--)
    206 			if (e->stack[d].is_objiter) {
    207 				s = json_object_iter_key(e->stack[d].iter);
    208 				break;
    209 			}
    210 	}
    211 	else if (json_is_string(e->selection))
    212 		s = json_string_value(e->selection);
    213 	else if (json_is_null(e->selection))
    214 		s = "";
    215 	else {
    216 		s = json_dumps(e->selection, JSON_ENCODE_ANY | JSON_COMPACT);
    217 		if (s == NULL)
    218 			return MUSTACH_ERROR_SYSTEM;
    219 		sbuf->freecb = free;
    220 	}
    221 	sbuf->value = s;
    222 	return 1;
    223 }
    224 
    225 const struct mustach_wrap_itf mustach_jansson_wrap_itf = {
    226 	.start = start,
    227 	.stop = NULL,
    228 	.compare = compare,
    229 	.sel = sel,
    230 	.subsel = subsel,
    231 	.enter = enter,
    232 	.next = next,
    233 	.leave = leave,
    234 	.get = get
    235 };
    236 
    237 int mustach_jansson_file(const char *template, size_t length, json_t *root, int flags, FILE *file)
    238 {
    239 	struct expl e;
    240 	e.root = root;
    241 	return mustach_wrap_file(template, length, &mustach_jansson_wrap_itf, &e, flags, file);
    242 }
    243 
    244 int mustach_jansson_fd(const char *template, size_t length, json_t *root, int flags, int fd)
    245 {
    246 	struct expl e;
    247 	e.root = root;
    248 	return mustach_wrap_fd(template, length, &mustach_jansson_wrap_itf, &e, flags, fd);
    249 }
    250 
    251 int mustach_jansson_mem(const char *template, size_t length, json_t *root, int flags, char **result, size_t *size)
    252 {
    253 	struct expl e;
    254 	e.root = root;
    255 	return mustach_wrap_mem(template, length, &mustach_jansson_wrap_itf, &e, flags, result, size);
    256 }
    257 
    258 int mustach_jansson_write(const char *template, size_t length, json_t *root, int flags, mustach_write_cb_t *writecb, void *closure)
    259 {
    260 	struct expl e;
    261 	e.root = root;
    262 	return mustach_wrap_write(template, length, &mustach_jansson_wrap_itf, &e, flags, writecb, closure);
    263 }
    264 
    265 int mustach_jansson_emit(const char *template, size_t length, json_t *root, int flags, mustach_emit_cb_t *emitcb, void *closure)
    266 {
    267 	struct expl e;
    268 	e.root = root;
    269 	return mustach_wrap_emit(template, length, &mustach_jansson_wrap_itf, &e, flags, emitcb, closure);
    270 }
    271