mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 20:15:34 +00:00
Added support for structs and strings in unions.
(C++ only for now). Also fixed vector of union support in the object API. Bug: 36902939 Change-Id: I935f4cc2c303a4728e26c7916a8ec0adcd6f84cb Tested: on Linux.
This commit is contained in:
@@ -735,6 +735,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseString(Value &val) {
|
||||
auto s = attribute_;
|
||||
EXPECT(kTokenStringConstant);
|
||||
val.constant = NumToString(builder_.CreateString(s).o);
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
size_t parent_fieldn,
|
||||
const StructDef *parent_struct_def) {
|
||||
@@ -784,16 +791,27 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
ECHECK(atot(constant.c_str(), *this, &enum_idx));
|
||||
auto enum_val = val.type.enum_def->ReverseLookup(enum_idx);
|
||||
if (!enum_val) return Error("illegal type id for: " + field->name);
|
||||
ECHECK(ParseTable(*enum_val->struct_def, &val.constant, nullptr));
|
||||
if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) {
|
||||
ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant,
|
||||
nullptr));
|
||||
if (enum_val->union_type.struct_def->fixed) {
|
||||
// All BASE_TYPE_UNION values are offsets, so turn this into one.
|
||||
SerializeStruct(*enum_val->union_type.struct_def, val);
|
||||
builder_.ClearOffsets();
|
||||
val.constant = NumToString(builder_.GetSize());
|
||||
}
|
||||
} else if (enum_val->union_type.base_type == BASE_TYPE_STRING) {
|
||||
ECHECK(ParseString(val));
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_STRUCT:
|
||||
ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
|
||||
break;
|
||||
case BASE_TYPE_STRING: {
|
||||
auto s = attribute_;
|
||||
EXPECT(kTokenStringConstant);
|
||||
val.constant = NumToString(builder_.CreateString(s).o);
|
||||
ECHECK(ParseString(val));
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_VECTOR: {
|
||||
@@ -1290,7 +1308,16 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) {
|
||||
return Error("enum value already exists: " + value_name);
|
||||
ev.doc_comment = value_comment;
|
||||
if (is_union) {
|
||||
ev.struct_def = LookupCreateStruct(full_name);
|
||||
if (Is(':')) {
|
||||
NEXT();
|
||||
ECHECK(ParseType(ev.union_type));
|
||||
if (ev.union_type.base_type != BASE_TYPE_STRUCT &&
|
||||
ev.union_type.base_type != BASE_TYPE_STRING)
|
||||
return Error("union value type may only be table/struct/string");
|
||||
enum_def.uses_type_aliases = true;
|
||||
} else {
|
||||
ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name));
|
||||
}
|
||||
}
|
||||
if (Is('=')) {
|
||||
NEXT();
|
||||
@@ -1994,6 +2021,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
return Error("type referenced but not defined: " + (*it)->name);
|
||||
}
|
||||
}
|
||||
// This check has to happen here and not earlier, because only now do we
|
||||
// know for sure what the type of these are.
|
||||
for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
|
||||
auto &enum_def = **it;
|
||||
if (enum_def.is_union) {
|
||||
@@ -2001,8 +2030,11 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
val_it != enum_def.vals.vec.end();
|
||||
++val_it) {
|
||||
auto &val = **val_it;
|
||||
if (val.struct_def && val.struct_def->fixed)
|
||||
return Error("only tables can be union elements: " + val.name);
|
||||
if (opts.lang_to_generate != IDLOptions::kCpp &&
|
||||
val.union_type.struct_def && val.union_type.struct_def->fixed)
|
||||
return Error(
|
||||
"only tables can be union elements in the generated language: "
|
||||
+ val.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2145,9 +2177,11 @@ Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const
|
||||
return reflection::CreateEnumVal(*builder,
|
||||
builder->CreateString(name),
|
||||
value,
|
||||
struct_def
|
||||
? struct_def->serialized_location
|
||||
: 0);
|
||||
union_type.struct_def
|
||||
? union_type.struct_def->
|
||||
serialized_location
|
||||
: 0,
|
||||
union_type.Serialize(builder));
|
||||
}
|
||||
|
||||
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
||||
|
||||
Reference in New Issue
Block a user