diff options
Diffstat (limited to 'flatcc/src/compiler/codegen_c_json_printer.c')
-rw-r--r-- | flatcc/src/compiler/codegen_c_json_printer.c | 732 |
1 files changed, 732 insertions, 0 deletions
diff --git a/flatcc/src/compiler/codegen_c_json_printer.c b/flatcc/src/compiler/codegen_c_json_printer.c new file mode 100644 index 0000000..efc4c3d --- /dev/null +++ b/flatcc/src/compiler/codegen_c_json_printer.c @@ -0,0 +1,732 @@ +#include "codegen_c.h" +#include "flatcc/flatcc_types.h" + +/* -DFLATCC_PORTABLE may help if inttypes.h is missing. */ +#ifndef PRId64 +#include <inttypes.h> +#endif + +static int gen_json_printer_pretext(fb_output_t *out) +{ + fprintf(out->fp, + "#ifndef %s_JSON_PRINTER_H\n" + "#define %s_JSON_PRINTER_H\n", + out->S->basenameup, out->S->basenameup); + + fprintf(out->fp, "\n/* " FLATCC_GENERATED_BY " */\n\n"); + fprintf(out->fp, "#include \"flatcc/flatcc_json_printer.h\"\n"); + fb_gen_c_includes(out, "_json_printer.h", "_JSON_PRINTER_H"); + gen_prologue(out); + fprintf(out->fp, "\n"); + return 0; +} + +static int gen_json_printer_footer(fb_output_t *out) +{ + gen_epilogue(out); + fprintf(out->fp, + "#endif /* %s_JSON_PRINTER_H */\n", + out->S->basenameup); + return 0; +} + +static int gen_json_printer_enum(fb_output_t *out, fb_compound_type_t *ct) +{ + fb_symbol_t *sym; + fb_member_t *member; + fb_scoped_name_t snt, snref; + const char *tp, *tn, *ns; + int bit_flags; + uint64_t mask = 0; + char *constwrap = ""; + char *ut = ""; + fb_scalar_type_t st = ct->type.st; + + fb_clear(snt); + fb_clear(snref); + fb_compound_name(ct, &snt); + tp = scalar_type_prefix(st); + tn = scalar_type_name(st); + ns = scalar_type_ns(st, out->nsc); + + bit_flags = !!(ct->metadata_flags & fb_f_bit_flags); + if (bit_flags) { + switch (ct->size) { + case 1: + mask = UINT8_MAX, constwrap = "UINT8_C", ut = "uint8_t"; + break; + case 2: + mask = UINT16_MAX, constwrap = "UINT16_C", ut = "uint16_t"; + break; + case 4: + mask = UINT32_MAX, constwrap = "UINT32_C", ut = "uint32_t"; + break; + default: + mask = UINT64_MAX, constwrap = "UINT64_C", ut = "uint64_t"; + break; + } + for (sym = ct->members; sym; sym = sym->link) { + member = (fb_member_t *)sym; + switch (member->value.type) { + case vt_uint: + mask &= ~(uint64_t)member->value.u; + break; + case vt_int: + mask &= ~(uint64_t)member->value.i; + break; + case vt_bool: + mask &= ~(uint64_t)member->value.b; + break; + } + } + } + + fprintf(out->fp, + "static void %s_print_json_enum(flatcc_json_printer_t *ctx, %s%s v)\n{\n", + snt.text, ns, tn); + if (bit_flags) { + if (strcmp(ut, tn)) { + fprintf(out->fp, " %s x = (%s)v;\n", ut, ut); + } else { + fprintf(out->fp, " %s x = v;\n", ut); + } + fprintf(out->fp, + " int multiple = 0 != (x & (x - 1));\n" + " int i = 0;\n"); + + fprintf(out->fp, "\n"); + /* + * If the value is not entirely within the known bit flags, print as + * a number. + */ + if (mask) { + fprintf(out->fp, + " if ((x & %s(0x%"PRIx64")) || x == 0) {\n" + " flatcc_json_printer_%s(ctx, v);\n" + " return;\n" + " }\n", + constwrap, mask, tp); + } + /* + * Test if multiple bits set. We may have a configuration option + * that requires multiple flags to be quoted like `color: "Red Green"` + * but unquoted if just a single value like `color: Green`. + * + * The index `i` is used to add space separators much like an + * index is provided for struct members to handle comma. + */ + fprintf(out->fp, " flatcc_json_printer_delimit_enum_flags(ctx, multiple);\n"); + for (sym = ct->members; sym; sym = sym->link) { + member = (fb_member_t *)sym; + switch (member->value.type) { + case vt_uint: + fprintf(out->fp, " if (x & %s(0x%"PRIx64")) flatcc_json_printer_enum_flag(ctx, i++, \"%.*s\", %ld);\n", + constwrap, member->value.u, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + case vt_int: + fprintf(out->fp, " if (x & %s(0x%"PRIx64")) flatcc_json_printer_enum_flag(ctx, i++, \"%.*s\", %ld);\n", + constwrap, (uint64_t)member->value.i, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + case vt_bool: + fprintf(out->fp, " if (x & %s(0x%"PRIx64")) flatcc_json_printer_enum_flag(ctx, i++, \"%.*s\", %ld);\n", + constwrap, (uint64_t)member->value.b, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + default: + gen_panic(out, "internal error: unexpected value type for enum json_print"); + break; + } + } + fprintf(out->fp, " flatcc_json_printer_delimit_enum_flags(ctx, multiple);\n"); + } else { + fprintf(out->fp, "\n switch (v) {\n"); + for (sym = ct->members; sym; sym = sym->link) { + member = (fb_member_t *)sym; + switch (member->value.type) { + case vt_uint: + fprintf(out->fp, " case %s(%"PRIu64"): flatcc_json_printer_enum(ctx, \"%.*s\", %ld); break;\n", + constwrap, member->value.u, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + case vt_int: + fprintf(out->fp, " case %s(%"PRId64"): flatcc_json_printer_enum(ctx, \"%.*s\", %ld); break;\n", + constwrap, member->value.i, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + case vt_bool: + fprintf(out->fp, " case %s(%u): flatcc_json_printer_enum(ctx, \"%.*s\", %ld); break;\n", + constwrap, member->value.b, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + default: + gen_panic(out, "internal error: unexpected value type for enum json_print"); + break; + } + } + fprintf(out->fp, + " default: flatcc_json_printer_%s(ctx, v); break;\n" + " }\n", + tp); + } + fprintf(out->fp, "}\n\n"); + return 0; +} + +static int gen_json_printer_union_type(fb_output_t *out, fb_compound_type_t *ct) +{ + fb_symbol_t *sym; + fb_member_t *member; + fb_scoped_name_t snt; + + fb_clear(snt); + fb_compound_name(ct, &snt); + + fprintf(out->fp, + "static void %s_print_json_union_type(flatcc_json_printer_t *ctx, flatbuffers_utype_t type)\n" + "{\n switch (type) {\n", + snt.text); + for (sym = ct->members; sym; sym = sym->link) { + member = (fb_member_t *)sym; + if (member->type.type == vt_missing) { + continue; + } + fprintf(out->fp, + " case %u:\n" + " flatcc_json_printer_enum(ctx, \"%.*s\", %ld);\n" + " break;\n", + (unsigned)member->value.u, (int)sym->ident->len, sym->ident->text, sym->ident->len); + } + fprintf(out->fp, + " default:\n" + " flatcc_json_printer_enum(ctx, \"NONE\", 4);\n" + " break;\n"); + fprintf(out->fp, + " }\n}\n\n"); + return 0; +} + +static int gen_json_printer_union_member(fb_output_t *out, fb_compound_type_t *ct) +{ + fb_symbol_t *sym; + fb_member_t *member; + fb_scoped_name_t snt, snref; + + fb_clear(snt); + fb_clear(snref); + fb_compound_name(ct, &snt); + + fprintf(out->fp, + "static void %s_print_json_union(flatcc_json_printer_t *ctx, flatcc_json_printer_union_descriptor_t *ud)\n" + "{\n switch (ud->type) {\n", + snt.text); + for (sym = ct->members; sym; sym = sym->link) { + member = (fb_member_t *)sym; + switch (member->type.type) { + case vt_missing: + continue; + case vt_compound_type_ref: + fb_compound_name(member->type.ct, &snref); + switch (member->type.ct->symbol.kind) { + case fb_is_table: + fprintf(out->fp, + " case %u:\n" + " flatcc_json_printer_union_table(ctx, ud, %s_print_json_table);\n" + " break;\n", + (unsigned)member->value.u, snref.text); + continue; + case fb_is_struct: + fprintf(out->fp, + " case %u:\n" + " flatcc_json_printer_union_struct(ctx, ud, %s_print_json_struct);\n" + " break;\n", + (unsigned)member->value.u, snref.text); + continue; + default: + gen_panic(out, "internal error: unexpected union type\n"); + return -1; + } + case vt_string_type: + fprintf(out->fp, + " case %u:\n" + " flatcc_json_printer_union_string(ctx, ud);\n" + " break;\n", + (unsigned)member->value.u); + continue; + default: + gen_panic(out, "internal error: unexpected union type\n"); + return -1; + } + } + fprintf(out->fp, + " default:\n" + " break;\n"); + fprintf(out->fp, + " }\n}\n\n"); + return 0; +} + +static int gen_json_printer_union(fb_output_t *out, fb_compound_type_t *ct) +{ + gen_json_printer_union_type(out, ct); + gen_json_printer_union_member(out, ct); + return 0; +} + +static int gen_json_printer_struct(fb_output_t *out, fb_compound_type_t *ct) +{ + fb_symbol_t *sym; + fb_member_t *member; + fb_scoped_name_t snt, snref; + int index = 0; + const char *tp; + + fb_clear(snt); + fb_clear(snref); + fb_compound_name(ct, &snt); + + fprintf(out->fp, + "static void %s_print_json_struct(flatcc_json_printer_t *ctx, const void *p)\n" + "{\n", + snt.text); + for (sym = ct->members; sym; ++index, sym = sym->link) { + member = (fb_member_t *)sym; + if (member->metadata_flags & fb_f_deprecated) { + continue; + } + switch (member->type.type) { + case vt_scalar_type: + tp = scalar_type_prefix(member->type.st); + fprintf( + out->fp, + " flatcc_json_printer_%s_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld);\n", + tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + case vt_fixed_array_type: + tp = scalar_type_prefix(member->type.st); + fprintf( + out->fp, + " flatcc_json_printer_%s_array_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, %d);\n", + tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->type.len); + break; + case vt_fixed_array_compound_type_ref: + fb_compound_name(member->type.ct, &snref); + switch (member->type.ct->symbol.kind) { + case fb_is_enum: +#if FLATCC_JSON_PRINT_MAP_ENUMS + tp = scalar_type_prefix(member->type.ct->type.st); + fprintf(out->fp, + " flatcc_json_printer_%s_enum_array_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, %d, %s_print_json_enum);\n", + tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->type.len, snref.text); + break; +#else + tp = scalar_type_prefix(member->type.ct->type.st); + fprintf( + out->fp, + " flatcc_json_printer_%s_array_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, %d);\n", + tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, member->type.len); + break; +#endif + case fb_is_struct: + fprintf(out->fp, + " flatcc_json_printer_embedded_struct_array_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, %"PRIu64", %"PRIu64", %s_print_json_struct);\n", + index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, + (uint64_t)member->type.ct->size, (uint64_t)member->type.len, snref.text); + } + break; + case vt_compound_type_ref: + fb_compound_name(member->type.ct, &snref); + switch (member->type.ct->symbol.kind) { + case fb_is_enum: +#if FLATCC_JSON_PRINT_MAP_ENUMS + tp = scalar_type_prefix(member->type.ct->type.st); + fprintf(out->fp, + " flatcc_json_printer_%s_enum_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, %s_print_json_enum);\n", + tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + break; +#else + tp = scalar_type_prefix(member->type.ct->type.st); + fprintf( + out->fp, + " flatcc_json_printer_%s_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld);\n", + tp, index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; +#endif + case fb_is_struct: + fprintf(out->fp, + " flatcc_json_printer_embedded_struct_field(ctx, %d, p, %"PRIu64", \"%.*s\", %ld, %s_print_json_struct);\n", + index, (uint64_t)member->offset, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + break; + } + break; + } + } + fprintf(out->fp, "}\n\n"); + fprintf(out->fp, + "static inline int %s_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid)\n" + "{\n return flatcc_json_printer_struct_as_root(ctx, buf, bufsiz, fid, %s_print_json_struct);\n}\n\n", + snt.text, snt.text); + return 0; +} + +static int gen_json_printer_table(fb_output_t *out, fb_compound_type_t *ct) +{ + fb_symbol_t *sym; + fb_member_t *member; + fb_scoped_name_t snt, snref; + const char *tp; + int is_optional; + int ret = 0; + + fb_clear(snt); + fb_clear(snref); + fb_compound_name(ct, &snt); + + /* Fields are printed in field id order for consistency across schema version. */ + fprintf(out->fp, + "static void %s_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td)\n" + "{", + snt.text); + + for (sym = ct->members; sym; sym = sym->link) { + member = (fb_member_t *)sym; + sym = &member->symbol; + if (member->metadata_flags & fb_f_deprecated) { + continue; + } + is_optional = !!(member->flags & fb_fm_optional); + fprintf(out->fp, "\n "); + switch (member->type.type) { + case vt_scalar_type: + tp = scalar_type_prefix(member->type.st); + if (is_optional) { + fprintf( out->fp, + "flatcc_json_printer_%s_optional_field(ctx, td, %"PRIu64", \"%.*s\", %ld);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len); + } else { + fb_literal_t literal; + if (!print_literal(member->type.st, &member->value, literal)) return -1; + fprintf( out->fp, + "flatcc_json_printer_%s_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, literal); + } + break; + case vt_vector_type: + if (member->metadata_flags & (fb_f_base64 | fb_f_base64url)) { + fprintf(out->fp, + "flatcc_json_printer_uint8_vector_base64_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %u);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, + !(member->metadata_flags & fb_f_base64)); + } else if (member->nest) { + fb_compound_name((fb_compound_type_t *)&member->nest->symbol, &snref); + if (member->nest->symbol.kind == fb_is_table) { + /* + * Always set fid to 0 since it is difficult to know what is right. + * We do know the type from the field attribute. + */ + fprintf(out->fp, + "flatcc_json_printer_table_as_nested_root(ctx, td, %"PRIu64", \"%.*s\", %ld, 0, %s_print_json_table);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + } else { + /* + * Always set fid to 0 since it is difficult to know what is right. + * We do know the type from the field attribute. + */ + fprintf(out->fp, + "flatcc_json_printer_struct_as_nested_root(ctx, td, %"PRIu64", \"%.*s\", %ld, 0, %s_print_json_struct);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + } + } else { + tp = scalar_type_prefix(member->type.st); + fprintf(out->fp, + "flatcc_json_printer_%s_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len); + } + break; + case vt_string_type: + fprintf(out->fp, + "flatcc_json_printer_string_field(ctx, td, %"PRIu64", \"%.*s\", %ld);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + case vt_vector_string_type: + fprintf(out->fp, + "flatcc_json_printer_string_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; + case vt_compound_type_ref: + fb_compound_name(member->type.ct, &snref); + switch (member->type.ct->symbol.kind) { + case fb_is_enum: + tp = scalar_type_prefix(member->type.ct->type.st); +#if FLATCC_JSON_PRINT_MAP_ENUMS + if (is_optional) { + fprintf(out->fp, + "flatcc_json_printer_%s_enum_optional_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s_print_json_enum);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + } else { + fb_literal_t literal; + if (!print_literal(member->type.ct->type.st, &member->value, literal)) return -1; + fprintf(out->fp, + "flatcc_json_printer_%s_enum_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s, %s_print_json_enum);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, literal, snref.text); + } +#else + if (is_optional) { + fprintf( out->fp, + "flatcc_json_printer_%s_optional_field(ctx, td, %"PRIu64", \"%.*s\", %ld);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len); + } else { + fb_literal_t literal; + if (!print_literal(member->type.ct->type.st, &member->value, literal)) return -1; + fprintf( out->fp, + "flatcc_json_printer_%s_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, literal); + } +#endif + break; + case fb_is_struct: + fprintf(out->fp, + "flatcc_json_printer_struct_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s_print_json_struct);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + break; + case fb_is_table: + fprintf(out->fp, + "flatcc_json_printer_table_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s_print_json_table);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + break; + case fb_is_union: + fprintf(out->fp, + "flatcc_json_printer_union_field(ctx, td, %"PRIu64", \"%.*s\", %ld, " + "%s_print_json_union_type, %s_print_json_union);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text, snref.text); + break; + default: + gen_panic(out, "internal error: unexpected compound type for table json_print"); + goto fail; + } + break; + case vt_vector_compound_type_ref: + fb_compound_name(member->type.ct, &snref); + switch (member->type.ct->symbol.kind) { + case fb_is_table: + fprintf(out->fp, + "flatcc_json_printer_table_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s_print_json_table);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + break; + case fb_is_enum: + tp = scalar_type_prefix(member->type.ct->type.st); +#if FLATCC_JSON_PRINT_MAP_ENUMS + fprintf(out->fp, + "flatcc_json_printer_%s_enum_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %s_print_json_enum);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text); + break; +#else + fprintf(out->fp, + "flatcc_json_printer_%s_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld);", + tp, member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len); + break; +#endif + case fb_is_struct: + fprintf(out->fp, + "flatcc_json_printer_struct_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld, %"PRIu64", %s_print_json_struct);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, (uint64_t)member->size, snref.text); + break; + case fb_is_union: + fprintf(out->fp, + "flatcc_json_printer_union_vector_field(ctx, td, %"PRIu64", \"%.*s\", %ld, " + "%s_print_json_union_type, %s_print_json_union);", + member->id, (int)sym->ident->len, sym->ident->text, sym->ident->len, snref.text, snref.text); + break; + + default: + gen_panic(out, "internal error: unexpected vector compound type for table json_print"); + goto fail; + } + break; + } + } + fprintf(out->fp, "\n}\n\n"); + fprintf(out->fp, + "static inline int %s_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid)\n" + "{\n return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, %s_print_json_table);\n}\n\n", + snt.text, snt.text); +done: + return ret; +fail: + ret = -1; + goto done; +} + +/* + * Only tables are mutually recursive. Structs are sorted and unions are + * defined earlier, depending on the table prototypes. + */ +static int gen_json_printer_prototypes(fb_output_t *out) +{ + fb_symbol_t *sym; + fb_scoped_name_t snt; + fb_symbol_t *root_type = out->S->root_type.type; + + fb_clear(snt); + + if (root_type) + switch (root_type->kind) { + case fb_is_table: + case fb_is_struct: + fprintf(out->fp, + "/*\n" + " * Prints the default root table or struct from a buffer which must have\n" + " * the schema declared file identifier, if any. It is also possible to\n" + " * call the type specific `print_json_as_root` function wich accepts an\n" + " * optional identifier (or 0) as argument. The printer `ctx` object must\n" + " * be initialized with the appropriate output type, or it can be 0 which\n" + " * defaults to stdout. NOTE: `ctx` is not generally allowed to be null, only\n" + " * here for a simplified interface.\n" + " */\n"); + fprintf(out->fp, + "static int %s_print_json(flatcc_json_printer_t *ctx, const char *buf, size_t bufsiz);\n\n", + out->S->basename); + break; + default: + break; + } + + for (sym = out->S->symbols; sym; sym = sym->link) { + switch (sym->kind) { + case fb_is_union: + fb_compound_name((fb_compound_type_t *)sym, &snt); + fprintf(out->fp, + "static void %s_print_json_union_type(flatcc_json_printer_t *ctx, flatbuffers_utype_t type);\n" + "static void %s_print_json_union(flatcc_json_printer_t *ctx, flatcc_json_printer_union_descriptor_t *ud);\n", + snt.text, snt.text); + break; + case fb_is_table: + fb_compound_name((fb_compound_type_t *)sym, &snt); + fprintf(out->fp, + "static void %s_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td);\n", + snt.text); + break; + case fb_is_struct: + fb_compound_name((fb_compound_type_t *)sym, &snt); + fprintf(out->fp, + "static void %s_print_json_struct(flatcc_json_printer_t *ctx, const void *p);\n", + snt.text); + break; + } + } + fprintf(out->fp, "\n"); + return 0; +} + +static int gen_json_printer_enums(fb_output_t *out) +{ + fb_symbol_t *sym; + + for (sym = out->S->symbols; sym; sym = sym->link) { + switch (sym->kind) { + case fb_is_enum: + gen_json_printer_enum(out, (fb_compound_type_t *)sym); + } + } + return 0; +} + +static int gen_json_printer_unions(fb_output_t *out) +{ + fb_symbol_t *sym; + + for (sym = out->S->symbols; sym; sym = sym->link) { + switch (sym->kind) { + case fb_is_union: + gen_json_printer_union(out, (fb_compound_type_t *)sym); + } + } + return 0; +} + +static int gen_json_printer_structs(fb_output_t *out) +{ + fb_symbol_t *sym; + + for (sym = out->S->symbols; sym; sym = sym->link) { + switch (sym->kind) { + case fb_is_struct: + gen_json_printer_struct(out, (fb_compound_type_t *)sym); + } + } + return 0; +} + +static int gen_json_printer_tables(fb_output_t *out) +{ + fb_symbol_t *sym; + + for (sym = out->S->symbols; sym; sym = sym->link) { + switch (sym->kind) { + case fb_is_table: + gen_json_printer_table(out, (fb_compound_type_t *)sym); + } + } + return 0; +} + +/* Same for structs and tables. */ +static int gen_root_type_printer(fb_output_t *out, fb_compound_type_t *ct) +{ + fb_scoped_name_t snt; + + fb_clear(snt); + fb_compound_name(ct, &snt); + + fprintf(out->fp, + "static int %s_print_json(flatcc_json_printer_t *ctx, const char *buf, size_t bufsiz)\n", + out->S->basename); + fprintf(out->fp, + "{\n" + " flatcc_json_printer_t printer;\n" + "\n" + " if (ctx == 0) {\n" + " ctx = &printer;\n" + " flatcc_json_printer_init(ctx, 0);\n" + " }\n" + " return %s_print_json_as_root(ctx, buf, bufsiz, ", + snt.text); + if (out->S->file_identifier.type == vt_string) { + fprintf(out->fp, + "\"%.*s\");\n", + out->S->file_identifier.s.len, out->S->file_identifier.s.s); + } else { + fprintf(out->fp, + "0);"); + } + fprintf(out->fp, + "}\n\n"); + return 0; +} + +static int gen_json_root_printer(fb_output_t *out) +{ + fb_symbol_t *root_type = out->S->root_type.type; + + if (!root_type) { + return 0; + } + if (root_type) { + switch (root_type->kind) { + case fb_is_table: + case fb_is_struct: + return gen_root_type_printer(out, (fb_compound_type_t *)root_type); + default: + break; + } + } + return 0; +} + +int fb_gen_c_json_printer(fb_output_t *out) +{ + gen_json_printer_pretext(out); + gen_json_printer_prototypes(out); + gen_json_printer_enums(out); + gen_json_printer_unions(out); + gen_json_printer_structs(out); + gen_json_printer_tables(out); + gen_json_root_printer(out); + gen_json_printer_footer(out); + return 0; +} |