mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-03 20:31:23 +00:00
Enums in C++ are now strongly typed.
Accessors and constructors now take enum types rather than ints. Bug: 16570507 Change-Id: I4b50fd64ad2e662ea2481bc0ccea784326fb31c0 Tested: on Linux and Windows.
This commit is contained in:
@@ -23,18 +23,38 @@
|
||||
namespace flatbuffers {
|
||||
namespace cpp {
|
||||
|
||||
// Ensure that a type is prefixed with its namespace whenever it is used
|
||||
// outside of its namespace.
|
||||
static std::string WrapInNameSpace(const Parser &parser, const Namespace *ns,
|
||||
const std::string &name) {
|
||||
if (parser.namespaces_.back() != ns) {
|
||||
std::string qualified_name;
|
||||
for (auto it = ns->components.begin();
|
||||
it != ns->components.end(); ++it) {
|
||||
qualified_name += *it + "::";
|
||||
}
|
||||
return qualified_name + name;
|
||||
} else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a C++ type from the table in idl.h
|
||||
static std::string GenTypeBasic(const Type &type) {
|
||||
static std::string GenTypeBasic(const Parser &parser, const Type &type,
|
||||
bool real_enum) {
|
||||
static const char *ctypename[] = {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE) #CTYPE,
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
};
|
||||
return ctypename[type.base_type];
|
||||
return real_enum && type.enum_def
|
||||
? WrapInNameSpace(parser, type.enum_def->defined_namespace,
|
||||
type.enum_def->name)
|
||||
: ctypename[type.base_type];
|
||||
}
|
||||
|
||||
static std::string GenTypeWire(const Parser &parser, const Type &type,
|
||||
const char *postfix);
|
||||
const char *postfix, bool real_enum);
|
||||
|
||||
// Return a C++ pointer type, specialized to the actual struct/table types,
|
||||
// and vector element types.
|
||||
@@ -44,19 +64,10 @@ static std::string GenTypePointer(const Parser &parser, const Type &type) {
|
||||
return "flatbuffers::String";
|
||||
case BASE_TYPE_VECTOR:
|
||||
return "flatbuffers::Vector<" +
|
||||
GenTypeWire(parser, type.VectorType(), "") + ">";
|
||||
GenTypeWire(parser, type.VectorType(), "", false) + ">";
|
||||
case BASE_TYPE_STRUCT: {
|
||||
auto ns = type.struct_def->defined_namespace;
|
||||
if (parser.namespaces_.back() != ns) {
|
||||
std::string qualified_name;
|
||||
for (auto it = ns->components.begin();
|
||||
it != ns->components.end(); ++it) {
|
||||
qualified_name += *it + "::";
|
||||
}
|
||||
return qualified_name + type.struct_def->name;
|
||||
} else {
|
||||
return type.struct_def->name;
|
||||
}
|
||||
return WrapInNameSpace(parser, type.struct_def->defined_namespace,
|
||||
type.struct_def->name);
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
// fall through
|
||||
@@ -68,9 +79,9 @@ static std::string GenTypePointer(const Parser &parser, const Type &type) {
|
||||
// Return a C++ type for any type (scalar/pointer) specifically for
|
||||
// building a flatbuffer.
|
||||
static std::string GenTypeWire(const Parser &parser, const Type &type,
|
||||
const char *postfix) {
|
||||
const char *postfix, bool real_enum) {
|
||||
return IsScalar(type.base_type)
|
||||
? GenTypeBasic(type) + postfix
|
||||
? GenTypeBasic(parser, type, real_enum) + postfix
|
||||
: IsStruct(type)
|
||||
? "const " + GenTypePointer(parser, type) + " *"
|
||||
: "flatbuffers::Offset<" + GenTypePointer(parser, type) + ">" + postfix;
|
||||
@@ -80,7 +91,7 @@ static std::string GenTypeWire(const Parser &parser, const Type &type,
|
||||
// serialized size.
|
||||
static std::string GenTypeSize(const Parser &parser, const Type &type) {
|
||||
return IsScalar(type.base_type)
|
||||
? GenTypeBasic(type)
|
||||
? GenTypeBasic(parser, type, false)
|
||||
: IsStruct(type)
|
||||
? GenTypePointer(parser, type)
|
||||
: "flatbuffers::uoffset_t";
|
||||
@@ -90,9 +101,9 @@ static std::string GenTypeSize(const Parser &parser, const Type &type) {
|
||||
// using a flatbuffer.
|
||||
static std::string GenTypeGet(const Parser &parser, const Type &type,
|
||||
const char *afterbasic, const char *beforeptr,
|
||||
const char *afterptr) {
|
||||
const char *afterptr, bool real_enum) {
|
||||
return IsScalar(type.base_type)
|
||||
? GenTypeBasic(type) + afterbasic
|
||||
? GenTypeBasic(parser, type, real_enum) + afterbasic
|
||||
: beforeptr + GenTypePointer(parser, type) + afterptr;
|
||||
}
|
||||
|
||||
@@ -110,7 +121,7 @@ static void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
std::string &code = *code_ptr;
|
||||
std::string &code_post = *code_ptr_post;
|
||||
GenComment(enum_def.doc_comment, code_ptr);
|
||||
code += "enum {\n";
|
||||
code += "enum " + enum_def.name + " {\n";
|
||||
for (auto it = enum_def.vals.vec.begin();
|
||||
it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
@@ -143,7 +154,7 @@ static void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
}
|
||||
code += "nullptr };\n return names;\n}\n\n";
|
||||
code += "inline const char *EnumName" + enum_def.name;
|
||||
code += "(int e) { return EnumNames" + enum_def.name + "()[e";
|
||||
code += "(" + enum_def.name + " e) { return EnumNames" + enum_def.name + "()[e";
|
||||
if (enum_def.vals.vec.front()->value)
|
||||
code += " - " + GenEnumVal(enum_def, *enum_def.vals.vec.front(), opts);
|
||||
code += "]; }\n\n";
|
||||
@@ -176,6 +187,18 @@ static void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a value with optionally a cast applied if the field has a
|
||||
// different underlying type from its interface type (currently only the
|
||||
// case for enums. "from" specify the direction, true meaning from the
|
||||
// underlying type to the interface type.
|
||||
std::string GenUnderlyingCast(const Parser &parser, const FieldDef &field,
|
||||
bool from, const std::string &val) {
|
||||
return field.value.type.enum_def && IsScalar(field.value.type.base_type)
|
||||
? "static_cast<" + GenTypeBasic(parser, field.value.type, from) + ">(" +
|
||||
val + ")"
|
||||
: val;
|
||||
}
|
||||
|
||||
// Generate an accessor struct, builder structs & function for a table.
|
||||
static void GenTable(const Parser &parser, StructDef &struct_def,
|
||||
std::string *code_ptr) {
|
||||
@@ -193,18 +216,21 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
|
||||
auto &field = **it;
|
||||
if (!field.deprecated) { // Deprecated fields won't be accessible.
|
||||
GenComment(field.doc_comment, code_ptr, " ");
|
||||
code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " *");
|
||||
code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " *",
|
||||
true);
|
||||
code += field.name + "() const { return ";
|
||||
// Call a different accessor for pointers, that indirects.
|
||||
code += IsScalar(field.value.type.base_type)
|
||||
std::string call = IsScalar(field.value.type.base_type)
|
||||
? "GetField<"
|
||||
: (IsStruct(field.value.type) ? "GetStruct<" : "GetPointer<");
|
||||
code += GenTypeGet(parser, field.value.type, "", "const ", " *") + ">(";
|
||||
code += NumToString(field.value.offset);
|
||||
call += GenTypeGet(parser, field.value.type, "", "const ", " *", false);
|
||||
call += ">(" + NumToString(field.value.offset);
|
||||
// Default value as second arg for non-pointer types.
|
||||
if (IsScalar(field.value.type.base_type))
|
||||
code += ", " + field.value.constant;
|
||||
code += "); }\n";
|
||||
call += ", " + field.value.constant;
|
||||
call += ")";
|
||||
code += GenUnderlyingCast(parser, field, true, call);
|
||||
code += "; }\n";
|
||||
auto nested = field.attributes.Lookup("nested_flatbuffer");
|
||||
if (nested) {
|
||||
auto nested_root = parser.structs_.Lookup(nested->constant);
|
||||
@@ -283,15 +309,18 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
|
||||
auto &field = **it;
|
||||
if (!field.deprecated) {
|
||||
code += " void add_" + field.name + "(";
|
||||
code += GenTypeWire(parser, field.value.type, " ") + field.name;
|
||||
code += GenTypeWire(parser, field.value.type, " ", true) + field.name;
|
||||
code += ") { fbb_.Add";
|
||||
if (IsScalar(field.value.type.base_type))
|
||||
code += "Element<" + GenTypeWire(parser, field.value.type, "") + ">";
|
||||
else if (IsStruct(field.value.type))
|
||||
if (IsScalar(field.value.type.base_type)) {
|
||||
code += "Element<" + GenTypeWire(parser, field.value.type, "", false);
|
||||
code += ">";
|
||||
} else if (IsStruct(field.value.type)) {
|
||||
code += "Struct";
|
||||
else
|
||||
} else {
|
||||
code += "Offset";
|
||||
code += "(" + NumToString(field.value.offset) + ", " + field.name;
|
||||
}
|
||||
code += "(" + NumToString(field.value.offset) + ", ";
|
||||
code += GenUnderlyingCast(parser, field, false, field.name);
|
||||
if (IsScalar(field.value.type.base_type))
|
||||
code += ", " + field.value.constant;
|
||||
code += "); }\n";
|
||||
@@ -327,8 +356,22 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
|
||||
++it) {
|
||||
auto &field = **it;
|
||||
if (!field.deprecated) {
|
||||
code += ",\n " + GenTypeWire(parser, field.value.type, " ");
|
||||
code += field.name + " = " + field.value.constant;
|
||||
code += ",\n " + GenTypeWire(parser, field.value.type, " ", true);
|
||||
code += field.name + " = ";
|
||||
if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) {
|
||||
auto ed = field.value.type.enum_def->ReverseLookup(
|
||||
StringToInt(field.value.constant.c_str()), false);
|
||||
if (ed) {
|
||||
code += WrapInNameSpace(parser,
|
||||
field.value.type.enum_def->defined_namespace,
|
||||
field.value.type.enum_def->name + "_" +
|
||||
ed->name);
|
||||
} else {
|
||||
code += GenUnderlyingCast(parser, field, true, field.value.constant);
|
||||
}
|
||||
} else {
|
||||
code += field.value.constant;
|
||||
}
|
||||
}
|
||||
}
|
||||
code += ") {\n " + struct_def.name + "Builder builder_(_fbb);\n";
|
||||
@@ -377,7 +420,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
it != struct_def.fields.vec.end();
|
||||
++it) {
|
||||
auto &field = **it;
|
||||
code += " " + GenTypeGet(parser, field.value.type, " ", "", " ");
|
||||
code += " " + GenTypeGet(parser, field.value.type, " ", "", " ", false);
|
||||
code += field.name + "_;\n";
|
||||
GenPadding(field, [&code, &padding_id](int bits) {
|
||||
code += " int" + NumToString(bits) +
|
||||
@@ -392,7 +435,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
++it) {
|
||||
auto &field = **it;
|
||||
if (it != struct_def.fields.vec.begin()) code += ", ";
|
||||
code += GenTypeGet(parser, field.value.type, " ", "const ", " &");
|
||||
code += GenTypeGet(parser, field.value.type, " ", "const ", " &", true);
|
||||
code += field.name;
|
||||
}
|
||||
code += ")\n : ";
|
||||
@@ -403,10 +446,13 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
auto &field = **it;
|
||||
if (it != struct_def.fields.vec.begin()) code += ", ";
|
||||
code += field.name + "_(";
|
||||
if (IsScalar(field.value.type.base_type))
|
||||
code += "flatbuffers::EndianScalar(" + field.name + "))";
|
||||
else
|
||||
if (IsScalar(field.value.type.base_type)) {
|
||||
code += "flatbuffers::EndianScalar(";
|
||||
code += GenUnderlyingCast(parser, field, false, field.name);
|
||||
code += "))";
|
||||
} else {
|
||||
code += field.name + ")";
|
||||
}
|
||||
GenPadding(field, [&code, &padding_id](int bits) {
|
||||
(void)bits;
|
||||
code += ", __padding" + NumToString(padding_id++) + "(0)";
|
||||
@@ -432,12 +478,13 @@ static void GenStruct(const Parser &parser, StructDef &struct_def,
|
||||
++it) {
|
||||
auto &field = **it;
|
||||
GenComment(field.doc_comment, code_ptr, " ");
|
||||
code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " &");
|
||||
code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " &",
|
||||
true);
|
||||
code += field.name + "() const { return ";
|
||||
if (IsScalar(field.value.type.base_type))
|
||||
code += "flatbuffers::EndianScalar(" + field.name + "_)";
|
||||
else
|
||||
code += field.name + "_";
|
||||
code += GenUnderlyingCast(parser, field, true,
|
||||
IsScalar(field.value.type.base_type)
|
||||
? "flatbuffers::EndianScalar(" + field.name + "_)"
|
||||
: field.name + "_");
|
||||
code += "; }\n";
|
||||
}
|
||||
code += "};\nSTRUCT_END(" + struct_def.name + ", ";
|
||||
|
||||
Reference in New Issue
Block a user