Union Vector

This commit is contained in:
Bei Li
2017-01-24 11:52:36 -08:00
parent bbef92c17d
commit 68bbe983e9
12 changed files with 567 additions and 121 deletions

View File

@@ -47,17 +47,17 @@ struct Generator {
const Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kBinary,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kJson,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
flatbuffers::GenerateCppGRPC,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kCpp,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
@@ -72,7 +72,7 @@ const Generator generators[] = {
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
@@ -82,12 +82,12 @@ const Generator generators[] = {
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kPhp,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
};
@@ -267,6 +267,7 @@ int main(int argc, const char *argv[]) {
arg == generators[i].generator_opt_short)) {
generator_enabled[i] = true;
any_generator = true;
opts.lang_to_generate |= generators[i].lang;
goto found;
}
}

View File

@@ -454,6 +454,13 @@ class CppGenerator : public BaseGenerator {
enum_def.name + " type)";
}
static std::string UnionVectorVerifySignature(const EnumDef &enum_def) {
return "bool Verify" + enum_def.name + "Vector" +
"(flatbuffers::Verifier &verifier, " +
"const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " +
"const flatbuffers::Vector<uint8_t> *types)";
}
static std::string UnionUnPackSignature(const EnumDef &enum_def,
bool inclass) {
return (inclass ? "static " : "") +
@@ -685,6 +692,7 @@ class CppGenerator : public BaseGenerator {
if (enum_def.is_union) {
code_ += UnionVerifySignature(enum_def) + ";";
code_ += UnionVectorVerifySignature(enum_def) + ";";
code_ += "";
}
}
@@ -721,6 +729,18 @@ class CppGenerator : public BaseGenerator {
code_ += "}";
code_ += "";
code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {";
code_ += " if (values->size() != types->size()) return false;";
code_ += " for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {";
code_ += " if (!Verify" + enum_def.name + "(";
code_ += " verifier, values->Get(i), types->GetEnum<" + enum_def.name + ">(i))) { ";
code_ += " return false; ";
code_ += " }";
code_ += " }";
code_ += " return true;";
code_ += "}";
code_ += "";
if (parser_.opts.generate_object_based_api) {
// Generate union Unpack() and Pack() functions.
code_ += "inline " + UnionUnPackSignature(enum_def, false) + " {";
@@ -995,6 +1015,10 @@ class CppGenerator : public BaseGenerator {
}
break;
}
case BASE_TYPE_UNION: {
code_ += "{{PRE}}Verify{{ENUM_NAME}}Vector(verifier, {{NAME}}(), {{NAME}}_type())\\";
break;
}
default:
break;
}

View File

@@ -70,108 +70,80 @@ struct LanguageParameters {
CommentConfig comment_config;
};
LanguageParameters language_parameters[] = {
{
IDLOptions::kJava,
false,
".java",
"String",
"boolean ",
" {\n",
"class ",
" final ",
"final ",
"final class ",
";\n",
"()",
"",
" extends ",
"package ",
";",
"",
"_bb.order(ByteOrder.LITTLE_ENDIAN); ",
"position()",
"offset()",
"",
"",
"",
"import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"
"import com.google.flatbuffers.*;\n\n@SuppressWarnings(\"unused\")\n",
const LanguageParameters& GetLangParams(IDLOptions::Language lang) {
static LanguageParameters language_parameters[] = {
{
"/**",
" *",
" */",
IDLOptions::kJava,
false,
".java",
"String",
"boolean ",
" {\n",
"class ",
" final ",
"final ",
"final class ",
";\n",
"()",
"",
" extends ",
"package ",
";",
"",
"_bb.order(ByteOrder.LITTLE_ENDIAN); ",
"position()",
"offset()",
"",
"",
"",
"import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"
"import com.google.flatbuffers.*;\n\n@SuppressWarnings(\"unused\")\n",
{
"/**",
" *",
" */",
},
},
},
{
IDLOptions::kCSharp,
true,
".cs",
"string",
"bool ",
"\n{\n",
"struct ",
" readonly ",
"",
"enum ",
",\n",
" { get",
"} ",
" : ",
"namespace ",
"\n{",
"\n}\n",
"",
"Position",
"Offset",
"__p.",
"Table.",
"?",
"using System;\nusing FlatBuffers;\n\n",
{
nullptr,
"///",
nullptr,
IDLOptions::kCSharp,
true,
".cs",
"string",
"bool ",
"\n{\n",
"struct ",
" readonly ",
"",
"enum ",
",\n",
" { get",
"} ",
" : ",
"namespace ",
"\n{",
"\n}\n",
"",
"Position",
"Offset",
"__p.",
"Table.",
"?",
"using System;\nusing FlatBuffers;\n\n",
{
nullptr,
"///",
nullptr,
},
},
},
// TODO: add Go support to the general generator.
// WARNING: this is currently only used for generating make rules for Go.
{
IDLOptions::kGo,
true,
".go",
"string",
"bool ",
"\n{\n",
"class ",
"const ",
" ",
"class ",
";\n",
"()",
"",
"",
"package ",
"",
"",
"",
"position()",
"offset()",
"",
"",
"",
"import (\n\tflatbuffers \"github.com/google/flatbuffers/go\"\n)",
{
nullptr,
"///",
nullptr,
},
}
};
};
static_assert(sizeof(language_parameters) / sizeof(LanguageParameters) ==
IDLOptions::kMAX,
"Please add extra elements to the arrays above.");
if (lang == IDLOptions::kJava) {
return language_parameters[0];
} else {
assert(lang == IDLOptions::kCSharp);
return language_parameters[1];
}
}
namespace general {
class GeneralGenerator : public BaseGenerator {
@@ -179,10 +151,10 @@ class GeneralGenerator : public BaseGenerator {
GeneralGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."),
lang_(language_parameters[parser_.opts.lang]),
lang_(GetLangParams(parser_.opts.lang)),
cur_name_space_( nullptr ) {
assert(parser_.opts.lang <= IDLOptions::kMAX);
};
}
GeneralGenerator &operator=(const GeneralGenerator &);
bool generate() {
std::string one_file_code;
@@ -258,9 +230,16 @@ static bool IsEnum(const Type& type) {
}
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
static const char *gtypename[] = {
static const char *java_typename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#JTYPE, #NTYPE, #GTYPE,
#JTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
};
static const char *csharp_typename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#NTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
};
@@ -274,7 +253,12 @@ std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
}
}
return gtypename[type.base_type * IDLOptions::kMAX + lang_.language];
if (lang_.language == IDLOptions::kJava) {
return java_typename[type.base_type];
} else {
assert(lang_.language == IDLOptions::kCSharp);
return csharp_typename[type.base_type];
}
}
std::string GenTypeBasic(const Type &type) {
@@ -1352,7 +1336,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += (lang_.language != IDLOptions::kJava) ? ";" : "";
code += "\n\n";
}
const LanguageParameters & lang_;
const LanguageParameters& lang_;
// This tracks the current namespace used to determine if a type need to be prefixed by its namespace
const Namespace *cur_name_space_;
};
@@ -1367,7 +1351,7 @@ bool GenerateGeneral(const Parser &parser, const std::string &path,
std::string GeneralMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
assert(parser.opts.lang <= IDLOptions::kMAX);
auto lang = language_parameters[parser.opts.lang];
const auto &lang = GetLangParams(parser.opts.lang);
std::string make_rule;

View File

@@ -554,12 +554,6 @@ CheckedError Parser::ParseType(Type &type) {
return Error(
"nested vector types not supported (wrap in table first).");
}
if (subtype.base_type == BASE_TYPE_UNION) {
// We could support this if we stored a struct of 2 elements per
// union element.
return Error(
"vector of union types not supported (wrap in table first).");
}
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
type.element = subtype.base_type;
EXPECT(']');
@@ -611,6 +605,19 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
// with a special suffix.
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
type.enum_def->underlying_type, &typefield));
} else if (type.base_type == BASE_TYPE_VECTOR &&
type.element == BASE_TYPE_UNION) {
// Only cpp supports the union vector feature so far.
if (opts.lang_to_generate != IDLOptions::kCpp) {
return Error("Vectors of unions are not yet supported in all "
"the specified programming languages.");
}
// For vector of union fields, add a second auto-generated vector field to
// hold the types, with a special suffix.
Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def);
union_vector.element = BASE_TYPE_UTYPE;
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
union_vector, &typefield));
}
FieldDef *field;