LIBS: updated flatbuffers

Martin Gerhardy 2020-02-05 20:15:46 +01:00
parent 199872b69e
commit e830e285b9
8 changed files with 1026 additions and 133 deletions

View File

@ -70,6 +70,9 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
ss << " " << full_name.str() << " " << name << " " << help << ".\n";
}
// clang-format off
// Output width
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
ss <<
" -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n"
@ -141,6 +144,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
" --schema Serialize schemas instead of JSON (use with -b).\n"
" --bfbs-comments Add doc comments to the binary schema files.\n"
" --bfbs-builtins Add builtin attributes to the binary schema files.\n"
" --bfbs-gen-embed Generate code to embed the bfbs schema to the source.\n"
" --conform FILE Specify a schema the following schemas should be\n"
" an evolution of. Gives errors if not.\n"
" --conform-includes Include path for the schema given with --conform PATH\n"
@ -166,6 +170,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
"Output files are named using the base file name of the input,\n"
"and written to the current directory or the path given by -o.\n"
"example: " << program_name << " -c -b schema1.fbs schema2.fbs data.json\n";
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
// clang-format on
return ss.str();
}
@ -201,22 +206,22 @@ int FlatCompiler::Compile(int argc, const char **argv) {
output_path = flatbuffers::ConCatPathFileName(
flatbuffers::PosixPath(argv[argi]), "");
} else if (arg == "-I") {
if (++argi >= argc) Error("missing path following" + arg, true);
if (++argi >= argc) Error("missing path following: " + arg, true);
include_directories_storage.push_back(
flatbuffers::PosixPath(argv[argi]));
include_directories.push_back(
include_directories_storage.back().c_str());
} else if (arg == "--conform") {
if (++argi >= argc) Error("missing path following" + arg, true);
if (++argi >= argc) Error("missing path following: " + arg, true);
conform_to_schema = flatbuffers::PosixPath(argv[argi]);
} else if (arg == "--conform-includes") {
if (++argi >= argc) Error("missing path following" + arg, true);
if (++argi >= argc) Error("missing path following: " + arg, true);
include_directories_storage.push_back(
flatbuffers::PosixPath(argv[argi]));
conform_include_directories.push_back(
include_directories_storage.back().c_str());
} else if (arg == "--include-prefix") {
if (++argi >= argc) Error("missing path following" + arg, true);
if (++argi >= argc) Error("missing path following: " + arg, true);
opts.include_prefix = flatbuffers::ConCatPathFileName(
flatbuffers::PosixPath(argv[argi]), "");
} else if (arg == "--keep-prefix") {
@ -261,13 +266,13 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--gen-compare") {
opts.gen_compare = true;
} else if (arg == "--cpp-include") {
if (++argi >= argc) Error("missing include following" + arg, true);
if (++argi >= argc) Error("missing include following: " + arg, true);
opts.cpp_includes.push_back(argv[argi]);
} else if (arg == "--cpp-ptr-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
if (++argi >= argc) Error("missing type following: " + arg, true);
opts.cpp_object_api_pointer_type = argv[argi];
} else if (arg == "--cpp-str-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
if (++argi >= argc) Error("missing type following: " + arg, true);
opts.cpp_object_api_string_type = argv[argi];
} else if (arg == "--cpp-str-flex-ctor") {
opts.cpp_object_api_string_flexible_constructor = true;
@ -278,10 +283,10 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--gen-generated") {
opts.gen_generated = true;
} else if (arg == "--object-prefix") {
if (++argi >= argc) Error("missing prefix following" + arg, true);
if (++argi >= argc) Error("missing prefix following: " + arg, true);
opts.object_prefix = argv[argi];
} else if (arg == "--object-suffix") {
if (++argi >= argc) Error("missing suffix following" + arg, true);
if (++argi >= argc) Error("missing suffix following: " + arg, true);
opts.object_suffix = argv[argi];
} else if (arg == "--gen-all") {
opts.generate_all = true;
@ -319,6 +324,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.binary_schema_comments = true;
} else if (arg == "--bfbs-builtins") {
opts.binary_schema_builtins = true;
} else if (arg == "--bfbs-gen-embed") {
opts.binary_schema_gen_embed= true;
} else if (arg == "--no-fb-import") {
opts.skip_flatbuffers_import = true;
} else if (arg == "--no-ts-reexport") {
@ -330,7 +337,7 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--reflect-names") {
opts.mini_reflect = IDLOptions::kTypesAndNames;
} else if (arg == "--root-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
if (++argi >= argc) Error("missing type following: " + arg, true);
opts.root_type = argv[argi];
} else if (arg == "--force-defaults") {
opts.force_defaults = true;
@ -466,8 +473,10 @@ int FlatCompiler::Compile(int argc, const char **argv) {
auto err = parser->ConformTo(conform_parser);
if (!err.empty()) Error("schemas don\'t conform: " + err);
}
if (schema_binary) {
if (schema_binary || opts.binary_schema_gen_embed) {
parser->Serialize();
}
if (schema_binary) {
parser->file_extension_ = reflection::SchemaExtension();
}
}

View File

@ -53,6 +53,33 @@ static std::string GeneratedFileName(const std::string &path,
return path + file_name + "_generated.h";
}
static std::string GenIncludeGuard(const std::string &file_name,
const Namespace &name_space,
const std::string &postfix= "") {
// Generate include guard.
std::string guard = file_name;
// Remove any non-alpha-numeric characters that may appear in a filename.
struct IsAlnum {
bool operator()(char c) const { return !is_alnum(c); }
};
guard.erase(std::remove_if(guard.begin(), guard.end(), IsAlnum()),
guard.end());
guard = "FLATBUFFERS_GENERATED_" + guard;
guard += "_";
// For further uniqueness, also add the namespace.
for (auto it = name_space.components.begin();
it != name_space.components.end(); ++it) {
guard += *it + "_";
}
// Anything extra to add to the guard?
if (!postfix.empty()) {
guard += postfix + "_";
}
guard += "H_";
std::transform(guard.begin(), guard.end(), guard.begin(), ToUpper);
return guard;
}
namespace cpp {
enum CppStandard { CPP_STD_X0 = 0, CPP_STD_11, CPP_STD_17 };
@ -182,28 +209,6 @@ class CppGenerator : public BaseGenerator {
for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
}
std::string GenIncludeGuard() const {
// Generate include guard.
std::string guard = file_name_;
// Remove any non-alpha-numeric characters that may appear in a filename.
struct IsAlnum {
bool operator()(char c) const { return !is_alnum(c); }
};
guard.erase(std::remove_if(guard.begin(), guard.end(), IsAlnum()),
guard.end());
guard = "FLATBUFFERS_GENERATED_" + guard;
guard += "_";
// For further uniqueness, also add the namespace.
auto name_space = parser_.current_namespace_;
for (auto it = name_space->components.begin();
it != name_space->components.end(); ++it) {
guard += *it + "_";
}
guard += "H_";
std::transform(guard.begin(), guard.end(), guard.begin(), ToUpper);
return guard;
}
void GenIncludeDependencies() {
int num_includes = 0;
for (auto it = parser_.native_included_files_.begin();
@ -241,13 +246,73 @@ class CppGenerator : public BaseGenerator {
std::string Name(const EnumVal &ev) const { return EscapeKeyword(ev.name); }
bool generate_bfbs_embed() {
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
// If we don't have a root struct definition,
if (!parser_.root_struct_def_) {
// put a comment in the output why there is no code generated.
code_ += "// Binary schema not generated, no root struct found";
} else {
auto &struct_def = *parser_.root_struct_def_;
const auto include_guard = GenIncludeGuard(file_name_, *struct_def.defined_namespace, "bfbs");
code_ += "#ifndef " + include_guard;
code_ += "#define " + include_guard;
code_ += "";
if (parser_.opts.gen_nullable) {
code_ += "#pragma clang system_header\n\n";
}
SetNameSpace(struct_def.defined_namespace);
auto name = Name(struct_def);
code_.SetValue("STRUCT_NAME", name);
// Create code to return the binary schema data.
auto binary_schema_hex_text = BufferToHexText(parser_.builder_.GetBufferPointer(),
parser_.builder_.GetSize(), 105, " ", "");
code_ += "struct {{STRUCT_NAME}}BinarySchema {";
code_ += " static const uint8_t *data() {";
code_ += " // Buffer containing the binary schema.";
code_ += " static const uint8_t bfbsData[" + NumToString(parser_.builder_.GetSize()) + "] = {";
code_ += binary_schema_hex_text;
code_ += " };";
code_ += " return bfbsData;";
code_ += " }";
code_ += " static size_t size() {";
code_ += " return " + NumToString(parser_.builder_.GetSize()) + ";";
code_ += " }";
code_ += " const uint8_t *begin() {";
code_ += " return data();";
code_ += " }";
code_ += " const uint8_t *end() {";
code_ += " return data() + size();";
code_ += " }";
code_ += "};";
code_ += "";
if (cur_name_space_) SetNameSpace(nullptr);
// Close the include guard.
code_ += "#endif // " + include_guard;
}
// We are just adding "_bfbs" to the generated filename.
const auto file_path = GeneratedFileName(path_, file_name_ + "_bfbs");
const auto final_code = code_.ToString();
return SaveFile(file_path.c_str(), final_code, false);
}
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
code_.Clear();
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
const auto include_guard = GenIncludeGuard();
const auto include_guard = GenIncludeGuard(file_name_, *parser_.current_namespace_);
code_ += "#ifndef " + include_guard;
code_ += "#define " + include_guard;
code_ += "";
@ -519,7 +584,10 @@ class CppGenerator : public BaseGenerator {
const auto file_path = GeneratedFileName(path_, file_name_);
const auto final_code = code_.ToString();
return SaveFile(file_path.c_str(), final_code, false);
// Save the file and optionally generate the binary schema code.
return SaveFile(file_path.c_str(), final_code, false) &&
(!parser_.opts.binary_schema_gen_embed || generate_bfbs_embed());
}
private:

View File

@ -55,7 +55,7 @@ class CSharpGenerator : public BaseGenerator {
std::string enumcode;
auto &enum_def = **it;
if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace;
GenEnum(enum_def, &enumcode);
GenEnum(enum_def, &enumcode, parser_.opts);
if (parser_.opts.one_file) {
one_file_code += enumcode;
} else {
@ -71,7 +71,7 @@ class CSharpGenerator : public BaseGenerator {
auto &struct_def = **it;
if (!parser_.opts.one_file)
cur_name_space_ = struct_def.defined_namespace;
GenStruct(struct_def, &declcode);
GenStruct(struct_def, &declcode, parser_.opts);
if (parser_.opts.one_file) {
one_file_code += declcode;
} else {
@ -106,7 +106,9 @@ class CSharpGenerator : public BaseGenerator {
code += "namespace " + namespace_name + "\n{\n\n";
}
if (needs_includes) {
code += "using global::System;\nusing global::FlatBuffers;\n\n";
code += "using global::System;\n";
code += "using global::System.Collections.Generic;\n";
code += "using global::FlatBuffers;\n\n";
}
code += classcode;
if (!namespace_name.empty()) { code += "\n}\n"; }
@ -257,7 +259,8 @@ class CSharpGenerator : public BaseGenerator {
return GenDefaultValueBasic(field, true);
}
void GenEnum(EnumDef &enum_def, std::string *code_ptr) const {
void GenEnum(EnumDef &enum_def, std::string *code_ptr,
const IDLOptions &opts) const {
std::string &code = *code_ptr;
if (enum_def.generated) return;
@ -290,6 +293,19 @@ class CSharpGenerator : public BaseGenerator {
}
// Close the class
code += "};\n\n";
if (opts.generate_object_based_api) {
GenEnum_ObjectAPI(enum_def, code_ptr, opts);
}
}
bool HasUnionStringValue(const EnumDef &enum_def) const {
if (!enum_def.is_union) return false;
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &val = **it;
if (val.union_type.base_type == BASE_TYPE_STRING) { return true; }
}
return false;
}
// Returns the function name that is able to read a value of the given type.
@ -488,7 +504,8 @@ class CSharpGenerator : public BaseGenerator {
return key_getter;
}
void GenStruct(StructDef &struct_def, std::string *code_ptr) const {
void GenStruct(StructDef &struct_def, std::string *code_ptr,
const IDLOptions &opts) const {
if (struct_def.generated) return;
std::string &code = *code_ptr;
@ -706,13 +723,29 @@ class CSharpGenerator : public BaseGenerator {
: (IsScalar(field.value.type.element) ? default_cast + "0"
: "null");
}
if (vectortype.base_type == BASE_TYPE_UNION &&
HasUnionStringValue(*vectortype.enum_def)) {
code += member_suffix;
code += "}\n";
code += " public string " + MakeCamel(field.name, true) +
"AsString(int j)";
code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING));
code += "(" + index + ") : null";
}
break;
}
case BASE_TYPE_UNION:
code += "() where TTable : struct, IFlatbufferObject";
code += offset_prefix + "(TTable?)" + getter;
code += "<TTable>(o + __p.bb_pos) : null";
if (HasUnionStringValue(*field.value.type.enum_def)) {
code += member_suffix;
code += "}\n";
code += " public string " + MakeCamel(field.name, true) +
"AsString()";
code += offset_prefix + GenGetter(Type(BASE_TYPE_STRING));
code += "(o + __p.bb_pos) : null";
}
break;
default: FLATBUFFERS_ASSERT(0);
}
@ -876,8 +909,11 @@ class CSharpGenerator : public BaseGenerator {
}
}
code += "\n";
auto struct_has_create = false;
std::set<flatbuffers::FieldDef *> field_has_create_set;
flatbuffers::FieldDef *key_field = nullptr;
if (struct_def.fixed) {
struct_has_create = true;
// create a struct constructor function
code += " public static " + GenOffsetType(struct_def) + " ";
code += "Create";
@ -907,6 +943,7 @@ class CSharpGenerator : public BaseGenerator {
// JVM specifications restrict default constructor params to be < 255.
// Longs and doubles take up 2 units, so we set the limit to be < 127.
if (has_no_struct_fields && num_fields && num_fields < 127) {
struct_has_create = true;
// Generate a table constructor of the form:
// public static int createName(FlatBufferBuilder builder, args...)
code += " public static " + GenOffsetType(struct_def) + " ";
@ -986,6 +1023,7 @@ class CSharpGenerator : public BaseGenerator {
auto alignment = InlineAlignment(vector_type);
auto elem_size = InlineSize(vector_type);
if (!IsStruct(vector_type)) {
field_has_create_set.insert(&field);
code += " public static VectorOffset ";
code += "Create";
code += MakeCamel(field.name);
@ -1105,7 +1143,16 @@ class CSharpGenerator : public BaseGenerator {
code += " return null;\n";
code += " }\n";
}
if (opts.generate_object_based_api) {
GenPackUnPack_ObjectAPI(struct_def, code_ptr, opts, struct_has_create,
field_has_create_set);
}
code += "};\n\n";
if (opts.generate_object_based_api) {
GenStruct_ObjectAPI(struct_def, code_ptr, opts);
}
}
void GenVectorAccessObject(StructDef &struct_def,
@ -1166,6 +1213,629 @@ class CSharpGenerator : public BaseGenerator {
code += " }\n";
}
void GenEnum_ObjectAPI(EnumDef &enum_def, std::string *code_ptr,
const IDLOptions &opts) const {
auto &code = *code_ptr;
if (enum_def.generated) return;
if (!enum_def.is_union) return;
if (enum_def.attributes.Lookup("private")) {
code += "internal ";
} else {
code += "public ";
}
auto union_name = enum_def.name + "Union";
code += "class " + union_name + " {\n";
// Type
code += " public " + enum_def.name + " Type { get; set; }\n";
// Value
code += " public object Value { get; set; }\n";
code += "\n";
// Constructor
code += " public " + union_name + "() {\n";
code += " this.Type = " + enum_def.name + "." +
enum_def.Vals()[0]->name + ";\n";
code += " this.Value = null;\n";
code += " }\n\n";
// As<T>
code += " public T As<T>() where T : class { return this.Value as T; }\n";
// As
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) continue;
auto type_name = GenTypeGet_ObjectAPI(ev.union_type, opts);
if (ev.union_type.base_type == BASE_TYPE_STRUCT &&
ev.union_type.struct_def->attributes.Lookup("private")) {
code += " internal ";
} else {
code += " public ";
}
code += type_name + " As" + ev.name + "() { return this.As<" + type_name +
">(); }\n";
}
code += "\n";
// Pack()
code += " public static int Pack(FlatBuffers.FlatBufferBuilder builder, " +
union_name + " _o) {\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: return 0;\n";
} else {
code += " case " + enum_def.name + "." + ev.name + ": return ";
if (ev.union_type.base_type == BASE_TYPE_STRING) {
code += "builder.CreateString(_o.As" + ev.name + "()).Value;\n";
} else {
code += GenTypeGet(ev.union_type) + ".Pack(builder, _o.As" + ev.name +
"()).Value;\n";
}
}
}
code += " }\n";
code += " }\n";
code += "}\n\n";
}
std::string GenTypeName_ObjectAPI(const std::string &name,
const IDLOptions &opts) const {
return opts.object_prefix + name + opts.object_suffix;
}
void GenUnionUnPack_ObjectAPI(const EnumDef &enum_def, std::string *code_ptr,
const std::string &camel_name,
bool is_vector) const {
auto &code = *code_ptr;
std::string varialbe_name = "_o." + camel_name;
std::string type_suffix = "";
std::string func_suffix = "()";
std::string indent = " ";
if (is_vector) {
varialbe_name = "_o_" + camel_name;
type_suffix = "(_j)";
func_suffix = "(_j)";
indent = " ";
}
if (is_vector) {
code += indent + "var " + varialbe_name + " = new ";
} else {
code += indent + varialbe_name + " = new ";
}
code += WrapInNameSpace(enum_def) + "Union();\n";
code += indent + varialbe_name + ".Type = this." + camel_name + "Type" +
type_suffix + ";\n";
code +=
indent + "switch (this." + camel_name + "Type" + type_suffix + ") {\n";
for (auto eit = enum_def.Vals().begin(); eit != enum_def.Vals().end();
++eit) {
auto &ev = **eit;
if (ev.union_type.base_type == BASE_TYPE_NONE) {
code += indent + " default: break;\n";
} else {
code += indent + " case " + WrapInNameSpace(enum_def) + "." + ev.name +
":\n";
code += indent + " " + varialbe_name + ".Value = this." + camel_name;
if (ev.union_type.base_type == BASE_TYPE_STRING) {
code += "AsString" + func_suffix + ";\n";
} else {
code += "<" + GenTypeGet(ev.union_type) + ">" + func_suffix;
code += ".HasValue ? this." + camel_name;
code += "<" + GenTypeGet(ev.union_type) + ">" + func_suffix +
".Value.UnPack() : null;\n";
}
code += indent + " break;\n";
}
}
code += indent + "}\n";
if (is_vector) {
code += indent + "_o." + camel_name + ".Add(" + varialbe_name + ");\n";
}
}
void GenPackUnPack_ObjectAPI(
StructDef &struct_def, std::string *code_ptr, const IDLOptions &opts,
bool struct_has_create,
const std::set<FieldDef *> &field_has_create) const {
auto &code = *code_ptr;
auto struct_name = GenTypeName_ObjectAPI(struct_def.name, opts);
// UnPack()
code += " public " + struct_name + " UnPack() {\n";
code += " var _o = new " + struct_name + "();\n";
code += " this.UnPackTo(_o);\n";
code += " return _o;\n";
code += " }\n";
// UnPackTo()
code += " public void UnPackTo(" + struct_name + " _o) {\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto camel_name = MakeCamel(field.name);
auto start = " _o." + camel_name + " = ";
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
auto fixed = struct_def.fixed && field.value.type.struct_def->fixed;
if (fixed) {
code += start + "this." + camel_name + ".UnPack();\n";
} else {
code += start + "this." + camel_name + ".HasValue ? this." +
camel_name + ".Value.UnPack() : null;\n";
}
break;
}
case BASE_TYPE_ARRAY: {
auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
auto length_str = NumToString(field.value.type.fixed_length);
auto unpack_method = field.value.type.struct_def == nullptr
? ""
: field.value.type.struct_def->fixed
? ".UnPack()"
: "?.UnPack()";
code += start + "new " + type_name.substr(0, type_name.length() - 1) +
length_str + "];\n";
code += " for (var _j = 0; _j < " + length_str + "; ++_j) { _o." +
camel_name + "[_j] = this." + camel_name + "(_j)" +
unpack_method + "; }\n";
break;
}
case BASE_TYPE_VECTOR:
if (field.value.type.element == BASE_TYPE_UNION) {
code += start + "new " +
GenTypeGet_ObjectAPI(field.value.type, opts) + "();\n";
code += " for (var _j = 0; _j < this." + camel_name +
"Length; ++_j) {\n";
GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
camel_name, true);
code += " }\n";
} else if (field.value.type.element != BASE_TYPE_UTYPE) {
auto fixed = field.value.type.struct_def == nullptr;
code += start + "new " +
GenTypeGet_ObjectAPI(field.value.type, opts) + "();\n";
code += " for (var _j = 0; _j < this." + camel_name +
"Length; ++_j) {";
code += "_o." + camel_name + ".Add(";
if (fixed) {
code += "this." + camel_name + "(_j)";
} else {
code += "this." + camel_name + "(_j).HasValue ? this." +
camel_name + "(_j).Value.UnPack() : null";
}
code += ");}\n";
}
break;
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
GenUnionUnPack_ObjectAPI(*field.value.type.enum_def, code_ptr,
camel_name, false);
break;
}
default: {
code += start + "this." + camel_name + ";\n";
break;
}
}
}
code += " }\n";
// Pack()
code += " public static " + GenOffsetType(struct_def) +
" Pack(FlatBufferBuilder builder, " + struct_name + " _o) {\n";
code += " if (_o == null) return default(" + GenOffsetType(struct_def) +
");\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto camel_name = MakeCamel(field.name);
// pre
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (!field.value.type.struct_def->fixed) {
code += " var _" + field.name + " = _o." + camel_name +
" == null ? default(" +
GenOffsetType(*field.value.type.struct_def) +
") : " + GenTypeGet(field.value.type) +
".Pack(builder, _o." + camel_name + ");\n";
}
break;
}
case BASE_TYPE_STRING: {
std::string create_string =
field.shared ? "CreateSharedString" : "CreateString";
code += " var _" + field.name + " = _o." + camel_name +
" == null ? default(StringOffset) : "
"builder." +
create_string + "(_o." + camel_name + ");\n";
break;
}
case BASE_TYPE_VECTOR: {
if (field_has_create.find(&field) != field_has_create.end()) {
auto property_name = camel_name;
auto gen_for_loop = true;
std::string array_name = "__" + field.name;
std::string array_type = "";
std::string to_array = "";
switch (field.value.type.element) {
case BASE_TYPE_STRING: {
std::string create_string =
field.shared ? "CreateSharedString" : "CreateString";
array_type = "StringOffset";
to_array += "builder." + create_string + "(_o." +
property_name + "[_j])";
break;
}
case BASE_TYPE_STRUCT:
array_type = "Offset<" + GenTypeGet(field.value.type) + ">";
to_array = GenTypeGet(field.value.type) + ".Pack(builder, _o." +
property_name + "[_j])";
break;
case BASE_TYPE_UTYPE:
property_name = camel_name.substr(0, camel_name.size() - 4);
array_type = WrapInNameSpace(*field.value.type.enum_def);
to_array = "_o." + property_name + "[_j].Type";
break;
case BASE_TYPE_UNION:
array_type = "int";
to_array = WrapInNameSpace(*field.value.type.enum_def) +
"Union.Pack(builder, _o." + property_name + "[_j])";
break;
default: gen_for_loop = false; break;
}
code += " var _" + field.name + " = default(VectorOffset);\n";
code += " if (_o." + property_name + " != null) {\n";
if (gen_for_loop) {
code += " var " + array_name + " = new " + array_type +
"[_o." + property_name + ".Count];\n";
code += " for (var _j = 0; _j < " + array_name +
".Length; ++_j) { ";
code += array_name + "[_j] = " + to_array + "; }\n";
} else {
code += " var " + array_name + " = _o." + property_name +
".ToArray();\n";
}
code += " _" + field.name + " = Create" + camel_name +
"Vector(builder, " + array_name + ");\n";
code += " }\n";
} else {
auto pack_method =
field.value.type.struct_def == nullptr
? "builder.Add" + GenMethod(field.value.type.VectorType()) +
"(_o." + camel_name + "[_j]);"
: GenTypeGet(field.value.type) + ".Pack(builder, _o." +
camel_name + "[_j]);";
code += " var _" + field.name + " = default(VectorOffset);\n";
code += " if (_o." + camel_name + " != null) {\n";
code += " Start" + camel_name + "Vector(builder, _o." +
camel_name + ".Count);\n";
code += " for (var _j = _o." + camel_name +
".Count - 1; _j >= 0; --_j) { " + pack_method + " }\n";
code += " _" + field.name + " = builder.EndVector();\n";
code += " }\n";
}
break;
}
case BASE_TYPE_ARRAY: {
if (field.value.type.struct_def != nullptr) {
std::vector<std::string> name_vec;
name_vec.push_back(field.name);
std::vector<int> array_length_vec;
array_length_vec.push_back(field.value.type.fixed_length);
GenArrayPackDecl_ObjectAPI(*field.value.type.struct_def, code_ptr,
name_vec, array_length_vec);
} else {
code += " var _" + field.name + " = _o." + camel_name + ";\n";
}
break;
}
case BASE_TYPE_UNION: {
code += " var _" + field.name + "_type = _o." + camel_name +
" == null ? " + WrapInNameSpace(*field.value.type.enum_def) +
".NONE : " + "_o." + camel_name + ".Type;\n";
code +=
" var _" + field.name + " = _o." + camel_name +
" == null ? 0 : " + GenTypeGet_ObjectAPI(field.value.type, opts) +
".Pack(builder, _o." + camel_name + ");\n";
break;
}
default: break;
}
}
if (struct_has_create) {
// Create
code += " return Create" + struct_def.name + "(\n";
code += " builder";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto camel_name = MakeCamel(field.name);
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (struct_def.fixed) {
GenStructArgs_ObjectAPI(*field.value.type.struct_def, code_ptr,
" _o." + camel_name + ".");
} else {
code += ",\n";
if (field.value.type.struct_def->fixed) {
code += " " + GenTypeGet(field.value.type) +
".Pack(builder, _o." + camel_name + ")";
} else {
code += " _" + field.name;
}
}
break;
}
case BASE_TYPE_ARRAY: {
if (field.value.type.struct_def != nullptr) {
GenArrayPackCall_ObjectAPI(*field.value.type.struct_def, code_ptr,
" _" + field.name + "_");
} else {
code += ",\n";
code += " _" + field.name;
}
break;
}
case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_UTYPE: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR: {
code += ",\n";
code += " _" + field.name;
break;
}
default: // scalar
code += ",\n";
code += " _o." + camel_name;
break;
}
}
code += ");\n";
} else {
// Start, End
code += " Start" + struct_def.name + "(builder);\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto camel_name = MakeCamel(field.name);
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (field.value.type.struct_def->fixed) {
code += " Add" + camel_name + "(builder, " +
GenTypeGet(field.value.type) + ".Pack(builder, _o." +
camel_name + "));\n";
} else {
code +=
" Add" + camel_name + "(builder, _" + field.name + ");\n";
}
break;
}
case BASE_TYPE_STRING: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR: {
code +=
" Add" + camel_name + "(builder, _" + field.name + ");\n";
break;
}
case BASE_TYPE_UTYPE: break;
case BASE_TYPE_UNION: {
code += " Add" + camel_name + "Type(builder, _" + field.name +
"_type);\n";
code +=
" Add" + camel_name + "(builder, _" + field.name + ");\n";
break;
}
// scalar
default: {
code +=
" Add" + camel_name + "(builder, _o." + camel_name + ");\n";
break;
}
}
}
code += " return End" + struct_def.name + "(builder);\n";
}
code += " }\n";
}
void GenStructArgs_ObjectAPI(const StructDef &struct_def,
std::string *code_ptr,
std::string prefix) const {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
const auto &field_type = field.value.type;
if (IsStruct(field_type)) {
GenStructArgs_ObjectAPI(*field_type.struct_def, code_ptr,
prefix + "." + MakeCamel(field.name) + ".");
} else {
code += ",\n";
code += prefix + MakeCamel(field.name);
}
}
}
void GenArrayPackDecl_ObjectAPI(const StructDef &struct_def,
std::string *code_ptr,
std::vector<std::string> name_vec,
std::vector<int> array_length_vec) const {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
auto is_array = IsArray(field.value.type);
const auto &field_type =
is_array ? field.value.type.VectorType() : field.value.type;
if (!IsStruct(field_type)) {
auto tmp_name_vec = name_vec;
tmp_name_vec.push_back(field.name);
auto tmp_array_length_vec = array_length_vec;
if (is_array) {
tmp_array_length_vec.push_back(field_type.fixed_length);
}
std::string name;
for (size_t tmp_name_index = 0; tmp_name_index < tmp_name_vec.size();
++tmp_name_index) {
name += "_" + tmp_name_vec[tmp_name_index];
}
code += " var " + name + " = new " + GenTypeBasic(field_type) + "[";
code += NumToString(tmp_array_length_vec[0]);
for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) {
auto array_length = tmp_array_length_vec[i];
code += "," + NumToString(array_length);
}
code += "];\n";
code += " ";
// initialize array
for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
auto array_length = tmp_array_length_vec[i];
auto idx = "idx" + NumToString(i);
code += "for (var " + idx + " = 0; " + idx + " < " +
NumToString(array_length) + "; ++" + idx + ") {";
}
code += name + "[idx0";
for (size_t i = 1; i < tmp_array_length_vec.size(); ++i) {
auto idx = "idx" + NumToString(i);
code += "," + idx;
}
code += "] = _o";
for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
auto idx = "idx" + NumToString(i);
code += "." + MakeCamel(tmp_name_vec[i]) + "[" + idx + "]";
}
if (!is_array) { code += "." + MakeCamel(field.name); }
code += ";";
for (size_t i = 0; i < tmp_array_length_vec.size(); ++i) {
code += "}";
}
code += "\n";
}
}
}
void GenArrayPackCall_ObjectAPI(const StructDef &struct_def,
std::string *code_ptr,
std::string prefix) const {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
const auto &field_type = field.value.type;
if (IsStruct(field_type)) {
GenArrayPackCall_ObjectAPI(*field_type.struct_def, code_ptr,
prefix + field.name + "_");
} else {
code += ",\n";
code += prefix + field.name;
}
}
}
std::string GenTypeGet_ObjectAPI(flatbuffers::Type type,
const IDLOptions &opts) const {
auto type_name = GenTypeGet(type);
// Replace to ObjectBaseAPI Type Name
switch (type.base_type) {
case BASE_TYPE_STRUCT: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
case BASE_TYPE_VECTOR: {
if (type.struct_def != nullptr) {
auto type_name_length = type.struct_def->name.length();
auto new_type_name =
GenTypeName_ObjectAPI(type.struct_def->name, opts);
type_name.replace(type_name.length() - type_name_length,
type_name_length, new_type_name);
} else if (type.element == BASE_TYPE_UNION) {
type_name = WrapInNameSpace(*type.enum_def) + "Union";
}
break;
}
case BASE_TYPE_UNION: {
type_name = WrapInNameSpace(*type.enum_def) + "Union";
break;
}
default: break;
}
switch (type.base_type) {
case BASE_TYPE_ARRAY: {
type_name = type_name + "[]";
break;
}
case BASE_TYPE_VECTOR: {
type_name = "List<" + type_name + ">";
break;
}
default: break;
}
return type_name;
}
void GenStruct_ObjectAPI(StructDef &struct_def, std::string *code_ptr,
const IDLOptions &opts) const {
auto &code = *code_ptr;
if (struct_def.attributes.Lookup("private")) {
code += "internal ";
} else {
code += "public ";
}
if (struct_def.attributes.Lookup("csharp_partial")) {
// generate a partial class for this C# struct/table
code += "partial ";
}
auto class_name = GenTypeName_ObjectAPI(struct_def.name, opts);
code += "class " + class_name;
code += "\n{\n";
// Generate Properties
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
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";
}
// Generate Constructor
code += "\n";
code += " public " + class_name + "() {\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
if (field.value.type.element == BASE_TYPE_UTYPE) continue;
code += " this." + MakeCamel(field.name) + " = ";
auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
if (IsScalar(field.value.type.base_type)) {
code += GenDefaultValue(field) + ";\n";
} else {
switch (field.value.type.base_type) {
case BASE_TYPE_STRUCT: {
if (IsStruct(field.value.type)) {
code += "new " + type_name + "();\n";
} else {
code += "null;\n";
}
break;
}
case BASE_TYPE_ARRAY: {
code += "new " + type_name.substr(0, type_name.length() - 1) +
NumToString(field.value.type.fixed_length) + "];\n";
break;
}
default: {
code += "null;\n";
break;
}
}
}
}
code += " }\n";
code += "}\n\n";
}
// This tracks the current namespace used to determine if a type need to be
// prefixed by its namespace
const Namespace *cur_name_space_;

