exchange

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

mustach-cjson.c (5534B)


      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 #include <stdlib.h>
     16 
     17 #include "mustach.h"
     18 #include "mustach-wrap.h"
     19 #include "mustach-cjson.h"
     20 
     21 struct expl {
     22 	cJSON null;
     23 	cJSON *root;
     24 	cJSON *selection;
     25 	int depth;
     26 	struct {
     27 		cJSON *cont;
     28 		cJSON *obj;
     29 		cJSON *next;
     30 		int is_objiter;
     31 	} stack[MUSTACH_MAX_DEPTH];
     32 };
     33 
     34 static int start(void *closure)
     35 {
     36 	struct expl *e = closure;
     37 	e->depth = 0;
     38 	memset(&e->null, 0, sizeof e->null);
     39 	e->null.type = cJSON_NULL;
     40 	e->selection = &e->null;
     41 	e->stack[0].cont = NULL;
     42 	e->stack[0].obj = e->root;
     43 	return MUSTACH_OK;
     44 }
     45 
     46 static int compare(void *closure, const char *value)
     47 {
     48 	struct expl *e = closure;
     49 	cJSON *o = e->selection;
     50 	double d;
     51 
     52 	if (cJSON_IsNumber(o)) {
     53 		d = o->valuedouble - atof(value);
     54 		return d < 0 ? -1 : d > 0 ? 1 : 0;
     55 	} else if (cJSON_IsString(o)) {
     56 		return strcmp(o->valuestring, value);
     57 	} else if (cJSON_IsTrue(o)) {
     58 		return strcmp("true", value);
     59 	} else if (cJSON_IsFalse(o)) {
     60 		return strcmp("false", value);
     61 	} else if (cJSON_IsNull(o)) {
     62 		return strcmp("null", value);
     63 	} else {
     64 		return 1;
     65 	}
     66 }
     67 
     68 static int sel(void *closure, const char *name)
     69 {
     70 	struct expl *e = closure;
     71 	cJSON *o;
     72 	int i, r;
     73 
     74 	if (name == NULL) {
     75 		o = e->stack[e->depth].obj;
     76 		r = 1;
     77 	} else {
     78 		i = e->depth;
     79 		while (i >= 0 && !(o = cJSON_GetObjectItemCaseSensitive(e->stack[i].obj, name)))
     80 			i--;
     81 		if (i >= 0)
     82 			r = 1;
     83 		else {
     84 			o = &e->null;
     85 			r = 0;
     86 		}
     87 	}
     88 	e->selection = o;
     89 	return r;
     90 }
     91 
     92 static int subsel(void *closure, const char *name)
     93 {
     94 	struct expl *e = closure;
     95 	cJSON *o = NULL;
     96 	int r = 0;
     97 
     98 	if (cJSON_IsObject(e->selection)) {
     99 		o = cJSON_GetObjectItemCaseSensitive(e->selection, name);
    100 		r = o != NULL;
    101 	}
    102 	else if (cJSON_IsArray(e->selection) && *name) {
    103 		char *end;
    104 		int idx = (int)strtol(name, &end, 10);
    105 		if (!*end && idx >= 0 && idx < cJSON_GetArraySize(e->selection)) {
    106 			o = cJSON_GetArrayItem(e->selection, idx);
    107 			r = 1;
    108 		}
    109 	}
    110 	if (r)
    111 		e->selection = o;
    112 	return r;
    113 }
    114 
    115 static int enter(void *closure, int objiter)
    116 {
    117 	struct expl *e = closure;
    118 	cJSON *o;
    119 
    120 	if (++e->depth >= MUSTACH_MAX_DEPTH)
    121 		return MUSTACH_ERROR_TOO_DEEP;
    122 
    123 	o = e->selection;
    124 	e->stack[e->depth].is_objiter = 0;
    125 	if (objiter) {
    126 		if (! cJSON_IsObject(o))
    127 			goto not_entering;
    128 		if (o->child == NULL)
    129 			goto not_entering;
    130 		e->stack[e->depth].obj = o->child;
    131 		e->stack[e->depth].next = o->child->next;
    132 		e->stack[e->depth].cont = o;
    133 		e->stack[e->depth].is_objiter = 1;
    134 	} else if (cJSON_IsArray(o)) {
    135 		if (o->child == NULL)
    136 			goto not_entering;
    137 		e->stack[e->depth].obj = o->child;
    138 		e->stack[e->depth].next = o->child->next;
    139 		e->stack[e->depth].cont = o;
    140 	} else if ((cJSON_IsObject(o) && o->child != NULL)
    141 	        || cJSON_IsTrue(o)
    142 	        || (cJSON_IsString(o) && cJSON_GetStringValue(o)[0] != '\0')
    143 	        || (cJSON_IsNumber(o) && cJSON_GetNumberValue(o) != 0)) {
    144 		e->stack[e->depth].obj = o;
    145 		e->stack[e->depth].cont = NULL;
    146 		e->stack[e->depth].next = NULL;
    147 	} else
    148 		goto not_entering;
    149 	return 1;
    150 
    151 not_entering:
    152 	e->depth--;
    153 	return 0;
    154 }
    155 
    156 static int next(void *closure)
    157 {
    158 	struct expl *e = closure;
    159 	cJSON *o;
    160 
    161 	if (e->depth <= 0)
    162 		return MUSTACH_ERROR_CLOSING;
    163 
    164 	o = e->stack[e->depth].next;
    165 	if (o == NULL)
    166 		return 0;
    167 
    168 	e->stack[e->depth].obj = o;
    169 	e->stack[e->depth].next = o->next;
    170 	return 1;
    171 }
    172 
    173 static int leave(void *closure)
    174 {
    175 	struct expl *e = closure;
    176 
    177 	if (e->depth <= 0)
    178 		return MUSTACH_ERROR_CLOSING;
    179 
    180 	e->depth--;
    181 	return 0;
    182 }
    183 
    184 static int get(void *closure, struct mustach_sbuf *sbuf, int key)
    185 {
    186 	struct expl *e = closure;
    187 	const char *s;
    188 	int d;
    189 
    190 	if (key) {
    191 		s = "";
    192 		for (d = e->depth ; d >= 0 ; d--)
    193 			if (e->stack[d].is_objiter) {
    194 				s = e->stack[d].obj->string;
    195 				break;
    196 			}
    197 	}
    198 	else if (cJSON_IsString(e->selection))
    199 		s = e->selection->valuestring;
    200 	else if (cJSON_IsNull(e->selection))
    201 		s = "";
    202 	else {
    203 		s = cJSON_PrintUnformatted(e->selection);
    204 		if (s == NULL)
    205 			return MUSTACH_ERROR_SYSTEM;
    206 		sbuf->freecb = cJSON_free;
    207 	}
    208 	sbuf->value = s;
    209 	return 1;
    210 }
    211 
    212 const struct mustach_wrap_itf mustach_cJSON_wrap_itf = {
    213 	.start = start,
    214 	.stop = NULL,
    215 	.compare = compare,
    216 	.sel = sel,
    217 	.subsel = subsel,
    218 	.enter = enter,
    219 	.next = next,
    220 	.leave = leave,
    221 	.get = get
    222 };
    223 
    224 int mustach_cJSON_file(const char *template, size_t length, cJSON *root, int flags, FILE *file)
    225 {
    226 	struct expl e;
    227 	e.root = root;
    228 	return mustach_wrap_file(template, length, &mustach_cJSON_wrap_itf, &e, flags, file);
    229 }
    230 
    231 int mustach_cJSON_fd(const char *template, size_t length, cJSON *root, int flags, int fd)
    232 {
    233 	struct expl e;
    234 	e.root = root;
    235 	return mustach_wrap_fd(template, length, &mustach_cJSON_wrap_itf, &e, flags, fd);
    236 }
    237 
    238 int mustach_cJSON_mem(const char *template, size_t length, cJSON *root, int flags, char **result, size_t *size)
    239 {
    240 	struct expl e;
    241 	e.root = root;
    242 	return mustach_wrap_mem(template, length, &mustach_cJSON_wrap_itf, &e, flags, result, size);
    243 }
    244 
    245 int mustach_cJSON_write(const char *template, size_t length, cJSON *root, int flags, mustach_write_cb_t *writecb, void *closure)
    246 {
    247 	struct expl e;
    248 	e.root = root;
    249 	return mustach_wrap_write(template, length, &mustach_cJSON_wrap_itf, &e, flags, writecb, closure);
    250 }
    251 
    252 int mustach_cJSON_emit(const char *template, size_t length, cJSON *root, int flags, mustach_emit_cb_t *emitcb, void *closure)
    253 {
    254 	struct expl e;
    255 	e.root = root;
    256 	return mustach_wrap_emit(template, length, &mustach_cJSON_wrap_itf, &e, flags, emitcb, closure);
    257 }
    258