exchange

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

mustach-json-c.c (6948B)


      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-json-c.h"
     19 
     20 struct expl {
     21 	struct json_object *root;
     22 	struct json_object *selection;
     23 	int depth;
     24 	struct {
     25 		struct json_object *cont;
     26 		struct json_object *obj;
     27 		struct json_object_iterator iter;
     28 		struct json_object_iterator enditer;
     29 		int is_objiter;
     30 		int index, count;
     31 	} stack[MUSTACH_MAX_DEPTH];
     32 };
     33 
     34 static int start(void *closure)
     35 {
     36 	struct expl *e = closure;
     37 	e->depth = 0;
     38 	e->selection = NULL;
     39 	e->stack[0].cont = NULL;
     40 	e->stack[0].obj = e->root;
     41 	e->stack[0].index = 0;
     42 	e->stack[0].count = 1;
     43 	return MUSTACH_OK;
     44 }
     45 
     46 static int compare(void *closure, const char *value)
     47 {
     48 	struct expl *e = closure;
     49 	struct json_object *o = e->selection;
     50 	double d;
     51 	int64_t i;
     52 
     53 	switch (json_object_get_type(o)) {
     54 	case json_type_double:
     55 		d = json_object_get_double(o) - atof(value);
     56 		return d < 0 ? -1 : d > 0 ? 1 : 0;
     57 	case json_type_int:
     58 		i = json_object_get_int64(o) - (int64_t)atoll(value);
     59 		return i < 0 ? -1 : i > 0 ? 1 : 0;
     60 	default:
     61 		return strcmp(json_object_get_string(o), value);
     62 	}
     63 }
     64 
     65 static int sel(void *closure, const char *name)
     66 {
     67 	struct expl *e = closure;
     68 	struct json_object *o;
     69 	int i, r;
     70 
     71 	if (name == NULL) {
     72 		o = e->stack[e->depth].obj;
     73 		r = 1;
     74 	} else {
     75 		i = e->depth;
     76 		while (i >= 0 && !json_object_object_get_ex(e->stack[i].obj, name, &o))
     77 			i--;
     78 		if (i >= 0)
     79 			r = 1;
     80 		else {
     81 			o = NULL;
     82 			r = 0;
     83 		}
     84 	}
     85 	e->selection = o;
     86 	return r;
     87 }
     88 
     89 static int subsel(void *closure, const char *name)
     90 {
     91 	struct expl *e = closure;
     92 	struct json_object *o = NULL;
     93 	int r = 0;
     94 
     95 	if (json_object_is_type(e->selection, json_type_object))
     96 		r = json_object_object_get_ex(e->selection, name, &o);
     97 	else if (json_object_is_type(e->selection, json_type_array)) {
     98 		char *end;
     99 		size_t idx = (size_t)strtol(name, &end, 10);
    100 		if (!*end && idx < json_object_array_length(e->selection)) {
    101 			o = json_object_array_get_idx(e->selection, idx);
    102 			r = 1;
    103 		}
    104 	}
    105 	if (r)
    106 		e->selection = o;
    107 	return r;
    108 }
    109 
    110 static int enter(void *closure, int objiter)
    111 {
    112 	struct expl *e = closure;
    113 	struct json_object *o;
    114 
    115 	if (++e->depth >= MUSTACH_MAX_DEPTH)
    116 		return MUSTACH_ERROR_TOO_DEEP;
    117 
    118 	o = e->selection;
    119 	e->stack[e->depth].is_objiter = 0;
    120 	if (objiter) {
    121 		if (!json_object_is_type(o, json_type_object))
    122 			goto not_entering;
    123 
    124 		e->stack[e->depth].iter = json_object_iter_begin(o);
    125 		e->stack[e->depth].enditer = json_object_iter_end(o);
    126 		if (json_object_iter_equal(&e->stack[e->depth].iter, &e->stack[e->depth].enditer))
    127 			goto not_entering;
    128 		e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].iter);
    129 		e->stack[e->depth].cont = o;
    130 		e->stack[e->depth].is_objiter = 1;
    131 	} else if (json_object_is_type(o, json_type_array)) {
    132 		e->stack[e->depth].count = json_object_array_length(o);
    133 		if (e->stack[e->depth].count == 0)
    134 			goto not_entering;
    135 		e->stack[e->depth].cont = o;
    136 		e->stack[e->depth].obj = json_object_array_get_idx(o, 0);
    137 		e->stack[e->depth].index = 0;
    138 	} else if ((json_object_is_type(o, json_type_object) && json_object_object_length(o) > 0)
    139 		|| json_object_get_boolean(o)) {
    140 		e->stack[e->depth].count = 1;
    141 		e->stack[e->depth].cont = NULL;
    142 		e->stack[e->depth].obj = o;
    143 		e->stack[e->depth].index = 0;
    144 	} else
    145 		goto not_entering;
    146 	return 1;
    147 
    148 not_entering:
    149 	e->depth--;
    150 	return 0;
    151 }
    152 
    153 static int next(void *closure)
    154 {
    155 	struct expl *e = closure;
    156 
    157 	if (e->depth <= 0)
    158 		return MUSTACH_ERROR_CLOSING;
    159 
    160 	if (e->stack[e->depth].is_objiter) {
    161 		json_object_iter_next(&e->stack[e->depth].iter);
    162 		if (json_object_iter_equal(&e->stack[e->depth].iter, &e->stack[e->depth].enditer))
    163 			return 0;
    164 		e->stack[e->depth].obj = json_object_iter_peek_value(&e->stack[e->depth].iter);
    165 		return 1;
    166 	}
    167 
    168 	e->stack[e->depth].index++;
    169 	if (e->stack[e->depth].index >= e->stack[e->depth].count)
    170 		return 0;
    171 
    172 	e->stack[e->depth].obj = json_object_array_get_idx(e->stack[e->depth].cont, e->stack[e->depth].index);
    173 	return 1;
    174 }
    175 
    176 static int leave(void *closure)
    177 {
    178 	struct expl *e = closure;
    179 
    180 	if (e->depth <= 0)
    181 		return MUSTACH_ERROR_CLOSING;
    182 
    183 	e->depth--;
    184 	return 0;
    185 }
    186 
    187 static int get(void *closure, struct mustach_sbuf *sbuf, int key)
    188 {
    189 	struct expl *e = closure;
    190 	const char *s;
    191 	int d;
    192 
    193 	if (key) {
    194 		s = "";
    195 		for (d = e->depth ; d >= 0 ; d--)
    196 			if (e->stack[d].is_objiter) {
    197 				s = json_object_iter_peek_name(&e->stack[d].iter);
    198 				break;
    199 			}
    200 	}
    201 	else
    202 		switch (json_object_get_type(e->selection)) {
    203 		case json_type_string:
    204 			s = json_object_get_string(e->selection);
    205 			break;
    206 		case json_type_null:
    207 			s = "";
    208 			break;
    209 		default:
    210 			s = json_object_to_json_string_ext(e->selection, 0);
    211 			break;
    212 		}
    213 	sbuf->value = s;
    214 	return 1;
    215 }
    216 
    217 const struct mustach_wrap_itf mustach_json_c_wrap_itf = {
    218 	.start = start,
    219 	.stop = NULL,
    220 	.compare = compare,
    221 	.sel = sel,
    222 	.subsel = subsel,
    223 	.enter = enter,
    224 	.next = next,
    225 	.leave = leave,
    226 	.get = get
    227 };
    228 
    229 int mustach_json_c_file(const char *template, size_t length, struct json_object *root, int flags, FILE *file)
    230 {
    231 	struct expl e;
    232 	e.root = root;
    233 	return mustach_wrap_file(template, length, &mustach_json_c_wrap_itf, &e, flags, file);
    234 }
    235 
    236 int mustach_json_c_fd(const char *template, size_t length, struct json_object *root, int flags, int fd)
    237 {
    238 	struct expl e;
    239 	e.root = root;
    240 	return mustach_wrap_fd(template, length, &mustach_json_c_wrap_itf, &e, flags, fd);
    241 }
    242 
    243 int mustach_json_c_mem(const char *template, size_t length, struct json_object *root, int flags, char **result, size_t *size)
    244 {
    245 	struct expl e;
    246 	e.root = root;
    247 	return mustach_wrap_mem(template, length, &mustach_json_c_wrap_itf, &e, flags, result, size);
    248 }
    249 
    250 int mustach_json_c_write(const char *template, size_t length, struct json_object *root, int flags, mustach_write_cb_t *writecb, void *closure)
    251 {
    252 	struct expl e;
    253 	e.root = root;
    254 	return mustach_wrap_write(template, length, &mustach_json_c_wrap_itf, &e, flags, writecb, closure);
    255 }
    256 
    257 int mustach_json_c_emit(const char *template, size_t length, struct json_object *root, int flags, mustach_emit_cb_t *emitcb, void *closure)
    258 {
    259 	struct expl e;
    260 	e.root = root;
    261 	return mustach_wrap_emit(template, length, &mustach_json_c_wrap_itf, &e, flags, emitcb, closure);
    262 }
    263 
    264 int fmustach_json_c(const char *template, struct json_object *root, FILE *file)
    265 {
    266 	return mustach_json_c_file(template, 0, root, -1, file);
    267 }
    268 
    269 int fdmustach_json_c(const char *template, struct json_object *root, int fd)
    270 {
    271 	return mustach_json_c_fd(template, 0, root, -1, fd);
    272 }
    273 
    274 int mustach_json_c(const char *template, struct json_object *root, char **result, size_t *size)
    275 {
    276 	return mustach_json_c_mem(template, 0, root, -1, result, size);
    277 }
    278 
    279 int umustach_json_c(const char *template, struct json_object *root, mustach_write_cb_t *writecb, void *closure)
    280 {
    281 	return mustach_json_c_write(template, 0, root, -1, writecb, closure);
    282 }
    283 
    284