Commit 30e7d161 authored by Yonggang Li's avatar Yonggang Li Committed by Wouter van Oortmerssen

_Nullable cpp interface (#4451)

* add _Nullable Support for C++ interface

* add _Nullable Support for C++ interface
parent 9c3920d0
...@@ -372,6 +372,7 @@ struct IDLOptions { ...@@ -372,6 +372,7 @@ struct IDLOptions {
bool generate_object_based_api; bool generate_object_based_api;
std::string cpp_object_api_pointer_type; std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type; std::string cpp_object_api_string_type;
bool clang_nullable;
std::string object_prefix; std::string object_prefix;
std::string object_suffix; std::string object_suffix;
bool union_value_namespacing; bool union_value_namespacing;
...@@ -426,6 +427,7 @@ struct IDLOptions { ...@@ -426,6 +427,7 @@ struct IDLOptions {
generate_name_strings(false), generate_name_strings(false),
generate_object_based_api(false), generate_object_based_api(false),
cpp_object_api_pointer_type("std::unique_ptr"), cpp_object_api_pointer_type("std::unique_ptr"),
clang_nullable(false),
object_suffix("T"), object_suffix("T"),
union_value_namespacing(true), union_value_namespacing(true),
allow_non_utf8(false), allow_non_utf8(false),
......
...@@ -89,6 +89,7 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const { ...@@ -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-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" " --cpp-str-type T Set object API string type (default std::string)\n"
" T::c_str() and T::length() must be supported\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-prefix Customise class prefix for C++ object-based API.\n"
" --object-suffix Customise class suffix for C++ object-based API.\n" " --object-suffix Customise class suffix for C++ object-based API.\n"
" Default value is \"T\"\n" " Default value is \"T\"\n"
...@@ -205,6 +206,8 @@ int FlatCompiler::Compile(int argc, const char** argv) { ...@@ -205,6 +206,8 @@ int FlatCompiler::Compile(int argc, const char** argv) {
} else if (arg == "--cpp-str-type") { } else if (arg == "--cpp-str-type") {
if (++argi >= argc) Error("missing type following" + arg, true); if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_string_type = argv[argi]; opts.cpp_object_api_string_type = argv[argi];
} else if (arg == "--clang-nullable") {
opts.clang_nullable = true;
} else if (arg == "--object-prefix") { } else if (arg == "--object-prefix") {
if (++argi >= argc) Error("missing prefix following" + arg, true); if (++argi >= argc) Error("missing prefix following" + arg, true);
opts.object_prefix = argv[argi]; opts.object_prefix = argv[argi];
......
...@@ -127,6 +127,10 @@ class CppGenerator : public BaseGenerator { ...@@ -127,6 +127,10 @@ class CppGenerator : public BaseGenerator {
code_ += "#define " + include_guard; code_ += "#define " + include_guard;
code_ += ""; code_ += "";
if (parser_.opts.clang_nullable) {
code_ += "#pragma clang system_header\n\n";
}
code_ += "#include \"flatbuffers/flatbuffers.h\""; code_ += "#include \"flatbuffers/flatbuffers.h\"";
if (parser_.uses_flexbuffers_) { if (parser_.uses_flexbuffers_) {
code_ += "#include \"flatbuffers/flexbuffers.h\""; code_ += "#include \"flatbuffers/flexbuffers.h\"";
...@@ -244,10 +248,11 @@ class CppGenerator : public BaseGenerator { ...@@ -244,10 +248,11 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_NAME", name); code_.SetValue("STRUCT_NAME", name);
code_.SetValue("CPP_NAME", cpp_name); code_.SetValue("CPP_NAME", cpp_name);
code_.SetValue("NULLABLE_EXT", NullableExtension());
// The root datatype accessor: // The root datatype accessor:
code_ += "inline \\"; 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_ += " return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
code_ += "}"; code_ += "}";
code_ += ""; code_ += "";
...@@ -427,6 +432,10 @@ class CppGenerator : public BaseGenerator { ...@@ -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) { 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; return sd && !sd->fixed ? opts.object_prefix + name + opts.object_suffix : name;
} }
...@@ -1469,10 +1478,12 @@ class CppGenerator : public BaseGenerator { ...@@ -1469,10 +1478,12 @@ class CppGenerator : public BaseGenerator {
} }
call += ")"; call += ")";
std::string afterptr = " *" + NullableExtension();
GenComment(field.doc_comment, " "); GenComment(field.doc_comment, " ");
code_.SetValue("FIELD_TYPE", 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("FIELD_VALUE", GenUnderlyingCast(field, true, call));
code_.SetValue("NULLABLE_EXT", NullableExtension());
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {"; code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
code_ += " return {{FIELD_VALUE}};"; code_ += " return {{FIELD_VALUE}};";
...@@ -1482,7 +1493,7 @@ class CppGenerator : public BaseGenerator { ...@@ -1482,7 +1493,7 @@ class CppGenerator : public BaseGenerator {
auto u = field.value.type.enum_def; auto u = field.value.type.enum_def;
code_ += " template<typename T> " 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(); for (auto u_it = u->vals.vec.begin();
u_it != u->vals.vec.end(); ++u_it) { u_it != u->vals.vec.end(); ++u_it) {
...@@ -1499,9 +1510,10 @@ class CppGenerator : public BaseGenerator { ...@@ -1499,9 +1510,10 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
code_.SetValue("U_FIELD_NAME", code_.SetValue("U_FIELD_NAME",
Name(field) + "_as_" + Name(ev)); Name(field) + "_as_" + Name(ev));
code_.SetValue("U_NULLABLE", NullableExtension());
// `const Type *union_name_asType() const` accessor. // `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}} ? " code_ += " return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
"static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) " "static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
": nullptr;"; ": nullptr;";
...@@ -1524,7 +1536,8 @@ class CppGenerator : public BaseGenerator { ...@@ -1524,7 +1536,8 @@ class CppGenerator : public BaseGenerator {
code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, {{DEFAULT_VALUE}});"; code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, {{DEFAULT_VALUE}});";
code_ += " }"; code_ += " }";
} else { } 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 + ")"; auto underlying = accessor + type + ">(" + offset_str + ")";
code_.SetValue("FIELD_TYPE", type); code_.SetValue("FIELD_TYPE", type);
code_.SetValue("FIELD_VALUE", code_.SetValue("FIELD_VALUE",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment