_Nullable cpp interface (#4451)

* add _Nullable Support for C++ interface

* add _Nullable Support for C++ interface
This commit is contained in:
Yonggang Li 2017-10-09 08:40:17 -07:00 committed by Wouter van Oortmerssen
parent 9c3920d0ab
commit 30e7d16104
3 changed files with 23 additions and 5 deletions

View File

@ -372,6 +372,7 @@ struct IDLOptions {
bool generate_object_based_api;
std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type;
bool clang_nullable;
std::string object_prefix;
std::string object_suffix;
bool union_value_namespacing;
@ -426,6 +427,7 @@ struct IDLOptions {
generate_name_strings(false),
generate_object_based_api(false),
cpp_object_api_pointer_type("std::unique_ptr"),
clang_nullable(false),
object_suffix("T"),
union_value_namespacing(true),
allow_non_utf8(false),

View File

@ -89,6 +89,7 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
" --cpp-str-type T Set object API string type (default std::string)\n"
" T::c_str() and T::length() must be supported\n"
" --clang-nullable Add Clang _Nullable for C++ pointers.\n"
" --object-prefix Customise class prefix for C++ object-based API.\n"
" --object-suffix Customise class suffix for C++ object-based API.\n"
" Default value is \"T\"\n"
@ -205,6 +206,8 @@ int FlatCompiler::Compile(int argc, const char** argv) {
} else if (arg == "--cpp-str-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_string_type = argv[argi];
} else if (arg == "--clang-nullable") {
opts.clang_nullable = true;
} else if (arg == "--object-prefix") {
if (++argi >= argc) Error("missing prefix following" + arg, true);
opts.object_prefix = argv[argi];

View File

@ -127,6 +127,10 @@ class CppGenerator : public BaseGenerator {
code_ += "#define " + include_guard;
code_ += "";
if (parser_.opts.clang_nullable) {
code_ += "#pragma clang system_header\n\n";
}
code_ += "#include \"flatbuffers/flatbuffers.h\"";
if (parser_.uses_flexbuffers_) {
code_ += "#include \"flatbuffers/flexbuffers.h\"";
@ -244,10 +248,11 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_NAME", name);
code_.SetValue("CPP_NAME", cpp_name);
code_.SetValue("NULLABLE_EXT", NullableExtension());
// The root datatype accessor:
code_ += "inline \\";
code_ += "const {{CPP_NAME}} *Get{{STRUCT_NAME}}(const void *buf) {";
code_ += "const {{CPP_NAME}} *{{NULLABLE_EXT}}Get{{STRUCT_NAME}}(const void *buf) {";
code_ += " return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
code_ += "}";
code_ += "";
@ -427,6 +432,10 @@ class CppGenerator : public BaseGenerator {
}
}
std::string NullableExtension() {
return parser_.opts.clang_nullable ? " _Nullable " : "";
}
static std::string NativeName(const std::string &name, const StructDef *sd, const IDLOptions & opts) {
return sd && !sd->fixed ? opts.object_prefix + name + opts.object_suffix : name;
}
@ -1469,10 +1478,12 @@ class CppGenerator : public BaseGenerator {
}
call += ")";
std::string afterptr = " *" + NullableExtension();
GenComment(field.doc_comment, " ");
code_.SetValue("FIELD_TYPE",
GenTypeGet(field.value.type, " ", "const ", " *", true));
GenTypeGet(field.value.type, " ", "const ", afterptr.c_str(), true));
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call));
code_.SetValue("NULLABLE_EXT", NullableExtension());
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
code_ += " return {{FIELD_VALUE}};";
@ -1482,7 +1493,7 @@ class CppGenerator : public BaseGenerator {
auto u = field.value.type.enum_def;
code_ += " template<typename T> "
"const T *{{FIELD_NAME}}_as() const;";
"const T *{{NULLABLE_EXT}}{{FIELD_NAME}}_as() const;";
for (auto u_it = u->vals.vec.begin();
u_it != u->vals.vec.end(); ++u_it) {
@ -1499,9 +1510,10 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
code_.SetValue("U_FIELD_NAME",
Name(field) + "_as_" + Name(ev));
code_.SetValue("U_NULLABLE", NullableExtension());
// `const Type *union_name_asType() const` accessor.
code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {";
code_ += " {{U_FIELD_TYPE}}{{U_NULLABLE}}{{U_FIELD_NAME}}() const {";
code_ += " return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
"static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
": nullptr;";
@ -1524,7 +1536,8 @@ class CppGenerator : public BaseGenerator {
code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, {{DEFAULT_VALUE}});";
code_ += " }";
} else {
auto type = GenTypeGet(field.value.type, " ", "", " *", true);
auto postptr = " *" + NullableExtension();
auto type = GenTypeGet(field.value.type, " ", "", postptr.c_str(), true);
auto underlying = accessor + type + ">(" + offset_str + ")";
code_.SetValue("FIELD_TYPE", type);
code_.SetValue("FIELD_VALUE",