View File

@ -449,13 +449,22 @@ class DartGenerator : public BaseGenerator {
code += " final " + _kFb + ".BufferContext _bc;\n";
code += " final int _bcOffset;\n\n";
GenImplementationGetters(struct_def, &code);
std::vector<std::pair<int, FieldDef*>> non_deprecated_fields;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto offset = static_cast<int>(it - struct_def.fields.vec.begin());
non_deprecated_fields.push_back(std::make_pair(offset, &field));
}
GenImplementationGetters(struct_def, non_deprecated_fields, &code);
code += "}\n\n";
GenReader(struct_def, &reader_name, &reader_code);
GenBuilder(struct_def, &builder_name, &builder_code);
GenObjectBuilder(struct_def, &object_builder_name, &builder_code);
GenBuilder(struct_def, non_deprecated_fields, &builder_name, &builder_code);
GenObjectBuilder(struct_def, non_deprecated_fields, &object_builder_name, &builder_code);
code += reader_code;
code += builder_code;
@ -492,13 +501,14 @@ class DartGenerator : public BaseGenerator {
}
void GenImplementationGetters(const StructDef &struct_def,
std::vector<std::pair<int, FieldDef*>> non_deprecated_fields,
std::string *code_ptr) {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
std::string field_name = MakeCamel(field.name, false);
std::string type_name = GenDartTypeName(
@ -544,6 +554,12 @@ class DartGenerator : public BaseGenerator {
if (!field.value.constant.empty() && field.value.constant != "0") {
if (IsBool(field.value.type.base_type)) {
code += "true";
} else if (field.value.constant == "nan" || field.value.constant == "+nan" || field.value.constant == "-nan") {
code += "double.nan";
} else if (field.value.constant == "inf" || field.value.constant == "+inf") {
code += "double.infinity";
} else if (field.value.constant == "-inf") {
code += "double.negativeInfinity";
} else {
code += field.value.constant;
}
@ -571,13 +587,13 @@ class DartGenerator : public BaseGenerator {
code += " @override\n";
code += " String toString() {\n";
code += " return '" + struct_def.name + "{";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
code +=
MakeCamel(field.name, false) + ": $" + MakeCamel(field.name, false);
if (it != struct_def.fields.vec.end() - 1) { code += ", "; }
if (it != non_deprecated_fields.end() - 1) { code += ", "; }
}
code += "}';\n";
code += " }\n";
@ -609,9 +625,11 @@ class DartGenerator : public BaseGenerator {
code += "}\n\n";
}
void GenBuilder(const StructDef &struct_def, std::string *builder_name_ptr,
void GenBuilder(const StructDef &struct_def,
std::vector<std::pair<int, FieldDef*>> non_deprecated_fields,
std::string *builder_name_ptr,
std::string *code_ptr) {
if (struct_def.fields.vec.size() == 0) { return; }
if (non_deprecated_fields.size() == 0) { return; }
auto &code = *code_ptr;
auto &builder_name = *builder_name_ptr;
@ -622,22 +640,24 @@ class DartGenerator : public BaseGenerator {
code += " final " + _kFb + ".Builder fbBuilder;\n\n";
if (struct_def.fixed) {
StructBuilderBody(struct_def, code_ptr);
StructBuilderBody(struct_def, non_deprecated_fields, code_ptr);
} else {
TableBuilderBody(struct_def, code_ptr);
TableBuilderBody(struct_def, non_deprecated_fields, code_ptr);
}
code += "}\n\n";
}
void StructBuilderBody(const StructDef &struct_def, std::string *code_ptr) {
void StructBuilderBody(const StructDef &struct_def,
std::vector<std::pair<int, FieldDef*>> non_deprecated_fields,
std::string *code_ptr) {
auto &code = *code_ptr;
code += " int finish(";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
if (IsStruct(field.value.type)) {
code += "fb.StructBuilder";
@ -646,15 +666,14 @@ class DartGenerator : public BaseGenerator {
field);
}
code += " " + field.name;
if (it != struct_def.fields.vec.end() - 1) { code += ", "; }
if (it != non_deprecated_fields.end() - 1) { code += ", "; }
}
code += ") {\n";
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.rbegin();
it != non_deprecated_fields.rend(); ++it) {
auto pair = *it;
auto &field = *pair.second;
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
@ -673,19 +692,20 @@ class DartGenerator : public BaseGenerator {
code += " }\n\n";
}
void TableBuilderBody(const StructDef &struct_def, std::string *code_ptr) {
void TableBuilderBody(const StructDef &struct_def,
std::vector<std::pair<int, FieldDef*>> non_deprecated_fields,
std::string *code_ptr) {
auto &code = *code_ptr;
code += " void begin() {\n";
code += " fbBuilder.startTable();\n";
code += " }\n\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto offset = it - struct_def.fields.vec.begin();
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
auto offset = pair.first;
if (IsScalar(field.value.type.base_type)) {
code += " int add" + MakeCamel(field.name) + "(";
@ -717,15 +737,18 @@ class DartGenerator : public BaseGenerator {
}
void GenObjectBuilder(const StructDef &struct_def,
std::string *builder_name_ptr, std::string *code_ptr) {
std::vector<std::pair<int, FieldDef*>> non_deprecated_fields,
std::string *builder_name_ptr,
std::string *code_ptr) {
auto &code = *code_ptr;
auto &builder_name = *builder_name_ptr;
code += "class " + builder_name + " extends " + _kFb + ".ObjectBuilder {\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
code += " final " +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
field, true) +
@ -733,14 +756,14 @@ class DartGenerator : public BaseGenerator {
}
code += "\n";
code += " " + builder_name + "(";
if (struct_def.fields.vec.size() != 0) {
code +=
"{\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
if (non_deprecated_fields.size() != 0) {
code += "{\n";
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
code += " " +
GenDartTypeName(field.value.type, struct_def.defined_namespace,
field, true) +
@ -748,13 +771,14 @@ class DartGenerator : public BaseGenerator {
}
code += " })\n";
code += " : ";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
code += "_" + MakeCamel(field.name, false) + " = " +
MakeCamel(field.name, false);
if (it == struct_def.fields.vec.end() - 1) {
if (it == non_deprecated_fields.end() - 1) {
code += ";\n\n";
} else {
code += ",\n ";
@ -770,10 +794,11 @@ class DartGenerator : public BaseGenerator {
code += " " + _kFb + ".Builder fbBuilder) {\n";
code += " assert(fbBuilder != null);\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type))
continue;
@ -813,9 +838,9 @@ class DartGenerator : public BaseGenerator {
code += "\n";
if (struct_def.fixed) {
StructObjectBuilderBody(struct_def, code_ptr);
StructObjectBuilderBody(non_deprecated_fields, code_ptr);
} else {
TableObjectBuilderBody(struct_def, code_ptr);
TableObjectBuilderBody(non_deprecated_fields, code_ptr);
}
code += " }\n\n";
@ -830,16 +855,15 @@ class DartGenerator : public BaseGenerator {
code += "}\n";
}
void StructObjectBuilderBody(const StructDef &struct_def,
void StructObjectBuilderBody(std::vector<std::pair<int, FieldDef*>> non_deprecated_fields,
std::string *code_ptr,
bool prependUnderscore = true) {
auto &code = *code_ptr;
for (auto it = struct_def.fields.vec.rbegin();
it != struct_def.fields.vec.rend(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
for (auto it = non_deprecated_fields.rbegin();
it != non_deprecated_fields.rend(); ++it) {
auto pair = *it;
auto &field = *pair.second;
if (field.padding) {
code += " fbBuilder.pad(" + NumToString(field.padding) + ");\n";
@ -861,19 +885,18 @@ class DartGenerator : public BaseGenerator {
code += " return fbBuilder.offset;\n";
}
void TableObjectBuilderBody(const StructDef &struct_def,
void TableObjectBuilderBody(std::vector<std::pair<int, FieldDef*>> non_deprecated_fields,
std::string *code_ptr,
bool prependUnderscore = true) {
std::string &code = *code_ptr;
code += " fbBuilder.startTable();\n";
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
for (auto it = non_deprecated_fields.begin();
it != non_deprecated_fields.end(); ++it) {
auto pair = *it;
auto &field = *pair.second;
auto offset = pair.first;
if (field.deprecated) continue;
auto offset = it - struct_def.fields.vec.begin();
if (IsScalar(field.value.type.base_type)) {
code += " fbBuilder.add" + GenType(field.value.type) + "(" +
NumToString(offset) + ", ";

View File

@ -37,8 +37,85 @@ class SwiftGenerator : public BaseGenerator {
cur_name_space_(nullptr) {
namespace_depth = 0;
static const char *const keywords[] = {
"enum", "private", "public", "internal", "fileprivate", "static", "var",
"URL", "struct", "let", "class", "Any", "nil", nullptr,
"associatedtype",
"class",
"deinit",
"enum",
"extension",
"fileprivate",
"func",
"import",
"init",
"inout",
"internal",
"let",
"open",
"operator",
"private",
"protocol",
"public",
"rethrows",
"static",
"struct",
"subscript",
"typealias",
"var",
"break",
"case",
"continue",
"default",
"defer",
"do",
"else",
"fallthrough",
"for",
"guard",
"if",
"in",
"repeat",
"return",
"switch",
"where",
"while",
"Any",
"catch",
"false",
"is",
"nil",
"super",
"self",
"Self",
"throw",
"throws",
"true",
"try",
"associativity",
"convenience",
"dynamic",
"didSet",
"final",
"get",
"infix",
"indirect",
"lazy",
"left",
"mutating",
"none",
"nonmutating",
"optional",
"override",
"postfix",
"precedence",
"prefix",
"Protocol",
"required",
"right",
"set",
"Type",
"unowned",
"weak",
"willSet",
nullptr,
};
for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
}
@ -160,12 +237,14 @@ class SwiftGenerator : public BaseGenerator {
}
void GenObjectHeader(const StructDef &struct_def) {
GenComment(struct_def.doc_comment);
code_.SetValue("STRUCTNAME", Name(struct_def));
code_.SetValue("PROTOCOL",
struct_def.fixed ? "Readable" : "FlatBufferObject");
code_.SetValue("OBJECTTYPE", struct_def.fixed ? "Struct" : "Table");
code_ += "public struct {{STRUCTNAME}}: {{PROTOCOL}} {";
code_ += "\tprivate var {{ACCESS}}: {{OBJECTTYPE}}";
code_ += "public struct {{STRUCTNAME}}: {{PROTOCOL}} {\n";
code_ += ValidateFunc();
code_ += "\n\tprivate var {{ACCESS}}: {{OBJECTTYPE}}";
if (struct_def.fixed) {
code_.SetValue("BYTESIZE", NumToString(struct_def.bytesize));
code_.SetValue("MINALIGN", NumToString(struct_def.minalign));
@ -256,10 +335,10 @@ class SwiftGenerator : public BaseGenerator {
create_func_header.substr(0, create_func_header.size() - 2) +
"\\";
code_ += ") -> Offset<UOffset> {";
code_ += "\t\tlet start = {{STRUCTNAME}}.start{{STRUCTNAME}}(fbb)";
code_ += "\t\tlet __start = {{STRUCTNAME}}.start{{STRUCTNAME}}(fbb)";
if (should_generate_create)
code_ += create_func_body.substr(0, create_func_body.size() - 1);
code_ += "\t\treturn {{STRUCTNAME}}.end{{STRUCTNAME}}(fbb, start: start)";
code_ += "\t\treturn {{STRUCTNAME}}.end{{STRUCTNAME}}(fbb, start: __start)";
code_ += "\t}";
std::string spacing = "\t\t";
@ -356,7 +435,7 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("OFFSET", offset);
code_.SetValue("CONSTANT", field.value.constant);
std::string const_string = "return o == 0 ? {{CONSTANT}} : ";
GenComment(field.doc_comment, "\t");
if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type) &&
!IsBool(field.value.type.base_type)) {
code_ += GenReaderMainBody() + GenOffset() + const_string +
@ -533,6 +612,7 @@ class SwiftGenerator : public BaseGenerator {
code_.SetValue("VALUENAME", name);
code_.SetValue("VALUETYPE", type);
code_.SetValue("OFFSET", offset);
GenComment(field.doc_comment, "\t");
if (IsScalar(field.value.type.base_type) && !IsEnum(field.value.type)) {
code_ +=
GenReaderMainBody() + "return " + GenReader("VALUETYPE") + " }";
@ -554,9 +634,10 @@ class SwiftGenerator : public BaseGenerator {
void GenEnum(const EnumDef &enum_def) {
if (enum_def.generated) return;
code_.SetValue("ENUM_NAME", GenEnumDecl(enum_def));
code_.SetValue("ENUM_NAME", Name(enum_def));
code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
code_ += "public {{ENUM_NAME}}: {{BASE_TYPE}}, Enum { ";
GenComment(enum_def.doc_comment);
code_ += "public enum {{ENUM_NAME}}: {{BASE_TYPE}}, Enum { ";
code_ += "\tpublic typealias T = {{BASE_TYPE}}";
code_ +=
"\tpublic static var byteSize: Int { return "
@ -564,23 +645,30 @@ class SwiftGenerator : public BaseGenerator {
"}";
code_ += "\tpublic var value: {{BASE_TYPE}} { return self.rawValue }";
std::string enum_code = "\tcase ";
int keyCount = 0;
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
const auto &ev = **it;
auto key = "KEY" + NumToString(keyCount);
auto value = "VALUE" + NumToString(keyCount);
auto name = Name(ev);
std::transform(name.begin(), name.end(), name.begin(), LowerCase);
code_.SetValue(key, name);
code_.SetValue(value, enum_def.ToString(ev));
enum_code += "{{" + key + "}} = {{" + value + "}}, ";
keyCount++;
code_.SetValue("KEY", name);
code_.SetValue("VALUE", enum_def.ToString(ev));
GenComment(ev.doc_comment, "\t");
code_ += "\tcase {{KEY}} = {{VALUE}}";
}
code_ += enum_code.substr(0, enum_code.size() - 2);
code_ += "\n";
AddMinOrMaxEnumValue(enum_def.MaxValue()->name, "max");
AddMinOrMaxEnumValue(enum_def.MinValue()->name, "min");
code_ += "}\n";
}
void AddMinOrMaxEnumValue(const std::string &str, const std::string &type) {
auto current_value = str;
std::transform(current_value.begin(), current_value.end(),
current_value.begin(), LowerCase);
code_.SetValue(type, current_value);
code_ += "\tpublic static var " + type + ": {{ENUM_NAME}} { return .{{" +
type + "}} }";
}
void GenLookup(const FieldDef &key_field) {
code_.SetValue("OFFSET", NumToString(key_field.value.offset));
auto offset_reader =
@ -628,6 +716,12 @@ class SwiftGenerator : public BaseGenerator {
code_ += "\t}";
}
void GenComment(const std::vector<std::string> &dc, const char *prefix = "") {
std::string text;
::flatbuffers::GenComment(dc, &text, nullptr, prefix);
code_ += text + "\\";
}
std::string GenOffset() { return "let o = {{ACCESS}}.offset({{OFFSET}}); "; }
std::string GenReaderMainBody(const std::string &optional = "") {
@ -678,6 +772,10 @@ class SwiftGenerator : public BaseGenerator {
return "{{VALUETYPE}}(rawValue: " + GenReader("BASEVALUE", at) + ") ";
}
std::string ValidateFunc() {
return "\tstatic func validateVersion() { FlatBuffersVersion_1_11_1() }";
}
std::string GenType(const Type &type) const {
return IsScalar(type.base_type)
? GenTypeBasic(type)
@ -718,10 +816,6 @@ class SwiftGenerator : public BaseGenerator {
return swift_type[static_cast<int>(type.base_type)];
}
std::string GenEnumDecl(const EnumDef &enum_def) const {
return "enum " + Name(enum_def);
}
std::string EscapeKeyword(const std::string &name) const {
return keywords_.find(name) == keywords_.end() ? name : name + "_";
}

View File

@ -274,4 +274,5 @@ void SetupDefaultCRTReportMode() {
// clang-format on
}
} // namespace flatbuffers

View File

@ -545,6 +545,7 @@ struct IDLOptions {
bool keep_include_path;
bool binary_schema_comments;
bool binary_schema_builtins;
bool binary_schema_gen_embed;
bool skip_flatbuffers_import;
std::string go_import;
std::string go_namespace;
@ -632,6 +633,7 @@ struct IDLOptions {
keep_include_path(false),
binary_schema_comments(false),
binary_schema_builtins(false),
binary_schema_gen_embed(false),
skip_flatbuffers_import(false),
reexport_ts_modules(true),
js_ts_short_names(false),

View File

@ -636,6 +636,32 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
return true;
}
inline std::string BufferToHexText(const void *buffer, size_t buffer_size, size_t max_length,
const std::string &wrapped_line_prefix,
const std::string &wrapped_line_suffix) {
std::string text = wrapped_line_prefix;
size_t start_offset = 0;
const char *s = reinterpret_cast<const char *>(buffer);
for (size_t i = 0; s && i < buffer_size; i++) {
// Last iteration or do we have more?
bool have_more= i + 1 < buffer_size;
text += "0x";
text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
if (have_more) {
text += ',';
}
// If we have more to process and we reached max_length
if (have_more && text.size() + wrapped_line_suffix.size() >= start_offset + max_length) {
text += wrapped_line_suffix;
text += '\n';
start_offset = text.size();
text += wrapped_line_prefix;
}
}
text += wrapped_line_suffix;
return text;
}
// Remove paired quotes in a string: "text"|'text' -> text.
std::string RemoveStringQuotes(const std::string &s);