LIBS: updated flatbuffers

Martin Gerhardy 2020-02-22 12:46:19 +01:00
parent 07daab9ddf
commit 09585ef6d1
5 changed files with 196 additions and 19 deletions

View File

@ -117,7 +117,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
" T::c_str(), T::length() and T::empty() must be supported.\n"
" The custom type also needs to be constructible from std::string\n"
" (see the --cpp-str-flex-ctor option to change this behavior).\n"
" --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
" --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
" from Flatbuffers, but (char* + length).\n"
" --cpp-std CPP_STD Generate a C++ code using features of selected C++ standard.\n"
" Supported CPP_STD values:\n"
@ -325,7 +325,7 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--bfbs-builtins") {
opts.binary_schema_builtins = true;
} else if (arg == "--bfbs-gen-embed") {
opts.binary_schema_gen_embed= true;
opts.binary_schema_gen_embed = true;
} else if (arg == "--no-fb-import") {
opts.skip_flatbuffers_import = true;
} else if (arg == "--no-ts-reexport") {
@ -348,9 +348,11 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.set_empty_vectors_to_null = false;
} else if (arg == "--java-primitive-has-method") {
opts.java_primitive_has_method = true;
} else if (arg == "--cs-gen-json-serializer") {
opts.cs_gen_json_serializer = true;
} else if (arg == "--flexbuffers") {
opts.use_flexbuffers = true;
} else if(arg == "--cpp-std") {
} else if (arg == "--cpp-std") {
if (++argi >= argc) Error("missing C++ standard specification" + arg, true);
opts.cpp_std = argv[argi];
} else {

View File

@ -625,6 +625,12 @@ class CppGenerator : public BaseGenerator {
return false;
}
bool VectorElementUserFacing(const Type& type) const {
return opts_.g_cpp_std >= cpp::CPP_STD_17 &&
opts_.g_only_fixed_enums &&
IsEnum(type);
}
void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
std::string text;
::flatbuffers::GenComment(dc, &text, nullptr, prefix);
@ -656,7 +662,8 @@ class CppGenerator : public BaseGenerator {
return "flatbuffers::String";
}
case BASE_TYPE_VECTOR: {
const auto type_name = GenTypeWire(type.VectorType(), "", false);
const auto type_name = GenTypeWire(type.VectorType(), "",
VectorElementUserFacing(type.VectorType()));
return "flatbuffers::Vector<" + type_name + ">";
}
case BASE_TYPE_STRUCT: {
@ -1622,7 +1629,7 @@ class CppGenerator : public BaseGenerator {
if (IsStruct(vtype)) {
type = WrapInNameSpace(*vtype.struct_def);
} else {
type = GenTypeWire(vtype, "", false);
type = GenTypeWire(vtype, "", VectorElementUserFacing(vtype));
}
if (TypeHasKey(vtype)) {
code_.SetValue("PARAM_TYPE", "std::vector<" + type + "> *");
@ -2322,7 +2329,8 @@ class CppGenerator : public BaseGenerator {
const auto type = WrapInNameSpace(*vtype.struct_def);
code_ += "_fbb.CreateVectorOfSortedTables<" + type + ">\\";
} else {
const auto type = GenTypeWire(vtype, "", false);
const auto type = GenTypeWire(
vtype, "", VectorElementUserFacing(vtype));
code_ += "_fbb.CreateVector<" + type + ">\\";
}
code_ +=
@ -2627,7 +2635,8 @@ class CppGenerator : public BaseGenerator {
break;
}
default: {
if (field.value.type.enum_def) {
if (field.value.type.enum_def &&
!VectorElementUserFacing(vector_type)) {
// For enumerations, we need to get access to the array data for
// the underlying storage type (eg. uint8_t).
const auto basetype = GenTypeBasic(
@ -2696,14 +2705,21 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_NAME", Name(struct_def));
code_.SetValue("NATIVE_NAME",
NativeName(Name(struct_def), &struct_def, opts_));
auto native_name =
NativeName(WrapInNameSpace(struct_def), &struct_def, parser_.opts);
code_.SetValue("POINTER_TYPE",
GenTypeNativePtr(native_name, nullptr, false));
if (opts_.generate_object_based_api) {
// Generate the X::UnPack() method.
code_ +=
"inline " + TableUnPackSignature(struct_def, false, opts_) + " {";
code_ += " auto _o = new {{NATIVE_NAME}}();";
code_ += " UnPackTo(_o, _resolver);";
code_ += " return _o;";
code_ +=
" {{POINTER_TYPE}} _o = {{POINTER_TYPE}}(new {{NATIVE_NAME}}());";
code_ += " UnPackTo(_o.get(), _resolver);";
code_ += " return _o.release();";
code_ += "}";
code_ += "";

View File

@ -271,6 +271,11 @@ class CSharpGenerator : public BaseGenerator {
// That, and Java Enums are expensive, and not universally liked.
GenComment(enum_def.doc_comment, code_ptr, &comment_config);
if (opts.cs_gen_json_serializer && opts.generate_object_based_api) {
code +=
"[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters."
"StringEnumConverter))]\n";
}
// In C# this indicates enumeration values can be treated as bit flags.
if (enum_def.attributes.Lookup("bit_flags")) {
code += "[System.FlagsAttribute]\n";
@ -1274,6 +1279,89 @@ class CSharpGenerator : public BaseGenerator {
code += " }\n";
code += " }\n";
code += "}\n\n";
// JsonConverter
if (opts.cs_gen_json_serializer) {
if (enum_def.attributes.Lookup("private")) {
code += "internal ";
} else {
code += "public ";
}
code += "class " + union_name +
"_JsonConverter : Newtonsoft.Json.JsonConverter {\n";
code += " public override bool CanConvert(System.Type objectType) {\n";
code += " return objectType == typeof(" + union_name +
") || objectType == typeof(System.Collections.Generic.List<" +
union_name + ">);\n";
code += " }\n";
code +=
" public override void WriteJson(Newtonsoft.Json.JsonWriter writer, "
"object value, "
"Newtonsoft.Json.JsonSerializer serializer) {\n";
code += " var _olist = value as System.Collections.Generic.List<" +
union_name + ">;\n";
code += " if (_olist != null) {\n";
code += " writer.WriteStartArray();\n";
code +=
" foreach (var _o in _olist) { this.WriteJson(writer, _o, "
"serializer); }\n";
code += " writer.WriteEndArray();\n";
code += " } else {\n";
code += " this.WriteJson(writer, value as " + union_name +
", serializer);\n";
code += " }\n";
code += " }\n";
code += " public void WriteJson(Newtonsoft.Json.JsonWriter writer, " +
union_name +
" _o, "
"Newtonsoft.Json.JsonSerializer serializer) {\n";
code += " if (_o == null) return;\n";
code += " serializer.Serialize(writer, _o.Value);\n";
code += " }\n";
code +=
" public override object ReadJson(Newtonsoft.Json.JsonReader "
"reader, "
"System.Type objectType, "
"object existingValue, Newtonsoft.Json.JsonSerializer serializer) "
"{\n";
code +=
" var _olist = existingValue as System.Collections.Generic.List<" +
union_name + ">;\n";
code += " if (_olist != null) {\n";
code += " for (var _j = 0; _j < _olist.Count; ++_j) {\n";
code += " reader.Read();\n";
code +=
" _olist[_j] = this.ReadJson(reader, _olist[_j], "
"serializer);\n";
code += " }\n";
code += " reader.Read();\n";
code += " return _olist;\n";
code += " } else {\n";
code += " return this.ReadJson(reader, existingValue as " +
union_name + ", serializer);\n";
code += " }\n";
code += " }\n";
code += " public " + union_name +
" ReadJson(Newtonsoft.Json.JsonReader reader, " + union_name +
" _o, Newtonsoft.Json.JsonSerializer serializer) {\n";
code += " if (_o == null) return null;\n";
code += " switch (_o.Type) {\n";
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
++it) {
auto &ev = **it;
if (ev.union_type.base_type == BASE_TYPE_NONE) {
code += " default: break;\n";
} else {
auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts);
code += " case " + enum_def.name + "." + ev.name +
": _o.Value = serializer.Deserialize<" + type_name +
">(reader); break;\n";
}
}
code += " }\n";
code += " return _o;\n";
code += " }\n";
code += "}\n\n";
}
}
std::string GenTypeName_ObjectAPI(const std::string &name,
@ -1794,8 +1882,62 @@ class CSharpGenerator : public BaseGenerator {
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
code += " public " + type_name + " " + MakeCamel(field.name, true) +
" { get; set; }\n";
auto camel_name = MakeCamel(field.name, true);
if (opts.cs_gen_json_serializer) {
if (IsUnion(field.value.type)) {
auto utype_name = WrapInNameSpace(*field.value.type.enum_def);
code +=
" [Newtonsoft.Json.JsonProperty(\"" + field.name + "_type\")]\n";
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
code += " private " + utype_name + "[] " + camel_name + "Type {\n";
code += " get {\n";
code += " if (this." + camel_name + " == null) return null;\n";
code += " var _o = new " + utype_name + "[this." + camel_name +
".Count];\n";
code +=
" for (var _j = 0; _j < _o.Length; ++_j) { _o[_j] = "
"this." +
camel_name + "[_j].Type; }\n";
code += " return _o;\n";
code += " }\n";
code += " set {\n";
code += " this." + camel_name + " = new List<" + utype_name +
"Union>();\n";
code += " for (var _j = 0; _j < value.Length; ++_j) {\n";
code += " var _o = new " + utype_name + "Union();\n";
code += " _o.Type = value[_j];\n";
code += " this." + camel_name + ".Add(_o);\n";
code += " }\n";
code += " }\n";
code += " }\n";
} else {
code += " private " + utype_name + " " + camel_name + "Type {\n";
code += " get {\n";
code += " return this." + camel_name + " != null ? this." +
camel_name + ".Type : " + utype_name + ".NONE;\n";
code += " }\n";
code += " set {\n";
code += " this." + camel_name + " = new " + utype_name +
"Union();\n";
code += " this." + camel_name + ".Type = value;\n";
code += " }\n";
code += " }\n";
}
}
code += " [Newtonsoft.Json.JsonProperty(\"" + field.name + "\")]\n";
if (IsUnion(field.value.type)) {
auto union_name =
(field.value.type.base_type == BASE_TYPE_VECTOR)
? GenTypeGet_ObjectAPI(field.value.type.VectorType(), opts)
: type_name;
code += " [Newtonsoft.Json.JsonConverter(typeof(" + union_name +
"_JsonConverter))]\n";
}
if (field.attributes.Lookup("hash")) {
code += " [Newtonsoft.Json.JsonIgnore()]\n";
}
}
code += " public " + type_name + " " + camel_name + " { get; set; }\n";
}
// Generate Constructor
code += "\n";
@ -1833,6 +1975,21 @@ class CSharpGenerator : public BaseGenerator {
}
}
code += " }\n";
// Generate Serialization
if (opts.cs_gen_json_serializer &&
parser_.root_struct_def_ == &struct_def) {
code += "\n";
code += " public static " + class_name +
" DeserializeFromJson(string jsonText) {\n";
code += " return Newtonsoft.Json.JsonConvert.DeserializeObject<" +
class_name + ">(jsonText);\n";
code += " }\n";
code += " public string SerializeToJson() {\n";
code +=
" return Newtonsoft.Json.JsonConvert.SerializeObject(this, "
"Newtonsoft.Json.Formatting.Indented);\n";
code += " }\n";
}
code += "}\n\n";
}

View File

@ -1494,6 +1494,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// TODO: instead of asserting, could write vector with larger elements
// instead, though that would be wasteful.
FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
Align(bit_width);
if (!fixed) Write<uint64_t>(len, byte_width);
auto vloc = buf_.size();
for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);

View File

@ -556,6 +556,7 @@ struct IDLOptions {
std::string root_type;
bool force_defaults;
bool java_primitive_has_method;
bool cs_gen_json_serializer;
std::vector<std::string> cpp_includes;
std::string cpp_std;
std::string proto_namespace_suffix;
@ -592,12 +593,12 @@ struct IDLOptions {
// for code generation.
unsigned long lang_to_generate;
// If set (default behavior), empty string fields will be set to nullptr to make
// the flatbuffer more compact.
// If set (default behavior), empty string fields will be set to nullptr to
// make the flatbuffer more compact.
bool set_empty_strings_to_null;
// If set (default behavior), empty vector fields will be set to nullptr to make
// the flatbuffer more compact.
// If set (default behavior), empty vector fields will be set to nullptr to
// make the flatbuffer more compact.
bool set_empty_vectors_to_null;
IDLOptions()
@ -641,6 +642,7 @@ struct IDLOptions {
size_prefixed(false),
force_defaults(false),
java_primitive_has_method(false),
cs_gen_json_serializer(false),
lang(IDLOptions::kJava),
mini_reflect(IDLOptions::kNone),
lang_to_generate(0),
@ -1119,9 +1121,8 @@ bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
// Generate GRPC Python interfaces.
// See idl_gen_grpc.cpp.
bool GeneratePythonGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name);
bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
const std::string &file_name);
} // namespace flatbuffers