2 Author: José Bollo <jobol@nonadev.net>
3 Author: José Bollo <jose.bollo@iot.bzh>
5 https://gitlab.com/jobol/mustach
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
11 http://www.apache.org/licenses/LICENSE-2.0
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS,
15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 See the License for the specific language governing permissions and
17 limitations under the License.
25 #include <json-c/json.h>
33 struct json_object *root;
36 struct json_object *cont;
37 struct json_object *obj;
43 * Scan a key=val text.
44 * If the sign = is found, drop it and returns a pointer to the value.
45 * If the sign = is not here, returns NULL.
46 * Replace any \= of the key by its unescaped version =.
48 static char *keyval(char *head)
53 while (c && c != '=') {
57 case '=': c = *++head;
65 return c == '=' ? ++head : NULL;
69 * Returns the unescaped version of the first component
70 * and update 'name' to point the next components if any.
72 static char *first(char **name)
81 while (c && c != '.') {
82 if (c == '\\' && (i[1] == '.' || i[1] == '\\'))
94 * Replace the last occurence of ':' followed by
95 * any character not being '*' by ':*', the
96 * globalisation of the key.
97 * Returns NULL if no globalisation is done
98 * or else the key globalized.
100 static char *globalize(char *key)
105 for (r = key; *r ; r++) {
106 if (r[0] == ':' && r[1] && r[1] != '*')
118 * find the object of 'name'
120 static struct json_object *find(struct expl *e, const char *name)
123 struct json_object *o, *r;
126 /* get a local key */
129 /* extract its value */
132 /* search the first component for each valid globalisation */
137 /* next globalisation */
141 else if (json_object_object_get_ex(e->stack[i].obj, c, &o)) {
143 /* found the root, search the subcomponents */
146 while (!json_object_object_get_ex(o, c, &r)) {
155 /* check the value if requested */
158 if (i == !strcmp(&v[i], json_object_get_string(o)))
168 static int start(void *closure)
170 struct expl *e = closure;
172 e->stack[0].cont = NULL;
173 e->stack[0].obj = e->root;
174 e->stack[0].index = 0;
175 e->stack[0].count = 1;
179 static void print(FILE *file, const char *string, int escape)
186 case '%': fputs("%%", file); break;
187 case '\n': fputs("\\n\\\n", file); break;
188 default: putc(*string, file); break;
193 static int put(void *closure, const char *name, int escape, FILE *file)
195 struct expl *e = closure;
196 struct json_object *o = find(e, name);
198 print(file, json_object_get_string(o), escape);
202 static int enter(void *closure, const char *name)
204 struct expl *e = closure;
205 struct json_object *o = find(e, name);
206 if (++e->depth >= MAX_DEPTH)
207 return MUSTACH_ERROR_TOO_DEPTH;
208 if (json_object_is_type(o, json_type_array)) {
209 e->stack[e->depth].count = json_object_array_length(o);
210 if (e->stack[e->depth].count == 0) {
214 e->stack[e->depth].cont = o;
215 e->stack[e->depth].obj = json_object_array_get_idx(o, 0);
216 e->stack[e->depth].index = 0;
217 } else if (json_object_is_type(o, json_type_object) || json_object_get_boolean(o)) {
218 e->stack[e->depth].count = 1;
219 e->stack[e->depth].cont = NULL;
220 e->stack[e->depth].obj = o;
221 e->stack[e->depth].index = 0;
229 static int next(void *closure)
231 struct expl *e = closure;
233 return MUSTACH_ERROR_CLOSING;
234 e->stack[e->depth].index++;
235 if (e->stack[e->depth].index >= e->stack[e->depth].count)
237 e->stack[e->depth].obj = json_object_array_get_idx(e->stack[e->depth].cont, e->stack[e->depth].index);
241 static int leave(void *closure)
243 struct expl *e = closure;
245 return MUSTACH_ERROR_CLOSING;
250 static struct mustach_itf itf = {
258 int apply_mustach(const char *template, struct json_object *root, char **result, size_t *size)
262 return mustach(template, &itf, &e, result, size);