summaryrefslogtreecommitdiff
path: root/src/idl_parser.cpp
diff options
context:
space:
mode:
authorVladimir Glavnyy <31897320+vglavnyy@users.noreply.github.com>2020-09-19 02:51:17 +0700
committerGitHub <noreply@github.com>2020-09-18 12:51:17 -0700
commit8c67b5b129f445c6bf5dbcbf2a18fec4c6334f16 (patch)
treed66e068636de0b57a475f0f942c5ccfae2b6ef2c /src/idl_parser.cpp
parent6228b66d3d1f0e5d2f79e59834c8931d84cccaaf (diff)
downloadflatbuffers-8c67b5b129f445c6bf5dbcbf2a18fec4c6334f16.tar.gz
flatbuffers-8c67b5b129f445c6bf5dbcbf2a18fec4c6334f16.tar.bz2
flatbuffers-8c67b5b129f445c6bf5dbcbf2a18fec4c6334f16.zip
Add support of Optional<T> scalars to C++ code generator (#6092)
Diffstat (limited to 'src/idl_parser.cpp')
-rw-r--r--src/idl_parser.cpp53
1 files changed, 39 insertions, 14 deletions
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 05b1b194..088246fc 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -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 {