Add support of Optional<T> scalars to C++ code generator (#6092)

This commit is contained in:
Vladimir Glavnyy
2020-09-19 02:51:17 +07:00
committed by GitHub
parent 6228b66d3d
commit 8c67b5b129
19 changed files with 2471 additions and 133 deletions

View File

@@ -743,6 +743,34 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
return Error(
"default values currently only supported for scalars in tables");
}
// Mark the optional scalars. Note that a side effect of ParseSingleValue is
// fixing field->value.constant to null.
if (IsScalar(type.base_type)) {
field->optional = (field->value.constant == "null");
if (field->optional) {
if (type.enum_def && type.enum_def->Lookup("null")) {
FLATBUFFERS_ASSERT(IsInteger(type.base_type));
return Error(
"the default 'null' is reserved for declaring optional scalar "
"fields, it conflicts with declaration of enum '" +
type.enum_def->name + "'.");
}
if (field->attributes.Lookup("key")) {
return Error("only a non-optional scalar field can be used as a 'key' field");
}
if (!SupportsOptionalScalars()) {
return Error(
"Optional scalars are not yet supported in at least one the of "
"the specified programming languages.");
}
}
} else {
// For nonscalars, only required fields are non-optional.
// At least until https://github.com/google/flatbuffers/issues/6053
field->optional = !field->required;
}
// Append .0 if the value has not it (skip hex and scientific floats).
// This suffix needed for generated C++ code.
if (IsFloat(type.base_type)) {
@@ -772,6 +800,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
} else {
// All unions should have the NONE ("0") enum value.
auto in_enum = type.enum_def->attributes.Lookup("bit_flags") ||
field->IsScalarOptional() ||
type.enum_def->FindByValue(field->value.constant);
if (false == in_enum)
return Error("default value of " + field->value.constant +
@@ -833,17 +862,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
if (field->required && (struct_def.fixed || IsScalar(type.base_type)))
return Error("only non-scalar fields in tables may be 'required'");
// Mark the optional scalars. Note that a side effect of ParseSingleValue is
// fixing field->value.constant to null.
if (IsScalar(type.base_type)) {
field->optional = (field->value.constant == "null");
if (field->optional && !SupportsOptionalScalars()) {
return Error(
"Optional scalars are not yet supported in at least one the of "
"the specified programming languages."
);
}
} else {
if(!IsScalar(type.base_type)) {
// For nonscalars, only required fields are non-optional.
// At least until https://github.com/google/flatbuffers/issues/6053
field->optional = !field->required;
@@ -2260,11 +2279,17 @@ CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields,
return NoError();
}
bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts){
static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
IDLOptions::kKotlin | IDLOptions::kCpp;
unsigned long langs = opts.lang_to_generate;
return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
}
bool Parser::SupportsOptionalScalars() const {
return !(opts.lang_to_generate &
~(IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
IDLOptions::kKotlin));
// Check in general if a language isn't specified.
return opts.lang_to_generate == 0 || SupportsOptionalScalars(opts);
}
bool Parser::SupportsAdvancedUnionFeatures() const {