Branch data Line data Source code
1 : : #include "codegen_c.h"
2 : : #include "flatcc/flatcc_types.h"
3 : :
4 : : /* -DFLATCC_PORTABLE may help if inttypes.h is missing. */
5 : : #ifndef PRId64
6 : : #include <inttypes.h>
7 : : #endif
8 : :
9 : 3 : static int gen_json_printer_pretext(fb_output_t *out)
10 : : {
11 : 3 : fprintf(out->fp,
12 : : "#ifndef %s_JSON_PRINTER_H\n"
13 : : "#define %s_JSON_PRINTER_H\n",
14 : 3 : out->S->basenameup, out->S->basenameup);
15 : :
16 : 3 : fprintf(out->fp, "\n/* " FLATCC_GENERATED_BY " */\n\n");
17 : 3 : fprintf(out->fp, "#include \"flatcc/flatcc_json_printer.h\"\n");
18 : 3 : fb_gen_c_includes(out, "_json_printer.h", "_JSON_PRINTER_H");
19 : : gen_pragma_push(out);
20 : 3 : fprintf(out->fp, "\n");
21 : 3 : return 0;
22 : : }
23 : :
24 : 3 : static int gen_json_printer_footer(fb_output_t *out)
25 : : {
26 : : gen_pragma_pop(out);
27 : 3 : fprintf(out->fp,
28 : : "#endif /* %s_JSON_PRINTER_H */\n",
29 : 3 : out->S->basenameup);
30 : 3 : return 0;
31 : : }
32 : :
33 : 3 : static int gen_json_printer_enum(fb_output_t *out, fb_compound_type_t *ct)
34 : : {
35 : : fb_symbol_t *sym;
36 : : fb_member_t *member;
37 : : fb_scoped_name_t snt, snref;
38 : : const char *tp, *tn, *ns;
39 : : int bit_flags;
40 : : uint64_t mask;
41 : : char *suffix;
42 : : char *ut;
43 : :
44 : 3 : fb_clear(snt);
45 : 3 : fb_clear(snref);
46 : : fb_compound_name(ct, &snt);
47 : 3 : tp = scalar_type_prefix(ct->type.st);
48 : 3 : tn = scalar_type_name(ct->type.st);
49 : 3 : ns = scalar_type_ns(ct->type.st, out->nsc);
50 : :
51 : 3 : bit_flags = !!(ct->metadata_flags & fb_f_bit_flags);
52 [ + + ]: 3 : if (bit_flags) {
53 [ - + ]: 1 : switch (ct->size) {
54 : : case 1:
55 : : mask = 0xff, suffix = "U", ut = "uint8_t";
56 : : break;
57 : : case 2:
58 : : mask = 0xffff, suffix = "U", ut = "uint16_t";
59 : : break;
60 : : case 4:
61 : : mask = 0xffffffffL, suffix = "UL", ut = "uint32_t";
62 : : break;
63 : : default:
64 : : mask = 0xffffffffffffffffULL, suffix = "ULL", ut = "uint64_t";
65 : : break;
66 : : }
67 [ + + ]: 4 : for (sym = ct->members; sym; sym = sym->link) {
68 : : member = (fb_member_t *)sym;
69 [ - + - - ]: 3 : switch (member->value.type) {
70 : : case vt_uint:
71 : 0 : mask &= ~(uint64_t)member->value.u;
72 : 0 : break;
73 : : case vt_int:
74 : 3 : mask &= ~(uint64_t)member->value.i;
75 : 3 : break;
76 : : case vt_bool:
77 : 0 : mask &= ~(uint64_t)member->value.b;
78 : 0 : break;
79 : : }
80 : : }
81 : : }
82 : :
83 : 3 : fprintf(out->fp,
84 : : "void __%s_print_json_enum(flatcc_json_printer_t *ctx, %s%s v)\n{\n",
85 : : snt.text, ns, tn);
86 [ + + ]: 3 : if (bit_flags) {
87 [ + - ]: 1 : if (strcmp(ut, tn)) {
88 : 1 : fprintf(out->fp, " %s x = (%s)v;\n", ut, ut);
89 : : } else {
90 : 0 : fprintf(out->fp, " %s x = v;\n", ut);
91 : : }
92 : 1 : fprintf(out->fp,
93 : : " int multiple = 0 != (x & (x - 1));\n"
94 : : " int i = 0;\n");
95 : :
96 : 1 : fprintf(out->fp, "\n");
97 : : /*
98 : : * If the value is not entirely within the known bit flags, print as
99 : : * a number.
100 : : */
101 [ + - ]: 1 : if (mask) {
102 : 1 : fprintf(out->fp,
103 : : " if ((x & 0x%"PRIx64") || x == 0) {\n"
104 : : " flatcc_json_printer_%s(ctx, v);\n"
105 : : " return;\n"
106 : : " }\n",
107 : : mask, tp);
108 : : }
109 : : /*
110 : : * Test if multiple bits set. We may have a configuration option
111 : : * that requires multiple flags to be quoted like `color: "Red Green"`
112 : : * but unquoted if just a single value like `color: Green`.
113 : : *
114 : : * The index `i` is used to add space separators much like an
115 : : * index is provided for struct members to handle comma.
116 : : */
117 : 1 : fprintf(out->fp, " flatcc_json_printer_delimit_enum_flags(ctx, multiple);\n");
118 [ + + ]: 4 : for (sym = ct->members; sym; sym = sym->link) {
119 : : member = (fb_member_t *)sym;
120 [ - + - - ]: 3 : switch (member->value.type) {
121 : : case vt_uint:
122 : 0 : fprintf(out->fp, " if (x & 0x%"PRIx64"%s) flatcc_json_printer_enum_flag(ctx, i++, \"%.*s\", %ld);\n",
123 : 0 : member->value.u, suffix, (int)sym->ident->len, sym->ident->text, sym->ident->len);
124 : 0 : break;
125 : : case vt_int:
126 : 3 : fprintf(out->fp, " if (x & 0x%"PRIx64"%s) flatcc_json_printer_enum_flag(ctx, i++, \"%.*s\", %ld);\n",
127 : 6 : (uint64_t)member->value.i, suffix, (int)sym->ident->len, sym->ident->text, sym->ident->len);
128 : 3 : break;
129 : : case vt_bool:
130 : 0 : fprintf(out->fp, " if (x & 0x%"PRIx64"%s) flatcc_json_printer_enum_flag(ctx, i++, \"%.*s\", %ld);\n",
131 : 0 : (uint64_t)member->value.b, suffix, (int)sym->ident->len, sym->ident->text, sym->ident->len);
132 : 0 : break;
133 : : default:
134 : 0 : gen_panic(out, "internal error: unexpected value type for enum json_print");
135 : : break;
136 : : }
137 : : }
138 : 1 : fprintf(out->fp, " flatcc_json_printer_delimit_enum_flags(ctx, multiple);\n");
139 : : } else {
140 : 2 : fprintf(out->fp, "\n switch (v) {\n");
141 [ + + ]: 5 : for (sym = ct->members; sym; sym = sym->link) {
142 : : member = (fb_member_t *)sym;
143 [ - + - - ]: 3 : switch (member->value.type) {
144 : : case vt_uint:
145 : 0 : fprintf(out->fp, " case %"PRIu64": flatcc_json_printer_enum(ctx, \"%.*s\", %ld); break;\n",
146 : 0 : member->value.u, (int)sym->ident->len, sym->ident->text, sym->ident->len);
147 : 0 : break;
148 : : case vt_int:
149 : 3 : fprintf(out->fp, " case %"PRId64": flatcc_json_printer_enum(ctx, \"%.*s\", %ld); break;\n",
150 : 3 : member->value.i, (int)sym->ident->len, sym->ident->text, sym->ident->len);
151 : 3 : break;
152 : : case vt_bool:
153 : 0 : fprintf(out->fp, " case %u: flatcc_json_printer_enum(ctx, \"%.*s\", %ld); break;\n",
154 : 0 : member->value.b, (int)sym->ident->len, sym->ident->text, sym->ident->len);
155 : 0 : break;
156 : : default:
157 : 0 : gen_panic(out, "internal error: unexpected value type for enum json_print");
158 : : break;
159 : : }
160 : : }
161 : 2 : fprintf(out->fp,
162 : : " default: flatcc_json_printer_%s(ctx, v); break;\n"
163 : : " }\n",
164 : : tp);
165 : : }
166 : 3 : fprintf(out->fp, "}\n\n");
167 : 3 : return 0;
168 : : }
169 : :
170 : 2 : static int gen_json_printer_union(fb_output_t *out, fb_compound_type_t *ct)
171 : : {
172 : : fb_symbol_t *sym;
173 : : fb_member_t *member;
174 : : fb_scoped_name_t snt, snref;
175 : :
176 : 1 : fb_clear(snt);
177 : 1 : fb_clear(snref);
178 : : fb_compound_name(ct, &snt);
179 : :
180 : 1 : fprintf(out->fp,
181 : : "void __%s_print_json_union(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td, int id, const char *name, int len)\n"
182 : : "{\n switch (flatcc_json_printer_read_union_type(td, id)) {\n",
183 : : snt.text);
184 [ + + ]: 4 : for (sym = ct->members; sym; sym = sym->link) {
185 : : member = (fb_member_t *)sym;
186 [ + + ]: 3 : if (member->type.type == vt_missing) {
187 : : /* NONE is of type vt_missing and already handled. */
188 : 1 : continue;
189 : : }
190 : : assert(member->type.type == vt_compound_type_ref);
191 : 2 : fb_compound_name(member->type.ct, &snref);
192 : : #if FLATCC_JSON_PRINT_MAP_ENUMS
193 : 2 : fprintf(out->fp,
194 : : " case %u:\n"
195 : : " flatcc_json_printer_union_type(ctx, td, name, len, %u, \"%.*s\", %ld);\n",
196 : 4 : (unsigned)member->value.u, (unsigned)member->value.u, (int)sym->ident->len, sym->ident->text, sym->ident->len);
197 : : #else
198 : : fprintf(out->fp,
199 : : " case %u:\n"
200 : : " flatcc_json_printer_union_type(ctx, td, name, len, %u, 0, 0);\n",
201 : : (unsigned)member->value.u, (unsigned)member->value.u);
202 : : #endif
203 : 2 : fprintf(out->fp,
204 : : " flatcc_json_printer_table_field(ctx, td, id, name, len, __%s_print_json_table);\n"
205 : : " break;\n",
206 : : snref.text);
207 : : }
208 : 1 : fprintf(out->fp,
209 : : " }\n}\n\n");
210 : 1 : return 0;
211 : : }
212 : :
213 : 10 : static int gen_json_printer_struct(fb_output_t *out, fb_compound_type_t *ct)
214 : : {
215 : : fb_symbol_t *sym;
216 : : fb_member_t *member;
217 : : fb_scoped_name_t snt, snref;
218 : : int index = 0;
219 : : const char *tp;
220 : :
221 : 5 : fb_clear(snt);
222 : 5 : fb_clear(snref);
223 : : fb_compound_name(ct, &snt);
224 : :
225 : 5 : fprintf(out->fp,
226 : : "static void __%s_print_json_struct(flatcc_json_printer_t *ctx, const void *p)\n"
227 : : "{\n",
228 : : snt.text);
229 [ + + ]: 13 : for (sym = ct->members; sym; ++index, sym = sym->link) {
230 : : member = (fb_member_t *)sym;
231 [ - + ]: 8 : if (member->metadata_flags & fb_f_deprecated) {
232 : 0 : continue;
233 : : }
234 [ + + - ]: 8 : switch (member->type.type) {
235 : : case vt_scalar_type:
236 : 6 : tp = scalar_type_prefix(member->type.st);
237 : 6 : fprintf(
238 : : out->fp,
239 : : " flatcc_json_printer_%s_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld);\n",
240 : 12 : tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len);
241 : : break;
242 : : case vt_compound_type_ref:
243 : 2 : fb_compound_name(member->type.ct, &snref);
244 [ + + - ]: 2 : switch (member->type.ct->symbol.kind) {
245 : : case fb_is_enum:
246 : : #if FLATCC_JSON_PRINT_MAP_ENUMS
247 : 1 : tp = scalar_type_prefix(member->type.ct->type.st);
248 : 1 : fprintf(out->fp,
249 : : " flatcc_json_printer_%s_enum_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, &__%s_print_json_enum);\n",
250 : 2 : tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text);
251 : : break;
252 : : #else
253 : : tp = scalar_type_prefix(member->type.ct->type.st);
254 : : fprintf(
255 : : out->fp,
256 : : " flatcc_json_printer_%s_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld);\n",
257 : : tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len);
258 : : break;
259 : : #endif
260 : : case fb_is_struct:
261 : 1 : fprintf(out->fp,
262 : : " flatcc_json_printer_embedded_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, &__%s_print_json_struct);\n",
263 : 2 : index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text);
264 : : break;
265 : : }
266 : : }
267 : : }
268 : 5 : fprintf(out->fp, "}\n\n");
269 : 5 : fprintf(out->fp,
270 : : "static inline int %s_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid)\n"
271 : : "{\n return flatcc_json_printer_struct_as_root(ctx, buf, bufsiz, fid, &__%s_print_json_struct);\n}\n\n",
272 : : snt.text, snt.text);
273 : 5 : return 0;
274 : : }
275 : :
276 : 7 : static int gen_json_printer_table(fb_output_t *out, fb_compound_type_t *ct)
277 : : {
278 : : fb_symbol_t *sym;
279 : : fb_member_t *member;
280 : : fb_scoped_name_t snt, snref;
281 : : const char *tp;
282 : : fb_member_t **map;
283 : : uint64_t i;
284 : : int ret = 0;
285 : :
286 : 7 : fb_clear(snt);
287 : 7 : fb_clear(snref);
288 : : fb_compound_name(ct, &snt);
289 : :
290 : : /*
291 : : * The compound type can be iterated by the textual order of the
292 : : * parsed schema, or in a sorted order which is either
293 : : * "original_order", i.e. the textual order, or ordered by
294 : : * alignment usinger ct->ordered_members.
295 : : * The textual order makes most sense, but to provide a unique
296 : : * ordering we sort by id which is not provided by the compound
297 : : * type directly, but easy to obtain.
298 : : *
299 : : * NOTE: due to unions, not all entries will be non-zero because the
300 : : * type field is not stored as a member so calloc is important.
301 : : */
302 : 7 : map = calloc((size_t)ct->count, sizeof(*map));
303 [ - + ][ # # ]: 7 : if (!map && ct->count > 0) {
304 : 0 : gen_panic(out, "internal error: memory allocation failure");
305 : : return -1;
306 : : }
307 [ + + ]: 48 : for (sym = ct->members; sym; sym = sym->link) {
308 : : member = (fb_member_t *)sym;
309 : 41 : map[member->id] = member;
310 : : }
311 : 7 : fprintf(out->fp,
312 : : "static void __%s_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td)\n"
313 : : "{",
314 : : snt.text);
315 : :
316 [ + + ]: 49 : for (i = 0; i < ct->count; ++i) {
317 : 42 : member = map[i];
318 [ + + ]: 42 : if (!member) {
319 : : /* A union type. */
320 : 1 : continue;
321 : : }
322 : : sym = &member->symbol;
323 [ + + ]: 41 : if (member->metadata_flags & fb_f_deprecated) {
324 : 1 : continue;
325 : : }
326 : 40 : fprintf(out->fp, "\n ");
327 [ + + + + : 40 : switch (member->type.type) {
+ + - ]
328 : : case vt_scalar_type:
329 : 18 : tp = scalar_type_prefix(member->type.st);
330 : :
331 [ + + - - ]: 18 : switch(member->value.type) {
332 : : case vt_bool:
333 : : case vt_uint:
334 : 9 : fprintf( out->fp,
335 : : "flatcc_json_printer_%s_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRIu64");",
336 : 9 : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->value.u);
337 : : break;
338 : : case vt_int:
339 : 9 : fprintf( out->fp,
340 : : "flatcc_json_printer_%s_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRId64");",
341 : 9 : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->value.i);
342 : : break;
343 : : case vt_float:
344 : 0 : fprintf( out->fp,
345 : : "flatcc_json_printer_%s_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %lf);",
346 : 0 : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->value.f);
347 : : break;
348 : : default:
349 : 0 : gen_panic(out, "internal error: unexpected default value type\n");
350 : : return -1;
351 : : }
352 : : break;
353 : : case vt_vector_type:
354 [ + + ]: 3 : if (member->nest) {
355 : : fb_compound_name((fb_compound_type_t *)&member->nest->symbol, &snref);
356 [ + - ]: 1 : if (member->nest->symbol.kind == fb_is_table) {
357 : : /*
358 : : * Always set fid to 0 since it is difficult to know what is right.
359 : : * We do know the type from the field attribute.
360 : : */
361 : 1 : fprintf(out->fp,
362 : : "flatcc_json_printer_table_as_nested_root(ctx, td, %"PRIu64", \"%.*s\", %ld, 0, __%s_print_json_table);",
363 : 1 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text);
364 : : } else {
365 : : /*
366 : : * Always set fid to 0 since it is difficult to know what is right.
367 : : * We do know the type from the field attribute.
368 : : */
369 : 0 : fprintf(out->fp,
370 : : "flatcc_json_printer_struct_as_nested_root(ctx, td, %"PRIu64", \"%.*s\", %ld, 0, __%s_print_json_struct);",
371 : 0 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text);
372 : : }
373 : : } else {
374 : 2 : tp = scalar_type_prefix(member->type.st);
375 : 2 : fprintf(out->fp,
376 : : "flatcc_json_printer_%s_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld);",
377 : 2 : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len);
378 : : }
379 : : break;
380 : : case vt_string_type:
381 : 3 : fprintf(out->fp,
382 : : "flatcc_json_printer_string_field(ctx, td, %"PRIu64", \"%.*s\", %ld);",
383 : 3 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len);
384 : : break;
385 : : case vt_vector_string_type:
386 : 1 : fprintf(out->fp,
387 : : "flatcc_json_printer_string_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld);",
388 : 1 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len);
389 : : break;
390 : : case vt_compound_type_ref:
391 : 13 : fb_compound_name(member->type.ct, &snref);
392 [ + + + + : 13 : switch (member->type.ct->symbol.kind) {
- ]
393 : : case fb_is_enum:
394 : 6 : tp = scalar_type_prefix(member->type.ct->type.st);
395 [ - + - ]: 6 : switch(member->value.type) {
396 : : case vt_bool:
397 : : #if FLATCC_JSON_PRINT_MAP_ENUMS
398 : : case vt_uint:
399 : 0 : fprintf( out->fp,
400 : : "flatcc_json_printer_%s_enum_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRIu64", &__%s_print_json_enum);",
401 : 0 : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->value.u, snref.text);
402 : : break;
403 : : case vt_int:
404 : 6 : fprintf( out->fp,
405 : : "flatcc_json_printer_%s_enum_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRId64", &__%s_print_json_enum);",
406 : 6 : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->value.i, snref.text);
407 : : break;
408 : : #else
409 : : case vt_uint:
410 : : fprintf( out->fp,
411 : : "flatcc_json_printer_%s_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRIu64");",
412 : : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->value.u);
413 : : break;
414 : : case vt_int:
415 : : fprintf( out->fp,
416 : : "flatcc_json_printer_%s_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRId64");",
417 : : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->value.i);
418 : : break;
419 : : #endif
420 : : default:
421 : 0 : gen_panic(out, "internal error: unexpected default value type for enum\n");
422 : : return -1;
423 : : }
424 : : break;
425 : : case fb_is_struct:
426 : 3 : fprintf(out->fp,
427 : : "flatcc_json_printer_struct_field(ctx, td, %"PRIu64", \"%.*s\", %ld, &__%s_print_json_struct);",
428 : 3 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text);
429 : : break;
430 : : case fb_is_table:
431 : 3 : fprintf(out->fp,
432 : : "flatcc_json_printer_table_field(ctx, td, %"PRIu64", \"%.*s\", %ld, &__%s_print_json_table);",
433 : 3 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text);
434 : : break;
435 : : case fb_is_union:
436 : 1 : fprintf(out->fp,
437 : : "__%s_print_json_union(ctx, td, %"PRIu64", \"%.*s\", %ld);",
438 : 1 : snref.text, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len);
439 : : break;
440 : : default:
441 : 0 : gen_panic(out, "internal error: unexpected compound type for table json_print");
442 : : goto fail;
443 : : }
444 : : break;
445 : : case vt_vector_compound_type_ref:
446 : 2 : fb_compound_name(member->type.ct, &snref);
447 [ + - + - ]: 2 : switch (member->type.ct->symbol.kind) {
448 : : case fb_is_table:
449 : 1 : fprintf(out->fp,
450 : : "flatcc_json_printer_table_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld, &__%s_print_json_table);",
451 : 1 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text);
452 : : break;
453 : : case fb_is_enum:
454 : : #if FLATCC_JSON_PRINT_MAP_ENUMS
455 : 0 : tp = scalar_type_prefix(member->type.st);
456 : 0 : fprintf(out->fp,
457 : : "flatcc_json_printer_%s_enum_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRIu64", &__%s_print_json_enum);",
458 : 0 : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, (uint64_t)ct->size, snref.text);
459 : : break;
460 : : #else
461 : : tp = scalar_type_prefix(member->type.st);
462 : : fprintf(out->fp,
463 : : "flatcc_json_printer_%s_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld);",
464 : : tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len);
465 : : break;
466 : : #endif
467 : : case fb_is_struct:
468 : 1 : fprintf(out->fp,
469 : : "flatcc_json_printer_struct_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRIu64", &__%s_print_json_struct);",
470 : 1 : member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, (uint64_t)member->size, snref.text);
471 : : break;
472 : : default:
473 : 0 : gen_panic(out, "internal error: unexpected vector compound type for table json_print");
474 : : goto fail;
475 : : }
476 : : break;
477 : : }
478 : : }
479 : 7 : fprintf(out->fp, "\n}\n\n");
480 : 7 : fprintf(out->fp,
481 : : "static inline int %s_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid)\n"
482 : : "{\n return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, &__%s_print_json_table);\n}\n\n",
483 : : snt.text, snt.text);
484 : : done:
485 [ + - ]: 7 : if (map) {
486 : 7 : free(map);
487 : : }
488 : : return ret;
489 : : fail:
490 : : ret = -1;
491 : : goto done;
492 : : }
493 : :
494 : : /*
495 : : * Only tables are mutually recursive. Structs are sorted and unions are
496 : : * defined earlier, depending on the table prototypes.
497 : : */
498 : 6 : static int gen_json_printer_prototypes(fb_output_t *out)
499 : : {
500 : : fb_symbol_t *sym;
501 : : fb_scoped_name_t snt;
502 : 3 : fb_symbol_t *root_type = out->S->root_type.type;
503 : :
504 : 3 : fb_clear(snt);
505 : :
506 [ + + ]: 3 : if (root_type)
507 [ + - ]: 1 : switch (root_type->kind) {
508 : : case fb_is_table:
509 : : case fb_is_struct:
510 : 1 : fprintf(out->fp,
511 : : "/*\n"
512 : : " * Prints the default root table or struct from a buffer which must have\n"
513 : : " * the schema declared file identifier, if any. It is also possible to\n"
514 : : " * call the type specific `print_json_as_root` function wich accepts an\n"
515 : : " * optional identifier (or 0) as argument. The printer `ctx` object must\n"
516 : : " * be initialized with the appropriate output type, or it can be 0 which\n"
517 : : " * defaults to stdout. NOTE: `ctx` is not generally allowed to be null, only\n"
518 : : " * here for a simplified interface.\n"
519 : : " */\n");
520 : 1 : fprintf(out->fp,
521 : : "static int %s_print_json(flatcc_json_printer_t *ctx, const char *buf, size_t bufsiz);\n\n",
522 : 1 : out->S->basename);
523 : : default:
524 : : break;
525 : : }
526 : :
527 [ + + ]: 19 : for (sym = out->S->symbols; sym; sym = sym->link) {
528 [ + + ]: 16 : switch (sym->kind) {
529 : : case fb_is_table:
530 : : fb_compound_name((fb_compound_type_t *)sym, &snt);
531 : 7 : fprintf(out->fp,
532 : : "static void __%s_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td);\n",
533 : : snt.text);
534 : : }
535 : : }
536 : 3 : fprintf(out->fp, "\n");
537 : 3 : return 0;
538 : : }
539 : :
540 : 3 : static int gen_json_printer_enums(fb_output_t *out)
541 : : {
542 : : fb_symbol_t *sym;
543 : :
544 [ + + ]: 19 : for (sym = out->S->symbols; sym; sym = sym->link) {
545 [ + + ]: 16 : switch (sym->kind) {
546 : : case fb_is_enum:
547 : 3 : gen_json_printer_enum(out, (fb_compound_type_t *)sym);
548 : : }
549 : : }
550 : 3 : return 0;
551 : : }
552 : :
553 : 3 : static int gen_json_printer_unions(fb_output_t *out)
554 : : {
555 : : fb_symbol_t *sym;
556 : :
557 [ + + ]: 19 : for (sym = out->S->symbols; sym; sym = sym->link) {
558 [ + + ]: 16 : switch (sym->kind) {
559 : : case fb_is_union:
560 : 1 : gen_json_printer_union(out, (fb_compound_type_t *)sym);
561 : : }
562 : : }
563 : 3 : return 0;
564 : : }
565 : :
566 : 3 : static int gen_json_printer_structs(fb_output_t *out)
567 : : {
568 : : fb_symbol_t *sym;
569 : :
570 [ + + ]: 19 : for (sym = out->S->symbols; sym; sym = sym->link) {
571 [ + + ]: 16 : switch (sym->kind) {
572 : : case fb_is_struct:
573 : 5 : gen_json_printer_struct(out, (fb_compound_type_t *)sym);
574 : : }
575 : : }
576 : 3 : return 0;
577 : : }
578 : :
579 : 3 : static int gen_json_printer_tables(fb_output_t *out)
580 : : {
581 : : fb_symbol_t *sym;
582 : :
583 [ + + ]: 19 : for (sym = out->S->symbols; sym; sym = sym->link) {
584 [ + + ]: 16 : switch (sym->kind) {
585 : : case fb_is_table:
586 : 7 : gen_json_printer_table(out, (fb_compound_type_t *)sym);
587 : : }
588 : : }
589 : 3 : return 0;
590 : : }
591 : :
592 : : /* Same for structs and tables. */
593 : 2 : static int gen_root_type_printer(fb_output_t *out, fb_compound_type_t *ct)
594 : : {
595 : : fb_scoped_name_t snt;
596 : :
597 : 1 : fb_clear(snt);
598 : : fb_compound_name(ct, &snt);
599 : :
600 : 1 : fprintf(out->fp,
601 : : "static int %s_print_json(flatcc_json_printer_t *ctx, const char *buf, size_t bufsiz)\n",
602 : 1 : out->S->basename);
603 : 1 : fprintf(out->fp,
604 : : "{\n"
605 : : " flatcc_json_printer_t printer;\n"
606 : : "\n"
607 : : " if (ctx == 0) {\n"
608 : : " ctx = &printer;\n"
609 : : " flatcc_json_printer_init(ctx, 0);\n"
610 : : " }\n"
611 : : " return %s_print_json_as_root(ctx, buf, bufsiz, ",
612 : : snt.text);
613 [ + - ]: 1 : if (out->S->file_identifier.type == vt_string) {
614 : 1 : fprintf(out->fp,
615 : : "\"%.*s\");\n",
616 : : out->S->file_identifier.s.len, out->S->file_identifier.s.s);
617 : : } else {
618 : 0 : fprintf(out->fp,
619 : : "0);");
620 : : }
621 : 1 : fprintf(out->fp,
622 : : "}\n\n");
623 : 1 : return 0;
624 : : }
625 : :
626 : 3 : static int gen_json_root_printer(fb_output_t *out)
627 : : {
628 : 3 : fb_symbol_t *root_type = out->S->root_type.type;
629 : :
630 [ + + ]: 3 : if (!root_type) {
631 : : return 0;
632 : : }
633 : : if (root_type) {
634 [ + - ]: 1 : switch (root_type->kind) {
635 : : case fb_is_table:
636 : : case fb_is_struct:
637 : 1 : return gen_root_type_printer(out, (fb_compound_type_t *)root_type);
638 : : default:
639 : : break;
640 : : }
641 : : }
642 : : return 0;
643 : : }
644 : :
645 : 3 : int fb_gen_c_json_printer(fb_output_t *out)
646 : : {
647 : 3 : gen_json_printer_pretext(out);
648 : 3 : gen_json_printer_prototypes(out);
649 : 3 : gen_json_printer_enums(out);
650 : 3 : gen_json_printer_unions(out);
651 : 3 : gen_json_printer_structs(out);
652 : 3 : gen_json_printer_tables(out);
653 : 3 : gen_json_root_printer(out);
654 : 3 : gen_json_printer_footer(out);
655 : 3 : return 0;
656 : : }
|