#include "codegen_c.h" #include "flatcc/flatcc_types.h" /* -DFLATCC_PORTABLE may help if inttypes.h is missing. */ #ifndef PRId64 #include #endif static int gen_verifier_pretext(fb_output_t *out) { fprintf(out->fp, "#ifndef %s_VERIFIER_H\n" "#define %s_VERIFIER_H\n", out->S->basenameup, out->S->basenameup); fprintf(out->fp, "\n/* " FLATCC_GENERATED_BY " */\n\n"); /* Needed to get the file identifiers */ fprintf(out->fp, "#ifndef %s_READER_H\n", out->S->basenameup); fprintf(out->fp, "#include \"%s_reader.h\"\n", out->S->basename); fprintf(out->fp, "#endif\n"); fprintf(out->fp, "#include \"flatcc/flatcc_verifier.h\"\n"); fb_gen_c_includes(out, "_verifier.h", "_VERIFIER_H"); gen_prologue(out); fprintf(out->fp, "\n"); return 0; } static int gen_verifier_footer(fb_output_t *out) { gen_epilogue(out); fprintf(out->fp, "#endif /* %s_VERIFIER_H */\n", out->S->basenameup); return 0; } static int gen_union_verifier(fb_output_t *out, fb_compound_type_t *ct) { fb_symbol_t *sym; fb_member_t *member; fb_scoped_name_t snt, snref; int n; const char *s; fb_clear(snt); fb_clear(snref); fb_compound_name(ct, &snt); fprintf(out->fp, "static int %s_union_verifier(flatcc_union_verifier_descriptor_t *ud)\n{\n switch (ud->type) {\n", snt.text); for (sym = ct->members; sym; sym = sym->link) { member = (fb_member_t *)sym; symbol_name(sym, &n, &s); switch (member->type.type) { case vt_missing: /* NONE is of type vt_missing and already handled. */ 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: return flatcc_verify_union_table(ud, %s_verify_table); /* %.*s */\n", (unsigned)member->value.u, snref.text, n, s); continue; case fb_is_struct: fprintf(out->fp, " case %u: return flatcc_verify_union_struct(ud, %"PRIu64", %"PRIu16"); /* %.*s */\n", (unsigned)member->value.u, member->type.ct->size, member->type.ct->align, n, s); continue; default: gen_panic(out, "internal error: unexpected compound type for union verifier"); return -1; } case vt_string_type: fprintf(out->fp, " case %u: return flatcc_verify_union_string(ud); /* %.*s */\n", (unsigned)member->value.u, n, s); continue; default: gen_panic(out, "internal error: unexpected type for union verifier"); return -1; } } fprintf(out->fp, " default: return flatcc_verify_ok;\n }\n}\n\n"); return 0; } static int gen_table_verifier(fb_output_t *out, fb_compound_type_t *ct) { fb_symbol_t *sym; fb_member_t *member; fb_scoped_name_t snt, snref; int required, first = 1; const char *nsc = out->nsc; fb_clear(snt); fb_clear(snref); fb_compound_name(ct, &snt); fprintf(out->fp, "static int %s_verify_table(flatcc_table_verifier_descriptor_t *td)\n{\n", snt.text); for (sym = ct->members; sym; sym = sym->link) { member = (fb_member_t *)sym; if (member->metadata_flags & fb_f_deprecated) { continue; } if (first) { fprintf(out->fp, " int ret;\n if ((ret = "); } else { fprintf(out->fp, ")) return ret;\n if ((ret = "); } first = 0; required = (member->metadata_flags & fb_f_required) != 0; switch (member->type.type) { case vt_scalar_type: fprintf( out->fp, "flatcc_verify_field(td, %"PRIu64", %"PRIu64", %"PRIu16")", member->id, member->size, member->align); break; case vt_vector_type: if (member->nest) { fb_compound_name((fb_compound_type_t *)&member->nest->symbol, &snref); if (member->nest->symbol.kind == fb_is_table) { fprintf(out->fp, "flatcc_verify_table_as_nested_root(td, %"PRIu64", " "%u, 0, %"PRIu16", %s_verify_table)", member->id, required, member->align, snref.text); } else { fprintf(out->fp, "flatcc_verify_struct_as_nested_root(td, %"PRIu64", " "%u, 0, %"PRIu64", %"PRIu16")", member->id, required, member->size, member->align); } } else { fprintf(out->fp, "flatcc_verify_vector_field(td, %"PRIu64", %d, %"PRIu64", %"PRIu16", INT64_C(%"PRIu64"))", member->id, required, member->size, member->align, (uint64_t)FLATBUFFERS_COUNT_MAX(member->size)); }; break; case vt_string_type: fprintf(out->fp, "flatcc_verify_string_field(td, %"PRIu64", %d)", member->id, required); break; case vt_vector_string_type: fprintf(out->fp, "flatcc_verify_string_vector_field(td, %"PRIu64", %d)", member->id, required); break; case vt_compound_type_ref: fb_compound_name(member->type.ct, &snref); switch (member->type.ct->symbol.kind) { case fb_is_enum: case fb_is_struct: fprintf(out->fp, "flatcc_verify_field(td, %"PRIu64", %"PRIu64", %"PRIu16")", member->id, member->size, member->align); break; case fb_is_table: fprintf(out->fp, "flatcc_verify_table_field(td, %"PRIu64", %d, &%s_verify_table)", member->id, required, snref.text); break; case fb_is_union: fprintf(out->fp, "flatcc_verify_union_field(td, %"PRIu64", %d, &%s_union_verifier)", member->id, required, snref.text); break; default: gen_panic(out, "internal error: unexpected compound type for table verifier"); return -1; } 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_verify_table_vector_field(td, %"PRIu64", %d, &%s_verify_table)", member->id, required, snref.text); break; case fb_is_enum: case fb_is_struct: fprintf(out->fp, "flatcc_verify_vector_field(td, %"PRIu64", %d, %"PRIu64", %"PRIu16", INT64_C(%"PRIu64"))", member->id, required, member->size, member->align, (uint64_t)FLATBUFFERS_COUNT_MAX(member->size)); break; case fb_is_union: fprintf(out->fp, "flatcc_verify_union_vector_field(td, %"PRIu64", %d, &%s_union_verifier)", member->id, required, snref.text); break; default: gen_panic(out, "internal error: unexpected vector compound type for table verifier"); return -1; } break; } fprintf(out->fp, " /* %.*s */", (int)sym->ident->len, sym->ident->text); } if (!first) { fprintf(out->fp, ")) return ret;\n"); } fprintf(out->fp, " return flatcc_verify_ok;\n"); fprintf(out->fp, "}\n\n"); fprintf(out->fp, "static inline int %s_verify_as_root(const void *buf, size_t bufsiz)\n" "{\n return flatcc_verify_table_as_root(buf, bufsiz, %s_identifier, &%s_verify_table);\n}\n\n", snt.text, snt.text, snt.text); fprintf(out->fp, "static inline int %s_verify_as_typed_root(const void *buf, size_t bufsiz)\n" "{\n return flatcc_verify_table_as_root(buf, bufsiz, %s_type_identifier, &%s_verify_table);\n}\n\n", snt.text, snt.text, snt.text); fprintf(out->fp, "static inline int %s_verify_as_root_with_identifier(const void *buf, size_t bufsiz, const char *fid)\n" "{\n return flatcc_verify_table_as_root(buf, bufsiz, fid, &%s_verify_table);\n}\n\n", snt.text, snt.text); fprintf(out->fp, "static inline int %s_verify_as_root_with_type_hash(const void *buf, size_t bufsiz, %sthash_t thash)\n" "{\n return flatcc_verify_table_as_typed_root(buf, bufsiz, thash, &%s_verify_table);\n}\n\n", snt.text, nsc, snt.text); return 0; } static int gen_struct_verifier(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 inline int %s_verify_as_root(const void *buf, size_t bufsiz)\n" "{\n return flatcc_verify_struct_as_root(buf, bufsiz, %s_identifier, %"PRIu64", %"PRIu16");\n}\n\n", snt.text, snt.text, ct->size, ct->align); fprintf(out->fp, "static inline int %s_verify_as_typed_root(const void *buf, size_t bufsiz)\n" "{\n return flatcc_verify_struct_as_typed_root(buf, bufsiz, %s_type_hash, %"PRIu64", %"PRIu16");\n}\n\n", snt.text, snt.text, ct->size, ct->align); fprintf(out->fp, "static inline int %s_verify_as_root_with_type_hash(const void *buf, size_t bufsiz, %sthash_t thash)\n" "{\n return flatcc_verify_struct_as_typed_root(buf, bufsiz, thash, %"PRIu64", %"PRIu16");\n}\n\n", snt.text, out->nsc, ct->size, ct->align); fprintf(out->fp, "static inline int %s_verify_as_root_with_identifier(const void *buf, size_t bufsiz, const char *fid)\n" "{\n return flatcc_verify_struct_as_root(buf, bufsiz, fid, %"PRIu64", %"PRIu16");\n}\n\n", snt.text, ct->size, ct->align); return 0; } static int gen_verifier_prototypes(fb_output_t *out) { fb_symbol_t *sym; fb_scoped_name_t snt; fb_clear(snt); for (sym = out->S->symbols; sym; sym = sym->link) { switch (sym->kind) { case fb_is_table: fb_compound_name((fb_compound_type_t *)sym, &snt); fprintf(out->fp, "static int %s_verify_table(flatcc_table_verifier_descriptor_t *td);\n", snt.text); } } fprintf(out->fp, "\n"); return 0; } static int gen_union_verifiers(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_union_verifier(out, (fb_compound_type_t *)sym); } } return 0; } static int gen_struct_verifiers(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_struct_verifier(out, (fb_compound_type_t *)sym); } } return 0; } static int gen_table_verifiers(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_table_verifier(out, (fb_compound_type_t *)sym); } } return 0; } int fb_gen_c_verifier(fb_output_t *out) { gen_verifier_pretext(out); gen_verifier_prototypes(out); gen_union_verifiers(out); gen_struct_verifiers(out); gen_table_verifiers(out); gen_verifier_footer(out); return 0; }