From 32254b7acdad8a0bd07f4f8348953b855e9b65c6 Mon Sep 17 00:00:00 2001 From: iceboy Date: Thu, 31 Oct 2019 11:13:45 -0700 Subject: [PATCH 01/28] [Go] Object API support (#5339) * start * works for current usages! * unpack: vector of struct * optimize byte slice * support nested struct * support null table * support struct * support union * update generated code * grumble * fix compiler warning * update generated code * wrap type in namespace * bug * wrap in namespace * enum byte arrays * generate struct for unions * basic testing * remove branching * fix assert * pack vector of fixed structs correctly * omit null vectors * Refactor Union Pack and UnPack methods Remove append usage to increase code efficiency when dealing with large vectors * generate goldens --- src/idl_gen_go.cpp | 373 +++++++++++++++- tests/GoTest.sh | 2 +- tests/MyGame/Example/Ability.go | 17 + tests/MyGame/Example/Any.go | 43 +- tests/MyGame/Example/AnyAmbiguousAliases.go | 41 +- tests/MyGame/Example/AnyUniqueAliases.go | 43 +- tests/MyGame/Example/Monster.go | 418 ++++++++++++++++++ tests/MyGame/Example/Referrable.go | 18 + tests/MyGame/Example/Stat.go | 25 ++ tests/MyGame/Example/Test.go | 17 + .../MyGame/Example/TestSimpleTableWithEnum.go | 18 + tests/MyGame/Example/TypeAliases.go | 77 ++++ tests/MyGame/Example/Vec3.go | 25 ++ tests/MyGame/Example2/Monster.go | 15 + tests/MyGame/InParentNamespace.go | 15 + tests/go_test.go | 22 + 16 files changed, 1160 insertions(+), 9 deletions(-) diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 5e62b6170..b092e5eab 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -75,15 +75,23 @@ class GoGenerator : public BaseGenerator { bool generate() { std::string one_file_code; + bool needs_imports = false; for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); ++it) { tracked_imported_namespaces_.clear(); + needs_imports = false; std::string enumcode; + if ((*it)->is_union && parser_.opts.generate_object_based_api) { + GenNativeUnion(**it, &enumcode); + GenNativeUnionPack(**it, &enumcode); + GenNativeUnionUnPack(**it, &enumcode); + needs_imports = true; + } GenEnum(**it, &enumcode); if (parser_.opts.one_file) { one_file_code += enumcode; } else { - if (!SaveType(**it, enumcode, false, true)) return false; + if (!SaveType(**it, enumcode, needs_imports, true)) return false; } } @@ -644,7 +652,7 @@ class GoGenerator : public BaseGenerator { } } - // Mutate the value of a struct's scalar. + // Mutate the value of a struct's scalar. void MutateScalarFieldOfStruct(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { @@ -739,6 +747,9 @@ class GoGenerator : public BaseGenerator { cur_name_space_ = struct_def.defined_namespace; GenComment(struct_def.doc_comment, code_ptr, nullptr); + if (parser_.opts.generate_object_based_api) { + GenNativeStruct(struct_def, code_ptr); + } BeginClass(struct_def, code_ptr); if (!struct_def.fixed) { // Generate a special accessor for the table that has been declared as @@ -771,6 +782,326 @@ class GoGenerator : public BaseGenerator { } } + void GenNativeStruct(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "type " + NativeName(struct_def) + " struct {\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + const FieldDef &field = **it; + if (field.deprecated) continue; + if (IsScalar(field.value.type.base_type) && + field.value.type.enum_def != nullptr && + field.value.type.enum_def->is_union) + continue; + code += "\t" + MakeCamel(field.name) + " " + + NativeType(field.value.type) + "\n"; + } + code += "}\n\n"; + + if (!struct_def.fixed) { + GenNativeTablePack(struct_def, code_ptr); + GenNativeTableUnPack(struct_def, code_ptr); + } else { + GenNativeStructPack(struct_def, code_ptr); + GenNativeStructUnPack(struct_def, code_ptr); + } + } + + void GenNativeUnion(const EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "type " + NativeName(enum_def) + " struct {\n"; + code += "\tType " + enum_def.name + "\n"; + code += "\tValue interface{}\n"; + code += "}\n\n"; + } + + void GenNativeUnionPack(const EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "func " + enum_def.name + "Pack(builder *flatbuffers.Builder, t *" + + NativeName(enum_def) + ") flatbuffers.UOffsetT {\n"; + code += "\tif t == nil {\n\t\treturn 0\n\t}\n"; + + code += "\tswitch t.Type {\n"; + for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end(); + ++it2) { + const EnumVal &ev = **it2; + if (ev.IsZero()) continue; + code += "\tcase " + enum_def.name + ev.name + ":\n"; + code += "\t\treturn " + + WrapInNameSpaceAndTrack(*ev.union_type.struct_def) + + "Pack(builder, t.Value.(" + NativeType(ev.union_type) + "))\n"; + } + code += "\t}\n"; + code += "\treturn 0\n"; + code += "}\n\n"; + } + + void GenNativeUnionUnPack(const EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "func " + enum_def.name + "UnPack(t " + enum_def.name + + ", table flatbuffers.Table) *" + NativeName(enum_def) + " {\n"; + code += "\tswitch t {\n"; + + for (auto it2 = enum_def.Vals().begin(); it2 != enum_def.Vals().end(); + ++it2) { + const EnumVal &ev = **it2; + if (ev.IsZero()) continue; + code += "\tcase " + enum_def.name + ev.name + ":\n"; + code += "\t\tx := " + ev.union_type.struct_def->name + "{_tab: table}\n"; + + code += "\t\treturn &" + + WrapInNameSpaceAndTrack(enum_def.defined_namespace, + NativeName(enum_def)) + + "{ Type: " + enum_def.name + ev.name + ", Value: x.UnPack() }\n"; + } + code += "\t}\n"; + code += "\treturn nil\n"; + code += "}\n\n"; + } + + void GenNativeTablePack(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "func " + struct_def.name + + "Pack(builder *flatbuffers.Builder, t *" + NativeName(struct_def) + + ") flatbuffers.UOffsetT {\n"; + code += "\tif t == nil { return 0 }\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + const FieldDef &field = **it; + if (field.deprecated) continue; + if (IsScalar(field.value.type.base_type)) continue; + + std::string offset = MakeCamel(field.name, false) + "Offset"; + + if (field.value.type.base_type == BASE_TYPE_STRING) { + code += "\t" + offset + " := builder.CreateString(t." + + MakeCamel(field.name) + ")\n"; + } else if (field.value.type.base_type == BASE_TYPE_VECTOR && + field.value.type.element == BASE_TYPE_UCHAR && + field.value.type.enum_def == nullptr) { + code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n"; + code += "\tif t." + MakeCamel(field.name) + " != nil {\n"; + code += "\t\t" + offset + " = builder.CreateByteString(t." + + MakeCamel(field.name) + ")\n"; + code += "\t}\n"; + } else if (field.value.type.base_type == BASE_TYPE_VECTOR) { + code += "\t" + offset + " := flatbuffers.UOffsetT(0)\n"; + code += "\tif t." + MakeCamel(field.name) + " != nil {\n"; + std::string length = MakeCamel(field.name, false) + "Length"; + std::string offsets = MakeCamel(field.name, false) + "Offsets"; + code += "\t\t" + length + " := len(t." + MakeCamel(field.name) + ")\n"; + if (field.value.type.element == BASE_TYPE_STRING) { + code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " + + length + ")\n"; + code += "\t\tfor j := 0; j < " + length + "; j++ {\n"; + code += "\t\t\t" + offsets + "[j] = builder.CreateString(t." + + MakeCamel(field.name) + "[j])\n"; + code += "\t\t}\n"; + } else if (field.value.type.element == BASE_TYPE_STRUCT && + !field.value.type.struct_def->fixed) { + code += "\t\t" + offsets + " := make([]flatbuffers.UOffsetT, " + + length + ")\n"; + code += "\t\tfor j := 0; j < " + length + "; j++ {\n"; + code += "\t\t\t" + offsets + "[j] = " + + WrapInNameSpaceAndTrack(*field.value.type.struct_def) + + "Pack(builder, t." + MakeCamel(field.name) + "[j])\n"; + code += "\t\t}\n"; + } + code += "\t\t" + struct_def.name + "Start" + MakeCamel(field.name) + + "Vector(builder, " + length + ")\n"; + code += "\t\tfor j := " + length + " - 1; j >= 0; j-- {\n"; + if (IsScalar(field.value.type.element)) { + code += "\t\t\tbuilder.Prepend" + + MakeCamel(GenTypeBasic(field.value.type.VectorType())) + "(" + + CastToBaseType( + field.value.type.VectorType(), + "t." + MakeCamel(field.name) + "[j]") + ")\n"; + } else if (field.value.type.element == BASE_TYPE_STRUCT && + field.value.type.struct_def->fixed) { + code += "\t\t\t" + + WrapInNameSpaceAndTrack(*field.value.type.struct_def) + + "Pack(builder, t." + MakeCamel(field.name) + "[j])\n"; + } else { + code += "\t\t\tbuilder.PrependUOffsetT(" + offsets + "[j])\n"; + } + code += "\t\t}\n"; + code += "\t\t" + offset + " = builder.EndVector(" + length + ")\n"; + code += "\t}\n"; + } else if (field.value.type.base_type == BASE_TYPE_STRUCT) { + if (field.value.type.struct_def->fixed) continue; + code += "\t" + offset + + " := " + WrapInNameSpaceAndTrack(*field.value.type.struct_def) + + "Pack(builder, t." + MakeCamel(field.name) + ")\n"; + } else if (field.value.type.base_type == BASE_TYPE_UNION) { + code += "\t" + offset + + " := " + WrapInNameSpaceAndTrack(*field.value.type.enum_def) + + "Pack(builder, t." + MakeCamel(field.name) + ")\n"; + code += "\t\n"; + } else { + FLATBUFFERS_ASSERT(0); + } + } + code += "\t" + struct_def.name + "Start(builder)\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + const FieldDef &field = **it; + if (field.deprecated) continue; + + std::string offset = MakeCamel(field.name, false) + "Offset"; + if (IsScalar(field.value.type.base_type)) { + if (field.value.type.enum_def == nullptr || + !field.value.type.enum_def->is_union) { + code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) + + "(builder, t." + MakeCamel(field.name) + ")\n"; + } + } else { + if (field.value.type.base_type == BASE_TYPE_STRUCT && + field.value.type.struct_def->fixed) { + code += "\t" + offset + " := " + + WrapInNameSpaceAndTrack(*field.value.type.struct_def) + + "Pack(builder, t." + MakeCamel(field.name) + ")\n"; + } else if (field.value.type.enum_def != nullptr && + field.value.type.enum_def->is_union) { + code += "\tif t." + MakeCamel(field.name) + " != nil {\n"; + code += "\t\t" + struct_def.name + "Add" + + MakeCamel(field.name + UnionTypeFieldSuffix()) + + "(builder, t." + MakeCamel(field.name) + ".Type)\n"; + code += "\t}\n"; + } + code += "\t" + struct_def.name + "Add" + MakeCamel(field.name) + + "(builder, " + offset + ")\n"; + } + } + code += "\treturn " + struct_def.name + "End(builder)\n"; + code += "}\n\n"; + } + + void GenNativeTableUnPack( + const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "func (rcv *" + struct_def.name + ") UnPack() *" + + NativeName(struct_def) + " {\n"; + code += "\tif rcv == nil { return nil }\n"; + code += "\tt := &" + NativeName(struct_def) + "{}\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + const FieldDef &field = **it; + if (field.deprecated) continue; + std::string field_name_camel = MakeCamel(field.name); + std::string length = MakeCamel(field.name, false) + "Length"; + if (IsScalar(field.value.type.base_type)) { + if (field.value.type.enum_def != nullptr && + field.value.type.enum_def->is_union) + continue; + code += "\tt." + field_name_camel + " = rcv." + field_name_camel + + "()\n"; + } else if (field.value.type.base_type == BASE_TYPE_STRING) { + code += "\tt." + field_name_camel + " = string(rcv." + + field_name_camel + "())\n"; + } else if (field.value.type.base_type == BASE_TYPE_VECTOR && + field.value.type.element == BASE_TYPE_UCHAR && + field.value.type.enum_def == nullptr) { + code += "\tt." + field_name_camel + " = rcv." + field_name_camel + + "Bytes()\n"; + } else if (field.value.type.base_type == BASE_TYPE_VECTOR) { + code += "\t" + length + " := rcv." + field_name_camel + "Length()\n"; + code += "\tt." + field_name_camel + " = make(" + + NativeType(field.value.type) + ", " + length + ")\n"; + code += "\tfor j := 0; j < " + length + "; j++ {\n"; + if (field.value.type.element == BASE_TYPE_STRUCT) { + code += "\t\tx := " + field.value.type.struct_def->name + "{}\n"; + code += "\t\trcv." + field_name_camel + "(&x, j)\n"; + } + code += "\t\tt." + field_name_camel + "[j] = "; + if (IsScalar(field.value.type.element)) { + code += "rcv." + field_name_camel + "(j)"; + } else if (field.value.type.element == BASE_TYPE_STRING) { + code += "string(rcv." + field_name_camel + "(j))"; + } else if (field.value.type.element == BASE_TYPE_STRUCT) { + code += "x.UnPack()"; + } else { + // TODO(iceboy): Support vector of unions. + FLATBUFFERS_ASSERT(0); + } + code += "\n"; + code += "\t}\n"; + } else if (field.value.type.base_type == BASE_TYPE_STRUCT) { + code += "\tt." + field_name_camel + " = rcv." + field_name_camel + + "(nil).UnPack()\n"; + } else if (field.value.type.base_type == BASE_TYPE_UNION) { + const EnumDef &enum_def = *field.value.type.enum_def; + std::string field_table = MakeCamel(field.name, false) + "Table"; + code += "\t" + field_table + " := flatbuffers.Table{}\n"; + code += + "\tif rcv." + MakeCamel(field.name) + "(&" + field_table + ") {\n"; + code += "\t\tt." + field_name_camel + " = " + enum_def.name + + "UnPack(rcv." + MakeCamel(field.name + UnionTypeFieldSuffix()) + + "(), " + field_table + ")\n"; + code += "\t}\n"; + } else { + FLATBUFFERS_ASSERT(0); + } + } + code += "\treturn t\n"; + code += "}\n\n"; + } + + void GenNativeStructPack(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "func " + struct_def.name + + "Pack(builder *flatbuffers.Builder, t *" + NativeName(struct_def) + + ") flatbuffers.UOffsetT {\n"; + code += "\tif t == nil { return 0 }\n"; + code += "\treturn Create" + struct_def.name + "(builder"; + StructPackArgs(struct_def, "", code_ptr); + code += ")\n"; + code += "}\n"; + } + + void StructPackArgs(const StructDef &struct_def, const char *nameprefix, + std::string *code_ptr) { + std::string &code = *code_ptr; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + const FieldDef &field = **it; + if (field.value.type.base_type == BASE_TYPE_STRUCT) { + StructPackArgs(*field.value.type.struct_def, + (nameprefix + MakeCamel(field.name) + ".").c_str(), + code_ptr); + } else { + code += std::string(", t.") + nameprefix + MakeCamel(field.name); + } + } + } + + void GenNativeStructUnPack( + const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "func (rcv *" + struct_def.name + ") UnPack() *" + + NativeName(struct_def) + " {\n"; + code += "\tif rcv == nil { return nil }\n"; + code += "\tt := &" + NativeName(struct_def) + "{}\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + const FieldDef &field = **it; + if (field.value.type.base_type == BASE_TYPE_STRUCT) { + code += "\tt." + MakeCamel(field.name) + " = rcv." + + MakeCamel(field.name) + "(nil).UnPack()\n"; + } else { + code += "\tt." + MakeCamel(field.name) + " = rcv." + + MakeCamel(field.name) + "()\n"; + } + } + code += "\treturn t\n"; + code += "}\n\n"; + } + // Generate enum declarations. void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { if (enum_def.generated) return; @@ -782,7 +1113,7 @@ class GoGenerator : public BaseGenerator { GenEnumType(enum_def, code_ptr); BeginEnum(code_ptr); for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { - auto &ev = **it; + const EnumVal &ev = **it; GenComment(ev.doc_comment, code_ptr, nullptr, "\t"); EnumMember(enum_def, ev, max_name_length, code_ptr); } @@ -790,7 +1121,7 @@ class GoGenerator : public BaseGenerator { BeginEnumNames(enum_def, code_ptr); for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { - auto &ev = **it; + const EnumVal &ev = **it; EnumNameMember(enum_def, ev, max_name_length, code_ptr); } EndEnumNames(code_ptr); @@ -880,11 +1211,43 @@ class GoGenerator : public BaseGenerator { std::string GenConstant(const FieldDef &field) { switch (field.value.type.base_type) { - case BASE_TYPE_BOOL: return field.value.constant == "0" ? "false" : "true";; + case BASE_TYPE_BOOL: return field.value.constant == "0" ? "false" : "true"; default: return field.value.constant; } } + std::string NativeName(const StructDef &struct_def) { + return parser_.opts.object_prefix + struct_def.name + + parser_.opts.object_suffix; + } + + std::string NativeName(const EnumDef &enum_def) { + return parser_.opts.object_prefix + enum_def.name + + parser_.opts.object_suffix; + } + + std::string NativeType(const Type &type) { + if (IsScalar(type.base_type)) { + if (type.enum_def == nullptr) { + return GenTypeBasic(type); + } else { + return GetEnumTypeName(*type.enum_def); + } + } else if (type.base_type == BASE_TYPE_STRING) { + return "string"; + } else if (type.base_type == BASE_TYPE_VECTOR) { + return "[]" + NativeType(type.VectorType()); + } else if (type.base_type == BASE_TYPE_STRUCT) { + return "*" + WrapInNameSpaceAndTrack( + type.struct_def->defined_namespace, NativeName(*type.struct_def)); + } else if (type.base_type == BASE_TYPE_UNION) { + return "*" + WrapInNameSpaceAndTrack( + type.enum_def->defined_namespace, NativeName(*type.enum_def)); + } + FLATBUFFERS_ASSERT(0); + return std::string(); + } + // Create a struct with a builder and the struct's arguments. void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) { BeginBuilderArgs(struct_def, code_ptr); diff --git a/tests/GoTest.sh b/tests/GoTest.sh index e69f0d8cb..60ef92778 100755 --- a/tests/GoTest.sh +++ b/tests/GoTest.sh @@ -20,7 +20,7 @@ go_path=${test_dir}/go_gen go_src=${go_path}/src # Emit Go code for the example schema in the test dir: -../flatc -g -I include_test monster_test.fbs +../flatc -g --gen-object-api -I include_test monster_test.fbs # Go requires a particular layout of files in order to link multiple packages. # Copy flatbuffer Go files to their own package directories to compile the diff --git a/tests/MyGame/Example/Ability.go b/tests/MyGame/Example/Ability.go index a56b44521..12ff1e58d 100644 --- a/tests/MyGame/Example/Ability.go +++ b/tests/MyGame/Example/Ability.go @@ -6,6 +6,23 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type AbilityT struct { + Id uint32 + Distance uint32 +} + +func AbilityPack(builder *flatbuffers.Builder, t *AbilityT) flatbuffers.UOffsetT { + if t == nil { return 0 } + return CreateAbility(builder, t.Id, t.Distance) +} +func (rcv *Ability) UnPack() *AbilityT { + if rcv == nil { return nil } + t := &AbilityT{} + t.Id = rcv.Id() + t.Distance = rcv.Distance() + return t +} + type Ability struct { _tab flatbuffers.Struct } diff --git a/tests/MyGame/Example/Any.go b/tests/MyGame/Example/Any.go index 8d9067e1d..7b9ffb918 100644 --- a/tests/MyGame/Example/Any.go +++ b/tests/MyGame/Example/Any.go @@ -2,7 +2,48 @@ package Example -import "strconv" +import ( + "strconv" + + flatbuffers "github.com/google/flatbuffers/go" + + MyGame__Example2 "MyGame/Example2" +) + +type AnyT struct { + Type Any + Value interface{} +} + +func AnyPack(builder *flatbuffers.Builder, t *AnyT) flatbuffers.UOffsetT { + if t == nil { + return 0 + } + switch t.Type { + case AnyMonster: + return MonsterPack(builder, t.Value.(*MonsterT)) + case AnyTestSimpleTableWithEnum: + return TestSimpleTableWithEnumPack(builder, t.Value.(*TestSimpleTableWithEnumT)) + case AnyMyGame_Example2_Monster: + return MyGame__Example2.MonsterPack(builder, t.Value.(*MyGame__Example2.MonsterT)) + } + return 0 +} + +func AnyUnPack(t Any, table flatbuffers.Table) *AnyT { + switch t { + case AnyMonster: + x := Monster{_tab: table} + return &AnyT{ Type: AnyMonster, Value: x.UnPack() } + case AnyTestSimpleTableWithEnum: + x := TestSimpleTableWithEnum{_tab: table} + return &AnyT{ Type: AnyTestSimpleTableWithEnum, Value: x.UnPack() } + case AnyMyGame_Example2_Monster: + x := Monster{_tab: table} + return &AnyT{ Type: AnyMyGame_Example2_Monster, Value: x.UnPack() } + } + return nil +} type Any byte diff --git a/tests/MyGame/Example/AnyAmbiguousAliases.go b/tests/MyGame/Example/AnyAmbiguousAliases.go index b9c3793a3..cc4adb8a0 100644 --- a/tests/MyGame/Example/AnyAmbiguousAliases.go +++ b/tests/MyGame/Example/AnyAmbiguousAliases.go @@ -2,7 +2,46 @@ package Example -import "strconv" +import ( + "strconv" + + flatbuffers "github.com/google/flatbuffers/go" +) + +type AnyAmbiguousAliasesT struct { + Type AnyAmbiguousAliases + Value interface{} +} + +func AnyAmbiguousAliasesPack(builder *flatbuffers.Builder, t *AnyAmbiguousAliasesT) flatbuffers.UOffsetT { + if t == nil { + return 0 + } + switch t.Type { + case AnyAmbiguousAliasesM1: + return MonsterPack(builder, t.Value.(*MonsterT)) + case AnyAmbiguousAliasesM2: + return MonsterPack(builder, t.Value.(*MonsterT)) + case AnyAmbiguousAliasesM3: + return MonsterPack(builder, t.Value.(*MonsterT)) + } + return 0 +} + +func AnyAmbiguousAliasesUnPack(t AnyAmbiguousAliases, table flatbuffers.Table) *AnyAmbiguousAliasesT { + switch t { + case AnyAmbiguousAliasesM1: + x := Monster{_tab: table} + return &AnyAmbiguousAliasesT{ Type: AnyAmbiguousAliasesM1, Value: x.UnPack() } + case AnyAmbiguousAliasesM2: + x := Monster{_tab: table} + return &AnyAmbiguousAliasesT{ Type: AnyAmbiguousAliasesM2, Value: x.UnPack() } + case AnyAmbiguousAliasesM3: + x := Monster{_tab: table} + return &AnyAmbiguousAliasesT{ Type: AnyAmbiguousAliasesM3, Value: x.UnPack() } + } + return nil +} type AnyAmbiguousAliases byte diff --git a/tests/MyGame/Example/AnyUniqueAliases.go b/tests/MyGame/Example/AnyUniqueAliases.go index 23d86491d..56b516380 100644 --- a/tests/MyGame/Example/AnyUniqueAliases.go +++ b/tests/MyGame/Example/AnyUniqueAliases.go @@ -2,7 +2,48 @@ package Example -import "strconv" +import ( + "strconv" + + flatbuffers "github.com/google/flatbuffers/go" + + MyGame__Example2 "MyGame/Example2" +) + +type AnyUniqueAliasesT struct { + Type AnyUniqueAliases + Value interface{} +} + +func AnyUniqueAliasesPack(builder *flatbuffers.Builder, t *AnyUniqueAliasesT) flatbuffers.UOffsetT { + if t == nil { + return 0 + } + switch t.Type { + case AnyUniqueAliasesM: + return MonsterPack(builder, t.Value.(*MonsterT)) + case AnyUniqueAliasesTS: + return TestSimpleTableWithEnumPack(builder, t.Value.(*TestSimpleTableWithEnumT)) + case AnyUniqueAliasesM2: + return MyGame__Example2.MonsterPack(builder, t.Value.(*MyGame__Example2.MonsterT)) + } + return 0 +} + +func AnyUniqueAliasesUnPack(t AnyUniqueAliases, table flatbuffers.Table) *AnyUniqueAliasesT { + switch t { + case AnyUniqueAliasesM: + x := Monster{_tab: table} + return &AnyUniqueAliasesT{ Type: AnyUniqueAliasesM, Value: x.UnPack() } + case AnyUniqueAliasesTS: + x := TestSimpleTableWithEnum{_tab: table} + return &AnyUniqueAliasesT{ Type: AnyUniqueAliasesTS, Value: x.UnPack() } + case AnyUniqueAliasesM2: + x := Monster{_tab: table} + return &AnyUniqueAliasesT{ Type: AnyUniqueAliasesM2, Value: x.UnPack() } + } + return nil +} type AnyUniqueAliases byte diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go index 6199049cc..32be49f19 100644 --- a/tests/MyGame/Example/Monster.go +++ b/tests/MyGame/Example/Monster.go @@ -9,6 +9,424 @@ import ( ) /// an example documentation comment: monster object +type MonsterT struct { + Pos *Vec3T + Mana int16 + Hp int16 + Name string + Inventory []byte + Color Color + Test *AnyT + Test4 []*TestT + Testarrayofstring []string + Testarrayoftables []*MonsterT + Enemy *MonsterT + Testnestedflatbuffer []byte + Testempty *StatT + Testbool bool + Testhashs32Fnv1 int32 + Testhashu32Fnv1 uint32 + Testhashs64Fnv1 int64 + Testhashu64Fnv1 uint64 + Testhashs32Fnv1a int32 + Testhashu32Fnv1a uint32 + Testhashs64Fnv1a int64 + Testhashu64Fnv1a uint64 + Testarrayofbools []bool + Testf float32 + Testf2 float32 + Testf3 float32 + Testarrayofstring2 []string + Testarrayofsortedstruct []*AbilityT + Flex []byte + Test5 []*TestT + VectorOfLongs []int64 + VectorOfDoubles []float64 + ParentNamespaceTest *MyGame.InParentNamespaceT + VectorOfReferrables []*ReferrableT + SingleWeakReference uint64 + VectorOfWeakReferences []uint64 + VectorOfStrongReferrables []*ReferrableT + CoOwningReference uint64 + VectorOfCoOwningReferences []uint64 + NonOwningReference uint64 + VectorOfNonOwningReferences []uint64 + AnyUnique *AnyUniqueAliasesT + AnyAmbiguous *AnyAmbiguousAliasesT + VectorOfEnums []Color + SignedEnum Race +} + +func MonsterPack(builder *flatbuffers.Builder, t *MonsterT) flatbuffers.UOffsetT { + if t == nil { return 0 } + nameOffset := builder.CreateString(t.Name) + inventoryOffset := flatbuffers.UOffsetT(0) + if t.Inventory != nil { + inventoryOffset = builder.CreateByteString(t.Inventory) + } + testOffset := AnyPack(builder, t.Test) + + test4Offset := flatbuffers.UOffsetT(0) + if t.Test4 != nil { + test4Length := len(t.Test4) + MonsterStartTest4Vector(builder, test4Length) + for j := test4Length - 1; j >= 0; j-- { + TestPack(builder, t.Test4[j]) + } + test4Offset = builder.EndVector(test4Length) + } + testarrayofstringOffset := flatbuffers.UOffsetT(0) + if t.Testarrayofstring != nil { + testarrayofstringLength := len(t.Testarrayofstring) + testarrayofstringOffsets := make([]flatbuffers.UOffsetT, testarrayofstringLength) + for j := 0; j < testarrayofstringLength; j++ { + testarrayofstringOffsets[j] = builder.CreateString(t.Testarrayofstring[j]) + } + MonsterStartTestarrayofstringVector(builder, testarrayofstringLength) + for j := testarrayofstringLength - 1; j >= 0; j-- { + builder.PrependUOffsetT(testarrayofstringOffsets[j]) + } + testarrayofstringOffset = builder.EndVector(testarrayofstringLength) + } + testarrayoftablesOffset := flatbuffers.UOffsetT(0) + if t.Testarrayoftables != nil { + testarrayoftablesLength := len(t.Testarrayoftables) + testarrayoftablesOffsets := make([]flatbuffers.UOffsetT, testarrayoftablesLength) + for j := 0; j < testarrayoftablesLength; j++ { + testarrayoftablesOffsets[j] = MonsterPack(builder, t.Testarrayoftables[j]) + } + MonsterStartTestarrayoftablesVector(builder, testarrayoftablesLength) + for j := testarrayoftablesLength - 1; j >= 0; j-- { + builder.PrependUOffsetT(testarrayoftablesOffsets[j]) + } + testarrayoftablesOffset = builder.EndVector(testarrayoftablesLength) + } + enemyOffset := MonsterPack(builder, t.Enemy) + testnestedflatbufferOffset := flatbuffers.UOffsetT(0) + if t.Testnestedflatbuffer != nil { + testnestedflatbufferOffset = builder.CreateByteString(t.Testnestedflatbuffer) + } + testemptyOffset := StatPack(builder, t.Testempty) + testarrayofboolsOffset := flatbuffers.UOffsetT(0) + if t.Testarrayofbools != nil { + testarrayofboolsLength := len(t.Testarrayofbools) + MonsterStartTestarrayofboolsVector(builder, testarrayofboolsLength) + for j := testarrayofboolsLength - 1; j >= 0; j-- { + builder.PrependBool(t.Testarrayofbools[j]) + } + testarrayofboolsOffset = builder.EndVector(testarrayofboolsLength) + } + testarrayofstring2Offset := flatbuffers.UOffsetT(0) + if t.Testarrayofstring2 != nil { + testarrayofstring2Length := len(t.Testarrayofstring2) + testarrayofstring2Offsets := make([]flatbuffers.UOffsetT, testarrayofstring2Length) + for j := 0; j < testarrayofstring2Length; j++ { + testarrayofstring2Offsets[j] = builder.CreateString(t.Testarrayofstring2[j]) + } + MonsterStartTestarrayofstring2Vector(builder, testarrayofstring2Length) + for j := testarrayofstring2Length - 1; j >= 0; j-- { + builder.PrependUOffsetT(testarrayofstring2Offsets[j]) + } + testarrayofstring2Offset = builder.EndVector(testarrayofstring2Length) + } + testarrayofsortedstructOffset := flatbuffers.UOffsetT(0) + if t.Testarrayofsortedstruct != nil { + testarrayofsortedstructLength := len(t.Testarrayofsortedstruct) + MonsterStartTestarrayofsortedstructVector(builder, testarrayofsortedstructLength) + for j := testarrayofsortedstructLength - 1; j >= 0; j-- { + AbilityPack(builder, t.Testarrayofsortedstruct[j]) + } + testarrayofsortedstructOffset = builder.EndVector(testarrayofsortedstructLength) + } + flexOffset := flatbuffers.UOffsetT(0) + if t.Flex != nil { + flexOffset = builder.CreateByteString(t.Flex) + } + test5Offset := flatbuffers.UOffsetT(0) + if t.Test5 != nil { + test5Length := len(t.Test5) + MonsterStartTest5Vector(builder, test5Length) + for j := test5Length - 1; j >= 0; j-- { + TestPack(builder, t.Test5[j]) + } + test5Offset = builder.EndVector(test5Length) + } + vectorOfLongsOffset := flatbuffers.UOffsetT(0) + if t.VectorOfLongs != nil { + vectorOfLongsLength := len(t.VectorOfLongs) + MonsterStartVectorOfLongsVector(builder, vectorOfLongsLength) + for j := vectorOfLongsLength - 1; j >= 0; j-- { + builder.PrependInt64(t.VectorOfLongs[j]) + } + vectorOfLongsOffset = builder.EndVector(vectorOfLongsLength) + } + vectorOfDoublesOffset := flatbuffers.UOffsetT(0) + if t.VectorOfDoubles != nil { + vectorOfDoublesLength := len(t.VectorOfDoubles) + MonsterStartVectorOfDoublesVector(builder, vectorOfDoublesLength) + for j := vectorOfDoublesLength - 1; j >= 0; j-- { + builder.PrependFloat64(t.VectorOfDoubles[j]) + } + vectorOfDoublesOffset = builder.EndVector(vectorOfDoublesLength) + } + parentNamespaceTestOffset := MyGame.InParentNamespacePack(builder, t.ParentNamespaceTest) + vectorOfReferrablesOffset := flatbuffers.UOffsetT(0) + if t.VectorOfReferrables != nil { + vectorOfReferrablesLength := len(t.VectorOfReferrables) + vectorOfReferrablesOffsets := make([]flatbuffers.UOffsetT, vectorOfReferrablesLength) + for j := 0; j < vectorOfReferrablesLength; j++ { + vectorOfReferrablesOffsets[j] = ReferrablePack(builder, t.VectorOfReferrables[j]) + } + MonsterStartVectorOfReferrablesVector(builder, vectorOfReferrablesLength) + for j := vectorOfReferrablesLength - 1; j >= 0; j-- { + builder.PrependUOffsetT(vectorOfReferrablesOffsets[j]) + } + vectorOfReferrablesOffset = builder.EndVector(vectorOfReferrablesLength) + } + vectorOfWeakReferencesOffset := flatbuffers.UOffsetT(0) + if t.VectorOfWeakReferences != nil { + vectorOfWeakReferencesLength := len(t.VectorOfWeakReferences) + MonsterStartVectorOfWeakReferencesVector(builder, vectorOfWeakReferencesLength) + for j := vectorOfWeakReferencesLength - 1; j >= 0; j-- { + builder.PrependUint64(t.VectorOfWeakReferences[j]) + } + vectorOfWeakReferencesOffset = builder.EndVector(vectorOfWeakReferencesLength) + } + vectorOfStrongReferrablesOffset := flatbuffers.UOffsetT(0) + if t.VectorOfStrongReferrables != nil { + vectorOfStrongReferrablesLength := len(t.VectorOfStrongReferrables) + vectorOfStrongReferrablesOffsets := make([]flatbuffers.UOffsetT, vectorOfStrongReferrablesLength) + for j := 0; j < vectorOfStrongReferrablesLength; j++ { + vectorOfStrongReferrablesOffsets[j] = ReferrablePack(builder, t.VectorOfStrongReferrables[j]) + } + MonsterStartVectorOfStrongReferrablesVector(builder, vectorOfStrongReferrablesLength) + for j := vectorOfStrongReferrablesLength - 1; j >= 0; j-- { + builder.PrependUOffsetT(vectorOfStrongReferrablesOffsets[j]) + } + vectorOfStrongReferrablesOffset = builder.EndVector(vectorOfStrongReferrablesLength) + } + vectorOfCoOwningReferencesOffset := flatbuffers.UOffsetT(0) + if t.VectorOfCoOwningReferences != nil { + vectorOfCoOwningReferencesLength := len(t.VectorOfCoOwningReferences) + MonsterStartVectorOfCoOwningReferencesVector(builder, vectorOfCoOwningReferencesLength) + for j := vectorOfCoOwningReferencesLength - 1; j >= 0; j-- { + builder.PrependUint64(t.VectorOfCoOwningReferences[j]) + } + vectorOfCoOwningReferencesOffset = builder.EndVector(vectorOfCoOwningReferencesLength) + } + vectorOfNonOwningReferencesOffset := flatbuffers.UOffsetT(0) + if t.VectorOfNonOwningReferences != nil { + vectorOfNonOwningReferencesLength := len(t.VectorOfNonOwningReferences) + MonsterStartVectorOfNonOwningReferencesVector(builder, vectorOfNonOwningReferencesLength) + for j := vectorOfNonOwningReferencesLength - 1; j >= 0; j-- { + builder.PrependUint64(t.VectorOfNonOwningReferences[j]) + } + vectorOfNonOwningReferencesOffset = builder.EndVector(vectorOfNonOwningReferencesLength) + } + anyUniqueOffset := AnyUniqueAliasesPack(builder, t.AnyUnique) + + anyAmbiguousOffset := AnyAmbiguousAliasesPack(builder, t.AnyAmbiguous) + + vectorOfEnumsOffset := flatbuffers.UOffsetT(0) + if t.VectorOfEnums != nil { + vectorOfEnumsLength := len(t.VectorOfEnums) + MonsterStartVectorOfEnumsVector(builder, vectorOfEnumsLength) + for j := vectorOfEnumsLength - 1; j >= 0; j-- { + builder.PrependByte(byte(t.VectorOfEnums[j])) + } + vectorOfEnumsOffset = builder.EndVector(vectorOfEnumsLength) + } + MonsterStart(builder) + posOffset := Vec3Pack(builder, t.Pos) + MonsterAddPos(builder, posOffset) + MonsterAddMana(builder, t.Mana) + MonsterAddHp(builder, t.Hp) + MonsterAddName(builder, nameOffset) + MonsterAddInventory(builder, inventoryOffset) + MonsterAddColor(builder, t.Color) + if t.Test != nil { + MonsterAddTestType(builder, t.Test.Type) + } + MonsterAddTest(builder, testOffset) + MonsterAddTest4(builder, test4Offset) + MonsterAddTestarrayofstring(builder, testarrayofstringOffset) + MonsterAddTestarrayoftables(builder, testarrayoftablesOffset) + MonsterAddEnemy(builder, enemyOffset) + MonsterAddTestnestedflatbuffer(builder, testnestedflatbufferOffset) + MonsterAddTestempty(builder, testemptyOffset) + MonsterAddTestbool(builder, t.Testbool) + MonsterAddTesthashs32Fnv1(builder, t.Testhashs32Fnv1) + MonsterAddTesthashu32Fnv1(builder, t.Testhashu32Fnv1) + MonsterAddTesthashs64Fnv1(builder, t.Testhashs64Fnv1) + MonsterAddTesthashu64Fnv1(builder, t.Testhashu64Fnv1) + MonsterAddTesthashs32Fnv1a(builder, t.Testhashs32Fnv1a) + MonsterAddTesthashu32Fnv1a(builder, t.Testhashu32Fnv1a) + MonsterAddTesthashs64Fnv1a(builder, t.Testhashs64Fnv1a) + MonsterAddTesthashu64Fnv1a(builder, t.Testhashu64Fnv1a) + MonsterAddTestarrayofbools(builder, testarrayofboolsOffset) + MonsterAddTestf(builder, t.Testf) + MonsterAddTestf2(builder, t.Testf2) + MonsterAddTestf3(builder, t.Testf3) + MonsterAddTestarrayofstring2(builder, testarrayofstring2Offset) + MonsterAddTestarrayofsortedstruct(builder, testarrayofsortedstructOffset) + MonsterAddFlex(builder, flexOffset) + MonsterAddTest5(builder, test5Offset) + MonsterAddVectorOfLongs(builder, vectorOfLongsOffset) + MonsterAddVectorOfDoubles(builder, vectorOfDoublesOffset) + MonsterAddParentNamespaceTest(builder, parentNamespaceTestOffset) + MonsterAddVectorOfReferrables(builder, vectorOfReferrablesOffset) + MonsterAddSingleWeakReference(builder, t.SingleWeakReference) + MonsterAddVectorOfWeakReferences(builder, vectorOfWeakReferencesOffset) + MonsterAddVectorOfStrongReferrables(builder, vectorOfStrongReferrablesOffset) + MonsterAddCoOwningReference(builder, t.CoOwningReference) + MonsterAddVectorOfCoOwningReferences(builder, vectorOfCoOwningReferencesOffset) + MonsterAddNonOwningReference(builder, t.NonOwningReference) + MonsterAddVectorOfNonOwningReferences(builder, vectorOfNonOwningReferencesOffset) + if t.AnyUnique != nil { + MonsterAddAnyUniqueType(builder, t.AnyUnique.Type) + } + MonsterAddAnyUnique(builder, anyUniqueOffset) + if t.AnyAmbiguous != nil { + MonsterAddAnyAmbiguousType(builder, t.AnyAmbiguous.Type) + } + MonsterAddAnyAmbiguous(builder, anyAmbiguousOffset) + MonsterAddVectorOfEnums(builder, vectorOfEnumsOffset) + MonsterAddSignedEnum(builder, t.SignedEnum) + return MonsterEnd(builder) +} + +func (rcv *Monster) UnPack() *MonsterT { + if rcv == nil { return nil } + t := &MonsterT{} + t.Pos = rcv.Pos(nil).UnPack() + t.Mana = rcv.Mana() + t.Hp = rcv.Hp() + t.Name = string(rcv.Name()) + t.Inventory = rcv.InventoryBytes() + t.Color = rcv.Color() + testTable := flatbuffers.Table{} + if rcv.Test(&testTable) { + t.Test = AnyUnPack(rcv.TestType(), testTable) + } + test4Length := rcv.Test4Length() + t.Test4 = make([]*TestT, test4Length) + for j := 0; j < test4Length; j++ { + x := Test{} + rcv.Test4(&x, j) + t.Test4[j] = x.UnPack() + } + testarrayofstringLength := rcv.TestarrayofstringLength() + t.Testarrayofstring = make([]string, testarrayofstringLength) + for j := 0; j < testarrayofstringLength; j++ { + t.Testarrayofstring[j] = string(rcv.Testarrayofstring(j)) + } + testarrayoftablesLength := rcv.TestarrayoftablesLength() + t.Testarrayoftables = make([]*MonsterT, testarrayoftablesLength) + for j := 0; j < testarrayoftablesLength; j++ { + x := Monster{} + rcv.Testarrayoftables(&x, j) + t.Testarrayoftables[j] = x.UnPack() + } + t.Enemy = rcv.Enemy(nil).UnPack() + t.Testnestedflatbuffer = rcv.TestnestedflatbufferBytes() + t.Testempty = rcv.Testempty(nil).UnPack() + t.Testbool = rcv.Testbool() + t.Testhashs32Fnv1 = rcv.Testhashs32Fnv1() + t.Testhashu32Fnv1 = rcv.Testhashu32Fnv1() + t.Testhashs64Fnv1 = rcv.Testhashs64Fnv1() + t.Testhashu64Fnv1 = rcv.Testhashu64Fnv1() + t.Testhashs32Fnv1a = rcv.Testhashs32Fnv1a() + t.Testhashu32Fnv1a = rcv.Testhashu32Fnv1a() + t.Testhashs64Fnv1a = rcv.Testhashs64Fnv1a() + t.Testhashu64Fnv1a = rcv.Testhashu64Fnv1a() + testarrayofboolsLength := rcv.TestarrayofboolsLength() + t.Testarrayofbools = make([]bool, testarrayofboolsLength) + for j := 0; j < testarrayofboolsLength; j++ { + t.Testarrayofbools[j] = rcv.Testarrayofbools(j) + } + t.Testf = rcv.Testf() + t.Testf2 = rcv.Testf2() + t.Testf3 = rcv.Testf3() + testarrayofstring2Length := rcv.Testarrayofstring2Length() + t.Testarrayofstring2 = make([]string, testarrayofstring2Length) + for j := 0; j < testarrayofstring2Length; j++ { + t.Testarrayofstring2[j] = string(rcv.Testarrayofstring2(j)) + } + testarrayofsortedstructLength := rcv.TestarrayofsortedstructLength() + t.Testarrayofsortedstruct = make([]*AbilityT, testarrayofsortedstructLength) + for j := 0; j < testarrayofsortedstructLength; j++ { + x := Ability{} + rcv.Testarrayofsortedstruct(&x, j) + t.Testarrayofsortedstruct[j] = x.UnPack() + } + t.Flex = rcv.FlexBytes() + test5Length := rcv.Test5Length() + t.Test5 = make([]*TestT, test5Length) + for j := 0; j < test5Length; j++ { + x := Test{} + rcv.Test5(&x, j) + t.Test5[j] = x.UnPack() + } + vectorOfLongsLength := rcv.VectorOfLongsLength() + t.VectorOfLongs = make([]int64, vectorOfLongsLength) + for j := 0; j < vectorOfLongsLength; j++ { + t.VectorOfLongs[j] = rcv.VectorOfLongs(j) + } + vectorOfDoublesLength := rcv.VectorOfDoublesLength() + t.VectorOfDoubles = make([]float64, vectorOfDoublesLength) + for j := 0; j < vectorOfDoublesLength; j++ { + t.VectorOfDoubles[j] = rcv.VectorOfDoubles(j) + } + t.ParentNamespaceTest = rcv.ParentNamespaceTest(nil).UnPack() + vectorOfReferrablesLength := rcv.VectorOfReferrablesLength() + t.VectorOfReferrables = make([]*ReferrableT, vectorOfReferrablesLength) + for j := 0; j < vectorOfReferrablesLength; j++ { + x := Referrable{} + rcv.VectorOfReferrables(&x, j) + t.VectorOfReferrables[j] = x.UnPack() + } + t.SingleWeakReference = rcv.SingleWeakReference() + vectorOfWeakReferencesLength := rcv.VectorOfWeakReferencesLength() + t.VectorOfWeakReferences = make([]uint64, vectorOfWeakReferencesLength) + for j := 0; j < vectorOfWeakReferencesLength; j++ { + t.VectorOfWeakReferences[j] = rcv.VectorOfWeakReferences(j) + } + vectorOfStrongReferrablesLength := rcv.VectorOfStrongReferrablesLength() + t.VectorOfStrongReferrables = make([]*ReferrableT, vectorOfStrongReferrablesLength) + for j := 0; j < vectorOfStrongReferrablesLength; j++ { + x := Referrable{} + rcv.VectorOfStrongReferrables(&x, j) + t.VectorOfStrongReferrables[j] = x.UnPack() + } + t.CoOwningReference = rcv.CoOwningReference() + vectorOfCoOwningReferencesLength := rcv.VectorOfCoOwningReferencesLength() + t.VectorOfCoOwningReferences = make([]uint64, vectorOfCoOwningReferencesLength) + for j := 0; j < vectorOfCoOwningReferencesLength; j++ { + t.VectorOfCoOwningReferences[j] = rcv.VectorOfCoOwningReferences(j) + } + t.NonOwningReference = rcv.NonOwningReference() + vectorOfNonOwningReferencesLength := rcv.VectorOfNonOwningReferencesLength() + t.VectorOfNonOwningReferences = make([]uint64, vectorOfNonOwningReferencesLength) + for j := 0; j < vectorOfNonOwningReferencesLength; j++ { + t.VectorOfNonOwningReferences[j] = rcv.VectorOfNonOwningReferences(j) + } + anyUniqueTable := flatbuffers.Table{} + if rcv.AnyUnique(&anyUniqueTable) { + t.AnyUnique = AnyUniqueAliasesUnPack(rcv.AnyUniqueType(), anyUniqueTable) + } + anyAmbiguousTable := flatbuffers.Table{} + if rcv.AnyAmbiguous(&anyAmbiguousTable) { + t.AnyAmbiguous = AnyAmbiguousAliasesUnPack(rcv.AnyAmbiguousType(), anyAmbiguousTable) + } + vectorOfEnumsLength := rcv.VectorOfEnumsLength() + t.VectorOfEnums = make([]Color, vectorOfEnumsLength) + for j := 0; j < vectorOfEnumsLength; j++ { + t.VectorOfEnums[j] = rcv.VectorOfEnums(j) + } + t.SignedEnum = rcv.SignedEnum() + return t +} + type Monster struct { _tab flatbuffers.Table } diff --git a/tests/MyGame/Example/Referrable.go b/tests/MyGame/Example/Referrable.go index 0fb06fb20..c2eb784dc 100644 --- a/tests/MyGame/Example/Referrable.go +++ b/tests/MyGame/Example/Referrable.go @@ -6,6 +6,24 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type ReferrableT struct { + Id uint64 +} + +func ReferrablePack(builder *flatbuffers.Builder, t *ReferrableT) flatbuffers.UOffsetT { + if t == nil { return 0 } + ReferrableStart(builder) + ReferrableAddId(builder, t.Id) + return ReferrableEnd(builder) +} + +func (rcv *Referrable) UnPack() *ReferrableT { + if rcv == nil { return nil } + t := &ReferrableT{} + t.Id = rcv.Id() + return t +} + type Referrable struct { _tab flatbuffers.Table } diff --git a/tests/MyGame/Example/Stat.go b/tests/MyGame/Example/Stat.go index 401712fbf..64ece1f0f 100644 --- a/tests/MyGame/Example/Stat.go +++ b/tests/MyGame/Example/Stat.go @@ -6,6 +6,31 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type StatT struct { + Id string + Val int64 + Count uint16 +} + +func StatPack(builder *flatbuffers.Builder, t *StatT) flatbuffers.UOffsetT { + if t == nil { return 0 } + idOffset := builder.CreateString(t.Id) + StatStart(builder) + StatAddId(builder, idOffset) + StatAddVal(builder, t.Val) + StatAddCount(builder, t.Count) + return StatEnd(builder) +} + +func (rcv *Stat) UnPack() *StatT { + if rcv == nil { return nil } + t := &StatT{} + t.Id = string(rcv.Id()) + t.Val = rcv.Val() + t.Count = rcv.Count() + return t +} + type Stat struct { _tab flatbuffers.Table } diff --git a/tests/MyGame/Example/Test.go b/tests/MyGame/Example/Test.go index 53f53fd41..31110d975 100644 --- a/tests/MyGame/Example/Test.go +++ b/tests/MyGame/Example/Test.go @@ -6,6 +6,23 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type TestT struct { + A int16 + B int8 +} + +func TestPack(builder *flatbuffers.Builder, t *TestT) flatbuffers.UOffsetT { + if t == nil { return 0 } + return CreateTest(builder, t.A, t.B) +} +func (rcv *Test) UnPack() *TestT { + if rcv == nil { return nil } + t := &TestT{} + t.A = rcv.A() + t.B = rcv.B() + return t +} + type Test struct { _tab flatbuffers.Struct } diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.go b/tests/MyGame/Example/TestSimpleTableWithEnum.go index 35a6c7c09..7af1edb09 100644 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.go +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.go @@ -6,6 +6,24 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type TestSimpleTableWithEnumT struct { + Color Color +} + +func TestSimpleTableWithEnumPack(builder *flatbuffers.Builder, t *TestSimpleTableWithEnumT) flatbuffers.UOffsetT { + if t == nil { return 0 } + TestSimpleTableWithEnumStart(builder) + TestSimpleTableWithEnumAddColor(builder, t.Color) + return TestSimpleTableWithEnumEnd(builder) +} + +func (rcv *TestSimpleTableWithEnum) UnPack() *TestSimpleTableWithEnumT { + if rcv == nil { return nil } + t := &TestSimpleTableWithEnumT{} + t.Color = rcv.Color() + return t +} + type TestSimpleTableWithEnum struct { _tab flatbuffers.Table } diff --git a/tests/MyGame/Example/TypeAliases.go b/tests/MyGame/Example/TypeAliases.go index d017b5bc3..497d5743a 100644 --- a/tests/MyGame/Example/TypeAliases.go +++ b/tests/MyGame/Example/TypeAliases.go @@ -6,6 +6,83 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type TypeAliasesT struct { + I8 int8 + U8 byte + I16 int16 + U16 uint16 + I32 int32 + U32 uint32 + I64 int64 + U64 uint64 + F32 float32 + F64 float64 + V8 []int8 + Vf64 []float64 +} + +func TypeAliasesPack(builder *flatbuffers.Builder, t *TypeAliasesT) flatbuffers.UOffsetT { + if t == nil { return 0 } + v8Offset := flatbuffers.UOffsetT(0) + if t.V8 != nil { + v8Length := len(t.V8) + TypeAliasesStartV8Vector(builder, v8Length) + for j := v8Length - 1; j >= 0; j-- { + builder.PrependInt8(t.V8[j]) + } + v8Offset = builder.EndVector(v8Length) + } + vf64Offset := flatbuffers.UOffsetT(0) + if t.Vf64 != nil { + vf64Length := len(t.Vf64) + TypeAliasesStartVf64Vector(builder, vf64Length) + for j := vf64Length - 1; j >= 0; j-- { + builder.PrependFloat64(t.Vf64[j]) + } + vf64Offset = builder.EndVector(vf64Length) + } + TypeAliasesStart(builder) + TypeAliasesAddI8(builder, t.I8) + TypeAliasesAddU8(builder, t.U8) + TypeAliasesAddI16(builder, t.I16) + TypeAliasesAddU16(builder, t.U16) + TypeAliasesAddI32(builder, t.I32) + TypeAliasesAddU32(builder, t.U32) + TypeAliasesAddI64(builder, t.I64) + TypeAliasesAddU64(builder, t.U64) + TypeAliasesAddF32(builder, t.F32) + TypeAliasesAddF64(builder, t.F64) + TypeAliasesAddV8(builder, v8Offset) + TypeAliasesAddVf64(builder, vf64Offset) + return TypeAliasesEnd(builder) +} + +func (rcv *TypeAliases) UnPack() *TypeAliasesT { + if rcv == nil { return nil } + t := &TypeAliasesT{} + t.I8 = rcv.I8() + t.U8 = rcv.U8() + t.I16 = rcv.I16() + t.U16 = rcv.U16() + t.I32 = rcv.I32() + t.U32 = rcv.U32() + t.I64 = rcv.I64() + t.U64 = rcv.U64() + t.F32 = rcv.F32() + t.F64 = rcv.F64() + v8Length := rcv.V8Length() + t.V8 = make([]int8, v8Length) + for j := 0; j < v8Length; j++ { + t.V8[j] = rcv.V8(j) + } + vf64Length := rcv.Vf64Length() + t.Vf64 = make([]float64, vf64Length) + for j := 0; j < vf64Length; j++ { + t.Vf64[j] = rcv.Vf64(j) + } + return t +} + type TypeAliases struct { _tab flatbuffers.Table } diff --git a/tests/MyGame/Example/Vec3.go b/tests/MyGame/Example/Vec3.go index 9131afdc1..3a75c88a1 100644 --- a/tests/MyGame/Example/Vec3.go +++ b/tests/MyGame/Example/Vec3.go @@ -6,6 +6,31 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type Vec3T struct { + X float32 + Y float32 + Z float32 + Test1 float64 + Test2 Color + Test3 *TestT +} + +func Vec3Pack(builder *flatbuffers.Builder, t *Vec3T) flatbuffers.UOffsetT { + if t == nil { return 0 } + return CreateVec3(builder, t.X, t.Y, t.Z, t.Test1, t.Test2, t.Test3.A, t.Test3.B) +} +func (rcv *Vec3) UnPack() *Vec3T { + if rcv == nil { return nil } + t := &Vec3T{} + t.X = rcv.X() + t.Y = rcv.Y() + t.Z = rcv.Z() + t.Test1 = rcv.Test1() + t.Test2 = rcv.Test2() + t.Test3 = rcv.Test3(nil).UnPack() + return t +} + type Vec3 struct { _tab flatbuffers.Struct } diff --git a/tests/MyGame/Example2/Monster.go b/tests/MyGame/Example2/Monster.go index d0fae94d9..b329d4322 100644 --- a/tests/MyGame/Example2/Monster.go +++ b/tests/MyGame/Example2/Monster.go @@ -6,6 +6,21 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type MonsterT struct { +} + +func MonsterPack(builder *flatbuffers.Builder, t *MonsterT) flatbuffers.UOffsetT { + if t == nil { return 0 } + MonsterStart(builder) + return MonsterEnd(builder) +} + +func (rcv *Monster) UnPack() *MonsterT { + if rcv == nil { return nil } + t := &MonsterT{} + return t +} + type Monster struct { _tab flatbuffers.Table } diff --git a/tests/MyGame/InParentNamespace.go b/tests/MyGame/InParentNamespace.go index fc6ce3263..186666a13 100644 --- a/tests/MyGame/InParentNamespace.go +++ b/tests/MyGame/InParentNamespace.go @@ -6,6 +6,21 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type InParentNamespaceT struct { +} + +func InParentNamespacePack(builder *flatbuffers.Builder, t *InParentNamespaceT) flatbuffers.UOffsetT { + if t == nil { return 0 } + InParentNamespaceStart(builder) + return InParentNamespaceEnd(builder) +} + +func (rcv *InParentNamespace) UnPack() *InParentNamespaceT { + if rcv == nil { return nil } + t := &InParentNamespaceT{} + return t +} + type InParentNamespace struct { _tab flatbuffers.Table } diff --git a/tests/go_test.go b/tests/go_test.go index 478470508..255b44038 100644 --- a/tests/go_test.go +++ b/tests/go_test.go @@ -90,6 +90,7 @@ func TestAll(t *testing.T) { // generated Go code: CheckReadBuffer(generated, off, t.Fatalf) CheckMutateBuffer(generated, off, t.Fatalf) + CheckObjectAPI(generated, off, t.Fatalf) // Verify that the buffer generated by C++ code is readable by the // generated Go code: @@ -99,6 +100,7 @@ func TestAll(t *testing.T) { } CheckReadBuffer(monsterDataCpp, 0, t.Fatalf) CheckMutateBuffer(monsterDataCpp, 0, t.Fatalf) + CheckObjectAPI(monsterDataCpp, 0, t.Fatalf) // Verify that vtables are deduplicated when written: CheckVtableDeduplication(t.Fatalf) @@ -448,6 +450,26 @@ func CheckMutateBuffer(org []byte, offset flatbuffers.UOffsetT, fail func(string } } +func CheckObjectAPI(buf []byte, offset flatbuffers.UOffsetT, fail func(string, ...interface{})) { + monster := example.GetRootAsMonster(buf, offset).UnPack() + + if got := monster.Hp; 80 != got { + fail(FailString("hp", 80, got)) + } + + // default + if got := monster.Mana; 150 != got { + fail(FailString("mana", 150, got)) + } + + builder := flatbuffers.NewBuilder(0) + builder.Finish(example.MonsterPack(builder, monster)) + monster2 := example.GetRootAsMonster(builder.FinishedBytes(), 0).UnPack() + if !reflect.DeepEqual(monster, monster2) { + fail(FailString("Pack/Unpack()", monster, monster2)) + } +} + // Low level stress/fuzz test: serialize/deserialize a variety of // different kinds of data in different combinations func checkFuzz(fuzzFields, fuzzObjects int, fail func(string, ...interface{})) { From 964365ba6952a75012489b3a8be48b016edce03c Mon Sep 17 00:00:00 2001 From: Lawrence Chan Date: Mon, 4 Nov 2019 14:12:25 -0600 Subject: [PATCH 02/28] [Go] Add UnPackTo functions (#5598) --- src/idl_gen_go.cpp | 26 +++++++++++++------ tests/MyGame/Example/Ability.go | 8 ++++-- tests/MyGame/Example/Monster.go | 10 ++++--- tests/MyGame/Example/Referrable.go | 6 ++++- tests/MyGame/Example/Stat.go | 10 ++++--- tests/MyGame/Example/Test.go | 8 ++++-- .../MyGame/Example/TestSimpleTableWithEnum.go | 6 ++++- tests/MyGame/Example/TypeAliases.go | 10 ++++--- tests/MyGame/Example/Vec3.go | 10 ++++--- tests/MyGame/Example2/Monster.go | 4 +++ tests/MyGame/InParentNamespace.go | 4 +++ 11 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index b092e5eab..aa25751da 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -983,10 +983,8 @@ class GoGenerator : public BaseGenerator { const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; - code += "func (rcv *" + struct_def.name + ") UnPack() *" + - NativeName(struct_def) + " {\n"; - code += "\tif rcv == nil { return nil }\n"; - code += "\tt := &" + NativeName(struct_def) + "{}\n"; + code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" + + NativeName(struct_def) + ") {\n"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const FieldDef &field = **it; @@ -1046,6 +1044,13 @@ class GoGenerator : public BaseGenerator { FLATBUFFERS_ASSERT(0); } } + code += "}\n\n"; + + code += "func (rcv *" + struct_def.name + ") UnPack() *" + + NativeName(struct_def) + " {\n"; + code += "\tif rcv == nil { return nil }\n"; + code += "\tt := &" + NativeName(struct_def) + "{}\n"; + code += "\trcv.UnPackTo(t)\n"; code += "\treturn t\n"; code += "}\n\n"; } @@ -1083,10 +1088,8 @@ class GoGenerator : public BaseGenerator { const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; - code += "func (rcv *" + struct_def.name + ") UnPack() *" + - NativeName(struct_def) + " {\n"; - code += "\tif rcv == nil { return nil }\n"; - code += "\tt := &" + NativeName(struct_def) + "{}\n"; + code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" + + NativeName(struct_def) + ") {\n"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const FieldDef &field = **it; @@ -1098,6 +1101,13 @@ class GoGenerator : public BaseGenerator { MakeCamel(field.name) + "()\n"; } } + code += "}\n\n"; + + code += "func (rcv *" + struct_def.name + ") UnPack() *" + + NativeName(struct_def) + " {\n"; + code += "\tif rcv == nil { return nil }\n"; + code += "\tt := &" + NativeName(struct_def) + "{}\n"; + code += "\trcv.UnPackTo(t)\n"; code += "\treturn t\n"; code += "}\n\n"; } diff --git a/tests/MyGame/Example/Ability.go b/tests/MyGame/Example/Ability.go index 12ff1e58d..eefb6139d 100644 --- a/tests/MyGame/Example/Ability.go +++ b/tests/MyGame/Example/Ability.go @@ -15,11 +15,15 @@ func AbilityPack(builder *flatbuffers.Builder, t *AbilityT) flatbuffers.UOffsetT if t == nil { return 0 } return CreateAbility(builder, t.Id, t.Distance) } +func (rcv *Ability) UnPackTo(t *AbilityT) { + t.Id = rcv.Id() + t.Distance = rcv.Distance() +} + func (rcv *Ability) UnPack() *AbilityT { if rcv == nil { return nil } t := &AbilityT{} - t.Id = rcv.Id() - t.Distance = rcv.Distance() + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go index 32be49f19..357b9513b 100644 --- a/tests/MyGame/Example/Monster.go +++ b/tests/MyGame/Example/Monster.go @@ -295,9 +295,7 @@ func MonsterPack(builder *flatbuffers.Builder, t *MonsterT) flatbuffers.UOffsetT return MonsterEnd(builder) } -func (rcv *Monster) UnPack() *MonsterT { - if rcv == nil { return nil } - t := &MonsterT{} +func (rcv *Monster) UnPackTo(t *MonsterT) { t.Pos = rcv.Pos(nil).UnPack() t.Mana = rcv.Mana() t.Hp = rcv.Hp() @@ -424,6 +422,12 @@ func (rcv *Monster) UnPack() *MonsterT { t.VectorOfEnums[j] = rcv.VectorOfEnums(j) } t.SignedEnum = rcv.SignedEnum() +} + +func (rcv *Monster) UnPack() *MonsterT { + if rcv == nil { return nil } + t := &MonsterT{} + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example/Referrable.go b/tests/MyGame/Example/Referrable.go index c2eb784dc..d05f69052 100644 --- a/tests/MyGame/Example/Referrable.go +++ b/tests/MyGame/Example/Referrable.go @@ -17,10 +17,14 @@ func ReferrablePack(builder *flatbuffers.Builder, t *ReferrableT) flatbuffers.UO return ReferrableEnd(builder) } +func (rcv *Referrable) UnPackTo(t *ReferrableT) { + t.Id = rcv.Id() +} + func (rcv *Referrable) UnPack() *ReferrableT { if rcv == nil { return nil } t := &ReferrableT{} - t.Id = rcv.Id() + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example/Stat.go b/tests/MyGame/Example/Stat.go index 64ece1f0f..9d052d8ee 100644 --- a/tests/MyGame/Example/Stat.go +++ b/tests/MyGame/Example/Stat.go @@ -22,12 +22,16 @@ func StatPack(builder *flatbuffers.Builder, t *StatT) flatbuffers.UOffsetT { return StatEnd(builder) } -func (rcv *Stat) UnPack() *StatT { - if rcv == nil { return nil } - t := &StatT{} +func (rcv *Stat) UnPackTo(t *StatT) { t.Id = string(rcv.Id()) t.Val = rcv.Val() t.Count = rcv.Count() +} + +func (rcv *Stat) UnPack() *StatT { + if rcv == nil { return nil } + t := &StatT{} + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example/Test.go b/tests/MyGame/Example/Test.go index 31110d975..4f66d447c 100644 --- a/tests/MyGame/Example/Test.go +++ b/tests/MyGame/Example/Test.go @@ -15,11 +15,15 @@ func TestPack(builder *flatbuffers.Builder, t *TestT) flatbuffers.UOffsetT { if t == nil { return 0 } return CreateTest(builder, t.A, t.B) } +func (rcv *Test) UnPackTo(t *TestT) { + t.A = rcv.A() + t.B = rcv.B() +} + func (rcv *Test) UnPack() *TestT { if rcv == nil { return nil } t := &TestT{} - t.A = rcv.A() - t.B = rcv.B() + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.go b/tests/MyGame/Example/TestSimpleTableWithEnum.go index 7af1edb09..81cda1ab4 100644 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.go +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.go @@ -17,10 +17,14 @@ func TestSimpleTableWithEnumPack(builder *flatbuffers.Builder, t *TestSimpleTabl return TestSimpleTableWithEnumEnd(builder) } +func (rcv *TestSimpleTableWithEnum) UnPackTo(t *TestSimpleTableWithEnumT) { + t.Color = rcv.Color() +} + func (rcv *TestSimpleTableWithEnum) UnPack() *TestSimpleTableWithEnumT { if rcv == nil { return nil } t := &TestSimpleTableWithEnumT{} - t.Color = rcv.Color() + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example/TypeAliases.go b/tests/MyGame/Example/TypeAliases.go index 497d5743a..0a6b73fcf 100644 --- a/tests/MyGame/Example/TypeAliases.go +++ b/tests/MyGame/Example/TypeAliases.go @@ -57,9 +57,7 @@ func TypeAliasesPack(builder *flatbuffers.Builder, t *TypeAliasesT) flatbuffers. return TypeAliasesEnd(builder) } -func (rcv *TypeAliases) UnPack() *TypeAliasesT { - if rcv == nil { return nil } - t := &TypeAliasesT{} +func (rcv *TypeAliases) UnPackTo(t *TypeAliasesT) { t.I8 = rcv.I8() t.U8 = rcv.U8() t.I16 = rcv.I16() @@ -80,6 +78,12 @@ func (rcv *TypeAliases) UnPack() *TypeAliasesT { for j := 0; j < vf64Length; j++ { t.Vf64[j] = rcv.Vf64(j) } +} + +func (rcv *TypeAliases) UnPack() *TypeAliasesT { + if rcv == nil { return nil } + t := &TypeAliasesT{} + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example/Vec3.go b/tests/MyGame/Example/Vec3.go index 3a75c88a1..0f081d0d8 100644 --- a/tests/MyGame/Example/Vec3.go +++ b/tests/MyGame/Example/Vec3.go @@ -19,15 +19,19 @@ func Vec3Pack(builder *flatbuffers.Builder, t *Vec3T) flatbuffers.UOffsetT { if t == nil { return 0 } return CreateVec3(builder, t.X, t.Y, t.Z, t.Test1, t.Test2, t.Test3.A, t.Test3.B) } -func (rcv *Vec3) UnPack() *Vec3T { - if rcv == nil { return nil } - t := &Vec3T{} +func (rcv *Vec3) UnPackTo(t *Vec3T) { t.X = rcv.X() t.Y = rcv.Y() t.Z = rcv.Z() t.Test1 = rcv.Test1() t.Test2 = rcv.Test2() t.Test3 = rcv.Test3(nil).UnPack() +} + +func (rcv *Vec3) UnPack() *Vec3T { + if rcv == nil { return nil } + t := &Vec3T{} + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/Example2/Monster.go b/tests/MyGame/Example2/Monster.go index b329d4322..c148b4109 100644 --- a/tests/MyGame/Example2/Monster.go +++ b/tests/MyGame/Example2/Monster.go @@ -15,9 +15,13 @@ func MonsterPack(builder *flatbuffers.Builder, t *MonsterT) flatbuffers.UOffsetT return MonsterEnd(builder) } +func (rcv *Monster) UnPackTo(t *MonsterT) { +} + func (rcv *Monster) UnPack() *MonsterT { if rcv == nil { return nil } t := &MonsterT{} + rcv.UnPackTo(t) return t } diff --git a/tests/MyGame/InParentNamespace.go b/tests/MyGame/InParentNamespace.go index 186666a13..b8d1f7e2c 100644 --- a/tests/MyGame/InParentNamespace.go +++ b/tests/MyGame/InParentNamespace.go @@ -15,9 +15,13 @@ func InParentNamespacePack(builder *flatbuffers.Builder, t *InParentNamespaceT) return InParentNamespaceEnd(builder) } +func (rcv *InParentNamespace) UnPackTo(t *InParentNamespaceT) { +} + func (rcv *InParentNamespace) UnPack() *InParentNamespaceT { if rcv == nil { return nil } t := &InParentNamespaceT{} + rcv.UnPackTo(t) return t } From 3c7b660d623b160c24fe72290011cb23be858fc2 Mon Sep 17 00:00:00 2001 From: Paulo Pinheiro Date: Mon, 4 Nov 2019 23:23:15 +0100 Subject: [PATCH 03/28] [flatc] Remove an always true condition for flexbuffers (#5604) The condition was unnecessary and Detected by PVS-Studio V560 [CWE-571] A part of conditional expression is always true: !opts.use_flexbuffers. flatc.cpp 438 --- src/flatc.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/flatc.cpp b/src/flatc.cpp index e52dad415..ab2b1faf5 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -435,8 +435,7 @@ int FlatCompiler::Compile(int argc, const char **argv) { } } else { ParseFile(*parser.get(), filename, contents, include_directories); - if (!opts.use_flexbuffers && !is_schema && - !parser->builder_.GetSize()) { + if (!is_schema && !parser->builder_.GetSize()) { // If a file doesn't end in .fbs, it must be json/binary. Ensure we // didn't just parse a schema with a different extension. Error("input file is neither json nor a .fbs (schema) file: " + From 8526e12d73d4b793024c60dd348f8b92a24c6ce2 Mon Sep 17 00:00:00 2001 From: Paulo Pinheiro Date: Mon, 4 Nov 2019 23:25:07 +0100 Subject: [PATCH 04/28] [Kotlin] Fix union vector accessor after change in Java API (#5605) Kolin uses java library as dependency, which changed the way it access union vector recently (e365c502ffc659752f9b7a8d60b0052a07e33659). This changes updates kotlin code generation to match Java's changes. --- src/idl_gen_kotlin.cpp | 5 +---- tests/MyGame/Example/Monster.kt | 6 +++--- tests/union_vector/Movie.kt | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/idl_gen_kotlin.cpp b/src/idl_gen_kotlin.cpp index 3ced7b374..d11599fe0 100644 --- a/src/idl_gen_kotlin.cpp +++ b/src/idl_gen_kotlin.cpp @@ -975,9 +975,6 @@ class KotlinGenerator : public BaseGenerator { params = "obj: " + field_type + ", j: Int"; } - - writer.SetValue("toType", "YYYYY"); - auto ret_type = return_type + nullable; GenerateFun(writer, field_name, params, ret_type, [&](){ auto inline_size = NumToString(InlineSize(vectortype)); @@ -1008,7 +1005,7 @@ class KotlinGenerator : public BaseGenerator { GenerateFun(writer, field_name, "obj: " + field_type, return_type + "?", [&](){ writer += OffsetWrapperOneLine(offset_val, - bbgetter + "(obj, o)", + bbgetter + "(obj, o + bb_pos)", "null"); }); break; diff --git a/tests/MyGame/Example/Monster.kt b/tests/MyGame/Example/Monster.kt index ff0d3a86f..bbeeb26a1 100644 --- a/tests/MyGame/Example/Monster.kt +++ b/tests/MyGame/Example/Monster.kt @@ -116,7 +116,7 @@ class Monster : Table() { } } fun test(obj: Table) : Table? { - val o = __offset(20); return if (o != 0) __union(obj, o) else null + val o = __offset(20); return if (o != 0) __union(obj, o + bb_pos) else null } fun test4(j: Int) : MyGame.Example.Test? = test4(MyGame.Example.Test(), j) fun test4(obj: MyGame.Example.Test, j: Int) : MyGame.Example.Test? { @@ -717,7 +717,7 @@ class Monster : Table() { } } fun anyUnique(obj: Table) : Table? { - val o = __offset(92); return if (o != 0) __union(obj, o) else null + val o = __offset(92); return if (o != 0) __union(obj, o + bb_pos) else null } val anyAmbiguousType : UByte get() { @@ -734,7 +734,7 @@ class Monster : Table() { } } fun anyAmbiguous(obj: Table) : Table? { - val o = __offset(96); return if (o != 0) __union(obj, o) else null + val o = __offset(96); return if (o != 0) __union(obj, o + bb_pos) else null } fun vectorOfEnums(j: Int) : UByte { val o = __offset(98) diff --git a/tests/union_vector/Movie.kt b/tests/union_vector/Movie.kt index b8a135ba8..e8d9decfa 100644 --- a/tests/union_vector/Movie.kt +++ b/tests/union_vector/Movie.kt @@ -30,7 +30,7 @@ class Movie : Table() { } } fun mainCharacter(obj: Table) : Table? { - val o = __offset(6); return if (o != 0) __union(obj, o) else null + val o = __offset(6); return if (o != 0) __union(obj, o + bb_pos) else null } fun charactersType(j: Int) : UByte { val o = __offset(8) From 661bedd837f3c9c3ddff092e812159d3a3ebecdc Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Mon, 4 Nov 2019 14:27:59 -0800 Subject: [PATCH 05/28] Add Lua FlatbufferBuilder Clean() method to enable reuseable builders (#5606) --- lua/flatbuffers/builder.lua | 17 ++++++++++++ tests/luatest.lua | 53 +++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/lua/flatbuffers/builder.lua b/lua/flatbuffers/builder.lua index 2fb22204d..19f214de5 100644 --- a/lua/flatbuffers/builder.lua +++ b/lua/flatbuffers/builder.lua @@ -60,6 +60,23 @@ function m.New(initialSize) return o end +-- Clears the builder and resets the state. It does not actually clear the backing binary array, it just reuses it as +-- needed. This is a performant way to use the builder for multiple constructions without the overhead of multiple +-- builder allocations. +function mt:Clear() + self.finished = false + self.nested = false + self.minalign = 1 + self.currentVTable = nil + self.objectEnd = nil + self.head = #self.bytes -- place the head at the end of the binary array + + -- clear vtables instead of making a new table + local vtable = self.vtables + local vtableCount = #vtable + for i=1,vtableCount do vtable[i] = nil end +end + function mt:Output(full) assert(self.finished, "Builder Not Finished") if full then diff --git a/tests/luatest.lua b/tests/luatest.lua index c85a4ec99..04f185ec6 100644 --- a/tests/luatest.lua +++ b/tests/luatest.lua @@ -81,8 +81,8 @@ local function checkReadBuffer(buf, offset, sizePrefix) assert(mon:Testempty() == nil) end -local function generateMonster(sizePrefix) - local b = flatbuffers.Builder(0) +local function generateMonster(sizePrefix, b) + b = b or flatbuffers.Builder(0) local str = b:CreateString("MyMonster") local test1 = b:CreateString("test1") local test2 = b:CreateString("test2") @@ -156,6 +156,51 @@ local function sizePrefix(sizePrefix) checkReadBuffer(buf, offset, sizePrefix) end +local function fbbClear() + -- Generate a builder that will be 'cleared' and reused to create two different objects. + local fbb = flatbuffers.Builder(0) + + -- First use the builder to read the normal monster data and verify it works + local buf, offset = generateMonster(false, fbb) + checkReadBuffer(buf, offset, false) + + -- Then clear the builder to be used again + fbb:Clear() + + -- Storage for the built monsters + local monsters = {} + local lastBuf + + -- Make another builder that will be use identically to the 'cleared' one so outputs can be compared. Build both the + -- Cleared builder and new builder in the exact same way, so we can compare their results + for i, builder in ipairs({fbb, flatbuffers.Builder(0)}) do + local strOffset = builder:CreateString("Hi there") + monster.Start(builder) + monster.AddPos(builder, vec3.CreateVec3(builder, 3.0, 2.0, 1.0, 17.0, 3, 100, 123)) + monster.AddName(builder, strOffset) + monster.AddMana(builder, 123) + builder:Finish(monster.End(builder)) + local buf = builder:Output(false) + if not lastBuf then + lastBuf = buf + else + -- the output, sized-buffer should be identical + assert(lastBuf == buf, "Monster output buffers are not identical") + end + monsters[i] = monster.GetRootAsMonster(flatbuffers.binaryArray.New(buf), 0) + end + + -- Check that all the fields for the generated monsters are as we expect + for i, monster in ipairs(monsters) do + assert(monster:Name() == "Hi there", "Monster Name is not 'Hi There' for monster "..i) + -- HP is default to 100 in the schema, but we change it in generateMonster to 80, so this is a good test to + -- see if the cleared builder really clears the data. + assert(monster:Hp() == 100, "HP doesn't equal the default value for monster "..i) + assert(monster:Mana() == 123, "Monster Mana is not '123' for monster "..i) + assert(monster:Pos():X() == 3.0, "Monster vec3.X is not '3' for monster "..i) + end +end + local function testCanonicalData() local f = assert(io.open('monsterdata_test.mon', 'rb')) local wireData = f:read("*a") @@ -219,6 +264,10 @@ local tests = d = "Test size prefix", args = {{true}, {false}} }, + { + f = fbbClear, + d = "FlatBufferBuilder Clear", + }, { f = testCanonicalData, d = "Tests Canonical flatbuffer file included in repo" From 7b38aa71e62cfdbc4530b104226177529469f076 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 4 Nov 2019 23:28:33 +0100 Subject: [PATCH 06/28] flatbuffers.h: fix documentation warning (#5607) Fixes following clang -Wdocumentation warning: ``` flatbuffers.h:1762:17: error: parameter ']' not found in the function declaration [-Werror,-Wdocumentation] /// @param[in]] v A const reference to the `std::vector` of structs to ``` --- include/flatbuffers/flatbuffers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index fcf1f27a8..250db7c31 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1759,7 +1759,7 @@ class FlatBufferBuilder { /// `vector`. /// @tparam T The data type of the `std::vector` struct elements. /// @tparam S The data type of the `std::vector` native struct elements. - /// @param[in]] v A const reference to the `std::vector` of structs to + /// @param[in] v A const reference to the `std::vector` of structs to /// serialize into the buffer as a `vector`. /// @return Returns a typed `Offset` into the serialized data indicating /// where the vector is stored. From 46ae3f80a618d230bcdc7d743fac181200898ac8 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Mon, 4 Nov 2019 14:54:44 -0800 Subject: [PATCH 07/28] [C++, Java, C#, TypeScript, JavaScript] Skip generation of mutable union types (#5599) * Skip generation of mutable union types * Removed C# and Java unit tests that mutated a Union type --- include/flatbuffers/idl.h | 79 ++++++++++--------- samples/monster_generated.h | 3 - src/idl_gen_cpp.cpp | 2 +- src/idl_gen_general.cpp | 2 +- src/idl_gen_js_ts.cpp | 2 +- .../FlatBuffersExampleTests.cs | 6 +- tests/JavaTest.java | 37 +++++---- tests/MyGame/Example/Monster.cs | 3 - tests/MyGame/Example/Monster.java | 3 - tests/monster_test_generated.h | 9 --- tests/monster_test_generated.js | 45 ----------- tests/monster_test_generated.ts | 45 ----------- tests/union_vector/Movie.cs | 2 - tests/union_vector/Movie.java | 2 - tests/union_vector/union_vector_generated.h | 3 - tests/union_vector/union_vector_generated.js | 15 ---- tests/union_vector/union_vector_generated.ts | 15 ---- 17 files changed, 64 insertions(+), 209 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 5dce91a78..f7707df24 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -338,44 +338,7 @@ struct StructDef : public Definition { flatbuffers::unique_ptr original_location; }; -inline bool IsStruct(const Type &type) { - return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed; -} -inline bool IsVector(const Type &type) { - return type.base_type == BASE_TYPE_VECTOR; -} - -inline bool IsArray(const Type &type) { - return type.base_type == BASE_TYPE_ARRAY; -} - -inline bool IsSeries(const Type &type) { - return IsVector(type) || IsArray(type); -} - -inline bool IsEnum(const Type &type) { - return type.enum_def != nullptr && IsInteger(type.base_type); -} - -inline size_t InlineSize(const Type &type) { - return IsStruct(type) - ? type.struct_def->bytesize - : (IsArray(type) - ? InlineSize(type.VectorType()) * type.fixed_length - : SizeOf(type.base_type)); -} - -inline size_t InlineAlignment(const Type &type) { - if (IsStruct(type)) { - return type.struct_def->minalign; - } else if (IsArray(type)) { - return IsStruct(type.VectorType()) ? type.struct_def->minalign - : SizeOf(type.element); - } else { - return SizeOf(type.base_type); - } -} struct EnumDef; struct EnumValBuilder; @@ -460,6 +423,48 @@ struct EnumDef : public Definition { SymbolTable vals; }; +inline bool IsStruct(const Type &type) { + return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed; +} + +inline bool IsUnion(const Type &type) { + return type.enum_def != nullptr && type.enum_def->is_union; +} + +inline bool IsVector(const Type &type) { + return type.base_type == BASE_TYPE_VECTOR; +} + +inline bool IsArray(const Type &type) { + return type.base_type == BASE_TYPE_ARRAY; +} + +inline bool IsSeries(const Type &type) { + return IsVector(type) || IsArray(type); +} + +inline bool IsEnum(const Type &type) { + return type.enum_def != nullptr && IsInteger(type.base_type); +} + +inline size_t InlineSize(const Type &type) { + return IsStruct(type) + ? type.struct_def->bytesize + : (IsArray(type) + ? InlineSize(type.VectorType()) * type.fixed_length + : SizeOf(type.base_type)); +} + +inline size_t InlineAlignment(const Type &type) { + if (IsStruct(type)) { + return type.struct_def->minalign; + } else if (IsArray(type)) { + return IsStruct(type.VectorType()) ? type.struct_def->minalign + : SizeOf(type.element); + } else { + return SizeOf(type.base_type); + } +} inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) { return lhs.value == rhs.value; } diff --git a/samples/monster_generated.h b/samples/monster_generated.h index ec2c24ce5..fefd7c13c 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -316,9 +316,6 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { MyGame::Sample::Equipment equipped_type() const { return static_cast(GetField(VT_EQUIPPED_TYPE, 0)); } - bool mutate_equipped_type(MyGame::Sample::Equipment _equipped_type) { - return SetField(VT_EQUIPPED_TYPE, static_cast(_equipped_type), 0); - } const void *equipped() const { return GetPointer(VT_EQUIPPED); } diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 826f6468e..d7b3abb5f 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -1925,7 +1925,7 @@ class CppGenerator : public BaseGenerator { } } - if (parser_.opts.mutable_buffer) { + if (parser_.opts.mutable_buffer && !(is_scalar && IsUnion(field.value.type))) { if (is_scalar) { const auto type = GenTypeWire(field.value.type, "", false); code_.SetValue("SET_FN", "SetField<" + type + ">"); diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 03ffb8810..bb2920f5d 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -1367,7 +1367,7 @@ class GeneralGenerator : public BaseGenerator { ? lang_.accessor_prefix + "bb_pos + " + NumToString(field.value.offset) : "o + " + lang_.accessor_prefix + "bb_pos"); - if (IsScalar(underlying_type.base_type)) { + if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) { code += " public "; code += struct_def.fixed ? "void " : lang_.bool_type; code += mutator_prefix + MakeCamel(field.name, true); diff --git a/src/idl_gen_js_ts.cpp b/src/idl_gen_js_ts.cpp index 9c4c149cd..84dc73747 100644 --- a/src/idl_gen_js_ts.cpp +++ b/src/idl_gen_js_ts.cpp @@ -1015,7 +1015,7 @@ class JsTsGenerator : public BaseGenerator { } // Adds the mutable scalar value to the output - if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) { + if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer && !IsUnion(field.value.type)) { std::string annotations = GenTypeAnnotation( kParam, GenTypeName(field.value.type, true), "value"); GenDocComment( diff --git a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs index 434b2a18e..bbd69f79a 100644 --- a/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs +++ b/tests/FlatBuffers.Test/FlatBuffersExampleTests.cs @@ -156,11 +156,7 @@ namespace FlatBuffers.Test Assert.IsTrue(monster.TestarrayoftablesByKey("Barney") != null); Assert.IsTrue(monster.TestarrayoftablesByKey("Wilma") != null); - // testType is an existing field and mutating it should succeed - Assert.AreEqual(monster.TestType, Any.Monster); - Assert.AreEqual(monster.MutateTestType(Any.NONE), true); - Assert.AreEqual(monster.TestType, Any.NONE); - Assert.AreEqual(monster.MutateTestType(Any.Monster), true); + // testType is an existing field Assert.AreEqual(monster.TestType, Any.Monster); //mutate the inventory vector diff --git a/tests/JavaTest.java b/tests/JavaTest.java index 9c11910d5..1443b779b 100644 --- a/tests/JavaTest.java +++ b/tests/JavaTest.java @@ -1,18 +1,3 @@ -/* - * Copyright 2014 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ import static com.google.flatbuffers.Constants.*; @@ -36,6 +21,24 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + class JavaTest { public static void main(String[] args) { @@ -438,10 +441,6 @@ class JavaTest { // testType is an existing field and mutating it should succeed TestEq(monster.testType(), (byte)Any.Monster); - TestEq(monster.mutateTestType(Any.NONE), true); - TestEq(monster.testType(), (byte)Any.NONE); - TestEq(monster.mutateTestType(Any.Monster), true); - TestEq(monster.testType(), (byte)Any.Monster); //mutate the inventory vector TestEq(monster.mutateInventory(0, 1), true); diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs index 36d6c2dde..4aa0c2409 100644 --- a/tests/MyGame/Example/Monster.cs +++ b/tests/MyGame/Example/Monster.cs @@ -44,7 +44,6 @@ public struct Monster : IFlatbufferObject public MyGame.Example.Color Color { get { int o = __p.__offset(16); return o != 0 ? (MyGame.Example.Color)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Color.Blue; } } public bool MutateColor(MyGame.Example.Color color) { int o = __p.__offset(16); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)color); return true; } else { return false; } } public MyGame.Example.Any TestType { get { int o = __p.__offset(18); return o != 0 ? (MyGame.Example.Any)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.Any.NONE; } } - public bool MutateTestType(MyGame.Example.Any test_type) { int o = __p.__offset(18); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)test_type); return true; } else { return false; } } public TTable? Test() where TTable : struct, IFlatbufferObject { int o = __p.__offset(20); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } public MyGame.Example.Test? Test4(int j) { int o = __p.__offset(22); return o != 0 ? (MyGame.Example.Test?)(new MyGame.Example.Test()).__assign(__p.__vector(o) + j * 4, __p.bb) : null; } public int Test4Length { get { int o = __p.__offset(22); return o != 0 ? __p.__vector_len(o) : 0; } } @@ -174,10 +173,8 @@ public struct Monster : IFlatbufferObject public ulong[] GetVectorOfNonOwningReferencesArray() { return __p.__vector_as_array(88); } public bool MutateVectorOfNonOwningReferences(int j, ulong vector_of_non_owning_references) { int o = __p.__offset(88); if (o != 0) { __p.bb.PutUlong(__p.__vector(o) + j * 8, vector_of_non_owning_references); return true; } else { return false; } } public MyGame.Example.AnyUniqueAliases AnyUniqueType { get { int o = __p.__offset(90); return o != 0 ? (MyGame.Example.AnyUniqueAliases)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.AnyUniqueAliases.NONE; } } - public bool MutateAnyUniqueType(MyGame.Example.AnyUniqueAliases any_unique_type) { int o = __p.__offset(90); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)any_unique_type); return true; } else { return false; } } public TTable? AnyUnique() where TTable : struct, IFlatbufferObject { int o = __p.__offset(92); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } public MyGame.Example.AnyAmbiguousAliases AnyAmbiguousType { get { int o = __p.__offset(94); return o != 0 ? (MyGame.Example.AnyAmbiguousAliases)__p.bb.Get(o + __p.bb_pos) : MyGame.Example.AnyAmbiguousAliases.NONE; } } - public bool MutateAnyAmbiguousType(MyGame.Example.AnyAmbiguousAliases any_ambiguous_type) { int o = __p.__offset(94); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)any_ambiguous_type); return true; } else { return false; } } public TTable? AnyAmbiguous() where TTable : struct, IFlatbufferObject { int o = __p.__offset(96); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } public MyGame.Example.Color VectorOfEnums(int j) { int o = __p.__offset(98); return o != 0 ? (MyGame.Example.Color)__p.bb.Get(__p.__vector(o) + j * 1) : (MyGame.Example.Color)0; } public int VectorOfEnumsLength { get { int o = __p.__offset(98); return o != 0 ? __p.__vector_len(o) : 0; } } diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java index 07c4e41b2..c9ef6ae90 100644 --- a/tests/MyGame/Example/Monster.java +++ b/tests/MyGame/Example/Monster.java @@ -38,7 +38,6 @@ public final class Monster extends Table { public int color() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) & 0xFF : 8; } public boolean mutateColor(int color) { int o = __offset(16); if (o != 0) { bb.put(o + bb_pos, (byte)color); return true; } else { return false; } } public byte testType() { int o = __offset(18); return o != 0 ? bb.get(o + bb_pos) : 0; } - public boolean mutateTestType(byte test_type) { int o = __offset(18); if (o != 0) { bb.put(o + bb_pos, test_type); return true; } else { return false; } } public Table test(Table obj) { int o = __offset(20); return o != 0 ? __union(obj, o + bb_pos) : null; } public MyGame.Example.Test test4(int j) { return test4(new MyGame.Example.Test(), j); } public MyGame.Example.Test test4(MyGame.Example.Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__assign(__vector(o) + j * 4, bb) : null; } @@ -183,10 +182,8 @@ public final class Monster extends Table { public ByteBuffer vectorOfNonOwningReferencesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 88, 8); } public boolean mutateVectorOfNonOwningReferences(int j, long vector_of_non_owning_references) { int o = __offset(88); if (o != 0) { bb.putLong(__vector(o) + j * 8, vector_of_non_owning_references); return true; } else { return false; } } public byte anyUniqueType() { int o = __offset(90); return o != 0 ? bb.get(o + bb_pos) : 0; } - public boolean mutateAnyUniqueType(byte any_unique_type) { int o = __offset(90); if (o != 0) { bb.put(o + bb_pos, any_unique_type); return true; } else { return false; } } public Table anyUnique(Table obj) { int o = __offset(92); return o != 0 ? __union(obj, o + bb_pos) : null; } public byte anyAmbiguousType() { int o = __offset(94); return o != 0 ? bb.get(o + bb_pos) : 0; } - public boolean mutateAnyAmbiguousType(byte any_ambiguous_type) { int o = __offset(94); if (o != 0) { bb.put(o + bb_pos, any_ambiguous_type); return true; } else { return false; } } public Table anyAmbiguous(Table obj) { int o = __offset(96); return o != 0 ? __union(obj, o + bb_pos) : null; } public int vectorOfEnums(int j) { int o = __offset(98); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; } public int vectorOfEnumsLength() { int o = __offset(98); return o != 0 ? __vector_len(o) : 0; } diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index c802a680c..40dd12030 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -1353,9 +1353,6 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { MyGame::Example::Any test_type() const { return static_cast(GetField(VT_TEST_TYPE, 0)); } - bool mutate_test_type(MyGame::Example::Any _test_type) { - return SetField(VT_TEST_TYPE, static_cast(_test_type), 0); - } const void *test() const { return GetPointer(VT_TEST); } @@ -1587,9 +1584,6 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { MyGame::Example::AnyUniqueAliases any_unique_type() const { return static_cast(GetField(VT_ANY_UNIQUE_TYPE, 0)); } - bool mutate_any_unique_type(MyGame::Example::AnyUniqueAliases _any_unique_type) { - return SetField(VT_ANY_UNIQUE_TYPE, static_cast(_any_unique_type), 0); - } const void *any_unique() const { return GetPointer(VT_ANY_UNIQUE); } @@ -1609,9 +1603,6 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { MyGame::Example::AnyAmbiguousAliases any_ambiguous_type() const { return static_cast(GetField(VT_ANY_AMBIGUOUS_TYPE, 0)); } - bool mutate_any_ambiguous_type(MyGame::Example::AnyAmbiguousAliases _any_ambiguous_type) { - return SetField(VT_ANY_AMBIGUOUS_TYPE, static_cast(_any_ambiguous_type), 0); - } const void *any_ambiguous() const { return GetPointer(VT_ANY_AMBIGUOUS); } diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js index 1a4f42b39..44eb9eba8 100644 --- a/tests/monster_test_generated.js +++ b/tests/monster_test_generated.js @@ -1153,21 +1153,6 @@ MyGame.Example.Monster.prototype.testType = function() { return offset ? /** @type {MyGame.Example.Any} */ (this.bb.readUint8(this.bb_pos + offset)) : MyGame.Example.Any.NONE; }; -/** - * @param {MyGame.Example.Any} value - * @returns {boolean} - */ -MyGame.Example.Monster.prototype.mutate_test_type = function(value) { - var offset = this.bb.__offset(this.bb_pos, 18); - - if (offset === 0) { - return false; - } - - this.bb.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param {flatbuffers.Table} obj * @returns {?flatbuffers.Table} @@ -1872,21 +1857,6 @@ MyGame.Example.Monster.prototype.anyUniqueType = function() { return offset ? /** @type {MyGame.Example.AnyUniqueAliases} */ (this.bb.readUint8(this.bb_pos + offset)) : MyGame.Example.AnyUniqueAliases.NONE; }; -/** - * @param {MyGame.Example.AnyUniqueAliases} value - * @returns {boolean} - */ -MyGame.Example.Monster.prototype.mutate_any_unique_type = function(value) { - var offset = this.bb.__offset(this.bb_pos, 90); - - if (offset === 0) { - return false; - } - - this.bb.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param {flatbuffers.Table} obj * @returns {?flatbuffers.Table} @@ -1904,21 +1874,6 @@ MyGame.Example.Monster.prototype.anyAmbiguousType = function() { return offset ? /** @type {MyGame.Example.AnyAmbiguousAliases} */ (this.bb.readUint8(this.bb_pos + offset)) : MyGame.Example.AnyAmbiguousAliases.NONE; }; -/** - * @param {MyGame.Example.AnyAmbiguousAliases} value - * @returns {boolean} - */ -MyGame.Example.Monster.prototype.mutate_any_ambiguous_type = function(value) { - var offset = this.bb.__offset(this.bb_pos, 94); - - if (offset === 0) { - return false; - } - - this.bb.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param {flatbuffers.Table} obj * @returns {?flatbuffers.Table} diff --git a/tests/monster_test_generated.ts b/tests/monster_test_generated.ts index 617300aa6..a6385171f 100644 --- a/tests/monster_test_generated.ts +++ b/tests/monster_test_generated.ts @@ -1001,21 +1001,6 @@ testType():MyGame.Example.Any { return offset ? /** */ (this.bb!.readUint8(this.bb_pos + offset)) : MyGame.Example.Any.NONE; }; -/** - * @param MyGame.Example.Any value - * @returns boolean - */ -mutate_test_type(value:MyGame.Example.Any):boolean { - var offset = this.bb!.__offset(this.bb_pos, 18); - - if (offset === 0) { - return false; - } - - this.bb!.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param flatbuffers.Table obj * @returns ?flatbuffers.Table @@ -1724,21 +1709,6 @@ anyUniqueType():MyGame.Example.AnyUniqueAliases { return offset ? /** */ (this.bb!.readUint8(this.bb_pos + offset)) : MyGame.Example.AnyUniqueAliases.NONE; }; -/** - * @param MyGame.Example.AnyUniqueAliases value - * @returns boolean - */ -mutate_any_unique_type(value:MyGame.Example.AnyUniqueAliases):boolean { - var offset = this.bb!.__offset(this.bb_pos, 90); - - if (offset === 0) { - return false; - } - - this.bb!.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param flatbuffers.Table obj * @returns ?flatbuffers.Table @@ -1756,21 +1726,6 @@ anyAmbiguousType():MyGame.Example.AnyAmbiguousAliases { return offset ? /** */ (this.bb!.readUint8(this.bb_pos + offset)) : MyGame.Example.AnyAmbiguousAliases.NONE; }; -/** - * @param MyGame.Example.AnyAmbiguousAliases value - * @returns boolean - */ -mutate_any_ambiguous_type(value:MyGame.Example.AnyAmbiguousAliases):boolean { - var offset = this.bb!.__offset(this.bb_pos, 94); - - if (offset === 0) { - return false; - } - - this.bb!.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param flatbuffers.Table obj * @returns ?flatbuffers.Table diff --git a/tests/union_vector/Movie.cs b/tests/union_vector/Movie.cs index d300b44ba..29f680e7d 100644 --- a/tests/union_vector/Movie.cs +++ b/tests/union_vector/Movie.cs @@ -17,7 +17,6 @@ public struct Movie : IFlatbufferObject public Movie __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public Character MainCharacterType { get { int o = __p.__offset(4); return o != 0 ? (Character)__p.bb.Get(o + __p.bb_pos) : Character.NONE; } } - public bool MutateMainCharacterType(Character main_character_type) { int o = __p.__offset(4); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)main_character_type); return true; } else { return false; } } public TTable? MainCharacter() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union(o + __p.bb_pos) : null; } public Character CharactersType(int j) { int o = __p.__offset(8); return o != 0 ? (Character)__p.bb.Get(__p.__vector(o) + j * 1) : (Character)0; } public int CharactersTypeLength { get { int o = __p.__offset(8); return o != 0 ? __p.__vector_len(o) : 0; } } @@ -27,7 +26,6 @@ public struct Movie : IFlatbufferObject public ArraySegment? GetCharactersTypeBytes() { return __p.__vector_as_arraysegment(8); } #endif public Character[] GetCharactersTypeArray() { int o = __p.__offset(8); if (o == 0) return null; int p = __p.__vector(o); int l = __p.__vector_len(o); Character[] a = new Character[l]; for (int i = 0; i < l; i++) { a[i] = (Character)__p.bb.Get(p + i * 1); } return a; } - public bool MutateCharactersType(int j, Character characters_type) { int o = __p.__offset(8); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, (byte)characters_type); return true; } else { return false; } } public TTable? Characters(int j) where TTable : struct, IFlatbufferObject { int o = __p.__offset(10); return o != 0 ? (TTable?)__p.__union(__p.__vector(o) + j * 4) : null; } public int CharactersLength { get { int o = __p.__offset(10); return o != 0 ? __p.__vector_len(o) : 0; } } diff --git a/tests/union_vector/Movie.java b/tests/union_vector/Movie.java index c22cae314..5c6c1da09 100644 --- a/tests/union_vector/Movie.java +++ b/tests/union_vector/Movie.java @@ -15,7 +15,6 @@ public final class Movie extends Table { public Movie __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public byte mainCharacterType() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } - public boolean mutateMainCharacterType(byte main_character_type) { int o = __offset(4); if (o != 0) { bb.put(o + bb_pos, main_character_type); return true; } else { return false; } } public Table mainCharacter(Table obj) { int o = __offset(6); return o != 0 ? __union(obj, o + bb_pos) : null; } public byte charactersType(int j) { int o = __offset(8); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } public int charactersTypeLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } @@ -23,7 +22,6 @@ public final class Movie extends Table { public ByteVector charactersTypeVector(ByteVector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer charactersTypeAsByteBuffer() { return __vector_as_bytebuffer(8, 1); } public ByteBuffer charactersTypeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); } - public boolean mutateCharactersType(int j, byte characters_type) { int o = __offset(8); if (o != 0) { bb.put(__vector(o) + j * 1, characters_type); return true; } else { return false; } } public Table characters(Table obj, int j) { int o = __offset(10); return o != 0 ? __union(obj, __vector(o) + j * 4) : null; } public int charactersLength() { int o = __offset(10); return o != 0 ? __vector_len(o) : 0; } public UnionVector charactersVector() { return charactersVector(new UnionVector()); } diff --git a/tests/union_vector/union_vector_generated.h b/tests/union_vector/union_vector_generated.h index fcb1d8c87..40fa6186d 100644 --- a/tests/union_vector/union_vector_generated.h +++ b/tests/union_vector/union_vector_generated.h @@ -361,9 +361,6 @@ struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { Character main_character_type() const { return static_cast(GetField(VT_MAIN_CHARACTER_TYPE, 0)); } - bool mutate_main_character_type(Character _main_character_type) { - return SetField(VT_MAIN_CHARACTER_TYPE, static_cast(_main_character_type), 0); - } const void *main_character() const { return GetPointer(VT_MAIN_CHARACTER); } diff --git a/tests/union_vector/union_vector_generated.js b/tests/union_vector/union_vector_generated.js index c9c071c4f..f65206edc 100644 --- a/tests/union_vector/union_vector_generated.js +++ b/tests/union_vector/union_vector_generated.js @@ -306,21 +306,6 @@ Movie.prototype.mainCharacterType = function() { return offset ? /** @type {Character} */ (this.bb.readUint8(this.bb_pos + offset)) : Character.NONE; }; -/** - * @param {Character} value - * @returns {boolean} - */ -Movie.prototype.mutate_main_character_type = function(value) { - var offset = this.bb.__offset(this.bb_pos, 4); - - if (offset === 0) { - return false; - } - - this.bb.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param {flatbuffers.Table} obj * @returns {?flatbuffers.Table} diff --git a/tests/union_vector/union_vector_generated.ts b/tests/union_vector/union_vector_generated.ts index 642f6728f..d0b1c3019 100644 --- a/tests/union_vector/union_vector_generated.ts +++ b/tests/union_vector/union_vector_generated.ts @@ -258,21 +258,6 @@ mainCharacterType():Character { return offset ? /** */ (this.bb!.readUint8(this.bb_pos + offset)) : Character.NONE; }; -/** - * @param Character value - * @returns boolean - */ -mutate_main_character_type(value:Character):boolean { - var offset = this.bb!.__offset(this.bb_pos, 4); - - if (offset === 0) { - return false; - } - - this.bb!.writeUint8(this.bb_pos + offset, value); - return true; -}; - /** * @param flatbuffers.Table obj * @returns ?flatbuffers.Table From 44b2ab087ca3bdecc218ad9fb7c56710cb5c26a6 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Mon, 4 Nov 2019 23:58:51 +0100 Subject: [PATCH 08/28] include/flatbuffers/base.h: fix no_sanitize issue with old clang (#5610) Older clang versions raise: ``` ./flatbuffers/base.h:365:1: error: unknown attribute 'no_sanitize' ignored [-Werror,-Wattributes] __supress_ubsan__("alignment") ^ ./flatbuffers/base.h:246:50: note: expanded from macro '__supress_ubsan__' #define __supress_ubsan__(type) __attribute__((no_sanitize(type))) ^ ``` Comparing https://releases.llvm.org/3.6.0/tools/clang/docs/AttributeReference.html with https://releases.llvm.org/3.7.0/tools/clang/docs/AttributeReference.html shows that __attribute__((no_sanitize(type))) is available since 3.7.0 --- include/flatbuffers/base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/flatbuffers/base.h b/include/flatbuffers/base.h index 9c4ae11d9..92c47a327 100644 --- a/include/flatbuffers/base.h +++ b/include/flatbuffers/base.h @@ -242,7 +242,7 @@ namespace flatbuffers { // Suppress Undefined Behavior Sanitizer (recoverable only). Usage: // - __supress_ubsan__("undefined") // - __supress_ubsan__("signed-integer-overflow") -#if defined(__clang__) +#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7)) #define __supress_ubsan__(type) __attribute__((no_sanitize(type))) #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409) #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined)) From 9834ee97874c95eee8b27677639eeb33aed12980 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 4 Nov 2019 17:15:56 -0800 Subject: [PATCH 09/28] Fixed Apache license not using canonical version. Now identical to https://www.apache.org/licenses/LICENSE-2.0.txt Change-Id: I6eab8bdee2472107dfc72265e204fdd16f3abc2e --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index a4c5efd82..d64569567 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -187,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2014 Google Inc. + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From e837d5a296c725d141802777808aaff944e7b427 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 4 Nov 2019 17:23:01 -0800 Subject: [PATCH 10/28] Fixed deprecated method in GRPC Java test. Change-Id: Iccae8fe9409adbf3cd3013a5cf3368e068175ad3 --- grpc/tests/JavaGrpcTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grpc/tests/JavaGrpcTest.java b/grpc/tests/JavaGrpcTest.java index 98a67b518..273291161 100644 --- a/grpc/tests/JavaGrpcTest.java +++ b/grpc/tests/JavaGrpcTest.java @@ -96,7 +96,7 @@ public class JavaGrpcTest { if (monster.hp() > maxHp.get()) { // Found a monster of higher hit points. maxHp.set(monster.hp()); - maxHpMonsterName.set(monster.name()); + maxHpMonsterName.set(monster.name()); maxHpCount.set(1); } else if (monster.hp() == maxHp.get()) { @@ -141,7 +141,7 @@ public class JavaGrpcTest { channel = ManagedChannelBuilder.forAddress("localhost", port) // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid // needing certificates. - .usePlaintext(true) + .usePlaintext() .directExecutor() .build(); blockingStub = MonsterStorageGrpc.newBlockingStub(channel); @@ -177,7 +177,7 @@ public class JavaGrpcTest { final CountDownLatch streamAlive = new CountDownLatch(1); StreamObserver statObserver = new StreamObserver() { - public void onCompleted() { + public void onCompleted() { streamAlive.countDown(); } public void onError(Throwable ex) { } From f0f0efe7b8bb1e32e7ea21b17bdea28835ad81c4 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Thu, 7 Nov 2019 12:22:54 -0800 Subject: [PATCH 11/28] [C++] Refactor to conform to Google C++ style guide (#5608) * Automatic refractor of C++ headers to Google C++ style guide * Automatic refractor of C++ source to Google C++ style guide * Automatic refractor of C++ tests to Google C++ style guide * Fixed clang-format issues by running clang-format twice to correct itself. Kotlin was missing clang-format on after turning it off, so it was changed, --- include/flatbuffers/code_generators.h | 4 +- include/flatbuffers/flatbuffers.h | 179 +- include/flatbuffers/flatc.h | 1 + include/flatbuffers/flexbuffers.h | 58 +- include/flatbuffers/grpc.h | 40 +- include/flatbuffers/hash.h | 8 +- include/flatbuffers/idl.h | 169 +- include/flatbuffers/minireflect.h | 3 +- include/flatbuffers/util.h | 4 +- src/code_generators.cpp | 6 +- src/flatc.cpp | 5 +- src/flatc_main.cpp | 19 +- src/flathash.cpp | 4 +- src/idl_gen_cpp.cpp | 35 +- src/idl_gen_dart.cpp | 32 +- src/idl_gen_general.cpp | 211 +- src/idl_gen_go.cpp | 127 +- src/idl_gen_grpc.cpp | 30 +- src/idl_gen_js_ts.cpp | 77 +- src/idl_gen_json_schema.cpp | 1 + src/idl_gen_kotlin.cpp | 2560 ++++++++++++------------- src/idl_gen_lobster.cpp | 90 +- src/idl_gen_lua.cpp | 1212 ++++++------ src/idl_gen_php.cpp | 3 +- src/idl_gen_python.cpp | 128 +- src/idl_gen_rust.cpp | 579 +++--- src/idl_gen_text.cpp | 26 +- src/idl_parser.cpp | 304 ++- src/reflection.cpp | 45 +- src/util.cpp | 6 +- tests/native_type_test_impl.cpp | 14 +- tests/native_type_test_impl.h | 34 +- tests/test.cpp | 258 +-- tests/test_assert.cpp | 14 +- tests/test_builder.cpp | 84 +- tests/test_builder.h | 81 +- 36 files changed, 3157 insertions(+), 3294 deletions(-) diff --git a/include/flatbuffers/code_generators.h b/include/flatbuffers/code_generators.h index 0bcec9102..618e4978a 100644 --- a/include/flatbuffers/code_generators.h +++ b/include/flatbuffers/code_generators.h @@ -19,6 +19,7 @@ #include #include + #include "flatbuffers/idl.h" namespace flatbuffers { @@ -95,8 +96,7 @@ class BaseGenerator { protected: BaseGenerator(const Parser &parser, const std::string &path, - const std::string &file_name, - std::string qualifying_start, + const std::string &file_name, std::string qualifying_start, std::string qualifying_separator) : parser_(parser), path_(path), diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 250db7c31..5c846a6d9 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -20,7 +20,7 @@ #include "flatbuffers/base.h" #if defined(FLATBUFFERS_NAN_DEFAULTS) -#include +# include #endif namespace flatbuffers { @@ -203,11 +203,10 @@ template struct VectorIterator { const uint8_t *data_; }; -template struct VectorReverseIterator : - public std::reverse_iterator { - - explicit VectorReverseIterator(Iterator iter) : - std::reverse_iterator(iter) {} +template +struct VectorReverseIterator : public std::reverse_iterator { + explicit VectorReverseIterator(Iterator iter) + : std::reverse_iterator(iter) {} typename Iterator::value_type operator*() const { return *(std::reverse_iterator::current); @@ -277,10 +276,14 @@ template class Vector { const_iterator end() const { return const_iterator(Data(), size()); } reverse_iterator rbegin() { return reverse_iterator(end() - 1); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(end() - 1); } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end() - 1); + } reverse_iterator rend() { return reverse_iterator(begin() - 1); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin() - 1); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin() - 1); + } const_iterator cbegin() const { return begin(); } @@ -403,7 +406,8 @@ template static inline size_t VectorLength(const Vector *v) { // This is used as a helper type for accessing arrays. template class Array { typedef - typename flatbuffers::integral_constant::value> + typename flatbuffers::integral_constant::value> scalar_tag; typedef typename flatbuffers::conditional::type @@ -449,9 +453,7 @@ template class Array { } // Change elements if you have a non-const pointer to this object. - void Mutate(uoffset_t i, const T &val) { - MutateImpl(scalar_tag(), i, val); - } + void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); } // The raw data in little endian format. Use with care. const uint8_t *Data() const { return data_; } @@ -544,13 +546,13 @@ struct String : public Vector { // Convenience function to get std::string from a String returning an empty // string on null pointer. -static inline std::string GetString(const String * str) { +static inline std::string GetString(const String *str) { return str ? str->str() : ""; } // Convenience function to get char* from a String returning an empty string on // null pointer. -static inline const char * GetCstring(const String * str) { +static inline const char *GetCstring(const String *str) { return str ? str->c_str() : ""; } @@ -587,9 +589,9 @@ class Allocator { // to `new_p` of `new_size`. Only memory of size `in_use_front` and // `in_use_back` will be copied from the front and back of the old memory // allocation. - void memcpy_downward(uint8_t *old_p, size_t old_size, - uint8_t *new_p, size_t new_size, - size_t in_use_back, size_t in_use_front) { + void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p, + size_t new_size, size_t in_use_back, + size_t in_use_front) { memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back, in_use_back); memcpy(new_p, old_p, in_use_front); @@ -603,13 +605,9 @@ class DefaultAllocator : public Allocator { return new uint8_t[size]; } - void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { - delete[] p; - } + void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; } - static void dealloc(void *p, size_t) { - delete[] static_cast(p); - } + static void dealloc(void *p, size_t) { delete[] static_cast(p); } }; // These functions allow for a null allocator to mean use the default allocator, @@ -622,18 +620,19 @@ inline uint8_t *Allocate(Allocator *allocator, size_t size) { } inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) { - if (allocator) allocator->deallocate(p, size); - else DefaultAllocator().deallocate(p, size); + if (allocator) + allocator->deallocate(p, size); + else + DefaultAllocator().deallocate(p, size); } inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p, size_t old_size, size_t new_size, size_t in_use_back, size_t in_use_front) { - return allocator - ? allocator->reallocate_downward(old_p, old_size, new_size, - in_use_back, in_use_front) - : DefaultAllocator().reallocate_downward(old_p, old_size, new_size, - in_use_back, in_use_front); + return allocator ? allocator->reallocate_downward(old_p, old_size, new_size, + in_use_back, in_use_front) + : DefaultAllocator().reallocate_downward( + old_p, old_size, new_size, in_use_back, in_use_front); } // DetachedBuffer is a finished flatbuffer memory region, detached from its @@ -678,8 +677,7 @@ class DetachedBuffer { #if !defined(FLATBUFFERS_CPP98_STL) // clang-format on DetachedBuffer &operator=(DetachedBuffer &&other) { - if (this == &other) - return *this; + if (this == &other) return *this; destroy(); @@ -737,7 +735,7 @@ class DetachedBuffer { #endif // !defined(FLATBUFFERS_CPP98_STL) // clang-format on -protected: + protected: Allocator *allocator_; bool own_allocator_; uint8_t *buf_; @@ -769,10 +767,8 @@ protected: // Essentially, this supports 2 std::vectors in a single buffer. class vector_downward { public: - explicit vector_downward(size_t initial_size, - Allocator *allocator, - bool own_allocator, - size_t buffer_minalign) + explicit vector_downward(size_t initial_size, Allocator *allocator, + bool own_allocator, size_t buffer_minalign) : allocator_(allocator), own_allocator_(own_allocator), initial_size_(initial_size), @@ -788,15 +784,15 @@ class vector_downward { #else vector_downward(vector_downward &other) #endif // defined(FLATBUFFERS_CPP98_STL) - // clang-format on - : allocator_(other.allocator_), - own_allocator_(other.own_allocator_), - initial_size_(other.initial_size_), - buffer_minalign_(other.buffer_minalign_), - reserved_(other.reserved_), - buf_(other.buf_), - cur_(other.cur_), - scratch_(other.scratch_) { + // clang-format on + : allocator_(other.allocator_), + own_allocator_(other.own_allocator_), + initial_size_(other.initial_size_), + buffer_minalign_(other.buffer_minalign_), + reserved_(other.reserved_), + buf_(other.buf_), + cur_(other.cur_), + scratch_(other.scratch_) { // No change in other.allocator_ // No change in other.initial_size_ // No change in other.buffer_minalign_ @@ -840,9 +836,7 @@ class vector_downward { clear_scratch(); } - void clear_scratch() { - scratch_ = buf_; - } + void clear_scratch() { scratch_ = buf_; } void clear_allocator() { if (own_allocator_ && allocator_) { delete allocator_; } @@ -995,8 +989,8 @@ class vector_downward { auto old_reserved = reserved_; auto old_size = size(); auto old_scratch_size = scratch_size(); - reserved_ += (std::max)(len, - old_reserved ? old_reserved / 2 : initial_size_); + reserved_ += + (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_); reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1); if (buf_) { buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_, @@ -1021,13 +1015,13 @@ const T *data(const std::vector &v) { // Eventually the returned pointer gets passed down to memcpy, so // we need it to be non-null to avoid undefined behavior. static uint8_t t; - return v.empty() ? reinterpret_cast(&t) : &v.front(); + return v.empty() ? reinterpret_cast(&t) : &v.front(); } template T *data(std::vector &v) { // Eventually the returned pointer gets passed down to memcpy, so // we need it to be non-null to avoid undefined behavior. static uint8_t t; - return v.empty() ? reinterpret_cast(&t) : &v.front(); + return v.empty() ? reinterpret_cast(&t) : &v.front(); } /// @endcond @@ -1054,11 +1048,10 @@ class FlatBufferBuilder { /// minimum alignment upon reallocation. Only needed if you intend to store /// types with custom alignment AND you wish to read the buffer in-place /// directly after creation. - explicit FlatBufferBuilder(size_t initial_size = 1024, - Allocator *allocator = nullptr, - bool own_allocator = false, - size_t buffer_minalign = - AlignOf()) + explicit FlatBufferBuilder( + size_t initial_size = 1024, Allocator *allocator = nullptr, + bool own_allocator = false, + size_t buffer_minalign = AlignOf()) : buf_(initial_size, allocator, own_allocator, buffer_minalign), num_field_loc(0), max_voffset_(0), @@ -1161,8 +1154,8 @@ class FlatBufferBuilder { /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards! /// @return A `FlatBuffer` that owns the buffer and its allocator and /// behaves similar to a `unique_ptr` with a deleter. - FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer - ReleaseBufferPointer() { + FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) + DetachedBuffer ReleaseBufferPointer() { Finished(); return buf_.release(); } @@ -1181,7 +1174,8 @@ class FlatBufferBuilder { /// `FlatBuffer` starts. /// @return A raw pointer to the start of the memory block containing /// the serialized `FlatBuffer`. - /// @remark If the allocator is owned, it gets deleted when the destructor is called.. + /// @remark If the allocator is owned, it gets deleted when the destructor is + /// called.. uint8_t *ReleaseRaw(size_t &size, size_t &offset) { Finished(); return buf_.release_raw(size, offset); @@ -1210,8 +1204,9 @@ class FlatBufferBuilder { /// @brief In order to save space, fields that are set to their default value /// don't get serialized into the buffer. - /// @param[in] fd When set to `true`, always serializes default values that are set. - /// Optional fields which are not set explicitly, will still not be serialized. + /// @param[in] fd When set to `true`, always serializes default values that + /// are set. Optional fields which are not set explicitly, will still not be + /// serialized. void ForceDefaults(bool fd) { force_defaults_ = fd; } /// @brief By default vtables are deduped in order to save space. @@ -1835,7 +1830,7 @@ class FlatBufferBuilder { extern T Pack(const S &); typedef T (*Pack_t)(const S &); std::vector vv(len); - std::transform(v, v + len, vv.begin(), static_cast(Pack)); + std::transform(v, v + len, vv.begin(), static_cast(Pack)); return CreateVectorOfSortedStructs(vv, len); } @@ -1916,12 +1911,12 @@ class FlatBufferBuilder { } template - Offset> CreateUninitializedVectorOfStructs(size_t len, T **buf) { + Offset> CreateUninitializedVectorOfStructs(size_t len, + T **buf) { return CreateUninitializedVector(len, sizeof(T), reinterpret_cast(buf)); } - // @brief Create a vector of scalar type T given as input a vector of scalar // type U, useful with e.g. pre "enum class" enums, or any existing scalar // data of the wrong type. @@ -1970,8 +1965,7 @@ class FlatBufferBuilder { buf_.swap_allocator(other.buf_); } -protected: - + protected: // You shouldn't really be copying instances of this class. FlatBufferBuilder(const FlatBufferBuilder &); FlatBufferBuilder &operator=(const FlatBufferBuilder &); @@ -2024,8 +2018,8 @@ protected: bool operator()(const Offset &a, const Offset &b) const { auto stra = reinterpret_cast(buf_->data_at(a.o)); auto strb = reinterpret_cast(buf_->data_at(b.o)); - return StringLessThan(stra->data(), stra->size(), - strb->data(), strb->size()); + return StringLessThan(stra->data(), stra->size(), strb->data(), + strb->size()); } const vector_downward *buf_; }; @@ -2089,13 +2083,15 @@ const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset offset) { /// This function is UNDEFINED for FlatBuffers whose schema does not include /// a file_identifier (likely points at padding or the start of a the root /// vtable). -inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) { +inline const char *GetBufferIdentifier(const void *buf, + bool size_prefixed = false) { return reinterpret_cast(buf) + ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); } // Helper to see if the identifier in a buffer has the expected value. -inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) { +inline bool BufferHasIdentifier(const void *buf, const char *identifier, + bool size_prefixed = false) { return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, FlatBufferBuilder::kFileIdentifierLength) == 0; } @@ -2112,8 +2108,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS { num_tables_(0), max_tables_(_max_tables), upper_bound_(0), - check_alignment_(_check_alignment) - { + check_alignment_(_check_alignment) { FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); } @@ -2162,8 +2157,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS { return Verify(static_cast(base - buf_) + elem_off, elem_len); } - template bool Verify(const uint8_t *base, voffset_t elem_off) - const { + template + bool Verify(const uint8_t *base, voffset_t elem_off) const { return Verify(static_cast(base - buf_) + elem_off, sizeof(T)); } @@ -2186,16 +2181,15 @@ class Verifier FLATBUFFERS_FINAL_CLASS { // Verify a pointer (may be NULL) to string. bool VerifyString(const String *str) const { size_t end; - return !str || - (VerifyVectorOrString(reinterpret_cast(str), - 1, &end) && - Verify(end, 1) && // Must have terminator - Check(buf_[end] == '\0')); // Terminating byte must be 0. + return !str || (VerifyVectorOrString(reinterpret_cast(str), + 1, &end) && + Verify(end, 1) && // Must have terminator + Check(buf_[end] == '\0')); // Terminating byte must be 0. } // Common code between vectors and strings. bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size, - size_t *end = nullptr) const { + size_t *end = nullptr) const { auto veco = static_cast(vec - buf_); // Check we can read the size field. if (!Verify(veco)) return false; @@ -2230,8 +2224,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS { return true; } - __supress_ubsan__("unsigned-integer-overflow") - bool VerifyTableStart(const uint8_t *table) { + __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart( + const uint8_t *table) { // Check the vtable offset. auto tableo = static_cast(table - buf_); if (!Verify(tableo)) return false; @@ -2246,9 +2240,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS { template bool VerifyBufferFromStart(const char *identifier, size_t start) { - if (identifier && - (size_ < 2 * sizeof(flatbuffers::uoffset_t) || - !BufferHasIdentifier(buf_ + start, identifier))) { + if (identifier && (size_ < 2 * sizeof(flatbuffers::uoffset_t) || + !BufferHasIdentifier(buf_ + start, identifier))) { return false; } @@ -2496,8 +2489,8 @@ class Table { uint8_t data_[1]; }; -template void FlatBufferBuilder::Required(Offset table, - voffset_t field) { +template +void FlatBufferBuilder::Required(Offset table, voffset_t field) { auto table_ptr = reinterpret_cast(buf_.data_at(table.o)); bool ok = table_ptr->GetOptionalFieldOffset(field) != 0; // If this fails, the caller will show what field needs to be set. @@ -2544,7 +2537,9 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) { } /// @brief This return the prefixed size of a FlatBuffer. -inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar(buf); } +inline uoffset_t GetPrefixedSize(const uint8_t *buf) { + return ReadScalar(buf); +} // Base class for native objects (FlatBuffer data de-serialized into native // C++ data structures). @@ -2687,10 +2682,10 @@ typedef const TypeTable *(*TypeFunction)(); struct TypeTable { SequenceType st; size_t num_elems; // of type_codes, values, names (but not type_refs). - const TypeCode *type_codes; // num_elems count + const TypeCode *type_codes; // num_elems count const TypeFunction *type_refs; // less than num_elems entries (see TypeCode). const int64_t *values; // Only set for non-consecutive enum/union or structs. - const char * const *names; // Only set if compiled with --reflect-names. + const char *const *names; // Only set if compiled with --reflect-names. }; // String which identifies the current version of FlatBuffers. diff --git a/include/flatbuffers/flatc.h b/include/flatbuffers/flatc.h index f2765d239..5afe3bc9a 100644 --- a/include/flatbuffers/flatc.h +++ b/include/flatbuffers/flatc.h @@ -17,6 +17,7 @@ #include #include #include + #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" diff --git a/include/flatbuffers/flexbuffers.h b/include/flatbuffers/flexbuffers.h index 583c90bba..870bc83a2 100644 --- a/include/flatbuffers/flexbuffers.h +++ b/include/flatbuffers/flexbuffers.h @@ -339,12 +339,12 @@ class Map : public Vector { template void AppendToString(std::string &s, T &&v, bool keys_quoted) { - s += "[ "; - for (size_t i = 0; i < v.size(); i++) { - if (i) s += ", "; - v[i].ToString(true, keys_quoted, s); - } - s += " ]"; + s += "[ "; + for (size_t i = 0; i < v.size(); i++) { + if (i) s += ", "; + v[i].ToString(true, keys_quoted, s); + } + s += " ]"; } class Reference { @@ -386,13 +386,17 @@ class Reference { bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; } bool IsUntypedVector() const { return type_ == FBT_VECTOR; } bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); } - bool IsFixedTypedVector() const { return flexbuffers::IsFixedTypedVector(type_); } - bool IsAnyVector() const { return (IsTypedVector() || IsFixedTypedVector() || IsVector());} + bool IsFixedTypedVector() const { + return flexbuffers::IsFixedTypedVector(type_); + } + bool IsAnyVector() const { + return (IsTypedVector() || IsFixedTypedVector() || IsVector()); + } bool IsMap() const { return type_ == FBT_MAP; } bool IsBlob() const { return type_ == FBT_BLOB; } bool AsBool() const { return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_) - : AsUInt64()) != 0; + : AsUInt64()) != 0; } // Reads any type as a int64_t. Never fails, does most sensible conversion. @@ -555,7 +559,8 @@ class Reference { AppendToString(s, AsFixedTypedVector(), keys_quoted); } else if (IsBlob()) { auto blob = AsBlob(); - flatbuffers::EscapeString(reinterpret_cast(blob.data()), blob.size(), &s, true, false); + flatbuffers::EscapeString(reinterpret_cast(blob.data()), + blob.size(), &s, true, false); } else { s += "(?)"; } @@ -729,9 +734,15 @@ template<> inline int32_t Reference::As() const { return AsInt32(); } template<> inline int64_t Reference::As() const { return AsInt64(); } template<> inline uint8_t Reference::As() const { return AsUInt8(); } -template<> inline uint16_t Reference::As() const { return AsUInt16(); } -template<> inline uint32_t Reference::As() const { return AsUInt32(); } -template<> inline uint64_t Reference::As() const { return AsUInt64(); } +template<> inline uint16_t Reference::As() const { + return AsUInt16(); +} +template<> inline uint32_t Reference::As() const { + return AsUInt32(); +} +template<> inline uint64_t Reference::As() const { + return AsUInt64(); +} template<> inline double Reference::As() const { return AsDouble(); } template<> inline float Reference::As() const { return AsFloat(); } @@ -920,9 +931,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { Bool(b); } - void IndirectInt(int64_t i) { - PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); - } + void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); } void IndirectInt(const char *key, int64_t i) { Key(key); IndirectInt(i); @@ -1214,9 +1223,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { // Works on any data type. struct Value; Value LastValue() { return stack_.back(); } - void ReuseValue(Value v) { - stack_.push_back(v); - } + void ReuseValue(Value v) { stack_.push_back(v); } void ReuseValue(const char *key, Value v) { Key(key); ReuseValue(v); @@ -1462,7 +1469,9 @@ class Builder FLATBUFFERS_FINAL_CLASS { Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed, bool fixed, const Value *keys = nullptr) { - FLATBUFFERS_ASSERT(!fixed || typed); // typed=false, fixed=true combination is not supported. + FLATBUFFERS_ASSERT( + !fixed || + typed); // typed=false, fixed=true combination is not supported. // Figure out smallest bit width we can store this vector with. auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len)); auto prefix_elems = 1; @@ -1542,7 +1551,8 @@ class Builder FLATBUFFERS_FINAL_CLASS { typedef std::pair StringOffset; struct StringOffsetCompare { - explicit StringOffsetCompare(const std::vector &buf) : buf_(&buf) {} + explicit StringOffsetCompare(const std::vector &buf) + : buf_(&buf) {} bool operator()(const StringOffset &a, const StringOffset &b) const { auto stra = reinterpret_cast( flatbuffers::vector_data(*buf_) + a.first); @@ -1562,8 +1572,8 @@ class Builder FLATBUFFERS_FINAL_CLASS { } // namespace flexbuffers -# if defined(_MSC_VER) -# pragma warning(pop) -# endif +#if defined(_MSC_VER) +# pragma warning(pop) +#endif #endif // FLATBUFFERS_FLEXBUFFERS_H_ diff --git a/include/flatbuffers/grpc.h b/include/flatbuffers/grpc.h index 7070aba6a..bd24c501b 100644 --- a/include/flatbuffers/grpc.h +++ b/include/flatbuffers/grpc.h @@ -88,8 +88,7 @@ class SliceAllocator : public Allocator { SliceAllocator(const SliceAllocator &other) = delete; SliceAllocator &operator=(const SliceAllocator &other) = delete; - SliceAllocator(SliceAllocator &&other) - : slice_(grpc_empty_slice()) { + SliceAllocator(SliceAllocator &&other) : slice_(grpc_empty_slice()) { // default-construct and swap idiom swap(other); } @@ -164,34 +163,36 @@ class MessageBuilder : private detail::SliceAllocatorMember, public FlatBufferBuilder { public: explicit MessageBuilder(uoffset_t initial_size = 1024) - : FlatBufferBuilder(initial_size, &slice_allocator_, false) {} + : FlatBufferBuilder(initial_size, &slice_allocator_, false) {} MessageBuilder(const MessageBuilder &other) = delete; MessageBuilder &operator=(const MessageBuilder &other) = delete; MessageBuilder(MessageBuilder &&other) - : FlatBufferBuilder(1024, &slice_allocator_, false) { + : FlatBufferBuilder(1024, &slice_allocator_, false) { // Default construct and swap idiom. Swap(other); } /// Create a MessageBuilder from a FlatBufferBuilder. - explicit MessageBuilder(FlatBufferBuilder &&src, void (*dealloc)(void*, size_t) = &DefaultAllocator::dealloc) - : FlatBufferBuilder(1024, &slice_allocator_, false) { + explicit MessageBuilder(FlatBufferBuilder &&src, + void (*dealloc)(void *, + size_t) = &DefaultAllocator::dealloc) + : FlatBufferBuilder(1024, &slice_allocator_, false) { src.Swap(*this); src.SwapBufAllocator(*this); if (buf_.capacity()) { - uint8_t *buf = buf_.scratch_data(); // pointer to memory - size_t capacity = buf_.capacity(); // size of memory + uint8_t *buf = buf_.scratch_data(); // pointer to memory + size_t capacity = buf_.capacity(); // size of memory slice_allocator_.slice_ = grpc_slice_new_with_len(buf, capacity, dealloc); - } - else { + } else { slice_allocator_.slice_ = grpc_empty_slice(); } } /// Move-assign a FlatBufferBuilder to a MessageBuilder. - /// Only FlatBufferBuilder with default allocator (basically, nullptr) is supported. + /// Only FlatBufferBuilder with default allocator (basically, nullptr) is + /// supported. MessageBuilder &operator=(FlatBufferBuilder &&src) { // Move construct a temporary and swap MessageBuilder temp(std::move(src)); @@ -209,10 +210,11 @@ class MessageBuilder : private detail::SliceAllocatorMember, void Swap(MessageBuilder &other) { slice_allocator_.swap(other.slice_allocator_); FlatBufferBuilder::Swap(other); - // After swapping the FlatBufferBuilder, we swap back the allocator, which restores - // the original allocator back in place. This is necessary because MessageBuilder's - // allocator is its own member (SliceAllocatorMember). The allocator passed to - // FlatBufferBuilder::vector_downward must point to this member. + // After swapping the FlatBufferBuilder, we swap back the allocator, which + // restores the original allocator back in place. This is necessary because + // MessageBuilder's allocator is its own member (SliceAllocatorMember). The + // allocator passed to FlatBufferBuilder::vector_downward must point to this + // member. buf_.swap_allocator(other.buf_); } @@ -232,10 +234,10 @@ class MessageBuilder : private detail::SliceAllocatorMember, // flatbuffers-encoded region and wraps it in a `Message` to handle buffer // ownership. template Message GetMessage() { - auto buf_data = buf_.scratch_data(); // pointer to memory - auto buf_size = buf_.capacity(); // size of memory - auto msg_data = buf_.data(); // pointer to msg - auto msg_size = buf_.size(); // size of msg + auto buf_data = buf_.scratch_data(); // pointer to memory + auto buf_size = buf_.capacity(); // size of memory + auto msg_data = buf_.data(); // pointer to msg + auto msg_size = buf_.size(); // size of msg // Do some sanity checks on data/size FLATBUFFERS_ASSERT(msg_data); FLATBUFFERS_ASSERT(msg_size); diff --git a/include/flatbuffers/hash.h b/include/flatbuffers/hash.h index 16536cb49..aebf0713f 100644 --- a/include/flatbuffers/hash.h +++ b/include/flatbuffers/hash.h @@ -57,17 +57,17 @@ template T HashFnv1a(const char *input) { return hash; } -template <> inline uint16_t HashFnv1(const char *input) { +template<> inline uint16_t HashFnv1(const char *input) { uint32_t hash = HashFnv1(input); return (hash >> 16) ^ (hash & 0xffff); } -template <> inline uint16_t HashFnv1a(const char *input) { +template<> inline uint16_t HashFnv1a(const char *input) { uint32_t hash = HashFnv1a(input); return (hash >> 16) ^ (hash & 0xffff); } -template struct NamedHashFunction { +template struct NamedHashFunction { const char *name; typedef T (*HashFunction)(const char *); @@ -75,7 +75,7 @@ template struct NamedHashFunction { }; const NamedHashFunction kHashFunctions16[] = { - { "fnv1_16", HashFnv1 }, + { "fnv1_16", HashFnv1 }, { "fnv1a_16", HashFnv1a }, }; diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index f7707df24..a4ad4964c 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -338,13 +338,12 @@ struct StructDef : public Definition { flatbuffers::unique_ptr original_location; }; - - struct EnumDef; struct EnumValBuilder; struct EnumVal { - Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; + Offset Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; bool Deserialize(const Parser &parser, const reflection::EnumVal *val); @@ -449,21 +448,21 @@ inline bool IsEnum(const Type &type) { inline size_t InlineSize(const Type &type) { return IsStruct(type) - ? type.struct_def->bytesize - : (IsArray(type) - ? InlineSize(type.VectorType()) * type.fixed_length - : SizeOf(type.base_type)); + ? type.struct_def->bytesize + : (IsArray(type) + ? InlineSize(type.VectorType()) * type.fixed_length + : SizeOf(type.base_type)); } inline size_t InlineAlignment(const Type &type) { - if (IsStruct(type)) { - return type.struct_def->minalign; - } else if (IsArray(type)) { - return IsStruct(type.VectorType()) ? type.struct_def->minalign - : SizeOf(type.element); - } else { - return SizeOf(type.base_type); - } + if (IsStruct(type)) { + return type.struct_def->minalign; + } else if (IsArray(type)) { + return IsStruct(type.VectorType()) ? type.struct_def->minalign + : SizeOf(type.element); + } else { + return SizeOf(type.base_type); + } } inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) { return lhs.value == rhs.value; @@ -480,7 +479,8 @@ inline bool EqualByName(const Type &a, const Type &b) { } struct RPCCall : public Definition { - Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; + Offset Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; bool Deserialize(Parser &parser, const reflection::RPCCall *call); @@ -488,7 +488,8 @@ struct RPCCall : public Definition { }; struct ServiceDef : public Definition { - Offset Serialize(FlatBufferBuilder *builder, const Parser &parser) const; + Offset Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; bool Deserialize(Parser &parser, const reflection::Service *service); SymbolTable calls; @@ -722,9 +723,7 @@ class Parser : public ParserState { source_(nullptr), anonymous_counter(0), recurse_protection_counter(0) { - if (opts.force_defaults) { - builder_.ForceDefaults(true); - } + if (opts.force_defaults) { builder_.ForceDefaults(true); } // Start out with the empty namespace being current. empty_namespace_ = new Namespace(); namespaces_.push_back(empty_namespace_); @@ -795,9 +794,9 @@ class Parser : public ParserState { // Fills internal structure as if the schema passed had been loaded by parsing // with Parse except that included filenames will not be populated. - bool Deserialize(const reflection::Schema* schema); + bool Deserialize(const reflection::Schema *schema); - Type* DeserializeType(const reflection::Type* type); + Type *DeserializeType(const reflection::Type *type); // Checks that the schema represented by this parser is a safe evolution // of the schema provided. Returns non-empty error on any problems. @@ -854,16 +853,19 @@ class Parser : public ParserState { FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue, FieldDef *field, size_t fieldn); FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array); - FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field, - size_t fieldn, - const StructDef *parent_struct_def); + FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer( + Value &val, FieldDef *field, size_t fieldn, + const StructDef *parent_struct_def); FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable *attributes); - FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e, - BaseType req, bool *destmatch); - FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field); + FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, + bool check, Value &e, BaseType req, + bool *destmatch); + FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field); FLATBUFFERS_CHECKED_ERROR TokenError(); - FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now); - FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result); + FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, + bool check_now); + FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, + std::string *result); StructDef *LookupCreateStruct(const std::string &name, bool create_if_new = true, bool definition = false); @@ -871,8 +873,7 @@ class Parser : public ParserState { FLATBUFFERS_CHECKED_ERROR ParseNamespace(); FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name, StructDef **dest); - FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, - bool is_union, + FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union, EnumDef **dest); FLATBUFFERS_CHECKED_ERROR ParseDecl(); FLATBUFFERS_CHECKED_ERROR ParseService(); @@ -888,16 +889,15 @@ class Parser : public ParserState { FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source, const char *source_filename); FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source, - const char **include_paths, - const char *source_filename); + const char **include_paths, + const char *source_filename); FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source, - const char **include_paths, - const char *source_filename, - const char *include_filename); - FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector &fields, + const char **include_paths, + const char *source_filename, + const char *include_filename); + FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector &fields, StructDef *struct_def, - const char *suffix, - BaseType baseType); + const char *suffix, BaseType baseType); bool SupportsAdvancedUnionFeatures() const; bool SupportsAdvancedArrayFeatures() const; @@ -914,7 +914,7 @@ class Parser : public ParserState { std::vector namespaces_; Namespace *current_namespace_; Namespace *empty_namespace_; - std::string error_; // User readable error_ if Parse() == false + std::string error_; // User readable error_ if Parse() == false FlatBufferBuilder builder_; // any data contained in the file flexbuffers::Builder flex_builder_; @@ -957,121 +957,101 @@ extern std::string MakeScreamingCamel(const std::string &in); // strict_json adds "quotes" around field names if true. // If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8 // byte arrays in String values), returns false. -extern bool GenerateTextFromTable(const Parser &parser, - const void *table, +extern bool GenerateTextFromTable(const Parser &parser, const void *table, const std::string &tablename, std::string *text); -extern bool GenerateText(const Parser &parser, - const void *flatbuffer, +extern bool GenerateText(const Parser &parser, const void *flatbuffer, std::string *text); -extern bool GenerateTextFile(const Parser &parser, - const std::string &path, +extern bool GenerateTextFile(const Parser &parser, const std::string &path, const std::string &file_name); // Generate binary files from a given FlatBuffer, and a given Parser // object that has been populated with the corresponding schema. // See idl_gen_general.cpp. -extern bool GenerateBinary(const Parser &parser, - const std::string &path, +extern bool GenerateBinary(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a C++ header from the definitions in the Parser object. // See idl_gen_cpp. -extern bool GenerateCPP(const Parser &parser, - const std::string &path, +extern bool GenerateCPP(const Parser &parser, const std::string &path, const std::string &file_name); -extern bool GenerateDart(const Parser &parser, - const std::string &path, +extern bool GenerateDart(const Parser &parser, const std::string &path, const std::string &file_name); -// Generate JavaScript or TypeScript code from the definitions in the Parser object. -// See idl_gen_js. -extern bool GenerateJSTS(const Parser &parser, - const std::string &path, - const std::string &file_name); +// Generate JavaScript or TypeScript code from the definitions in the Parser +// object. See idl_gen_js. +extern bool GenerateJSTS(const Parser &parser, const std::string &path, + const std::string &file_name); // Generate Go files from the definitions in the Parser object. // See idl_gen_go.cpp. -extern bool GenerateGo(const Parser &parser, - const std::string &path, +extern bool GenerateGo(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Php code from the definitions in the Parser object. // See idl_gen_php. -extern bool GeneratePhp(const Parser &parser, - const std::string &path, +extern bool GeneratePhp(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Python files from the definitions in the Parser object. // See idl_gen_python.cpp. -extern bool GeneratePython(const Parser &parser, - const std::string &path, +extern bool GeneratePython(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Lobster files from the definitions in the Parser object. // See idl_gen_lobster.cpp. -extern bool GenerateLobster(const Parser &parser, - const std::string &path, +extern bool GenerateLobster(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Lua files from the definitions in the Parser object. // See idl_gen_lua.cpp. -extern bool GenerateLua(const Parser &parser, - const std::string &path, - const std::string &file_name); +extern bool GenerateLua(const Parser &parser, const std::string &path, + const std::string &file_name); // Generate Rust files from the definitions in the Parser object. // See idl_gen_rust.cpp. -extern bool GenerateRust(const Parser &parser, - const std::string &path, +extern bool GenerateRust(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Json schema file // See idl_gen_json_schema.cpp. -extern bool GenerateJsonSchema(const Parser &parser, - const std::string &path, - const std::string &file_name); +extern bool GenerateJsonSchema(const Parser &parser, const std::string &path, + const std::string &file_name); extern bool GenerateKotlin(const Parser &parser, const std::string &path, const std::string &file_name); // Generate Java/C#/.. files from the definitions in the Parser object. // See idl_gen_general.cpp. -extern bool GenerateGeneral(const Parser &parser, - const std::string &path, +extern bool GenerateGeneral(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a schema file from the internal representation, useful after // parsing a .proto schema. extern std::string GenerateFBS(const Parser &parser, const std::string &file_name); -extern bool GenerateFBS(const Parser &parser, - const std::string &path, +extern bool GenerateFBS(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated JavaScript or TypeScript code. // See idl_gen_js.cpp. -extern std::string JSTSMakeRule(const Parser &parser, - const std::string &path, - const std::string &file_name); +extern std::string JSTSMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name); // Generate a make rule for the generated C++ header. // See idl_gen_cpp.cpp. -extern std::string CPPMakeRule(const Parser &parser, - const std::string &path, +extern std::string CPPMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated Dart code // see idl_gen_dart.cpp -extern std::string DartMakeRule(const Parser &parser, - const std::string &path, +extern std::string DartMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated Rust code. // See idl_gen_rust.cpp. -extern std::string RustMakeRule(const Parser &parser, - const std::string &path, +extern std::string RustMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate a make rule for the generated Java/C#/... files. @@ -1082,32 +1062,27 @@ extern std::string GeneralMakeRule(const Parser &parser, // Generate a make rule for the generated text (JSON) files. // See idl_gen_text.cpp. -extern std::string TextMakeRule(const Parser &parser, - const std::string &path, +extern std::string TextMakeRule(const Parser &parser, const std::string &path, const std::string &file_names); // Generate a make rule for the generated binary files. // See idl_gen_general.cpp. -extern std::string BinaryMakeRule(const Parser &parser, - const std::string &path, +extern std::string BinaryMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Cpp interfaces. // See idl_gen_grpc.cpp. -bool GenerateCppGRPC(const Parser &parser, - const std::string &path, +bool GenerateCppGRPC(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Go interfaces. // See idl_gen_grpc.cpp. -bool GenerateGoGRPC(const Parser &parser, - const std::string &path, +bool GenerateGoGRPC(const Parser &parser, const std::string &path, const std::string &file_name); // Generate GRPC Java classes. // See idl_gen_grpc.cpp -bool GenerateJavaGRPC(const Parser &parser, - const std::string &path, +bool GenerateJavaGRPC(const Parser &parser, const std::string &path, const std::string &file_name); } // namespace flatbuffers diff --git a/include/flatbuffers/minireflect.h b/include/flatbuffers/minireflect.h index 9d648ec08..67a79a93e 100644 --- a/include/flatbuffers/minireflect.h +++ b/include/flatbuffers/minireflect.h @@ -88,7 +88,8 @@ inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) { switch (type_table->st) { case ST_TABLE: case ST_UNION: return 4; - case ST_STRUCT: return static_cast(type_table->values[type_table->num_elems]); + case ST_STRUCT: + return static_cast(type_table->values[type_table->num_elems]); default: FLATBUFFERS_ASSERT(false); return 1; } default: FLATBUFFERS_ASSERT(false); return 1; diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h index 072fe9e10..d10d2f17f 100644 --- a/include/flatbuffers/util.h +++ b/include/flatbuffers/util.h @@ -17,10 +17,10 @@ #ifndef FLATBUFFERS_UTIL_H_ #define FLATBUFFERS_UTIL_H_ -#include "flatbuffers/base.h" - #include +#include "flatbuffers/base.h" + #ifndef FLATBUFFERS_PREFER_PRINTF # include #else // FLATBUFFERS_PREFER_PRINTF diff --git a/src/code_generators.cpp b/src/code_generators.cpp index 52ca3056c..a46c4b73d 100644 --- a/src/code_generators.cpp +++ b/src/code_generators.cpp @@ -15,12 +15,14 @@ */ #include "flatbuffers/code_generators.h" + #include -#include "flatbuffers/base.h" -#include "flatbuffers/util.h" #include +#include "flatbuffers/base.h" +#include "flatbuffers/util.h" + #if defined(_MSC_VER) # pragma warning(push) # pragma warning(disable : 4127) // C4127: conditional expression is constant diff --git a/src/flatc.cpp b/src/flatc.cpp index ab2b1faf5..74f2e2381 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -42,7 +42,7 @@ void FlatCompiler::LoadBinarySchema(flatbuffers::Parser &parser, const std::string &filename, const std::string &contents) { if (!parser.Deserialize(reinterpret_cast(contents.c_str()), - contents.size())) { + contents.size())) { Error("failed to load binary schema: " + filename, false, false); } } @@ -402,7 +402,8 @@ int FlatCompiler::Compile(int argc, const char **argv) { "\" matches the schema, use --raw-binary to read this file" " anyway."); } else if (!flatbuffers::BufferHasIdentifier( - contents.c_str(), parser->file_identifier_.c_str(), opts.size_prefixed)) { + contents.c_str(), parser->file_identifier_.c_str(), + opts.size_prefixed)) { Error("binary \"" + filename + "\" does not have expected file_identifier \"" + parser->file_identifier_ + diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index 72bb4a2f0..352c31454 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -61,13 +61,15 @@ int main(int argc, const char *argv[]) { flatbuffers::GeneralMakeRule }, { flatbuffers::GenerateJSTS, "-s", "--js", "JavaScript", true, nullptr, flatbuffers::IDLOptions::kJs, - "Generate JavaScript code for tables/structs", flatbuffers::JSTSMakeRule }, + "Generate JavaScript code for tables/structs", + flatbuffers::JSTSMakeRule }, { flatbuffers::GenerateDart, "-d", "--dart", "Dart", true, nullptr, flatbuffers::IDLOptions::kDart, "Generate Dart classes for tables/structs", flatbuffers::DartMakeRule }, { flatbuffers::GenerateJSTS, "-T", "--ts", "TypeScript", true, nullptr, flatbuffers::IDLOptions::kTs, - "Generate TypeScript code for tables/structs", flatbuffers::JSTSMakeRule }, + "Generate TypeScript code for tables/structs", + flatbuffers::JSTSMakeRule }, { flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", true, nullptr, flatbuffers::IDLOptions::kCSharp, "Generate C# classes for tables/structs", flatbuffers::GeneralMakeRule }, @@ -75,23 +77,22 @@ int main(int argc, const char *argv[]) { flatbuffers::IDLOptions::kPython, "Generate Python files for tables/structs", flatbuffers::GeneralMakeRule }, - { flatbuffers::GenerateLobster, nullptr, "--lobster", "Lobster", true, nullptr, - flatbuffers::IDLOptions::kLobster, + { flatbuffers::GenerateLobster, nullptr, "--lobster", "Lobster", true, + nullptr, flatbuffers::IDLOptions::kLobster, "Generate Lobster files for tables/structs", flatbuffers::GeneralMakeRule }, { flatbuffers::GenerateLua, "-l", "--lua", "Lua", true, nullptr, - flatbuffers::IDLOptions::kLua, - "Generate Lua files for tables/structs", + flatbuffers::IDLOptions::kLua, "Generate Lua files for tables/structs", flatbuffers::GeneralMakeRule }, { flatbuffers::GenerateRust, "-r", "--rust", "Rust", true, nullptr, - flatbuffers::IDLOptions::kRust, - "Generate Rust files for tables/structs", + flatbuffers::IDLOptions::kRust, "Generate Rust files for tables/structs", flatbuffers::RustMakeRule }, { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true, nullptr, flatbuffers::IDLOptions::kPhp, "Generate PHP files for tables/structs", flatbuffers::GeneralMakeRule }, { flatbuffers::GenerateKotlin, nullptr, "--kotlin", "Kotlin", true, nullptr, - flatbuffers::IDLOptions::kKotlin, "Generate Kotlin classes for tables/structs", + flatbuffers::IDLOptions::kKotlin, + "Generate Kotlin classes for tables/structs", flatbuffers::GeneralMakeRule }, { flatbuffers::GenerateJsonSchema, nullptr, "--jsonschema", "JsonSchema", true, nullptr, flatbuffers::IDLOptions::kJsonSchema, diff --git a/src/flathash.cpp b/src/flathash.cpp index bc3d2df29..1264f821c 100644 --- a/src/flathash.cpp +++ b/src/flathash.cpp @@ -15,9 +15,11 @@ */ #include + #include #include #include + #include "flatbuffers/hash.h" enum OutputFormat { kDecimal, kHexadecimal, kHexadecimal0x }; @@ -35,7 +37,7 @@ int main(int argc, char *argv[]) { } printf(" 32 bit:\n"); size = sizeof(flatbuffers::kHashFunctions32) / - sizeof(flatbuffers::kHashFunctions32[0]); + sizeof(flatbuffers::kHashFunctions32[0]); for (size_t i = 0; i < size; ++i) { printf(" * %s\n", flatbuffers::kHashFunctions32[i].name); } diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index d7b3abb5f..706732b0f 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -16,13 +16,13 @@ // independent from idl_parser, since this code is not needed for most clients +#include + #include "flatbuffers/code_generators.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include - namespace flatbuffers { // Pedantic warning free version of toupper(). @@ -208,9 +208,7 @@ class CppGenerator : public BaseGenerator { for (std::size_t i = 0; i < parser_.opts.cpp_includes.size(); ++i) { code_ += "#include \"" + parser_.opts.cpp_includes[i] + "\""; } - if (!parser_.opts.cpp_includes.empty()) { - code_ += ""; - } + if (!parser_.opts.cpp_includes.empty()) { code_ += ""; } } std::string EscapeKeyword(const std::string &name) const { @@ -577,7 +575,9 @@ class CppGenerator : public BaseGenerator { } case BASE_TYPE_UNION: // fall through - default: { return "void"; } + default: { + return "void"; + } } } @@ -696,7 +696,9 @@ class CppGenerator : public BaseGenerator { case BASE_TYPE_UNION: { return type.enum_def->name + "Union"; } - default: { return GenTypeBasic(type, true); } + default: { + return GenTypeBasic(type, true); + } } } @@ -1163,7 +1165,8 @@ class CppGenerator : public BaseGenerator { code_ += " void Set(T&& val) {"; code_ += " using RT = typename std::remove_reference::type;"; code_ += " Reset();"; - code_ += " type = {{NAME}}Traits::enum_value;"; + code_ += + " type = {{NAME}}Traits::enum_value;"; code_ += " if (type != {{NONE}}) {"; code_ += " value = new RT(std::forward(val));"; code_ += " }"; @@ -1276,7 +1279,8 @@ class CppGenerator : public BaseGenerator { " auto ptr = reinterpret_cast(obj);"; if (ev.union_type.base_type == BASE_TYPE_STRUCT) { if (ev.union_type.struct_def->fixed) { - code_ += " return verifier.Verify<{{TYPE}}>(static_cast(static_cast(obj), 0);"; } else { code_ += getptr; @@ -1295,7 +1299,7 @@ class CppGenerator : public BaseGenerator { code_ += " }"; } } - code_ += " default: return true;"; // unknown values are OK. + code_ += " default: return true;"; // unknown values are OK. code_ += " }"; code_ += "}"; code_ += ""; @@ -1763,7 +1767,9 @@ class CppGenerator : public BaseGenerator { } break; } - default: { break; } + default: { + break; + } } } @@ -1925,7 +1931,8 @@ class CppGenerator : public BaseGenerator { } } - if (parser_.opts.mutable_buffer && !(is_scalar && IsUnion(field.value.type))) { + if (parser_.opts.mutable_buffer && + !(is_scalar && IsUnion(field.value.type))) { if (is_scalar) { const auto type = GenTypeWire(field.value.type, "", false); code_.SetValue("SET_FN", "SetField<" + type + ">"); @@ -2901,8 +2908,8 @@ class CppGenerator : public BaseGenerator { } else if (IsArray(field.value.type)) { auto underlying = GenTypeGet(field.value.type, "", "", "", false); code_ += " flatbuffers::Array<" + mut_field_type + ", " + - NumToString(field.value.type.fixed_length) + - "> *" + "mutable_{{FIELD_NAME}}() {"; + NumToString(field.value.type.fixed_length) + "> *" + + "mutable_{{FIELD_NAME}}() {"; code_ += " return reinterpret_castfirst.empty()) { - code += "library " + kv->first + ";\n\n"; - } + if (!kv->first.empty()) { code += "library " + kv->first + ";\n\n"; } code += "import 'dart:typed_data' show Uint8List;\n"; code += "import 'package:flat_buffers/flat_buffers.dart' as " + _kFb + @@ -87,16 +85,20 @@ class DartGenerator : public BaseGenerator { ++kv2) { if (kv2->first != kv->first) { code += "import '" + - GeneratedFileName("./", file_name_ + (!kv2->first.empty() ? "_" + kv2->first : "")) + + GeneratedFileName( + "./", file_name_ + + (!kv2->first.empty() ? "_" + kv2->first : "")) + "' as " + ImportAliasName(kv2->first) + ";\n"; } } code += "\n"; code += kv->second; - if (!SaveFile( - GeneratedFileName(path_, file_name_ + (!kv->first.empty() ? "_" + kv->first : "")).c_str(), - code, false)) { + if (!SaveFile(GeneratedFileName( + path_, file_name_ + + (!kv->first.empty() ? "_" + kv->first : "")) + .c_str(), + code, false)) { return false; } } @@ -117,9 +119,7 @@ class DartGenerator : public BaseGenerator { } static std::string BuildNamespaceName(const Namespace &ns) { - if (ns.components.empty()) { - return ""; - } + if (ns.components.empty()) { return ""; } std::stringstream sstream; std::copy(ns.components.begin(), ns.components.end() - 1, std::ostream_iterator(sstream, ".")); @@ -139,7 +139,8 @@ class DartGenerator : public BaseGenerator { return ret; } - void GenIncludeDependencies(std::string* code, const std::string& the_namespace) { + void GenIncludeDependencies(std::string *code, + const std::string &the_namespace) { for (auto it = parser_.included_files_.begin(); it != parser_.included_files_.end(); ++it) { if (it->second.empty()) continue; @@ -147,7 +148,11 @@ class DartGenerator : public BaseGenerator { auto noext = flatbuffers::StripExtension(it->second); auto basename = flatbuffers::StripPath(noext); - *code += "import '" + GeneratedFileName("", basename + (the_namespace == "" ? "" : "_" + the_namespace)) + "';\n"; + *code += + "import '" + + GeneratedFileName( + "", basename + (the_namespace == "" ? "" : "_" + the_namespace)) + + "';\n"; } } @@ -798,7 +803,8 @@ class DartGenerator : public BaseGenerator { } code += "\n : null;\n"; } else if (field.value.type.base_type == BASE_TYPE_STRING) { - code += " = fbBuilder.writeString(_" + MakeCamel(field.name, false) + ");\n"; + code += " = fbBuilder.writeString(_" + MakeCamel(field.name, false) + + ");\n"; } else { code += " = _" + MakeCamel(field.name, false) + "?.getOrCreateOffset(fbBuilder);\n"; diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index bb2920f5d..48ec2b73e 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -69,75 +69,71 @@ const LanguageParameters &GetLangParams(IDLOptions::Language lang) { "Double.", "Float.", "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY"); static const 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.*;\nimport com.google.flatbuffers.*;\n", - "\n@SuppressWarnings(\"unused\")\n", - "\n@javax.annotation.Generated(value=\"flatc\")\n", - { - "/**", - " *", - " */", - }, - &JavaFloatGen - }, - { - IDLOptions::kCSharp, - true, - ".cs", - "string", - "bool ", - "\n{\n", - "struct ", - " readonly ", - "", - "enum ", - ",\n", - " { get", - "} ", - " : ", - "namespace ", - "\n{", - "\n}\n", - "", - "Position", - "Offset", - "__p.", - "Table.", - "?", - "using global::System;\nusing global::FlatBuffers;\n\n", - "", - "", - { - nullptr, - "///", - nullptr, - }, - &CSharpFloatGen - }, + { 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.*;\nimport com.google.flatbuffers.*;\n", + "\n@SuppressWarnings(\"unused\")\n", + "\n@javax.annotation.Generated(value=\"flatc\")\n", + { + "/**", + " *", + " */", + }, + &JavaFloatGen }, + { IDLOptions::kCSharp, + true, + ".cs", + "string", + "bool ", + "\n{\n", + "struct ", + " readonly ", + "", + "enum ", + ",\n", + " { get", + "} ", + " : ", + "namespace ", + "\n{", + "\n}\n", + "", + "Position", + "Offset", + "__p.", + "Table.", + "?", + "using global::System;\nusing global::FlatBuffers;\n\n", + "", + "", + { + nullptr, + "///", + nullptr, + }, + &CSharpFloatGen }, }; if (lang == IDLOptions::kJava) { @@ -233,9 +229,7 @@ class GeneralGenerator : public BaseGenerator { } code += lang_.class_annotation; } - if (parser_.opts.gen_generated) { - code += lang_.generated_type_annotation; - } + if (parser_.opts.gen_generated) { code += lang_.generated_type_annotation; } code += classcode; if (!namespace_name.empty()) code += lang_.namespace_end; auto filename = NamespaceDir(ns) + defname + lang_.file_extension; @@ -339,7 +333,7 @@ class GeneralGenerator : public BaseGenerator { case BASE_TYPE_ARRAY: case BASE_TYPE_VECTOR: if (vectorelem) return DestinationType(type.VectorType(), vectorelem); - FLATBUFFERS_FALLTHROUGH(); // else fall thru + FLATBUFFERS_FALLTHROUGH(); // else fall thru default: return type; } } @@ -383,7 +377,7 @@ class GeneralGenerator : public BaseGenerator { case BASE_TYPE_UINT: return " & 0xFFFFFFFFL"; case BASE_TYPE_VECTOR: if (vectorelem) return DestinationMask(type.VectorType(), vectorelem); - FLATBUFFERS_FALLTHROUGH(); // else fall thru + FLATBUFFERS_FALLTHROUGH(); // else fall thru default: return ""; } } @@ -440,7 +434,9 @@ class GeneralGenerator : public BaseGenerator { return ""; } - std::string SourceCast(const Type &type) const { return SourceCast(type, true); } + std::string SourceCast(const Type &type) const { + return SourceCast(type, true); + } std::string SourceCastBasic(const Type &type, bool castFromDest) const { return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : ""; @@ -459,8 +455,9 @@ class GeneralGenerator : public BaseGenerator { : value.constant; } - std::string GenDefaultValue(const FieldDef &field, bool enableLangOverrides) const { - auto& value = field.value; + std::string GenDefaultValue(const FieldDef &field, + bool enableLangOverrides) const { + auto &value = field.value; if (enableLangOverrides) { // handles both enum case and vector of enum case if (lang_.language == IDLOptions::kCSharp && @@ -482,7 +479,7 @@ class GeneralGenerator : public BaseGenerator { case BASE_TYPE_UINT: case BASE_TYPE_LONG: return value.constant + longSuffix; default: - if(IsFloat(value.type.base_type)) + if (IsFloat(value.type.base_type)) return lang_.float_gen->GenFloatConstant(field); else return value.constant; @@ -495,7 +492,7 @@ class GeneralGenerator : public BaseGenerator { std::string GenDefaultValueBasic(const FieldDef &field, bool enableLangOverrides) const { - auto& value = field.value; + auto &value = field.value; if (!IsScalar(value.type.base_type)) { if (enableLangOverrides) { if (lang_.language == IDLOptions::kCSharp) { @@ -530,15 +527,14 @@ class GeneralGenerator : public BaseGenerator { GenComment(enum_def.doc_comment, code_ptr, &lang_.comment_config); // In C# this indicates enumeration values can be treated as bit flags. - if (lang_.language == IDLOptions::kCSharp && enum_def.attributes.Lookup("bit_flags")) { + if (lang_.language == IDLOptions::kCSharp && + enum_def.attributes.Lookup("bit_flags")) { code += "[System.FlagsAttribute]\n"; } if (enum_def.attributes.Lookup("private")) { // For Java, we leave the enum unmarked to indicate package-private // For C# we mark the enum as internal - if (lang_.language == IDLOptions::kCSharp) { - code += "internal "; - } + if (lang_.language == IDLOptions::kCSharp) { code += "internal "; } } else { code += "public "; } @@ -870,9 +866,7 @@ class GeneralGenerator : public BaseGenerator { if (struct_def.attributes.Lookup("private")) { // For Java, we leave the struct unmarked to indicate package-private // For C# we mark the struct as internal - if (lang_.language == IDLOptions::kCSharp) { - code += "internal "; - } + if (lang_.language == IDLOptions::kCSharp) { code += "internal "; } } else { code += "public "; } @@ -1016,8 +1010,8 @@ class GeneralGenerator : public BaseGenerator { code += "(new " + type_name + "(), j); }\n"; } } else if (field.value.type.base_type == BASE_TYPE_UNION || - (field.value.type.base_type == BASE_TYPE_VECTOR && - field.value.type.VectorType().base_type == BASE_TYPE_UNION)) { + (field.value.type.base_type == BASE_TYPE_VECTOR && + field.value.type.VectorType().base_type == BASE_TYPE_UNION)) { if (lang_.language == IDLOptions::kCSharp) { // Union types in C# use generic Table-derived type for better type // safety. @@ -1092,8 +1086,8 @@ class GeneralGenerator : public BaseGenerator { auto vectortype = field.value.type.VectorType(); if (vectortype.base_type == BASE_TYPE_UNION && lang_.language == IDLOptions::kCSharp) { - conditional_cast = "(TTable?)"; - getter += ""; + conditional_cast = "(TTable?)"; + getter += ""; } code += "("; if (vectortype.base_type == BASE_TYPE_STRUCT) { @@ -1145,7 +1139,8 @@ class GeneralGenerator : public BaseGenerator { if (lang_.language == IDLOptions::kCSharp) { code += "() where TTable : struct, IFlatbufferObject"; code += offset_prefix + "(TTable?)" + getter; - code += "(o + " + lang_.accessor_prefix + "bb_pos) : null"; + code += + "(o + " + lang_.accessor_prefix + "bb_pos) : null"; } else { code += "(" + type_name + " obj)" + offset_prefix + getter; code += "(obj, o + " + lang_.accessor_prefix + "bb_pos) : null"; @@ -1174,19 +1169,21 @@ class GeneralGenerator : public BaseGenerator { auto &key_field = **kit; if (key_field.key) { auto qualified_name = WrapInNameSpace(sd); - code += " public " + qualified_name + lang_.optional_suffix + " "; + code += + " public " + qualified_name + lang_.optional_suffix + " "; code += MakeCamel(field.name, lang_.first_camel_upper) + "ByKey("; code += GenTypeNameDest(key_field.value.type) + " key)"; code += offset_prefix; code += qualified_name + ".__lookup_by_key("; - if (lang_.language == IDLOptions::kJava) - code += "null, "; + if (lang_.language == IDLOptions::kJava) code += "null, "; code += lang_.accessor_prefix + "__vector(o), key, "; code += lang_.accessor_prefix + "bb) : null; "; code += "}\n"; if (lang_.language == IDLOptions::kJava) { - code += " public " + qualified_name + lang_.optional_suffix + " "; - code += MakeCamel(field.name, lang_.first_camel_upper) + "ByKey("; + code += + " public " + qualified_name + lang_.optional_suffix + " "; + code += + MakeCamel(field.name, lang_.first_camel_upper) + "ByKey("; code += qualified_name + lang_.optional_suffix + " obj, "; code += GenTypeNameDest(key_field.value.type) + " key)"; code += offset_prefix; @@ -1259,12 +1256,15 @@ class GeneralGenerator : public BaseGenerator { break; case IDLOptions::kCSharp: code += "#if ENABLE_SPAN_T\n"; - code += " public Span<" + GenTypeBasic(field.value.type.VectorType()) + "> Get"; + code += " public Span<" + + GenTypeBasic(field.value.type.VectorType()) + "> Get"; code += MakeCamel(field.name, lang_.first_camel_upper); code += "Bytes() { return "; - code += lang_.accessor_prefix + "__vector_as_span<"+ GenTypeBasic(field.value.type.VectorType()) +">("; + code += lang_.accessor_prefix + "__vector_as_span<" + + GenTypeBasic(field.value.type.VectorType()) + ">("; code += NumToString(field.value.offset); - code += ", " + NumToString(SizeOf(field.value.type.VectorType().base_type)); + code += ", " + NumToString( + SizeOf(field.value.type.VectorType().base_type)); code += "); }\n"; code += "#else\n"; code += " public ArraySegment? Get"; @@ -1596,10 +1596,10 @@ class GeneralGenerator : public BaseGenerator { std::string size_prefix[] = { "", "SizePrefixed" }; for (int i = 0; i < 2; ++i) { code += " public static void "; - code += FunctionStart('F') + "inish" + size_prefix[i] + - struct_def.name; - code += "Buffer(FlatBufferBuilder builder, " + - GenOffsetType(struct_def); + code += + FunctionStart('F') + "inish" + size_prefix[i] + struct_def.name; + code += + "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def); code += " offset) {"; code += " builder." + FunctionStart('F') + "inish" + size_prefix[i] + "(offset"; @@ -1636,7 +1636,7 @@ class GeneralGenerator : public BaseGenerator { code += "\n public static " + struct_def.name + lang_.optional_suffix; code += " __lookup_by_key("; if (lang_.language == IDLOptions::kJava) - code += struct_def.name + " obj, "; + code += struct_def.name + " obj, "; code += "int vectorLocation, "; code += GenTypeNameDest(key_field->value.type); code += " key, ByteBuffer bb) {\n"; @@ -1684,8 +1684,7 @@ class GeneralGenerator : public BaseGenerator { // Generate a vector of structs accessor class. code += "\n"; code += " "; - if (!struct_def.attributes.Lookup("private")) - code += "public "; + if (!struct_def.attributes.Lookup("private")) code += "public "; code += "static "; code += lang_.unsubclassable_decl; code += lang_.accessor_type + "Vector" + lang_.inheritance_marker; diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index aa25751da..4ed1a80b2 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -43,7 +43,7 @@ static std::string GeneratedFileName(const std::string &path, namespace go { // see https://golang.org/ref/spec#Keywords -static const char * const g_golang_keywords[] = { +static const char *const g_golang_keywords[] = { "break", "default", "func", "interface", "select", "case", "defer", "go", "map", "struct", "chan", "else", "goto", "package", "switch", "const", "fallthrough", "if", "range", "type", "continue", @@ -151,7 +151,8 @@ class GoGenerator : public BaseGenerator { // Construct the name of the type for this enum. std::string GetEnumTypeName(const EnumDef &enum_def) { - return WrapInNameSpaceAndTrack(enum_def.defined_namespace, GoIdentity(enum_def.name)); + return WrapInNameSpaceAndTrack(enum_def.defined_namespace, + GoIdentity(enum_def.name)); } // Create a type for the enum values. @@ -222,7 +223,7 @@ class GoGenerator : public BaseGenerator { code += "\tif s, ok := EnumNames" + enum_def.name + "[v]; ok {\n"; code += "\t\treturn s\n"; code += "\t}\n"; - code += "\treturn \""+ enum_def.name; + code += "\treturn \"" + enum_def.name; code += "(\" + strconv.FormatInt(int64(v), 10) + \")\"\n"; code += "}\n\n"; } @@ -325,23 +326,21 @@ class GoGenerator : public BaseGenerator { // Get the value of a struct's scalar. void GetScalarFieldOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; std::string getter = GenGetter(field.value.type); GenReceiver(struct_def, code_ptr); code += " " + MakeCamel(field.name); code += "() " + TypeName(field) + " {\n"; - code += "\treturn " + CastToEnum( - field.value.type, - getter + "(rcv._tab.Pos + flatbuffers.UOffsetT(" + - NumToString(field.value.offset) + "))"); + code += "\treturn " + + CastToEnum(field.value.type, + getter + "(rcv._tab.Pos + flatbuffers.UOffsetT(" + + NumToString(field.value.offset) + "))"); code += "\n}\n"; } // Get the value of a table's scalar. - void GetScalarFieldOfTable(const StructDef &struct_def, - const FieldDef &field, + void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; std::string getter = GenGetter(field.value.type); @@ -358,8 +357,7 @@ class GoGenerator : public BaseGenerator { // Get a struct by initializing an existing struct. // Specific to Struct. void GetStructFieldOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; GenReceiver(struct_def, code_ptr); code += " " + MakeCamel(field.name); @@ -377,8 +375,7 @@ class GoGenerator : public BaseGenerator { // Get a struct by initializing an existing struct. // Specific to Table. - void GetStructFieldOfTable(const StructDef &struct_def, - const FieldDef &field, + void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; GenReceiver(struct_def, code_ptr); @@ -400,8 +397,7 @@ class GoGenerator : public BaseGenerator { } // Get the value of a string. - void GetStringField(const StructDef &struct_def, - const FieldDef &field, + void GetStringField(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; GenReceiver(struct_def, code_ptr); @@ -428,8 +424,7 @@ class GoGenerator : public BaseGenerator { // Get the value of a vector's struct member. void GetMemberOfVectorOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; auto vectortype = field.value.type.VectorType(); @@ -461,10 +456,11 @@ class GoGenerator : public BaseGenerator { code += "(j int) " + TypeName(field) + " "; code += OffsetPrefix(field); code += "\t\ta := rcv._tab.Vector(o)\n"; - code += "\t\treturn " + CastToEnum( - field.value.type, - GenGetter(field.value.type) + "(a + flatbuffers.UOffsetT(j*" + - NumToString(InlineSize(vectortype)) + "))"); + code += "\t\treturn " + + CastToEnum(field.value.type, + GenGetter(field.value.type) + + "(a + flatbuffers.UOffsetT(j*" + + NumToString(InlineSize(vectortype)) + "))"); code += "\n\t}\n"; if (vectortype.base_type == BASE_TYPE_STRING) { code += "\treturn nil\n"; @@ -518,8 +514,8 @@ class GoGenerator : public BaseGenerator { // Recursively generate struct construction statements and instert manual // padding. - void StructBuilderBody(const StructDef &struct_def, - const char *nameprefix, std::string *code_ptr) { + void StructBuilderBody(const StructDef &struct_def, const char *nameprefix, + std::string *code_ptr) { std::string &code = *code_ptr; code += "\tbuilder.Prep(" + NumToString(struct_def.minalign) + ", "; code += NumToString(struct_def.bytesize) + ")\n"; @@ -533,7 +529,9 @@ class GoGenerator : public BaseGenerator { (nameprefix + (field.name + "_")).c_str(), code_ptr); } else { code += "\tbuilder.Prepend" + GenMethod(field) + "("; - code += CastToBaseType(field.value.type, nameprefix + GoIdentity(field.name)) + ")\n"; + code += CastToBaseType(field.value.type, + nameprefix + GoIdentity(field.name)) + + ")\n"; } } } @@ -582,8 +580,8 @@ class GoGenerator : public BaseGenerator { } // Set the value of one of the members of a table's vector. - void BuildVectorOfTable(const StructDef &struct_def, - const FieldDef &field, std::string *code_ptr) { + void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { std::string &code = *code_ptr; code += "func " + struct_def.name + "Start"; code += MakeCamel(field.name); @@ -612,8 +610,8 @@ class GoGenerator : public BaseGenerator { } // Generate a struct field getter, conditioned on its child type(s). - void GenStructAccessor(const StructDef &struct_def, - const FieldDef &field, std::string *code_ptr) { + void GenStructAccessor(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { GenComment(field.doc_comment, code_ptr, nullptr, ""); if (IsScalar(field.value.type.base_type)) { if (struct_def.fixed) { @@ -630,7 +628,9 @@ class GoGenerator : public BaseGenerator { GetStructFieldOfTable(struct_def, field, code_ptr); } break; - case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break; + case BASE_TYPE_STRING: + GetStringField(struct_def, field, code_ptr); + break; case BASE_TYPE_VECTOR: { auto vectortype = field.value.type.VectorType(); if (vectortype.base_type == BASE_TYPE_STRUCT) { @@ -652,10 +652,9 @@ class GoGenerator : public BaseGenerator { } } - // Mutate the value of a struct's scalar. + // Mutate the value of a struct's scalar. void MutateScalarFieldOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; std::string type = MakeCamel(GenTypeBasic(field.value.type)); std::string setter = "rcv._tab.Mutate" + type; @@ -669,8 +668,7 @@ class GoGenerator : public BaseGenerator { // Mutate the value of a table's scalar. void MutateScalarFieldOfTable(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; std::string type = MakeCamel(GenTypeBasic(field.value.type)); std::string setter = "rcv._tab.Mutate" + type + "Slot"; @@ -916,9 +914,9 @@ class GoGenerator : public BaseGenerator { if (IsScalar(field.value.type.element)) { code += "\t\t\tbuilder.Prepend" + MakeCamel(GenTypeBasic(field.value.type.VectorType())) + "(" + - CastToBaseType( - field.value.type.VectorType(), - "t." + MakeCamel(field.name) + "[j]") + ")\n"; + CastToBaseType(field.value.type.VectorType(), + "t." + MakeCamel(field.name) + "[j]") + + ")\n"; } else if (field.value.type.element == BASE_TYPE_STRUCT && field.value.type.struct_def->fixed) { code += "\t\t\t" + @@ -979,8 +977,8 @@ class GoGenerator : public BaseGenerator { code += "}\n\n"; } - void GenNativeTableUnPack( - const StructDef &struct_def, std::string *code_ptr) { + void GenNativeTableUnPack(const StructDef &struct_def, + std::string *code_ptr) { std::string &code = *code_ptr; code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" + @@ -995,8 +993,8 @@ class GoGenerator : public BaseGenerator { if (field.value.type.enum_def != nullptr && field.value.type.enum_def->is_union) continue; - code += "\tt." + field_name_camel + " = rcv." + field_name_camel + - "()\n"; + code += + "\tt." + field_name_camel + " = rcv." + field_name_camel + "()\n"; } else if (field.value.type.base_type == BASE_TYPE_STRING) { code += "\tt." + field_name_camel + " = string(rcv." + field_name_camel + "())\n"; @@ -1084,8 +1082,8 @@ class GoGenerator : public BaseGenerator { } } - void GenNativeStructUnPack( - const StructDef &struct_def, std::string *code_ptr) { + void GenNativeStructUnPack(const StructDef &struct_def, + std::string *code_ptr) { std::string &code = *code_ptr; code += "func (rcv *" + struct_def.name + ") UnPackTo(t *" + @@ -1137,8 +1135,7 @@ class GoGenerator : public BaseGenerator { EndEnumNames(code_ptr); BeginEnumValues(enum_def, code_ptr); - for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); - ++it) { + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { auto &ev = **it; EnumValueMember(enum_def, ev, max_name_length, code_ptr); } @@ -1189,9 +1186,7 @@ class GoGenerator : public BaseGenerator { } std::string GenTypeGet(const Type &type) { - if (type.enum_def != nullptr) { - return GetEnumTypeName(*type.enum_def); - } + if (type.enum_def != nullptr) { return GetEnumTypeName(*type.enum_def); } return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type); } @@ -1221,7 +1216,8 @@ class GoGenerator : public BaseGenerator { std::string GenConstant(const FieldDef &field) { switch (field.value.type.base_type) { - case BASE_TYPE_BOOL: return field.value.constant == "0" ? "false" : "true"; + case BASE_TYPE_BOOL: + return field.value.constant == "0" ? "false" : "true"; default: return field.value.constant; } } @@ -1248,11 +1244,11 @@ class GoGenerator : public BaseGenerator { } else if (type.base_type == BASE_TYPE_VECTOR) { return "[]" + NativeType(type.VectorType()); } else if (type.base_type == BASE_TYPE_STRUCT) { - return "*" + WrapInNameSpaceAndTrack( - type.struct_def->defined_namespace, NativeName(*type.struct_def)); + return "*" + WrapInNameSpaceAndTrack(type.struct_def->defined_namespace, + NativeName(*type.struct_def)); } else if (type.base_type == BASE_TYPE_UNION) { - return "*" + WrapInNameSpaceAndTrack( - type.enum_def->defined_namespace, NativeName(*type.enum_def)); + return "*" + WrapInNameSpaceAndTrack(type.enum_def->defined_namespace, + NativeName(*type.enum_def)); } FLATBUFFERS_ASSERT(0); return std::string(); @@ -1271,13 +1267,12 @@ class GoGenerator : public BaseGenerator { void BeginFile(const std::string &name_space_name, const bool needs_imports, const bool is_enum, std::string *code_ptr) { std::string &code = *code_ptr; - code = code + "// Code generated by the FlatBuffers compiler. DO NOT EDIT.\n\n"; + code = code + + "// Code generated by the FlatBuffers compiler. DO NOT EDIT.\n\n"; code += "package " + name_space_name + "\n\n"; if (needs_imports) { code += "import (\n"; - if (is_enum) { - code += "\t\"strconv\"\n\n"; - } + if (is_enum) { code += "\t\"strconv\"\n\n"; } if (!parser_.opts.go_import.empty()) { code += "\tflatbuffers \"" + parser_.opts.go_import + "\"\n"; } else { @@ -1286,17 +1281,14 @@ class GoGenerator : public BaseGenerator { if (tracked_imported_namespaces_.size() > 0) { code += "\n"; for (auto it = tracked_imported_namespaces_.begin(); - it != tracked_imported_namespaces_.end(); - ++it) { - code += "\t" + NamespaceImportName(*it) + " \"" + \ - NamespaceImportPath(*it) + "\"\n"; + it != tracked_imported_namespaces_.end(); ++it) { + code += "\t" + NamespaceImportName(*it) + " \"" + + NamespaceImportPath(*it) + "\"\n"; } } code += ")\n\n"; } else { - if (is_enum) { - code += "import \"strconv\"\n\n"; - } + if (is_enum) { code += "import \"strconv\"\n\n"; } } } @@ -1364,8 +1356,7 @@ class GoGenerator : public BaseGenerator { static size_t MaxNameLength(const EnumDef &enum_def) { size_t max = 0; - for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); - ++it) { + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { max = std::max((*it)->name.length(), max); } return max; diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp index 1d5e8e5ed..ec129902c 100644 --- a/src/idl_gen_grpc.cpp +++ b/src/idl_gen_grpc.cpp @@ -20,7 +20,6 @@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" - #include "src/compiler/cpp_generator.h" #include "src/compiler/go_generator.h" #include "src/compiler/java_generator.h" @@ -35,9 +34,7 @@ namespace flatbuffers { class FlatBufMethod : public grpc_generator::Method { public: - enum Streaming { - kNone, kClient, kServer, kBiDi - }; + enum Streaming { kNone, kClient, kServer, kBiDi }; FlatBufMethod(const RPCCall *method) : method_(method) { streaming_ = kNone; @@ -171,7 +168,7 @@ class FlatBufPrinter : public grpc_generator::Printer { void Outdent() { indent_--; - FLATBUFFERS_ASSERT(indent_ >= 0); + FLATBUFFERS_ASSERT(indent_ >= 0); } private: @@ -182,9 +179,7 @@ class FlatBufPrinter : public grpc_generator::Printer { class FlatBufFile : public grpc_generator::File { public: - enum Language { - kLanguageGo, kLanguageCpp, kLanguageJava - }; + enum Language { kLanguageGo, kLanguageCpp, kLanguageJava }; FlatBufFile(const Parser &parser, const std::string &file_name, Language language) @@ -270,7 +265,8 @@ class GoGRPCGenerator : public flatbuffers::BaseGenerator { auto service = file.service(i); const Definition *def = parser_.services_.vec[i]; p.package_name = LastNamespacePart(*(def->defined_namespace)); - p.service_prefix = def->defined_namespace->GetFullyQualifiedName(""); // file.package(); + p.service_prefix = + def->defined_namespace->GetFullyQualifiedName(""); // file.package(); std::string output = grpc_go_generator::GenerateServiceSource(&file, service.get(), &p); std::string filename = @@ -313,20 +309,20 @@ bool GenerateCppGRPC(const Parser &parser, const std::string &path, std::string header_code = grpc_cpp_generator::GetHeaderPrologue(&fbfile, generator_parameters) + - grpc_cpp_generator::GetHeaderIncludes(&fbfile, generator_parameters) + - grpc_cpp_generator::GetHeaderServices(&fbfile, generator_parameters) + - grpc_cpp_generator::GetHeaderEpilogue(&fbfile, generator_parameters); + grpc_cpp_generator::GetHeaderIncludes(&fbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderServices(&fbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderEpilogue(&fbfile, generator_parameters); std::string source_code = grpc_cpp_generator::GetSourcePrologue(&fbfile, generator_parameters) + - grpc_cpp_generator::GetSourceIncludes(&fbfile, generator_parameters) + - grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) + - grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters); + grpc_cpp_generator::GetSourceIncludes(&fbfile, generator_parameters) + + grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) + + grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters); return flatbuffers::SaveFile((path + file_name + ".grpc.fb.h").c_str(), header_code, false) && - flatbuffers::SaveFile((path + file_name + ".grpc.fb.cc").c_str(), - source_code, false); + flatbuffers::SaveFile((path + file_name + ".grpc.fb.cc").c_str(), + source_code, false); } class JavaGRPCGenerator : public flatbuffers::BaseGenerator { diff --git a/src/idl_gen_js_ts.cpp b/src/idl_gen_js_ts.cpp index 84dc73747..8d86d3022 100644 --- a/src/idl_gen_js_ts.cpp +++ b/src/idl_gen_js_ts.cpp @@ -127,9 +127,7 @@ class JsTsGenerator : public BaseGenerator { const auto &file = *it; const auto basename = flatbuffers::StripPath(flatbuffers::StripExtension(file)); - if (basename != file_name_) { - code += GenPrefixedImport(file, basename); - } + if (basename != file_name_) { code += GenPrefixedImport(file, basename); } } } @@ -309,14 +307,12 @@ class JsTsGenerator : public BaseGenerator { result += " " + type_name; break; } - default: { result += " {" + type_name + "}"; } - } - if (!arg_name.empty()) { - result += " " + arg_name; - } - if (include_newline) { - result += "\n"; + default: { + result += " {" + type_name + "}"; + } } + if (!arg_name.empty()) { result += " " + arg_name; } + if (include_newline) { result += "\n"; } return result; } @@ -605,7 +601,8 @@ class JsTsGenerator : public BaseGenerator { } void GenerateRootAccessor(StructDef &struct_def, std::string *code_ptr, - std::string &code, std::string &object_name, bool size_prefixed) { + std::string &code, std::string &object_name, + bool size_prefixed) { if (!struct_def.fixed) { GenDocComment(code_ptr, GenTypeAnnotation(kParam, "flatbuffers.ByteBuffer", "bb") + @@ -613,11 +610,13 @@ class JsTsGenerator : public BaseGenerator { GenTypeAnnotation(kReturns, object_name, "", false)); std::string sizePrefixed("SizePrefixed"); if (lang_.language == IDLOptions::kTs) { - code += "static get" + (size_prefixed ? sizePrefixed : "") + "Root" + Verbose(struct_def, "As"); + code += "static get" + (size_prefixed ? sizePrefixed : "") + "Root" + + Verbose(struct_def, "As"); code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name + "):" + object_name + " {\n"; } else { - code += object_name + ".get" + (size_prefixed ? sizePrefixed : "") + "Root" + Verbose(struct_def, "As"); + code += object_name + ".get" + (size_prefixed ? sizePrefixed : "") + + "Root" + Verbose(struct_def, "As"); code += " = function(bb, obj) {\n"; } code += " return (obj || new " + object_name; @@ -627,21 +626,22 @@ class JsTsGenerator : public BaseGenerator { } void GenerateFinisher(StructDef &struct_def, std::string *code_ptr, - std::string &code, std::string &object_name, bool size_prefixed) { + std::string &code, std::string &object_name, + bool size_prefixed) { if (parser_.root_struct_def_ == &struct_def) { std::string sizePrefixed("SizePrefixed"); GenDocComment( code_ptr, GenTypeAnnotation(kParam, "flatbuffers.Builder", "builder") + - GenTypeAnnotation(kParam, "flatbuffers.Offset", "offset", - false)); + GenTypeAnnotation(kParam, "flatbuffers.Offset", "offset", false)); if (lang_.language == IDLOptions::kTs) { - code += "static finish" + (size_prefixed ? sizePrefixed : "") + Verbose(struct_def) + "Buffer"; - code += - "(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {\n"; + code += "static finish" + (size_prefixed ? sizePrefixed : "") + + Verbose(struct_def) + "Buffer"; + code += "(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {\n"; } else { - code += object_name + ".finish" + (size_prefixed ? sizePrefixed : "") + Verbose(struct_def) + "Buffer"; + code += object_name + ".finish" + (size_prefixed ? sizePrefixed : "") + + Verbose(struct_def) + "Buffer"; code += " = function(builder, offset) {\n"; } @@ -650,9 +650,7 @@ class JsTsGenerator : public BaseGenerator { code += ", '" + parser_.file_identifier_ + "'"; } if (size_prefixed) { - if (parser_.file_identifier_.empty()) { - code += ", undefined"; - } + if (parser_.file_identifier_.empty()) { code += ", undefined"; } code += ", true"; } code += ");\n"; @@ -682,7 +680,8 @@ class JsTsGenerator : public BaseGenerator { code += " {\n"; if (lang_.language != IDLOptions::kTs) { code += " /**\n"; - code += " * " + GenTypeAnnotation(kType, "flatbuffers.ByteBuffer", ""); + code += + " * " + GenTypeAnnotation(kType, "flatbuffers.ByteBuffer", ""); code += " */\n"; } code += " bb: flatbuffers.ByteBuffer|null = null;\n"; @@ -752,10 +751,9 @@ class JsTsGenerator : public BaseGenerator { // Generate the identifier check method if (!struct_def.fixed && parser_.root_struct_def_ == &struct_def && !parser_.file_identifier_.empty()) { - GenDocComment( - code_ptr, - GenTypeAnnotation(kParam, "flatbuffers.ByteBuffer", "bb") + - GenTypeAnnotation(kReturns, "boolean", "", false)); + GenDocComment(code_ptr, + GenTypeAnnotation(kParam, "flatbuffers.ByteBuffer", "bb") + + GenTypeAnnotation(kReturns, "boolean", "", false)); if (lang_.language == IDLOptions::kTs) { code += "static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean " @@ -872,7 +870,8 @@ class JsTsGenerator : public BaseGenerator { code += ", " + GenBBAccess() + ") : null;\n"; } - if (lang_.language == IDLOptions::kTs && !parser_.opts.generate_all) { + if (lang_.language == IDLOptions::kTs && + !parser_.opts.generate_all) { imported_files.insert(field.value.type.struct_def->file); } @@ -1290,8 +1289,7 @@ class JsTsGenerator : public BaseGenerator { for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; - if (field.deprecated) - continue; + if (field.deprecated) continue; paramDoc += GenTypeAnnotation(kParam, GetArgType(field), GetArgName(field)); } @@ -1311,8 +1309,7 @@ class JsTsGenerator : public BaseGenerator { for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; - if (field.deprecated) - continue; + if (field.deprecated) continue; if (lang_.language == IDLOptions::kTs) { code += ", " + GetArgName(field) + ":" + GetArgType(field); @@ -1336,8 +1333,7 @@ class JsTsGenerator : public BaseGenerator { for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; - if (field.deprecated) - continue; + if (field.deprecated) continue; code += " " + methodPrefix + ".add" + MakeCamel(field.name) + "("; code += "builder, " + GetArgName(field) + ");\n"; @@ -1346,14 +1342,11 @@ class JsTsGenerator : public BaseGenerator { code += " return " + methodPrefix + ".end" + Verbose(struct_def) + "(builder);\n"; code += "}\n"; - if (lang_.language == IDLOptions::kJs) - code += "\n"; + if (lang_.language == IDLOptions::kJs) code += "\n"; } if (lang_.language == IDLOptions::kTs) { - if (!object_namespace.empty()) { - code += "}\n"; - } + if (!object_namespace.empty()) { code += "}\n"; } code += "}\n"; } } @@ -1372,9 +1365,7 @@ class JsTsGenerator : public BaseGenerator { return argname; } - std::string Verbose(const StructDef &struct_def, - const char* prefix = "") - { + std::string Verbose(const StructDef &struct_def, const char *prefix = "") { return parser_.opts.js_ts_short_names ? "" : prefix + struct_def.name; } }; diff --git a/src/idl_gen_json_schema.cpp b/src/idl_gen_json_schema.cpp index 27e2cd460..5d7bad6d8 100644 --- a/src/idl_gen_json_schema.cpp +++ b/src/idl_gen_json_schema.cpp @@ -15,6 +15,7 @@ */ #include + #include "flatbuffers/code_generators.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" diff --git a/src/idl_gen_kotlin.cpp b/src/idl_gen_kotlin.cpp index d11599fe0..b12e554d3 100644 --- a/src/idl_gen_kotlin.cpp +++ b/src/idl_gen_kotlin.cpp @@ -18,12 +18,13 @@ #include #include + #include "flatbuffers/code_generators.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" #if defined(FLATBUFFERS_CPP98_STL) -#include +# include #endif // defined(FLATBUFFERS_CPP98_STL) namespace flatbuffers { @@ -35,21 +36,20 @@ static TypedFloatConstantGenerator KotlinFloatGen("Double.", "Float.", "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY"); -static const CommentConfig comment_config = {"/**", " *", " */"}; +static const CommentConfig comment_config = { "/**", " *", " */" }; static const std::string ident_pad = " "; static const char *keywords[] = { - "package", "as", "typealias", "class", "this", "super", - "val", "var", "fun", "for", "null", "true", - "false", "is", "in", "throw", "return", "break", - "continue", "object", "if", "try", "else", "while", - "do", "when", "interface", "typeof", "Any", "Character"}; + "package", "as", "typealias", "class", "this", "super", + "val", "var", "fun", "for", "null", "true", + "false", "is", "in", "throw", "return", "break", + "continue", "object", "if", "try", "else", "while", + "do", "when", "interface", "typeof", "Any", "Character" +}; // Escape Keywords static std::string Esc(const std::string &name) { for (size_t i = 0; i < sizeof(keywords) / sizeof(keywords[0]); i++) { - if (name == keywords[i]) { - return MakeCamel(name + "_", false); - } + if (name == keywords[i]) { return MakeCamel(name + "_", false); } } return MakeCamel(name, false); @@ -145,1380 +145,1298 @@ class KotlinGenerator : public BaseGenerator { #KTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - }; - return kotlin_typename[type]; + // clang-format on + }; + return kotlin_typename[type]; + } + std::string GenTypePointer(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "String"; + case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType()); + case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def); + default: return "Table"; + } + } + + std::string GenTypeGet(const Type &type) const { + return IsScalar(type.base_type) ? GenTypeBasic(type.base_type) + : GenTypePointer(type); + } + + std::string GenEnumDefaultValue(const FieldDef &field) const { + auto &value = field.value; + FLATBUFFERS_ASSERT(value.type.enum_def); + auto &enum_def = *value.type.enum_def; + auto enum_val = enum_def.FindByValue(value.constant); + return enum_val ? (WrapInNameSpace(enum_def) + "." + enum_val->name) + : value.constant; + } + + // Generate default values to compare against a default value when + // `force_defaults` is `false`. + // Main differences are: + // - Floats are upcasted to doubles + // - Unsigned are casted to signed + std::string GenFBBDefaultValue(const FieldDef &field) const { + auto out = GenDefaultValue(field, true); + // All FlatBufferBuilder default floating point values are doubles + if (field.value.type.base_type == BASE_TYPE_FLOAT) { + if (out.find("Float") != std::string::npos) { + out.replace(0, 5, "Double"); + } + } + // Guarantee all values are doubles + if (out.back() == 'f') out.pop_back(); + return out; + } + + // FlatBufferBuilder only store signed types, so this function + // returns a cast for unsigned values + std::string GenFBBValueCast(const FieldDef &field) const { + if (IsUnsigned(field.value.type.base_type)) { + return CastToSigned(field.value.type); + } + return ""; + } + + std::string GenDefaultValue(const FieldDef &field, + bool force_signed = false) const { + auto &value = field.value; + auto base_type = field.value.type.base_type; + if (IsFloat(base_type)) { + auto val = KotlinFloatGen.GenFloatConstant(field); + if (base_type == BASE_TYPE_DOUBLE && val.back() == 'f') { + val.pop_back(); + } + return val; } - std::string GenTypePointer(const Type &type) const { - switch (type.base_type) { - case BASE_TYPE_STRING: - return "String"; - case BASE_TYPE_VECTOR: - return GenTypeGet(type.VectorType()); - case BASE_TYPE_STRUCT: - return WrapInNameSpace(*type.struct_def); - default: - return "Table"; - } + if (base_type == BASE_TYPE_BOOL) { + return value.constant == "0" ? "false" : "true"; } - std::string GenTypeGet(const Type &type) const { - return IsScalar(type.base_type) ? GenTypeBasic(type.base_type) - : GenTypePointer(type); + std::string suffix = ""; + + if (base_type == BASE_TYPE_LONG || !force_signed) { + suffix = LiteralSuffix(base_type); } + return value.constant + suffix; + } - std::string GenEnumDefaultValue(const FieldDef &field) const { - auto &value = field.value; - FLATBUFFERS_ASSERT(value.type.enum_def); - auto &enum_def = *value.type.enum_def; - auto enum_val = enum_def.FindByValue(value.constant); - return enum_val ? (WrapInNameSpace(enum_def) + "." + enum_val->name) - : value.constant; - } + void GenEnum(EnumDef &enum_def, CodeWriter &writer) const { + if (enum_def.generated) return; + GenerateComment(enum_def.doc_comment, writer, &comment_config); - // Generate default values to compare against a default value when - // `force_defaults` is `false`. - // Main differences are: - // - Floats are upcasted to doubles - // - Unsigned are casted to signed - std::string GenFBBDefaultValue(const FieldDef &field) const { - auto out = GenDefaultValue(field, true); - // All FlatBufferBuilder default floating point values are doubles - if (field.value.type.base_type == BASE_TYPE_FLOAT) { - if (out.find("Float") != std::string::npos) { - out.replace(0, 5, "Double"); - } - } - //Guarantee all values are doubles - if (out.back() == 'f') - out.pop_back(); - return out; - } + writer += "@Suppress(\"unused\")"; + writer += "@ExperimentalUnsignedTypes"; + writer += "class " + Esc(enum_def.name) + " private constructor() {"; + writer.IncrementIdentLevel(); + GenerateCompanionObject(writer, [&]() { + // Write all properties + auto vals = enum_def.Vals(); + for (auto it = vals.begin(); it != vals.end(); ++it) { + auto &ev = **it; + auto field_type = GenTypeBasic(enum_def.underlying_type.base_type); + auto val = enum_def.ToString(ev); + auto suffix = LiteralSuffix(enum_def.underlying_type.base_type); + writer.SetValue("name", Esc(ev.name)); + writer.SetValue("type", field_type); + writer.SetValue("val", val + suffix); + GenerateComment(ev.doc_comment, writer, &comment_config); + writer += "const val {{name}}: {{type}} = {{val}}"; + } - // FlatBufferBuilder only store signed types, so this function - // returns a cast for unsigned values - std::string GenFBBValueCast(const FieldDef &field) const { - if (IsUnsigned(field.value.type.base_type)) { - return CastToSigned(field.value.type); - } - return ""; - } - - std::string GenDefaultValue(const FieldDef &field, - bool force_signed = false) const { - auto &value = field.value; - auto base_type = field.value.type.base_type; - if (IsFloat(base_type)) { - auto val = KotlinFloatGen.GenFloatConstant(field); - if (base_type == BASE_TYPE_DOUBLE && - val.back() == 'f') { - val.pop_back(); - } - return val; - } - - if (base_type == BASE_TYPE_BOOL) { - return value.constant == "0" ? "false" : "true"; - } - - std::string suffix = ""; - - if (base_type == BASE_TYPE_LONG || !force_signed) { - suffix = LiteralSuffix(base_type); - } - return value.constant + suffix; - } - - void GenEnum(EnumDef &enum_def, CodeWriter &writer) const { - if (enum_def.generated) return; - - GenerateComment(enum_def.doc_comment, writer, &comment_config); - - writer += "@Suppress(\"unused\")"; - writer += "@ExperimentalUnsignedTypes"; - writer += "class " + Esc(enum_def.name) + " private constructor() {"; - writer.IncrementIdentLevel(); - - GenerateCompanionObject(writer, [&](){ - // Write all properties - auto vals = enum_def.Vals(); - for (auto it = vals.begin(); it != vals.end(); ++it) { - auto &ev = **it; - auto field_type = GenTypeBasic(enum_def.underlying_type.base_type); - auto val = enum_def.ToString(ev); - auto suffix = LiteralSuffix(enum_def.underlying_type.base_type); - writer.SetValue("name", Esc(ev.name)); - writer.SetValue("type", field_type); - writer.SetValue("val", val + suffix); - GenerateComment(ev.doc_comment, writer, &comment_config); - writer += "const val {{name}}: {{type}} = {{val}}"; - } - - // Generate a generate string table for enum values. - // Problem is, if values are very sparse that could generate really - // big tables. Ideally in that case we generate a map lookup - // instead, but for the moment we simply don't output a table at all. - auto range = enum_def.Distance(); - // Average distance between values above which we consider a table - // "too sparse". Change at will. - static const uint64_t kMaxSparseness = 5; - if (range / static_cast(enum_def.size()) < kMaxSparseness) { - GeneratePropertyOneLine(writer, "names", "Array", - [&](){ - writer += "arrayOf(\\"; - auto val = enum_def.Vals().front(); - for (auto it = vals.begin(); it != vals.end(); ++it) { - auto ev = *it; - for (auto k = enum_def.Distance(val, ev); k > 1; --k) - writer += "\"\", \\"; - val = ev; - writer += "\"" + (*it)->name + "\"\\"; - if (it+1 != vals.end()) { - writer += ", \\"; - } - } - writer += ")"; - }); - GenerateFunOneLine(writer, "name", "e: Int", "String", [&](){ - writer += "names[e\\"; - if (enum_def.MinValue()->IsNonZero()) - writer += " - " + enum_def.MinValue()->name + ".toInt()\\"; - writer += "]"; - }); - } + // Generate a generate string table for enum values. + // Problem is, if values are very sparse that could generate really + // big tables. Ideally in that case we generate a map lookup + // instead, but for the moment we simply don't output a table at all. + auto range = enum_def.Distance(); + // Average distance between values above which we consider a table + // "too sparse". Change at will. + static const uint64_t kMaxSparseness = 5; + if (range / static_cast(enum_def.size()) < kMaxSparseness) { + GeneratePropertyOneLine(writer, "names", "Array", [&]() { + writer += "arrayOf(\\"; + auto val = enum_def.Vals().front(); + for (auto it = vals.begin(); it != vals.end(); ++it) { + auto ev = *it; + for (auto k = enum_def.Distance(val, ev); k > 1; --k) + writer += "\"\", \\"; + val = ev; + writer += "\"" + (*it)->name + "\"\\"; + if (it + 1 != vals.end()) { writer += ", \\"; } + } + writer += ")"; }); - writer.DecrementIdentLevel(); - writer += "}"; - } + GenerateFunOneLine(writer, "name", "e: Int", "String", [&]() { + writer += "names[e\\"; + if (enum_def.MinValue()->IsNonZero()) + writer += " - " + enum_def.MinValue()->name + ".toInt()\\"; + writer += "]"; + }); + } + }); + writer.DecrementIdentLevel(); + writer += "}"; + } - // Returns the function name that is able to read a value of the given type. - std::string ByteBufferGetter(const Type &type, std::string bb_var_name) const { - switch (type.base_type) { - case BASE_TYPE_STRING: - return "__string"; - case BASE_TYPE_STRUCT: - return "__struct"; - case BASE_TYPE_UNION: - return "__union"; - case BASE_TYPE_VECTOR: - return ByteBufferGetter(type.VectorType(), bb_var_name); + // Returns the function name that is able to read a value of the given type. + std::string ByteBufferGetter(const Type &type, + std::string bb_var_name) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "__string"; + case BASE_TYPE_STRUCT: return "__struct"; + case BASE_TYPE_UNION: return "__union"; + case BASE_TYPE_VECTOR: + return ByteBufferGetter(type.VectorType(), bb_var_name); + case BASE_TYPE_INT: + case BASE_TYPE_UINT: return bb_var_name + ".getInt"; + case BASE_TYPE_SHORT: + case BASE_TYPE_USHORT: return bb_var_name + ".getShort"; + case BASE_TYPE_ULONG: + case BASE_TYPE_LONG: return bb_var_name + ".getLong"; + case BASE_TYPE_FLOAT: return bb_var_name + ".getFloat"; + case BASE_TYPE_DOUBLE: return bb_var_name + ".getDouble"; + case BASE_TYPE_CHAR: + case BASE_TYPE_UCHAR: + case BASE_TYPE_NONE: + case BASE_TYPE_UTYPE: return bb_var_name + ".get"; + case BASE_TYPE_BOOL: return "0.toByte() != " + bb_var_name + ".get"; + default: + return bb_var_name + ".get" + MakeCamel(GenTypeBasic(type.base_type)); + } + } + + std::string ByteBufferSetter(const Type &type) const { + if (IsScalar(type.base_type)) { + switch (type.base_type) { case BASE_TYPE_INT: - case BASE_TYPE_UINT: - return bb_var_name + ".getInt"; + case BASE_TYPE_UINT: return "bb.putInt"; case BASE_TYPE_SHORT: - case BASE_TYPE_USHORT: - return bb_var_name + ".getShort"; + case BASE_TYPE_USHORT: return "bb.putShort"; case BASE_TYPE_ULONG: - case BASE_TYPE_LONG: - return bb_var_name + ".getLong"; - case BASE_TYPE_FLOAT: - return bb_var_name + ".getFloat"; - case BASE_TYPE_DOUBLE: - return bb_var_name + ".getDouble"; + case BASE_TYPE_LONG: return "bb.putLong"; + case BASE_TYPE_FLOAT: return "bb.putFloat"; + case BASE_TYPE_DOUBLE: return "bb.putDouble"; case BASE_TYPE_CHAR: case BASE_TYPE_UCHAR: - case BASE_TYPE_NONE: - case BASE_TYPE_UTYPE: - return bb_var_name + ".get"; case BASE_TYPE_BOOL: - return "0.toByte() != " + bb_var_name + ".get"; - default: - return bb_var_name + ".get" + MakeCamel(GenTypeBasic(type.base_type)); - } - } - - std::string ByteBufferSetter(const Type &type) const { - if (IsScalar(type.base_type)) { - switch (type.base_type) { - case BASE_TYPE_INT: - case BASE_TYPE_UINT: - return "bb.putInt"; - case BASE_TYPE_SHORT: - case BASE_TYPE_USHORT: - return "bb.putShort"; - case BASE_TYPE_ULONG: - case BASE_TYPE_LONG: - return "bb.putLong"; - case BASE_TYPE_FLOAT: - return "bb.putFloat"; - case BASE_TYPE_DOUBLE: - return "bb.putDouble"; - case BASE_TYPE_CHAR: - case BASE_TYPE_UCHAR: - case BASE_TYPE_BOOL: - case BASE_TYPE_NONE: - case BASE_TYPE_UTYPE: - return "bb.put"; - default: - return "bb.put" + MakeCamel(GenTypeBasic(type.base_type)); - } - } - return ""; - } - - // Returns the function name that is able to read a value of the given type. - std::string GenLookupByKey(flatbuffers::FieldDef *key_field, - const std::string &bb_var_name, - const char *num = nullptr) const { - auto type = key_field->value.type; - return ByteBufferGetter(type, bb_var_name) + "(" + GenOffsetGetter(key_field, num) + ")"; - - } - - // Returns the method name for use with add/put calls. - static std::string GenMethod(const Type &type) { - return IsScalar(type.base_type) ? ToSignedType(type) - : (IsStruct(type) ? "Struct" : "Offset"); - } - - // Recursively generate arguments for a constructor, to deal with nested - // structs. - static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer, - const char *nameprefix) { - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (IsStruct(field.value.type)) { - // Generate arguments for a struct inside a struct. To ensure - // names don't clash, and to make it obvious these arguments are - // constructing a nested struct, prefix the name with the field - // name. - GenStructArgs(*field.value.type.struct_def, writer, - (nameprefix + (field.name + "_")).c_str()); - } else { - writer += std::string(", ") + nameprefix + "\\"; - writer += MakeCamel(field.name) + ": \\"; - writer += GenTypeBasic(field.value.type.base_type) + "\\"; - } - } - } - - // Recusively generate struct construction statements of the form: - // builder.putType(name); - // and insert manual padding. - static void GenStructBody(const StructDef &struct_def, CodeWriter &writer, - const char *nameprefix) { - writer.SetValue("align", NumToString(struct_def.minalign)); - writer.SetValue("size", NumToString(struct_def.bytesize)); - writer += "builder.prep({{align}}, {{size}})"; - auto fields_vec = struct_def.fields.vec; - for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); ++it) { - auto &field = **it; - - if (field.padding) { - writer.SetValue("pad", NumToString(field.padding)); - writer += "builder.pad({{pad}})"; - } - if (IsStruct(field.value.type)) { - GenStructBody(*field.value.type.struct_def, writer, - (nameprefix + (field.name + "_")).c_str()); - } else { - writer.SetValue("type", GenMethod(field.value.type)); - writer.SetValue("argname", nameprefix + - MakeCamel(field.name, false)); - writer.SetValue("cast", CastToSigned(field.value.type)); - writer += "builder.put{{type}}({{argname}}{{cast}})"; - } - } - } - - std::string GenByteBufferLength(const char *bb_name) const { - std::string bb_len = bb_name; - bb_len += ".capacity()"; - return bb_len; - } - - std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, - const char *num = nullptr) const { - std::string key_offset = "__offset(" + - NumToString(key_field->value.offset) + ", "; - if (num) { - key_offset += num; - key_offset += ", _bb)"; - } else { - key_offset += GenByteBufferLength("bb"); - key_offset += " - tableOffset, bb)"; - } - return key_offset; - } - - void GenStruct(StructDef &struct_def, CodeWriter &writer) const { - if (struct_def.generated) return; - - GenerateComment(struct_def.doc_comment, writer, &comment_config); - auto fixed = struct_def.fixed; - - writer.SetValue("struct_name", Esc(struct_def.name)); - writer.SetValue("superclass", fixed ? "Struct" : "Table"); - - writer += "@Suppress(\"unused\")"; - writer += "@ExperimentalUnsignedTypes"; - writer += "class {{struct_name}} : {{superclass}}() {\n"; - - writer.IncrementIdentLevel(); - - { - // Generate the __init() method that sets the field in a pre-existing - // accessor object. This is to allow object reuse. - GenerateFun(writer, "__init", "_i: Int, _bb: ByteBuffer", "", [&]() { - writer += "__reset(_i, _bb)"; - }); - - // Generate assign method - GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer", - Esc(struct_def.name), [&]() { - writer += "__init(_i, _bb)"; - writer += "return this"; - }); - - // Generate all getters - GenerateStructGetters(struct_def, writer); - - // Generate Static Fields - GenerateCompanionObject(writer, [&](){ - - if (!struct_def.fixed) { - FieldDef *key_field = nullptr; - - // Generate verson check method. - // Force compile time error if not using the same version - // runtime. - GenerateFunOneLine(writer, "validateVersion", "", "", [&](){ - writer += "Constants.FLATBUFFERS_1_11_1()"; - }); - - GenerateGetRootAsAccessors(Esc(struct_def.name), writer); - GenerateBufferHasIdentifier(struct_def, writer); - GenerateTableCreator(struct_def, writer); - - GenerateStartStructMethod(struct_def, writer); - - // Static Add for fields - auto fields = struct_def.fields.vec; - int field_pos = -1; - for (auto it = fields.begin(); it != fields.end(); ++it) { - auto &field = **it; - field_pos++; - if (field.deprecated) continue; - if (field.key) key_field = &field; - GenerateAddField(NumToString(field_pos), field, writer); - - if (field.value.type.base_type == BASE_TYPE_VECTOR) { - auto vector_type = field.value.type.VectorType(); - if (!IsStruct(vector_type)) { - GenerateCreateVectorField(field, writer); - } - GenerateStartVectorField(field, writer); - } - } - - GenerateEndStructMethod(struct_def, writer); - auto file_identifier = parser_.file_identifier_; - if (parser_.root_struct_def_ == &struct_def) { - GenerateFinishStructBuffer(struct_def, - file_identifier, - writer); - GenerateFinishSizePrefixed(struct_def, - file_identifier, - writer); - } - - if (struct_def.has_key) { - GenerateLookupByKey(key_field, struct_def, writer); - } - } else { - GenerateStaticConstructor(struct_def, writer); - } - }); - } - - // class closing - writer.DecrementIdentLevel(); - writer += "}"; - } - - // TODO: move key_field to reference instead of pointer - void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def, - CodeWriter &writer) const { - std::stringstream params; - params << "obj: " << Esc(struct_def.name) << "?" << ", "; - params << "vectorLocation: Int, "; - params << "key: " << GenTypeGet(key_field->value.type) << ", "; - params << "bb: ByteBuffer"; - - auto statements = [&]() { - auto base_type = key_field->value.type.base_type; - writer.SetValue("struct_name", Esc(struct_def.name)); - if (base_type == BASE_TYPE_STRING) { - writer += "val byteKey = key." - "toByteArray(Table.UTF8_CHARSET.get()!!)"; - } - writer += "var span = bb.getInt(vectorLocation - 4)"; - writer += "var start = 0"; - writer += "while (span != 0) {"; - writer.IncrementIdentLevel(); - writer += "var middle = span / 2"; - writer += "val tableOffset = __indirect(vector" - "Location + 4 * (start + middle), bb)"; - if (key_field->value.type.base_type == BASE_TYPE_STRING) { - writer += "val comp = compareStrings(\\"; - writer += GenOffsetGetter(key_field) + "\\"; - writer += ", byteKey, bb)"; - } else { - auto cast = CastToUsigned(key_field->value.type); - auto get_val = GenLookupByKey(key_field, "bb"); - writer += "val value = " + get_val + cast; - writer += "val comp = value.compareTo(key)"; - } - writer += "when {"; - writer.IncrementIdentLevel(); - writer += "comp > 0 -> span = middle"; - writer += "comp < 0 -> {"; - writer.IncrementIdentLevel(); - writer += "middle++"; - writer += "start += middle"; - writer += "span -= middle"; - writer.DecrementIdentLevel(); - writer += "}"; // end comp < 0 - writer += "else -> {"; - writer.IncrementIdentLevel(); - writer += "return (obj ?: {{struct_name}}()).__assign(tableOffset, bb)"; - writer.DecrementIdentLevel(); - writer += "}"; // end else - writer.DecrementIdentLevel(); - writer += "}"; // end when - writer.DecrementIdentLevel(); - writer += "}"; // end while - writer += "return null"; - }; - GenerateFun(writer, "__lookup_by_key", - params.str(), - Esc(struct_def.name) + "?", - statements); - } - - void GenerateFinishSizePrefixed(StructDef &struct_def, - const std::string &identifier, - CodeWriter &writer) const { - auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; - auto params = "builder: FlatBufferBuilder, offset: Int"; - auto method_name = "finishSizePrefixed" + Esc(struct_def.name) + "Buffer"; - GenerateFunOneLine(writer, method_name, params, "", [&]() { - writer += "builder.finishSizePrefixed(offset" + id + ")"; - }); - } - void GenerateFinishStructBuffer(StructDef &struct_def, - const std::string &identifier, - CodeWriter &writer) const { - auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; - auto params = "builder: FlatBufferBuilder, offset: Int"; - auto method_name = "finish" + Esc(struct_def.name) + "Buffer"; - GenerateFunOneLine(writer, method_name, params, "", [&]() { - writer += "builder.finish(offset" + id + ")"; - }); - } - - void GenerateEndStructMethod(StructDef &struct_def, CodeWriter &writer) const { - // Generate end{{TableName}}(builder: FlatBufferBuilder) method - auto name = "end" + Esc(struct_def.name); - auto params = "builder: FlatBufferBuilder"; - auto returns = "Int"; - auto field_vec = struct_def.fields.vec; - - GenerateFun(writer, name, params, returns, [&](){ - writer += "val o = builder.endTable()"; - writer.IncrementIdentLevel(); - for (auto it = field_vec.begin(); it != field_vec.end(); ++it) { - auto &field = **it; - if (field.deprecated || !field.required) { - continue; - } - writer.SetValue("offset", NumToString(field.value.offset)); - writer += "builder.required(o, {{offset}})"; - } - writer.DecrementIdentLevel(); - writer += "return o"; - }); - } - - // Generate a method to create a vector from a Kotlin array. - void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer) const { - auto vector_type = field.value.type.VectorType(); - auto method_name = "create" + MakeCamel(Esc(field.name)) + "Vector"; - auto params = "builder: FlatBufferBuilder, data: " + - GenTypeBasic(vector_type.base_type) + "Array"; - writer.SetValue("size", NumToString(InlineSize(vector_type))); - writer.SetValue("align", NumToString(InlineAlignment(vector_type))); - writer.SetValue("root", GenMethod(vector_type)); - writer.SetValue("cast", CastToSigned(vector_type)); - - GenerateFun(writer, method_name, params, "Int", [&](){ - writer += "builder.startVector({{size}}, data.size, {{align}})"; - writer += "for (i in data.size - 1 downTo 0) {"; - writer.IncrementIdentLevel(); - writer += "builder.add{{root}}(data[i]{{cast}})"; - writer.DecrementIdentLevel(); - writer += "}"; - writer += "return builder.endVector()"; - }); - } - - void GenerateStartVectorField(FieldDef &field, CodeWriter &writer) const { - // Generate a method to start a vector, data to be added manually - // after. - auto vector_type = field.value.type.VectorType(); - auto params = "builder: FlatBufferBuilder, numElems: Int"; - writer.SetValue("size", NumToString(InlineSize(vector_type))); - writer.SetValue("align", NumToString(InlineAlignment(vector_type))); - - GenerateFunOneLine(writer, - "start" + MakeCamel(Esc(field.name) + "Vector", true), - params, - "", - [&]() { - writer += "builder.startVector({{size}}, numElems, {{align}})"; - }); - } - - void GenerateAddField(std::string field_pos, FieldDef &field, - CodeWriter &writer) const { - auto field_type = GenTypeBasic(field.value.type.base_type); - auto secondArg = MakeCamel(Esc(field.name), false) + ": " + field_type; - GenerateFunOneLine(writer, "add" + MakeCamel(Esc(field.name), true), - "builder: FlatBufferBuilder, " + secondArg, "", [&](){ - auto method = GenMethod(field.value.type); - writer.SetValue("field_name", MakeCamel(Esc(field.name), false)); - writer.SetValue("method_name", method); - writer.SetValue("pos", field_pos); - writer.SetValue("default", GenFBBDefaultValue(field)); - writer.SetValue("cast", GenFBBValueCast(field)); - - writer += "builder.add{{method_name}}({{pos}}, \\"; - writer += "{{field_name}}{{cast}}, {{default}})"; - }); - } - - static std::string ToSignedType(const Type & type) { - switch(type.base_type) { - case BASE_TYPE_UINT: - return GenTypeBasic(BASE_TYPE_INT); - case BASE_TYPE_ULONG: - return GenTypeBasic(BASE_TYPE_LONG); - case BASE_TYPE_UCHAR: case BASE_TYPE_NONE: - case BASE_TYPE_UTYPE: - return GenTypeBasic(BASE_TYPE_CHAR); - case BASE_TYPE_USHORT: - return GenTypeBasic(BASE_TYPE_SHORT); - case BASE_TYPE_VECTOR: - return ToSignedType(type.VectorType()); - default: - return GenTypeBasic(type.base_type); - } + case BASE_TYPE_UTYPE: return "bb.put"; + default: return "bb.put" + MakeCamel(GenTypeBasic(type.base_type)); + } } + return ""; + } - static std::string FlexBufferBuilderCast(const std::string &method, - FieldDef &field, - bool isFirst) { - auto field_type = GenTypeBasic(field.value.type.base_type); - std::string to_type; - if (method == "Boolean") - to_type = "Boolean"; - else if (method == "Long") - to_type = "Long"; - else if (method == "Int" || method == "Offset" || method == "Struct") - to_type = "Int"; - else if (method == "Byte" || method.empty()) - to_type = isFirst ? "Byte" : "Int"; - else if (method == "Short") - to_type = isFirst ? "Short" : "Int"; - else if (method == "Double") - to_type = "Double"; - else if (method == "Float") - to_type = isFirst ? "Float" : "Double"; - else if (method == "UByte") + // Returns the function name that is able to read a value of the given type. + std::string GenLookupByKey(flatbuffers::FieldDef *key_field, + const std::string &bb_var_name, + const char *num = nullptr) const { + auto type = key_field->value.type; + return ByteBufferGetter(type, bb_var_name) + "(" + + GenOffsetGetter(key_field, num) + ")"; + } - if (field_type != to_type) - return ".to" + to_type + "()"; - return ""; + // Returns the method name for use with add/put calls. + static std::string GenMethod(const Type &type) { + return IsScalar(type.base_type) ? ToSignedType(type) + : (IsStruct(type) ? "Struct" : "Offset"); + } + + // Recursively generate arguments for a constructor, to deal with nested + // structs. + static void GenStructArgs(const StructDef &struct_def, CodeWriter &writer, + const char *nameprefix) { + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (IsStruct(field.value.type)) { + // Generate arguments for a struct inside a struct. To ensure + // names don't clash, and to make it obvious these arguments are + // constructing a nested struct, prefix the name with the field + // name. + GenStructArgs(*field.value.type.struct_def, writer, + (nameprefix + (field.name + "_")).c_str()); + } else { + writer += std::string(", ") + nameprefix + "\\"; + writer += MakeCamel(field.name) + ": \\"; + writer += GenTypeBasic(field.value.type.base_type) + "\\"; + } } + } - // fun startMonster(builder: FlatBufferBuilder) = builder.startTable(11) - void GenerateStartStructMethod(StructDef &struct_def, CodeWriter &code) const { - GenerateFunOneLine(code, "start" + Esc(struct_def.name), - "builder: FlatBufferBuilder", "", [&] () { - code += "builder.startTable("+ NumToString(struct_def.fields.vec.size()) + ")"; - }); + // Recusively generate struct construction statements of the form: + // builder.putType(name); + // and insert manual padding. + static void GenStructBody(const StructDef &struct_def, CodeWriter &writer, + const char *nameprefix) { + writer.SetValue("align", NumToString(struct_def.minalign)); + writer.SetValue("size", NumToString(struct_def.bytesize)); + writer += "builder.prep({{align}}, {{size}})"; + auto fields_vec = struct_def.fields.vec; + for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); ++it) { + auto &field = **it; + + if (field.padding) { + writer.SetValue("pad", NumToString(field.padding)); + writer += "builder.pad({{pad}})"; + } + if (IsStruct(field.value.type)) { + GenStructBody(*field.value.type.struct_def, writer, + (nameprefix + (field.name + "_")).c_str()); + } else { + writer.SetValue("type", GenMethod(field.value.type)); + writer.SetValue("argname", nameprefix + MakeCamel(field.name, false)); + writer.SetValue("cast", CastToSigned(field.value.type)); + writer += "builder.put{{type}}({{argname}}{{cast}})"; + } } + } - void GenerateTableCreator(StructDef &struct_def, CodeWriter &writer) const { - // Generate a method that creates a table in one go. This is only possible - // when the table has no struct fields, since those have to be created - // inline, and there's no way to do so in Java. - bool has_no_struct_fields = true; - int num_fields = 0; - auto fields_vec = struct_def.fields.vec; + std::string GenByteBufferLength(const char *bb_name) const { + std::string bb_len = bb_name; + bb_len += ".capacity()"; + return bb_len; + } - for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - if (IsStruct(field.value.type)) { - has_no_struct_fields = false; - } else { - num_fields++; - } - } - // 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) { - // Generate a table constructor of the form: - // public static int createName(FlatBufferBuilder builder, args...) - - auto name = "create" + Esc(struct_def.name); - std::stringstream params; - params << "builder: FlatBufferBuilder"; - for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - params << ", " << MakeCamel(Esc(field.name), false); - if (!IsScalar(field.value.type.base_type)){ - params << "Offset: "; - } else { - params << ": "; - } - params << GenTypeBasic(field.value.type.base_type); - } - - GenerateFun(writer, name, params.str(), "Int", [&]() { - writer.SetValue("vec_size", NumToString(fields_vec.size())); - - writer += "builder.startTable({{vec_size}})"; - - auto sortbysize = struct_def.sortbysize; - auto largest = sortbysize ? sizeof(largest_scalar_t) : 1; - for (size_t size = largest; size; size /= 2) { - for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); - ++it) { - auto &field = **it; - auto base_type_size = SizeOf(field.value.type.base_type); - if (!field.deprecated && - (!sortbysize || size == base_type_size)) { - writer.SetValue("camel_field_name", - MakeCamel(Esc(field.name), true)); - writer.SetValue("field_name", - MakeCamel(Esc(field.name), false)); - - writer += "add{{camel_field_name}}(builder, {{field_name}}\\"; - if (!IsScalar(field.value.type.base_type)){ - writer += "Offset\\"; - } - writer += ")"; - } - } - } - writer += "return end{{struct_name}}(builder)"; - }); - } - - } - void GenerateBufferHasIdentifier(StructDef &struct_def, - CodeWriter &writer) const { - auto file_identifier = parser_.file_identifier_; - // Check if a buffer has the identifier. - if (parser_.root_struct_def_ != &struct_def || !file_identifier.length()) - return; - auto name = MakeCamel(Esc(struct_def.name), false); - GenerateFunOneLine(writer, name + "BufferHasIdentifier", - "_bb: ByteBuffer", - "Boolean", - [&]() { - writer += "__has_identifier(_bb, \"" + file_identifier + "\")"; - }); - } - - void GenerateStructGetters(StructDef &struct_def, CodeWriter &writer) const { - auto fields_vec = struct_def.fields.vec; - FieldDef *key_field = nullptr; - for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { + std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, + const char *num = nullptr) const { + std::string key_offset = + "__offset(" + NumToString(key_field->value.offset) + ", "; + if (num) { + key_offset += num; + key_offset += ", _bb)"; + } else { + key_offset += GenByteBufferLength("bb"); + key_offset += " - tableOffset, bb)"; + } + return key_offset; + } + + void GenStruct(StructDef &struct_def, CodeWriter &writer) const { + if (struct_def.generated) return; + + GenerateComment(struct_def.doc_comment, writer, &comment_config); + auto fixed = struct_def.fixed; + + writer.SetValue("struct_name", Esc(struct_def.name)); + writer.SetValue("superclass", fixed ? "Struct" : "Table"); + + writer += "@Suppress(\"unused\")"; + writer += "@ExperimentalUnsignedTypes"; + writer += "class {{struct_name}} : {{superclass}}() {\n"; + + writer.IncrementIdentLevel(); + + { + // Generate the __init() method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + GenerateFun(writer, "__init", "_i: Int, _bb: ByteBuffer", "", + [&]() { writer += "__reset(_i, _bb)"; }); + + // Generate assign method + GenerateFun(writer, "__assign", "_i: Int, _bb: ByteBuffer", + Esc(struct_def.name), [&]() { + writer += "__init(_i, _bb)"; + writer += "return this"; + }); + + // Generate all getters + GenerateStructGetters(struct_def, writer); + + // Generate Static Fields + GenerateCompanionObject(writer, [&]() { + if (!struct_def.fixed) { + FieldDef *key_field = nullptr; + + // Generate verson check method. + // Force compile time error if not using the same version + // runtime. + GenerateFunOneLine(writer, "validateVersion", "", "", [&]() { + writer += "Constants.FLATBUFFERS_1_11_1()"; + }); + + GenerateGetRootAsAccessors(Esc(struct_def.name), writer); + GenerateBufferHasIdentifier(struct_def, writer); + GenerateTableCreator(struct_def, writer); + + GenerateStartStructMethod(struct_def, writer); + + // Static Add for fields + auto fields = struct_def.fields.vec; + int field_pos = -1; + for (auto it = fields.begin(); it != fields.end(); ++it) { auto &field = **it; + field_pos++; if (field.deprecated) continue; if (field.key) key_field = &field; + GenerateAddField(NumToString(field_pos), field, writer); - GenerateComment(field.doc_comment, writer, &comment_config); + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + auto vector_type = field.value.type.VectorType(); + if (!IsStruct(vector_type)) { + GenerateCreateVectorField(field, writer); + } + GenerateStartVectorField(field, writer); + } + } - auto field_name = MakeCamel(Esc(field.name), false); - auto field_type = GenTypeGet(field.value.type); - auto field_default_value = GenDefaultValue(field); - auto return_type = GenTypeGet(field.value.type); - auto bbgetter = ByteBufferGetter(field.value.type, "bb"); - auto ucast = CastToUsigned(field); - auto offset_val = NumToString(field.value.offset); - auto offset_prefix = "val o = __offset(" + offset_val - + "); return o != 0 ? "; - auto value_base_type = field.value.type.base_type; - // Most field accessors need to retrieve and test the field offset - // first, this is the offset value for that: - writer.SetValue("offset", NumToString(field.value.offset)); - writer.SetValue("return_type", return_type); - writer.SetValue("field_type", field_type); - writer.SetValue("field_name", field_name); - writer.SetValue("field_default", field_default_value); - writer.SetValue("bbgetter", bbgetter); - writer.SetValue("ucast", ucast); + GenerateEndStructMethod(struct_def, writer); + auto file_identifier = parser_.file_identifier_; + if (parser_.root_struct_def_ == &struct_def) { + GenerateFinishStructBuffer(struct_def, file_identifier, writer); + GenerateFinishSizePrefixed(struct_def, file_identifier, writer); + } - auto opt_ret_type = return_type + "?"; - // Generate the accessors that don't do object reuse. - if (value_base_type == BASE_TYPE_STRUCT) { - // Calls the accessor that takes an accessor object with a - // new object. - // val pos - // get() = pos(Vec3()) - GenerateGetterOneLine(writer, field_name, opt_ret_type, [&](){ - writer += "{{field_name}}({{field_type}}())"; - }); - } else if (value_base_type == BASE_TYPE_VECTOR && - field.value.type.element == BASE_TYPE_STRUCT) { - // Accessors for vectors of structs also take accessor objects, - // this generates a variant without that argument. - // ex: fun weapons(j: Int) = weapons(Weapon(), j) - GenerateFunOneLine(writer, field_name, "j: Int", opt_ret_type, [&](){ - writer += "{{field_name}}({{return_type}}(), j)"; - }); + if (struct_def.has_key) { + GenerateLookupByKey(key_field, struct_def, writer); + } + } else { + GenerateStaticConstructor(struct_def, writer); + } + }); + } + + // class closing + writer.DecrementIdentLevel(); + writer += "}"; + } + + // TODO: move key_field to reference instead of pointer + void GenerateLookupByKey(FieldDef *key_field, StructDef &struct_def, + CodeWriter &writer) const { + std::stringstream params; + params << "obj: " << Esc(struct_def.name) << "?" + << ", "; + params << "vectorLocation: Int, "; + params << "key: " << GenTypeGet(key_field->value.type) << ", "; + params << "bb: ByteBuffer"; + + auto statements = [&]() { + auto base_type = key_field->value.type.base_type; + writer.SetValue("struct_name", Esc(struct_def.name)); + if (base_type == BASE_TYPE_STRING) { + writer += + "val byteKey = key." + "toByteArray(Table.UTF8_CHARSET.get()!!)"; + } + writer += "var span = bb.getInt(vectorLocation - 4)"; + writer += "var start = 0"; + writer += "while (span != 0) {"; + writer.IncrementIdentLevel(); + writer += "var middle = span / 2"; + writer += + "val tableOffset = __indirect(vector" + "Location + 4 * (start + middle), bb)"; + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + writer += "val comp = compareStrings(\\"; + writer += GenOffsetGetter(key_field) + "\\"; + writer += ", byteKey, bb)"; + } else { + auto cast = CastToUsigned(key_field->value.type); + auto get_val = GenLookupByKey(key_field, "bb"); + writer += "val value = " + get_val + cast; + writer += "val comp = value.compareTo(key)"; + } + writer += "when {"; + writer.IncrementIdentLevel(); + writer += "comp > 0 -> span = middle"; + writer += "comp < 0 -> {"; + writer.IncrementIdentLevel(); + writer += "middle++"; + writer += "start += middle"; + writer += "span -= middle"; + writer.DecrementIdentLevel(); + writer += "}"; // end comp < 0 + writer += "else -> {"; + writer.IncrementIdentLevel(); + writer += "return (obj ?: {{struct_name}}()).__assign(tableOffset, bb)"; + writer.DecrementIdentLevel(); + writer += "}"; // end else + writer.DecrementIdentLevel(); + writer += "}"; // end when + writer.DecrementIdentLevel(); + writer += "}"; // end while + writer += "return null"; + }; + GenerateFun(writer, "__lookup_by_key", params.str(), + Esc(struct_def.name) + "?", statements); + } + + void GenerateFinishSizePrefixed(StructDef &struct_def, + const std::string &identifier, + CodeWriter &writer) const { + auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; + auto params = "builder: FlatBufferBuilder, offset: Int"; + auto method_name = "finishSizePrefixed" + Esc(struct_def.name) + "Buffer"; + GenerateFunOneLine(writer, method_name, params, "", [&]() { + writer += "builder.finishSizePrefixed(offset" + id + ")"; + }); + } + void GenerateFinishStructBuffer(StructDef &struct_def, + const std::string &identifier, + CodeWriter &writer) const { + auto id = identifier.length() > 0 ? ", \"" + identifier + "\"" : ""; + auto params = "builder: FlatBufferBuilder, offset: Int"; + auto method_name = "finish" + Esc(struct_def.name) + "Buffer"; + GenerateFunOneLine(writer, method_name, params, "", + [&]() { writer += "builder.finish(offset" + id + ")"; }); + } + + void GenerateEndStructMethod(StructDef &struct_def, + CodeWriter &writer) const { + // Generate end{{TableName}}(builder: FlatBufferBuilder) method + auto name = "end" + Esc(struct_def.name); + auto params = "builder: FlatBufferBuilder"; + auto returns = "Int"; + auto field_vec = struct_def.fields.vec; + + GenerateFun(writer, name, params, returns, [&]() { + writer += "val o = builder.endTable()"; + writer.IncrementIdentLevel(); + for (auto it = field_vec.begin(); it != field_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated || !field.required) { continue; } + writer.SetValue("offset", NumToString(field.value.offset)); + writer += "builder.required(o, {{offset}})"; + } + writer.DecrementIdentLevel(); + writer += "return o"; + }); + } + + // Generate a method to create a vector from a Kotlin array. + void GenerateCreateVectorField(FieldDef &field, CodeWriter &writer) const { + auto vector_type = field.value.type.VectorType(); + auto method_name = "create" + MakeCamel(Esc(field.name)) + "Vector"; + auto params = "builder: FlatBufferBuilder, data: " + + GenTypeBasic(vector_type.base_type) + "Array"; + writer.SetValue("size", NumToString(InlineSize(vector_type))); + writer.SetValue("align", NumToString(InlineAlignment(vector_type))); + writer.SetValue("root", GenMethod(vector_type)); + writer.SetValue("cast", CastToSigned(vector_type)); + + GenerateFun(writer, method_name, params, "Int", [&]() { + writer += "builder.startVector({{size}}, data.size, {{align}})"; + writer += "for (i in data.size - 1 downTo 0) {"; + writer.IncrementIdentLevel(); + writer += "builder.add{{root}}(data[i]{{cast}})"; + writer.DecrementIdentLevel(); + writer += "}"; + writer += "return builder.endVector()"; + }); + } + + void GenerateStartVectorField(FieldDef &field, CodeWriter &writer) const { + // Generate a method to start a vector, data to be added manually + // after. + auto vector_type = field.value.type.VectorType(); + auto params = "builder: FlatBufferBuilder, numElems: Int"; + writer.SetValue("size", NumToString(InlineSize(vector_type))); + writer.SetValue("align", NumToString(InlineAlignment(vector_type))); + + GenerateFunOneLine( + writer, "start" + MakeCamel(Esc(field.name) + "Vector", true), params, + "", [&]() { + writer += "builder.startVector({{size}}, numElems, {{align}})"; + }); + } + + void GenerateAddField(std::string field_pos, FieldDef &field, + CodeWriter &writer) const { + auto field_type = GenTypeBasic(field.value.type.base_type); + auto secondArg = MakeCamel(Esc(field.name), false) + ": " + field_type; + GenerateFunOneLine(writer, "add" + MakeCamel(Esc(field.name), true), + "builder: FlatBufferBuilder, " + secondArg, "", [&]() { + auto method = GenMethod(field.value.type); + writer.SetValue("field_name", + MakeCamel(Esc(field.name), false)); + writer.SetValue("method_name", method); + writer.SetValue("pos", field_pos); + writer.SetValue("default", GenFBBDefaultValue(field)); + writer.SetValue("cast", GenFBBValueCast(field)); + + writer += "builder.add{{method_name}}({{pos}}, \\"; + writer += "{{field_name}}{{cast}}, {{default}})"; + }); + } + + static std::string ToSignedType(const Type &type) { + switch (type.base_type) { + case BASE_TYPE_UINT: return GenTypeBasic(BASE_TYPE_INT); + case BASE_TYPE_ULONG: return GenTypeBasic(BASE_TYPE_LONG); + case BASE_TYPE_UCHAR: + case BASE_TYPE_NONE: + case BASE_TYPE_UTYPE: return GenTypeBasic(BASE_TYPE_CHAR); + case BASE_TYPE_USHORT: return GenTypeBasic(BASE_TYPE_SHORT); + case BASE_TYPE_VECTOR: return ToSignedType(type.VectorType()); + default: return GenTypeBasic(type.base_type); + } + } + + static std::string FlexBufferBuilderCast(const std::string &method, + FieldDef &field, bool isFirst) { + auto field_type = GenTypeBasic(field.value.type.base_type); + std::string to_type; + if (method == "Boolean") + to_type = "Boolean"; + else if (method == "Long") + to_type = "Long"; + else if (method == "Int" || method == "Offset" || method == "Struct") + to_type = "Int"; + else if (method == "Byte" || method.empty()) + to_type = isFirst ? "Byte" : "Int"; + else if (method == "Short") + to_type = isFirst ? "Short" : "Int"; + else if (method == "Double") + to_type = "Double"; + else if (method == "Float") + to_type = isFirst ? "Float" : "Double"; + else if (method == "UByte") + + if (field_type != to_type) return ".to" + to_type + "()"; + return ""; + } + + // fun startMonster(builder: FlatBufferBuilder) = builder.startTable(11) + void GenerateStartStructMethod(StructDef &struct_def, + CodeWriter &code) const { + GenerateFunOneLine(code, "start" + Esc(struct_def.name), + "builder: FlatBufferBuilder", "", [&]() { + code += "builder.startTable(" + + NumToString(struct_def.fields.vec.size()) + + ")"; + }); + } + + void GenerateTableCreator(StructDef &struct_def, CodeWriter &writer) const { + // Generate a method that creates a table in one go. This is only possible + // when the table has no struct fields, since those have to be created + // inline, and there's no way to do so in Java. + bool has_no_struct_fields = true; + int num_fields = 0; + auto fields_vec = struct_def.fields.vec; + + for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (IsStruct(field.value.type)) { + has_no_struct_fields = false; + } else { + num_fields++; + } + } + // 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) { + // Generate a table constructor of the form: + // public static int createName(FlatBufferBuilder builder, args...) + + auto name = "create" + Esc(struct_def.name); + std::stringstream params; + params << "builder: FlatBufferBuilder"; + for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + params << ", " << MakeCamel(Esc(field.name), false); + if (!IsScalar(field.value.type.base_type)) { + params << "Offset: "; + } else { + params << ": "; + } + params << GenTypeBasic(field.value.type.base_type); + } + + GenerateFun(writer, name, params.str(), "Int", [&]() { + writer.SetValue("vec_size", NumToString(fields_vec.size())); + + writer += "builder.startTable({{vec_size}})"; + + auto sortbysize = struct_def.sortbysize; + auto largest = sortbysize ? sizeof(largest_scalar_t) : 1; + for (size_t size = largest; size; size /= 2) { + for (auto it = fields_vec.rbegin(); it != fields_vec.rend(); ++it) { + auto &field = **it; + auto base_type_size = SizeOf(field.value.type.base_type); + if (!field.deprecated && (!sortbysize || size == base_type_size)) { + writer.SetValue("camel_field_name", + MakeCamel(Esc(field.name), true)); + writer.SetValue("field_name", MakeCamel(Esc(field.name), false)); + + writer += "add{{camel_field_name}}(builder, {{field_name}}\\"; + if (!IsScalar(field.value.type.base_type)) { + writer += "Offset\\"; + } + writer += ")"; + } + } + } + writer += "return end{{struct_name}}(builder)"; + }); + } + } + void GenerateBufferHasIdentifier(StructDef &struct_def, + CodeWriter &writer) const { + auto file_identifier = parser_.file_identifier_; + // Check if a buffer has the identifier. + if (parser_.root_struct_def_ != &struct_def || !file_identifier.length()) + return; + auto name = MakeCamel(Esc(struct_def.name), false); + GenerateFunOneLine(writer, name + "BufferHasIdentifier", "_bb: ByteBuffer", + "Boolean", [&]() { + writer += "__has_identifier(_bb, \"" + + file_identifier + "\")"; + }); + } + + void GenerateStructGetters(StructDef &struct_def, CodeWriter &writer) const { + auto fields_vec = struct_def.fields.vec; + FieldDef *key_field = nullptr; + for (auto it = fields_vec.begin(); it != fields_vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (field.key) key_field = &field; + + GenerateComment(field.doc_comment, writer, &comment_config); + + auto field_name = MakeCamel(Esc(field.name), false); + auto field_type = GenTypeGet(field.value.type); + auto field_default_value = GenDefaultValue(field); + auto return_type = GenTypeGet(field.value.type); + auto bbgetter = ByteBufferGetter(field.value.type, "bb"); + auto ucast = CastToUsigned(field); + auto offset_val = NumToString(field.value.offset); + auto offset_prefix = + "val o = __offset(" + offset_val + "); return o != 0 ? "; + auto value_base_type = field.value.type.base_type; + // Most field accessors need to retrieve and test the field offset + // first, this is the offset value for that: + writer.SetValue("offset", NumToString(field.value.offset)); + writer.SetValue("return_type", return_type); + writer.SetValue("field_type", field_type); + writer.SetValue("field_name", field_name); + writer.SetValue("field_default", field_default_value); + writer.SetValue("bbgetter", bbgetter); + writer.SetValue("ucast", ucast); + + auto opt_ret_type = return_type + "?"; + // Generate the accessors that don't do object reuse. + if (value_base_type == BASE_TYPE_STRUCT) { + // Calls the accessor that takes an accessor object with a + // new object. + // val pos + // get() = pos(Vec3()) + GenerateGetterOneLine(writer, field_name, opt_ret_type, [&]() { + writer += "{{field_name}}({{field_type}}())"; + }); + } else if (value_base_type == BASE_TYPE_VECTOR && + field.value.type.element == BASE_TYPE_STRUCT) { + // Accessors for vectors of structs also take accessor objects, + // this generates a variant without that argument. + // ex: fun weapons(j: Int) = weapons(Weapon(), j) + GenerateFunOneLine(writer, field_name, "j: Int", opt_ret_type, [&]() { + writer += "{{field_name}}({{return_type}}(), j)"; + }); + } + + if (IsScalar(value_base_type)) { + if (struct_def.fixed) { + GenerateGetterOneLine(writer, field_name, return_type, [&]() { + writer += "{{bbgetter}}(bb_pos + {{offset}}){{ucast}}"; + }); + } else { + GenerateGetter(writer, field_name, return_type, [&]() { + writer += "val o = __offset({{offset}})"; + writer += + "return if(o != 0) {{bbgetter}}" + "(o + bb_pos){{ucast}} else " + "{{field_default}}"; + }); + } + } else { + switch (value_base_type) { + case BASE_TYPE_STRUCT: + if (struct_def.fixed) { + // create getter with object reuse + // ex: + // fun pos(obj: Vec3) : Vec3? = obj.__assign(bb_pos + 4, bb) + // ? adds nullability annotation + GenerateFunOneLine( + writer, field_name, "obj: " + field_type, return_type + "?", + [&]() { writer += "obj.__assign(bb_pos + {{offset}}, bb)"; }); + } else { + // create getter with object reuse + // ex: + // fun pos(obj: Vec3) : Vec3? { + // val o = __offset(4) + // return if(o != 0) { + // obj.__assign(o + bb_pos, bb) + // else { + // null + // } + // } + // ? adds nullability annotation + GenerateFun( + writer, field_name, "obj: " + field_type, return_type + "?", + [&]() { + auto fixed = field.value.type.struct_def->fixed; + + writer.SetValue("seek", Indirect("o + bb_pos", fixed)); + OffsetWrapper( + writer, offset_val, + [&]() { writer += "obj.__assign({{seek}}, bb)"; }, + [&]() { writer += "null"; }); + }); + } + break; + case BASE_TYPE_STRING: + // create string getter + // e.g. + // val Name : String? + // get() = { + // val o = __offset(10) + // return if (o != 0) __string(o + bb_pos) else null + // } + // ? adds nullability annotation + GenerateGetter(writer, field_name, return_type + "?", [&]() { + writer += "val o = __offset({{offset}})"; + writer += "return if (o != 0) __string(o + bb_pos) else null"; + }); + break; + case BASE_TYPE_VECTOR: { + // e.g. + // fun inventory(j: Int) : UByte { + // val o = __offset(14) + // return if (o != 0) { + // bb.get(__vector(o) + j * 1).toUByte() + // } else { + // 0 + // } + // } + + auto vectortype = field.value.type.VectorType(); + std::string params = "j: Int"; + std::string nullable = IsScalar(vectortype.base_type) ? "" : "?"; + + if (vectortype.base_type == BASE_TYPE_STRUCT || + vectortype.base_type == BASE_TYPE_UNION) { + params = "obj: " + field_type + ", j: Int"; } - if (IsScalar(value_base_type)) { - if (struct_def.fixed) { - GenerateGetterOneLine(writer, field_name, return_type, [&](){ - writer += "{{bbgetter}}(bb_pos + {{offset}}){{ucast}}"; - }); - } else { - GenerateGetter(writer, field_name, return_type, [&](){ - writer += "val o = __offset({{offset}})"; - writer += "return if(o != 0) {{bbgetter}}" - "(o + bb_pos){{ucast}} else " - "{{field_default}}"; - }); - } - } else { - switch (value_base_type) { - case BASE_TYPE_STRUCT: - if (struct_def.fixed) { - // create getter with object reuse - // ex: - // fun pos(obj: Vec3) : Vec3? = obj.__assign(bb_pos + 4, bb) - // ? adds nullability annotation - GenerateFunOneLine(writer, - field_name, "obj: " + field_type , - return_type + "?", [&](){ - writer += "obj.__assign(bb_pos + {{offset}}, bb)"; - }); - } else { - // create getter with object reuse - // ex: - // fun pos(obj: Vec3) : Vec3? { - // val o = __offset(4) - // return if(o != 0) { - // obj.__assign(o + bb_pos, bb) - // else { - // null - // } - // } - // ? adds nullability annotation - GenerateFun(writer, field_name, "obj: " + field_type, - return_type + "?", [&](){ - auto fixed = field.value.type.struct_def->fixed; - - writer.SetValue("seek", Indirect("o + bb_pos", fixed)); - OffsetWrapper(writer, - offset_val, - [&]() { writer += "obj.__assign({{seek}}, bb)"; }, - [&]() { writer += "null"; }); - }); - } - break; - case BASE_TYPE_STRING: - // create string getter - // e.g. - // val Name : String? - // get() = { - // val o = __offset(10) - // return if (o != 0) __string(o + bb_pos) else null - // } - // ? adds nullability annotation - GenerateGetter(writer, field_name, return_type + "?", [&](){ - - writer += "val o = __offset({{offset}})"; - writer += "return if (o != 0) __string(o + bb_pos) else null"; - }); - break; - case BASE_TYPE_VECTOR: { - // e.g. - // fun inventory(j: Int) : UByte { - // val o = __offset(14) - // return if (o != 0) { - // bb.get(__vector(o) + j * 1).toUByte() - // } else { - // 0 - // } - // } - - auto vectortype = field.value.type.VectorType(); - std::string params = "j: Int"; - std::string nullable = IsScalar(vectortype.base_type) ? "" - : "?"; - - if (vectortype.base_type == BASE_TYPE_STRUCT || - vectortype.base_type == BASE_TYPE_UNION) { - params = "obj: " + field_type + ", j: Int"; - } - - auto ret_type = return_type + nullable; - GenerateFun(writer, field_name, params, ret_type, [&](){ - auto inline_size = NumToString(InlineSize(vectortype)); - auto index = "__vector(o) + j * " + inline_size; - auto not_found = NotFoundReturn(field.value.type.element); - auto found = ""; - writer.SetValue("index", index); - switch(vectortype.base_type) { - case BASE_TYPE_STRUCT: { - bool fixed = vectortype.struct_def->fixed; - writer.SetValue("index", Indirect(index, fixed)); - found = "obj.__assign({{index}}, bb)"; - break; - } - case BASE_TYPE_UNION: - found = "{{bbgetter}}(obj, {{index}} - bb_pos){{ucast}}"; - break; - default: - found = "{{bbgetter}}({{index}}){{ucast}}"; - } - OffsetWrapper(writer, offset_val, - [&]() { writer += found; } , - [&]() { writer += not_found; }); - }); - break; + auto ret_type = return_type + nullable; + GenerateFun(writer, field_name, params, ret_type, [&]() { + auto inline_size = NumToString(InlineSize(vectortype)); + auto index = "__vector(o) + j * " + inline_size; + auto not_found = NotFoundReturn(field.value.type.element); + auto found = ""; + writer.SetValue("index", index); + switch (vectortype.base_type) { + case BASE_TYPE_STRUCT: { + bool fixed = vectortype.struct_def->fixed; + writer.SetValue("index", Indirect(index, fixed)); + found = "obj.__assign({{index}}, bb)"; + break; } case BASE_TYPE_UNION: - GenerateFun(writer, field_name, "obj: " + field_type, - return_type + "?", [&](){ - writer += OffsetWrapperOneLine(offset_val, - bbgetter + "(obj, o + bb_pos)", - "null"); - }); - break; - default: - FLATBUFFERS_ASSERT(0); - } - } - - if (value_base_type == BASE_TYPE_VECTOR) { - // Generate Lenght functions for vectors - GenerateGetter(writer, field_name + "Length", "Int", [&](){ - writer += OffsetWrapperOneLine(offset_val, - "__vector_len(o)", "0"); - }); - - // See if we should generate a by-key accessor. - if (field.value.type.element == BASE_TYPE_STRUCT && - !field.value.type.struct_def->fixed) { - auto &sd = *field.value.type.struct_def; - auto &fields = sd.fields.vec; - for (auto kit = fields.begin(); kit != fields.end(); ++kit) { - auto &kfield = **kit; - if (kfield.key) { - auto qualified_name = WrapInNameSpace(sd); - auto name = MakeCamel(Esc(field.name), false) + "ByKey"; - auto params = "key: " + GenTypeGet(kfield.value.type); - auto rtype = qualified_name + "?"; - GenerateFun(writer, name, params, rtype, [&] () { - OffsetWrapper(writer, offset_val, - [&] () { - writer += qualified_name + - ".__lookup_by_key(null, __vector(o), key, bb)"; - }, - [&] () { - writer += "null"; - }); - }); - - auto param2 = "obj: " + qualified_name + - ", key: " + - GenTypeGet(kfield.value.type); - GenerateFun(writer, name, param2, rtype, [&](){ - OffsetWrapper(writer, offset_val, - [&] () { - writer += qualified_name + - ".__lookup_by_key(obj, __vector(o), key, bb)"; - }, - [&]() { writer += "null"; }); - }); - - break; - } - } - } - } - - if ((value_base_type == BASE_TYPE_VECTOR && - IsScalar(field.value.type.VectorType().base_type)) || - value_base_type == BASE_TYPE_STRING) { - - auto end_idx = NumToString(value_base_type == BASE_TYPE_STRING - ? 1 - : InlineSize(field.value.type.VectorType())); - // Generate a ByteBuffer accessor for strings & vectors of scalars. - // e.g. - // val inventoryByteBuffer: ByteBuffer - // get = __vector_as_bytebuffer(14, 1) - - GenerateGetterOneLine(writer, field_name + "AsByteBuffer", - "ByteBuffer", [&](){ - writer.SetValue("end", end_idx); - writer += "__vector_as_bytebuffer({{offset}}, {{end}})"; - }); - - // Generate a ByteBuffer accessor for strings & vectors of scalars. - // e.g. - // fun inventoryInByteBuffer(_bb: Bytebuffer): - // ByteBuffer = __vector_as_bytebuffer(_bb, 14, 1) - GenerateFunOneLine(writer, field_name + "InByteBuffer", - "_bb: ByteBuffer", "ByteBuffer", [&](){ - writer.SetValue("end", end_idx); - writer += "__vector_in_bytebuffer(_bb, {{offset}}, {{end}})"; - }); - } - - // generate object accessors if is nested_flatbuffer - //fun testnestedflatbufferAsMonster() : Monster? - //{ return testnestedflatbufferAsMonster(new Monster()); } - - if (field.nested_flatbuffer) { - auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer); - auto nested_method_name = - field_name + "As" + - field.nested_flatbuffer->name; - - GenerateGetterOneLine(writer, - nested_method_name, - nested_type_name + "?", [&](){ - writer += nested_method_name + "(" + nested_type_name + "())"; - }); - - GenerateFun(writer, - nested_method_name, - "obj: " + nested_type_name, - nested_type_name + "?", [&](){ - OffsetWrapper(writer, offset_val, - [&]() { writer += "obj.__assign(__indirect(__vector(o)), bb)"; }, - [&]() { writer += "null";}); - }); - } - - // Generate mutators for scalar fields or vectors of scalars. - if (parser_.opts.mutable_buffer) { - auto value_type = field.value.type; - auto underlying_type = value_base_type == BASE_TYPE_VECTOR - ? value_type.VectorType() - : value_type; - auto name = "mutate" + MakeCamel(Esc(field.name), true); - auto size = NumToString(InlineSize(underlying_type)); - auto params = Esc(field.name) + ": " + GenTypeGet(underlying_type); - // A vector mutator also needs the index of the vector element it should - // mutate. - if (value_base_type == BASE_TYPE_VECTOR) - params.insert(0, "j: Int, "); - - // Boolean parameters have to be explicitly converted to byte - // representation. - auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL - ? "(if(" + Esc(field.name) + ") 1 else 0).toByte()" - : Esc(field.name); - - auto setter_index = value_base_type == BASE_TYPE_VECTOR - ? "__vector(o) + j * " + size - : (struct_def.fixed - ? "bb_pos + " + offset_val - : "o + bb_pos"); - if (IsScalar(value_base_type) || (value_base_type == BASE_TYPE_VECTOR && - IsScalar(value_type.VectorType().base_type))) { - - auto statements = [&] () { - writer.SetValue("bbsetter", ByteBufferSetter(underlying_type)); - writer.SetValue("index", setter_index); - writer.SetValue("params", setter_parameter); - writer.SetValue("cast", CastToSigned(field)); - if (struct_def.fixed) { - writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})"; - } else { - OffsetWrapper(writer, offset_val, [&](){ - writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})"; - writer += "true"; - }, [&](){ writer += "false";}); - } - }; - - if (struct_def.fixed) { - GenerateFunOneLine(writer, name, params, "ByteBuffer", - statements); - } else { - GenerateFun(writer, name, params, "Boolean", - statements); - } - } - } - } - if (struct_def.has_key && !struct_def.fixed) { - // Key Comparison method - GenerateOverrideFun( - writer, - "keysCompare", - "o1: Int, o2: Int, _bb: ByteBuffer", "Int", [&]() { - if (key_field->value.type.base_type == BASE_TYPE_STRING) { - writer.SetValue("offset", NumToString(key_field->value.offset)); - writer += " return compareStrings(__offset({{offset}}, o1, " - "_bb), __offset({{offset}}, o2, _bb), _bb)"; - - } else { - auto getter1 = GenLookupByKey(key_field, "_bb", "o1"); - auto getter2 = GenLookupByKey(key_field, "_bb", "o2"); - writer += "val val_1 = " + getter1; - writer += "val val_2 = " + getter2; - writer += "return (val_1 - val_2).sign"; - } + found = "{{bbgetter}}(obj, {{index}} - bb_pos){{ucast}}"; + break; + default: found = "{{bbgetter}}({{index}}){{ucast}}"; + } + OffsetWrapper( + writer, offset_val, [&]() { writer += found; }, + [&]() { writer += not_found; }); }); + break; + } + case BASE_TYPE_UNION: + GenerateFun(writer, field_name, "obj: " + field_type, + return_type + "?", [&]() { + writer += OffsetWrapperOneLine( + offset_val, bbgetter + "(obj, o + bb_pos)", + "null"); + }); + break; + default: FLATBUFFERS_ASSERT(0); } - } - - static std::string CastToUsigned(const FieldDef &field) { - return CastToUsigned(field.value.type); - } - - static std::string CastToUsigned(const Type type) { - switch (type.base_type) { - case BASE_TYPE_UINT: - return ".toUInt()"; - case BASE_TYPE_UCHAR: - case BASE_TYPE_UTYPE: - return ".toUByte()"; - case BASE_TYPE_USHORT: - return ".toUShort()"; - case BASE_TYPE_ULONG: - return ".toULong()"; - case BASE_TYPE_VECTOR: - return CastToUsigned(type.VectorType()); - default: - return ""; - } - } - - static std::string CastToSigned(const FieldDef &field) { - return CastToSigned(field.value.type); - } - - static std::string CastToSigned(const Type type) { - switch (type.base_type) { - case BASE_TYPE_UINT: - return ".toInt()"; - case BASE_TYPE_UCHAR: - case BASE_TYPE_UTYPE: - return ".toByte()"; - case BASE_TYPE_USHORT: - return ".toShort()"; - case BASE_TYPE_ULONG: - return ".toLong()"; - case BASE_TYPE_VECTOR: - return CastToSigned(type.VectorType()); - default: - return ""; - } - } - - static std::string LiteralSuffix(const BaseType type) { - switch (type) { - case BASE_TYPE_UINT: - case BASE_TYPE_UCHAR: - case BASE_TYPE_UTYPE: - case BASE_TYPE_USHORT: - return "u"; - case BASE_TYPE_ULONG: - return "UL"; - case BASE_TYPE_LONG: - return "L"; - default: - return ""; - } - } - - void GenerateCompanionObject(CodeWriter &code, - const std::function &callback) const { - code += "companion object {"; - code.IncrementIdentLevel(); - callback(); - code.DecrementIdentLevel(); - code += "}"; - } - - // Generate a documentation comment, if available. - void GenerateComment(const std::vector &dc, CodeWriter &writer, - const CommentConfig *config) const { - if (dc.begin() == dc.end()) { - // Don't output empty comment blocks with 0 lines of comment content. - return; } - if (config != nullptr && config->first_line != nullptr) { - writer += std::string(config->first_line); - } - std::string line_prefix = - ((config != nullptr && config->content_line_prefix != nullptr) - ? config->content_line_prefix - : "///"); - for (auto it = dc.begin(); it != dc.end(); ++it) { - writer += line_prefix + *it; - } - if (config != nullptr && config->last_line != nullptr) { - writer += std::string(config->last_line); - } - } - - static void GenerateGetRootAsAccessors(const std::string &struct_name, - CodeWriter &writer) { - // Generate a special accessor for the table that when used as the root - // ex: fun getRootAsMonster(_bb: ByteBuffer): Monster {...} - writer.SetValue("gr_name", struct_name); - writer.SetValue("gr_method", "getRootAs" + struct_name); - - // create convenience method that doesn't require an existing object - writer += "fun {{gr_method}}(_bb: ByteBuffer): {{gr_name}} = \\"; - writer += "{{gr_method}}(_bb, {{gr_name}}())"; - - // create method that allows object reuse - // ex: fun Monster getRootAsMonster(_bb: ByteBuffer, obj: Monster) {...} - writer += "fun {{gr_method}}" - "(_bb: ByteBuffer, obj: {{gr_name}}): {{gr_name}} {"; - writer.IncrementIdentLevel(); - writer += "_bb.order(ByteOrder.LITTLE_ENDIAN)"; - writer += "return (obj.__assign(_bb.getInt(_bb.position())" - " + _bb.position(), _bb))"; - writer.DecrementIdentLevel(); - writer += "}"; - } - - static void GenerateStaticConstructor(const StructDef &struct_def, - CodeWriter &code) { - // create a struct constructor function - auto params = StructConstructorParams(struct_def); - GenerateFun(code, "create" + Esc(struct_def.name), params, "Int", [&](){ - GenStructBody(struct_def, code, ""); - code += "return builder.offset()"; + if (value_base_type == BASE_TYPE_VECTOR) { + // Generate Lenght functions for vectors + GenerateGetter(writer, field_name + "Length", "Int", [&]() { + writer += OffsetWrapperOneLine(offset_val, "__vector_len(o)", "0"); }); - } - static std::string StructConstructorParams(const StructDef &struct_def, - const std::string &prefix = "") { - //builder: FlatBufferBuilder - std::stringstream out; - auto field_vec = struct_def.fields.vec; - if (prefix.empty()) { - out << "builder: FlatBufferBuilder"; - } - for (auto it = field_vec.begin(); it != field_vec.end(); ++it) { - auto &field = **it; - if (IsStruct(field.value.type)) { - // Generate arguments for a struct inside a struct. To ensure - // names don't clash, and to make it obvious these arguments are - // constructing a nested struct, prefix the name with the field - // name. - out << StructConstructorParams(*field.value.type.struct_def, - prefix + (Esc(field.name) + "_")); - } else { - out << ", " << prefix << MakeCamel(Esc(field.name), false) - << ": " - << GenTypeBasic(field.value.type.base_type); + // See if we should generate a by-key accessor. + if (field.value.type.element == BASE_TYPE_STRUCT && + !field.value.type.struct_def->fixed) { + auto &sd = *field.value.type.struct_def; + auto &fields = sd.fields.vec; + for (auto kit = fields.begin(); kit != fields.end(); ++kit) { + auto &kfield = **kit; + if (kfield.key) { + auto qualified_name = WrapInNameSpace(sd); + auto name = MakeCamel(Esc(field.name), false) + "ByKey"; + auto params = "key: " + GenTypeGet(kfield.value.type); + auto rtype = qualified_name + "?"; + GenerateFun(writer, name, params, rtype, [&]() { + OffsetWrapper( + writer, offset_val, + [&]() { + writer += qualified_name + + ".__lookup_by_key(null, __vector(o), key, bb)"; + }, + [&]() { writer += "null"; }); + }); + + auto param2 = "obj: " + qualified_name + + ", key: " + GenTypeGet(kfield.value.type); + GenerateFun(writer, name, param2, rtype, [&]() { + OffsetWrapper( + writer, offset_val, + [&]() { + writer += qualified_name + + ".__lookup_by_key(obj, __vector(o), key, bb)"; + }, + [&]() { writer += "null"; }); + }); + + break; } + } } - return out.str(); - } + } - static void GeneratePropertyOneLine(CodeWriter &writer, - const std::string &name, - const std::string &type, - const std::function &body) { - // Generates Kotlin getter for properties - // e.g.: - // val prop: Mytype = x - writer.SetValue("_name", name); - writer.SetValue("_type", type); - writer += "val {{_name}} : {{_type}} = \\"; - body(); - } - static void GenerateGetterOneLine(CodeWriter &writer, - const std::string &name, - const std::string &type, - const std::function &body) { - // Generates Kotlin getter for properties - // e.g.: - // val prop: Mytype get() = x - writer.SetValue("_name", name); - writer.SetValue("_type", type); - writer += "val {{_name}} : {{_type}} get() = \\"; - body(); - } + if ((value_base_type == BASE_TYPE_VECTOR && + IsScalar(field.value.type.VectorType().base_type)) || + value_base_type == BASE_TYPE_STRING) { + auto end_idx = + NumToString(value_base_type == BASE_TYPE_STRING + ? 1 + : InlineSize(field.value.type.VectorType())); + // Generate a ByteBuffer accessor for strings & vectors of scalars. + // e.g. + // val inventoryByteBuffer: ByteBuffer + // get = __vector_as_bytebuffer(14, 1) - static void GenerateGetter(CodeWriter &writer, - const std::string &name, - const std::string &type, - const std::function &body) { - // Generates Kotlin getter for properties - // e.g.: - // val prop: Mytype - // get() = { - // return x - // } - writer.SetValue("name", name); - writer.SetValue("type", type); - writer += "val {{name}} : {{type}}"; - writer.IncrementIdentLevel(); - writer += "get() {"; - writer.IncrementIdentLevel(); - body(); - writer.DecrementIdentLevel(); - writer += "}"; - writer.DecrementIdentLevel(); - } + GenerateGetterOneLine( + writer, field_name + "AsByteBuffer", "ByteBuffer", [&]() { + writer.SetValue("end", end_idx); + writer += "__vector_as_bytebuffer({{offset}}, {{end}})"; + }); - static void GenerateFun(CodeWriter &writer, - const std::string &name, - const std::string ¶ms, - const std::string &returnType, - const std::function &body) { - // Generates Kotlin function - // e.g.: - // fun path(j: Int): Vec3 { - // return path(Vec3(), j) - // } - auto noreturn = returnType.empty(); - writer.SetValue("name", name); - writer.SetValue("params", params); - writer.SetValue("return_type", noreturn ? "" : ": " + returnType); - writer += "fun {{name}}({{params}}) {{return_type}} {"; - writer.IncrementIdentLevel(); - body(); - writer.DecrementIdentLevel(); - writer += "}"; - } + // Generate a ByteBuffer accessor for strings & vectors of scalars. + // e.g. + // fun inventoryInByteBuffer(_bb: Bytebuffer): + // ByteBuffer = __vector_as_bytebuffer(_bb, 14, 1) + GenerateFunOneLine( + writer, field_name + "InByteBuffer", "_bb: ByteBuffer", + "ByteBuffer", [&]() { + writer.SetValue("end", end_idx); + writer += "__vector_in_bytebuffer(_bb, {{offset}}, {{end}})"; + }); + } - static void GenerateFunOneLine(CodeWriter &writer, - const std::string &name, - const std::string ¶ms, - const std::string &returnType, - const std::function &body) { - // Generates Kotlin function - // e.g.: - // fun path(j: Int): Vec3 = return path(Vec3(), j) - writer.SetValue("name", name); - writer.SetValue("params", params); - writer.SetValue("return_type_p", returnType.empty() ? "" : - " : " + returnType); - writer += "fun {{name}}({{params}}){{return_type_p}} = \\"; - body(); - } + // generate object accessors if is nested_flatbuffer + // fun testnestedflatbufferAsMonster() : Monster? + //{ return testnestedflatbufferAsMonster(new Monster()); } - static void GenerateOverrideFun(CodeWriter &writer, - const std::string &name, - const std::string ¶ms, - const std::string &returnType, - const std::function &body) { - // Generates Kotlin function - // e.g.: - // override fun path(j: Int): Vec3 = return path(Vec3(), j) - writer += "override \\"; - GenerateFun(writer, name, params, returnType, body); - } + if (field.nested_flatbuffer) { + auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer); + auto nested_method_name = + field_name + "As" + field.nested_flatbuffer->name; - static void GenerateOverrideFunOneLine(CodeWriter &writer, - const std::string &name, - const std::string ¶ms, - const std::string &returnType, - const std::string &statement) { - // Generates Kotlin function - // e.g.: - // override fun path(j: Int): Vec3 = return path(Vec3(), j) - writer.SetValue("name", name); - writer.SetValue("params", params); - writer.SetValue("return_type", returnType.empty() ? "" : - " : " + returnType); - writer += "override fun {{name}}({{params}}){{return_type}} = \\"; - writer += statement; - } + GenerateGetterOneLine( + writer, nested_method_name, nested_type_name + "?", [&]() { + writer += nested_method_name + "(" + nested_type_name + "())"; + }); - static std::string OffsetWrapperOneLine(const std::string &offset, - const std::string &found, - const std::string ¬_found) { - return "val o = __offset(" + offset + "); return if (o != 0) " + found + - " else " + not_found; - } + GenerateFun(writer, nested_method_name, "obj: " + nested_type_name, + nested_type_name + "?", [&]() { + OffsetWrapper( + writer, offset_val, + [&]() { + writer += + "obj.__assign(__indirect(__vector(o)), bb)"; + }, + [&]() { writer += "null"; }); + }); + } - static void OffsetWrapper(CodeWriter &code, - const std::string &offset, - const std::function &found, - const std::function ¬_found) { - code += "val o = __offset(" + offset + ")"; - code +="return if (o != 0) {"; - code.IncrementIdentLevel(); - found(); - code.DecrementIdentLevel(); - code += "} else {"; - code.IncrementIdentLevel(); - not_found(); - code.DecrementIdentLevel(); - code += "}"; - } + // Generate mutators for scalar fields or vectors of scalars. + if (parser_.opts.mutable_buffer) { + auto value_type = field.value.type; + auto underlying_type = value_base_type == BASE_TYPE_VECTOR + ? value_type.VectorType() + : value_type; + auto name = "mutate" + MakeCamel(Esc(field.name), true); + auto size = NumToString(InlineSize(underlying_type)); + auto params = Esc(field.name) + ": " + GenTypeGet(underlying_type); + // A vector mutator also needs the index of the vector element it should + // mutate. + if (value_base_type == BASE_TYPE_VECTOR) params.insert(0, "j: Int, "); - static std::string Indirect(const std::string &index, bool fixed) { - // We apply __indirect() and struct is not fixed. - if (!fixed) - return "__indirect(" + index + ")"; - return index; - } + // Boolean parameters have to be explicitly converted to byte + // representation. + auto setter_parameter = + underlying_type.base_type == BASE_TYPE_BOOL + ? "(if(" + Esc(field.name) + ") 1 else 0).toByte()" + : Esc(field.name); - static std::string NotFoundReturn(BaseType el) { - switch (el) { - case BASE_TYPE_FLOAT: - return "0.0f"; - case BASE_TYPE_DOUBLE: - return "0.0"; - case BASE_TYPE_BOOL: - return "false"; - case BASE_TYPE_LONG: - case BASE_TYPE_INT: - case BASE_TYPE_CHAR: - case BASE_TYPE_SHORT: - return "0"; - case BASE_TYPE_UINT: - case BASE_TYPE_UCHAR: - case BASE_TYPE_USHORT: - case BASE_TYPE_UTYPE: - return "0u"; - case BASE_TYPE_ULONG: - return "0uL"; - default: - return "null"; + auto setter_index = + value_base_type == BASE_TYPE_VECTOR + ? "__vector(o) + j * " + size + : (struct_def.fixed ? "bb_pos + " + offset_val : "o + bb_pos"); + if (IsScalar(value_base_type) || + (value_base_type == BASE_TYPE_VECTOR && + IsScalar(value_type.VectorType().base_type))) { + auto statements = [&]() { + writer.SetValue("bbsetter", ByteBufferSetter(underlying_type)); + writer.SetValue("index", setter_index); + writer.SetValue("params", setter_parameter); + writer.SetValue("cast", CastToSigned(field)); + if (struct_def.fixed) { + writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})"; + } else { + OffsetWrapper( + writer, offset_val, + [&]() { + writer += "{{bbsetter}}({{index}}, {{params}}{{cast}})"; + writer += "true"; + }, + [&]() { writer += "false"; }); + } + }; + + if (struct_def.fixed) { + GenerateFunOneLine(writer, name, params, "ByteBuffer", statements); + } else { + GenerateFun(writer, name, params, "Boolean", statements); + } } + } + } + if (struct_def.has_key && !struct_def.fixed) { + // Key Comparison method + GenerateOverrideFun( + writer, "keysCompare", "o1: Int, o2: Int, _bb: ByteBuffer", "Int", + [&]() { + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + writer.SetValue("offset", NumToString(key_field->value.offset)); + writer += + " return compareStrings(__offset({{offset}}, o1, " + "_bb), __offset({{offset}}, o2, _bb), _bb)"; + + } else { + auto getter1 = GenLookupByKey(key_field, "_bb", "o1"); + auto getter2 = GenLookupByKey(key_field, "_bb", "o2"); + writer += "val val_1 = " + getter1; + writer += "val val_2 = " + getter2; + writer += "return (val_1 - val_2).sign"; + } + }); + } + } + + static std::string CastToUsigned(const FieldDef &field) { + return CastToUsigned(field.value.type); + } + + static std::string CastToUsigned(const Type type) { + switch (type.base_type) { + case BASE_TYPE_UINT: return ".toUInt()"; + case BASE_TYPE_UCHAR: + case BASE_TYPE_UTYPE: return ".toUByte()"; + case BASE_TYPE_USHORT: return ".toUShort()"; + case BASE_TYPE_ULONG: return ".toULong()"; + case BASE_TYPE_VECTOR: return CastToUsigned(type.VectorType()); + default: return ""; + } + } + + static std::string CastToSigned(const FieldDef &field) { + return CastToSigned(field.value.type); + } + + static std::string CastToSigned(const Type type) { + switch (type.base_type) { + case BASE_TYPE_UINT: return ".toInt()"; + case BASE_TYPE_UCHAR: + case BASE_TYPE_UTYPE: return ".toByte()"; + case BASE_TYPE_USHORT: return ".toShort()"; + case BASE_TYPE_ULONG: return ".toLong()"; + case BASE_TYPE_VECTOR: return CastToSigned(type.VectorType()); + default: return ""; + } + } + + static std::string LiteralSuffix(const BaseType type) { + switch (type) { + case BASE_TYPE_UINT: + case BASE_TYPE_UCHAR: + case BASE_TYPE_UTYPE: + case BASE_TYPE_USHORT: return "u"; + case BASE_TYPE_ULONG: return "UL"; + case BASE_TYPE_LONG: return "L"; + default: return ""; + } + } + + void GenerateCompanionObject(CodeWriter &code, + const std::function &callback) const { + code += "companion object {"; + code.IncrementIdentLevel(); + callback(); + code.DecrementIdentLevel(); + code += "}"; + } + + // Generate a documentation comment, if available. + void GenerateComment(const std::vector &dc, CodeWriter &writer, + const CommentConfig *config) const { + if (dc.begin() == dc.end()) { + // Don't output empty comment blocks with 0 lines of comment content. + return; } - // This tracks the current namespace used to determine if a type need to be - // prefixed by its namespace - const Namespace *cur_name_space_; + if (config != nullptr && config->first_line != nullptr) { + writer += std::string(config->first_line); + } + std::string line_prefix = + ((config != nullptr && config->content_line_prefix != nullptr) + ? config->content_line_prefix + : "///"); + for (auto it = dc.begin(); it != dc.end(); ++it) { + writer += line_prefix + *it; + } + if (config != nullptr && config->last_line != nullptr) { + writer += std::string(config->last_line); + } + } + + static void GenerateGetRootAsAccessors(const std::string &struct_name, + CodeWriter &writer) { + // Generate a special accessor for the table that when used as the root + // ex: fun getRootAsMonster(_bb: ByteBuffer): Monster {...} + writer.SetValue("gr_name", struct_name); + writer.SetValue("gr_method", "getRootAs" + struct_name); + + // create convenience method that doesn't require an existing object + writer += "fun {{gr_method}}(_bb: ByteBuffer): {{gr_name}} = \\"; + writer += "{{gr_method}}(_bb, {{gr_name}}())"; + + // create method that allows object reuse + // ex: fun Monster getRootAsMonster(_bb: ByteBuffer, obj: Monster) {...} + writer += + "fun {{gr_method}}" + "(_bb: ByteBuffer, obj: {{gr_name}}): {{gr_name}} {"; + writer.IncrementIdentLevel(); + writer += "_bb.order(ByteOrder.LITTLE_ENDIAN)"; + writer += + "return (obj.__assign(_bb.getInt(_bb.position())" + " + _bb.position(), _bb))"; + writer.DecrementIdentLevel(); + writer += "}"; + } + + static void GenerateStaticConstructor(const StructDef &struct_def, + CodeWriter &code) { + // create a struct constructor function + auto params = StructConstructorParams(struct_def); + GenerateFun(code, "create" + Esc(struct_def.name), params, "Int", [&]() { + GenStructBody(struct_def, code, ""); + code += "return builder.offset()"; + }); + } + + static std::string StructConstructorParams(const StructDef &struct_def, + const std::string &prefix = "") { + // builder: FlatBufferBuilder + std::stringstream out; + auto field_vec = struct_def.fields.vec; + if (prefix.empty()) { out << "builder: FlatBufferBuilder"; } + for (auto it = field_vec.begin(); it != field_vec.end(); ++it) { + auto &field = **it; + if (IsStruct(field.value.type)) { + // Generate arguments for a struct inside a struct. To ensure + // names don't clash, and to make it obvious these arguments are + // constructing a nested struct, prefix the name with the field + // name. + out << StructConstructorParams(*field.value.type.struct_def, + prefix + (Esc(field.name) + "_")); + } else { + out << ", " << prefix << MakeCamel(Esc(field.name), false) << ": " + << GenTypeBasic(field.value.type.base_type); + } + } + return out.str(); + } + + static void GeneratePropertyOneLine(CodeWriter &writer, + const std::string &name, + const std::string &type, + const std::function &body) { + // Generates Kotlin getter for properties + // e.g.: + // val prop: Mytype = x + writer.SetValue("_name", name); + writer.SetValue("_type", type); + writer += "val {{_name}} : {{_type}} = \\"; + body(); + } + static void GenerateGetterOneLine(CodeWriter &writer, const std::string &name, + const std::string &type, + const std::function &body) { + // Generates Kotlin getter for properties + // e.g.: + // val prop: Mytype get() = x + writer.SetValue("_name", name); + writer.SetValue("_type", type); + writer += "val {{_name}} : {{_type}} get() = \\"; + body(); + } + + static void GenerateGetter(CodeWriter &writer, const std::string &name, + const std::string &type, + const std::function &body) { + // Generates Kotlin getter for properties + // e.g.: + // val prop: Mytype + // get() = { + // return x + // } + writer.SetValue("name", name); + writer.SetValue("type", type); + writer += "val {{name}} : {{type}}"; + writer.IncrementIdentLevel(); + writer += "get() {"; + writer.IncrementIdentLevel(); + body(); + writer.DecrementIdentLevel(); + writer += "}"; + writer.DecrementIdentLevel(); + } + + static void GenerateFun(CodeWriter &writer, const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::function &body) { + // Generates Kotlin function + // e.g.: + // fun path(j: Int): Vec3 { + // return path(Vec3(), j) + // } + auto noreturn = returnType.empty(); + writer.SetValue("name", name); + writer.SetValue("params", params); + writer.SetValue("return_type", noreturn ? "" : ": " + returnType); + writer += "fun {{name}}({{params}}) {{return_type}} {"; + writer.IncrementIdentLevel(); + body(); + writer.DecrementIdentLevel(); + writer += "}"; + } + + static void GenerateFunOneLine(CodeWriter &writer, const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::function &body) { + // Generates Kotlin function + // e.g.: + // fun path(j: Int): Vec3 = return path(Vec3(), j) + writer.SetValue("name", name); + writer.SetValue("params", params); + writer.SetValue("return_type_p", + returnType.empty() ? "" : " : " + returnType); + writer += "fun {{name}}({{params}}){{return_type_p}} = \\"; + body(); + } + + static void GenerateOverrideFun(CodeWriter &writer, const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::function &body) { + // Generates Kotlin function + // e.g.: + // override fun path(j: Int): Vec3 = return path(Vec3(), j) + writer += "override \\"; + GenerateFun(writer, name, params, returnType, body); + } + + static void GenerateOverrideFunOneLine(CodeWriter &writer, + const std::string &name, + const std::string ¶ms, + const std::string &returnType, + const std::string &statement) { + // Generates Kotlin function + // e.g.: + // override fun path(j: Int): Vec3 = return path(Vec3(), j) + writer.SetValue("name", name); + writer.SetValue("params", params); + writer.SetValue("return_type", + returnType.empty() ? "" : " : " + returnType); + writer += "override fun {{name}}({{params}}){{return_type}} = \\"; + writer += statement; + } + + static std::string OffsetWrapperOneLine(const std::string &offset, + const std::string &found, + const std::string ¬_found) { + return "val o = __offset(" + offset + "); return if (o != 0) " + found + + " else " + not_found; + } + + static void OffsetWrapper(CodeWriter &code, const std::string &offset, + const std::function &found, + const std::function ¬_found) { + code += "val o = __offset(" + offset + ")"; + code += "return if (o != 0) {"; + code.IncrementIdentLevel(); + found(); + code.DecrementIdentLevel(); + code += "} else {"; + code.IncrementIdentLevel(); + not_found(); + code.DecrementIdentLevel(); + code += "}"; + } + + static std::string Indirect(const std::string &index, bool fixed) { + // We apply __indirect() and struct is not fixed. + if (!fixed) return "__indirect(" + index + ")"; + return index; + } + + static std::string NotFoundReturn(BaseType el) { + switch (el) { + case BASE_TYPE_FLOAT: return "0.0f"; + case BASE_TYPE_DOUBLE: return "0.0"; + case BASE_TYPE_BOOL: return "false"; + case BASE_TYPE_LONG: + case BASE_TYPE_INT: + case BASE_TYPE_CHAR: + case BASE_TYPE_SHORT: return "0"; + case BASE_TYPE_UINT: + case BASE_TYPE_UCHAR: + case BASE_TYPE_USHORT: + case BASE_TYPE_UTYPE: return "0u"; + case BASE_TYPE_ULONG: return "0uL"; + default: return "null"; + } + } + + // This tracks the current namespace used to determine if a type need to be + // prefixed by its namespace + const Namespace *cur_name_space_; }; } // namespace kotlin bool GenerateKotlin(const Parser &parser, const std::string &path, const std::string &file_name) { - kotlin::KotlinGenerator generator(parser, path, file_name); - return generator.generate(); + kotlin::KotlinGenerator generator(parser, path, file_name); + return generator.generate(); } } // namespace flatbuffers diff --git a/src/idl_gen_lobster.cpp b/src/idl_gen_lobster.cpp index ef9e474c5..d5c99f7ee 100644 --- a/src/idl_gen_lobster.cpp +++ b/src/idl_gen_lobster.cpp @@ -27,14 +27,16 @@ namespace lobster { class LobsterGenerator : public BaseGenerator { public: - LobsterGenerator(const Parser &parser, const std::string &path, - const std::string &file_name) + LobsterGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) : BaseGenerator(parser, path, file_name, "" /* not used */, "_") { - static const char * const keywords[] = { - "nil", "true", "false", "return", "struct", "class", "import", "int", - "float", "string", "any", "def", "is", "from", "program", "private", - "coroutine", "resource", "enum", "typeof", "var", "let", "pakfile", - "switch", "case", "default", "namespace", "not", "and", "or", "bool", + static const char *const keywords[] = { + "nil", "true", "false", "return", "struct", "class", + "import", "int", "float", "string", "any", "def", + "is", "from", "program", "private", "coroutine", "resource", + "enum", "typeof", "var", "let", "pakfile", "switch", + "case", "default", "namespace", "not", "and", "or", + "bool", }; keywords_.insert(std::begin(keywords), std::end(keywords)); } @@ -66,7 +68,8 @@ class LobsterGenerator : public BaseGenerator { std::string LobsterType(const Type &type) { if (IsFloat(type.base_type)) return "float"; - if (IsScalar(type.base_type) && type.enum_def) return NormalizedName(*type.enum_def); + if (IsScalar(type.base_type) && type.enum_def) + return NormalizedName(*type.enum_def); if (!IsScalar(type.base_type)) return "flatbuffers_offset"; return "int"; } @@ -74,14 +77,14 @@ class LobsterGenerator : public BaseGenerator { // Returns the method name for use with add/put calls. std::string GenMethod(const Type &type) { return IsScalar(type.base_type) - ? MakeCamel(GenTypeBasic(type)) - : (IsStruct(type) ? "Struct" : "UOffsetTRelative"); + ? MakeCamel(GenTypeBasic(type)) + : (IsStruct(type) ? "Struct" : "UOffsetTRelative"); } // This uses Python names for now.. std::string GenTypeBasic(const Type &type) { static const char *ctypename[] = { - // clang-format off + // clang-format off #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ #PTYPE, @@ -93,8 +96,8 @@ class LobsterGenerator : public BaseGenerator { } // Generate a struct field, conditioned on its child type(s). - void GenStructAccessor(const StructDef &struct_def, - const FieldDef &field, std::string *code_ptr) { + void GenStructAccessor(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { GenComment(field.doc_comment, code_ptr, nullptr, " "); std::string &code = *code_ptr; auto offsets = NumToString(field.value.offset); @@ -102,13 +105,12 @@ class LobsterGenerator : public BaseGenerator { if (IsScalar(field.value.type.base_type)) { std::string acc; if (struct_def.fixed) { - acc = "buf_.read_" + GenTypeName(field.value.type) + - "_le(pos_ + " + offsets + ")"; + acc = "buf_.read_" + GenTypeName(field.value.type) + "_le(pos_ + " + + offsets + ")"; } else { - acc = "buf_.flatbuffers_field_" + - GenTypeName(field.value.type) + "(pos_, " + offsets + ", " + - field.value.constant + ")"; + acc = "buf_.flatbuffers_field_" + GenTypeName(field.value.type) + + "(pos_, " + offsets + ", " + field.value.constant + ")"; } if (field.value.type.enum_def) acc = NormalizedName(*field.value.type.enum_def) + "(" + acc + ")"; @@ -130,7 +132,8 @@ class LobsterGenerator : public BaseGenerator { break; } case BASE_TYPE_STRING: - code += def + "():\n return buf_.flatbuffers_field_string(pos_, " + + code += def + + "():\n return buf_.flatbuffers_field_string(pos_, " + offsets + ")\n"; break; case BASE_TYPE_VECTOR: { @@ -171,19 +174,20 @@ class LobsterGenerator : public BaseGenerator { } if (field.value.type.base_type == BASE_TYPE_VECTOR) { code += def + - "_length():\n return buf_.flatbuffers_field_vector_len(pos_, " + + "_length():\n return " + "buf_.flatbuffers_field_vector_len(pos_, " + offsets + ")\n"; } } // Generate table constructors, conditioned on its members' types. - void GenTableBuilders(const StructDef &struct_def, - std::string *code_ptr) { + void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; code += "struct " + NormalizedName(struct_def) + "Builder:\n b_:flatbuffers_builder\n"; code += " def start():\n b_.StartObject(" + - NumToString(struct_def.fields.vec.size()) + ")\n return this\n"; + NumToString(struct_def.fields.vec.size()) + + ")\n return this\n"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; @@ -209,8 +213,8 @@ class LobsterGenerator : public BaseGenerator { auto vector_type = field.value.type.VectorType(); auto alignment = InlineAlignment(vector_type); auto elem_size = InlineSize(vector_type); - code += NumToString(elem_size) + ", n_, " + NumToString(alignment) + - ")\n"; + code += + NumToString(elem_size) + ", n_, " + NumToString(alignment) + ")\n"; if (vector_type.base_type != BASE_TYPE_STRUCT || !vector_type.struct_def->fixed) { code += "def " + NormalizedName(struct_def) + "Create" + @@ -218,8 +222,7 @@ class LobsterGenerator : public BaseGenerator { "Vector(b_:flatbuffers_builder, v_:[" + LobsterType(vector_type) + "]):\n b_.StartVector(" + NumToString(elem_size) + ", v_.length, " + - NumToString(alignment) + - ")\n reverse(v_) e_: b_.Prepend" + + NumToString(alignment) + ")\n reverse(v_) e_: b_.Prepend" + GenMethod(vector_type) + "(e_)\n return b_.EndVector(v_.length)\n"; } @@ -243,7 +246,7 @@ class LobsterGenerator : public BaseGenerator { GenComment(struct_def.doc_comment, code_ptr, nullptr, ""); code += "class " + NormalizedName(struct_def) + " : flatbuffers_handle\n"; for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { + it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (field.deprecated) continue; GenStructAccessor(struct_def, field, code_ptr); @@ -252,8 +255,8 @@ class LobsterGenerator : public BaseGenerator { if (!struct_def.fixed) { // Generate a special accessor for the table that has been declared as // the root type. - code += "def GetRootAs" + NormalizedName(struct_def) + "(buf:string): return " + - NormalizedName(struct_def) + + code += "def GetRootAs" + NormalizedName(struct_def) + + "(buf:string): return " + NormalizedName(struct_def) + " { buf, buf.flatbuffers_indirect(0) }\n\n"; } if (struct_def.fixed) { @@ -283,8 +286,8 @@ class LobsterGenerator : public BaseGenerator { // Recursively generate arguments for a constructor, to deal with nested // structs. - void StructBuilderArgs(const StructDef &struct_def, - const char *nameprefix, std::string *code_ptr) { + void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix, + std::string *code_ptr) { for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; @@ -293,7 +296,8 @@ class LobsterGenerator : public BaseGenerator { // don't clash, and to make it obvious these arguments are constructing // a nested struct, prefix the name with the field name. StructBuilderArgs(*field.value.type.struct_def, - (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr); + (nameprefix + (NormalizedName(field) + "_")).c_str(), + code_ptr); } else { std::string &code = *code_ptr; code += ", " + (nameprefix + NormalizedName(field)) + ":" + @@ -304,8 +308,8 @@ class LobsterGenerator : public BaseGenerator { // Recursively generate struct construction statements and instert manual // padding. - void StructBuilderBody(const StructDef &struct_def, - const char *nameprefix, std::string *code_ptr) { + void StructBuilderBody(const StructDef &struct_def, const char *nameprefix, + std::string *code_ptr) { std::string &code = *code_ptr; code += " b_.Prep(" + NumToString(struct_def.minalign) + ", " + NumToString(struct_def.bytesize) + ")\n"; @@ -316,7 +320,8 @@ class LobsterGenerator : public BaseGenerator { code += " b_.Pad(" + NumToString(field.padding) + ")\n"; if (IsStruct(field.value.type)) { StructBuilderBody(*field.value.type.struct_def, - (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr); + (nameprefix + (NormalizedName(field) + "_")).c_str(), + code_ptr); } else { code += " b_.Prepend" + GenMethod(field.value.type) + "(" + nameprefix + NormalizedName(field) + ")\n"; @@ -325,11 +330,10 @@ class LobsterGenerator : public BaseGenerator { } // Create a struct with a builder and the struct's arguments. - void GenStructBuilder(const StructDef &struct_def, - std::string *code_ptr) { + void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; - code += "def Create" + NormalizedName(struct_def) + - "(b_:flatbuffers_builder"; + code += + "def Create" + NormalizedName(struct_def) + "(b_:flatbuffers_builder"; StructBuilderArgs(struct_def, "", code_ptr); code += "):\n"; StructBuilderBody(struct_def, "", code_ptr); @@ -363,8 +367,8 @@ class LobsterGenerator : public BaseGenerator { auto &struct_def = **it; GenStruct(struct_def, &code); } - return SaveFile((path_ + file_name_ + "_generated.lobster").c_str(), - code, false); + return SaveFile((path_ + file_name_ + "_generated.lobster").c_str(), code, + false); } private: @@ -375,7 +379,7 @@ class LobsterGenerator : public BaseGenerator { } // namespace lobster bool GenerateLobster(const Parser &parser, const std::string &path, - const std::string &file_name) { + const std::string &file_name) { lobster::LobsterGenerator generator(parser, path, file_name); return generator.generate(); } diff --git a/src/idl_gen_lua.cpp b/src/idl_gen_lua.cpp index 10df23117..6ae7dd4cd 100644 --- a/src/idl_gen_lua.cpp +++ b/src/idl_gen_lua.cpp @@ -14,716 +14,710 @@ * limitations under the License. */ - // independent from idl_parser, since this code is not needed for most clients +// independent from idl_parser, since this code is not needed for most clients #include +#include #include "flatbuffers/code_generators.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include - namespace flatbuffers { namespace lua { - // Hardcode spaces per indentation. - const CommentConfig def_comment = { nullptr, "--", nullptr }; - const char * Indent = " "; - const char * Comment = "-- "; - const char * End = "end\n"; - const char * EndFunc = "end\n"; - const char * SelfData = "self.view"; - const char * SelfDataPos = "self.view.pos"; - const char * SelfDataBytes = "self.view.bytes"; +// Hardcode spaces per indentation. +const CommentConfig def_comment = { nullptr, "--", nullptr }; +const char *Indent = " "; +const char *Comment = "-- "; +const char *End = "end\n"; +const char *EndFunc = "end\n"; +const char *SelfData = "self.view"; +const char *SelfDataPos = "self.view.pos"; +const char *SelfDataBytes = "self.view.bytes"; - class LuaGenerator : public BaseGenerator { - public: - LuaGenerator(const Parser &parser, const std::string &path, - const std::string &file_name) +class LuaGenerator : public BaseGenerator { + public: + LuaGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) : BaseGenerator(parser, path, file_name, "" /* not used */, - "" /* not used */) { - static const char * const keywords[] = { - "and", - "break", - "do", - "else", - "elseif", - "end", - "false", - "for", - "function", - "goto", - "if", - "in", - "local", - "nil", - "not", - "or", - "repeat", - "return", - "then", - "true", - "until", - "while" - }; - keywords_.insert(std::begin(keywords), std::end(keywords)); + "" /* not used */) { + static const char *const keywords[] = { + "and", "break", "do", "else", "elseif", "end", "false", "for", + "function", "goto", "if", "in", "local", "nil", "not", "or", + "repeat", "return", "then", "true", "until", "while" + }; + keywords_.insert(std::begin(keywords), std::end(keywords)); + } + + // Most field accessors need to retrieve and test the field offset first, + // this is the prefix code for that. + std::string OffsetPrefix(const FieldDef &field) { + return std::string(Indent) + "local o = " + SelfData + ":Offset(" + + NumToString(field.value.offset) + ")\n" + Indent + + "if o ~= 0 then\n"; + } + + // Begin a class declaration. + void BeginClass(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "local " + NormalizedName(struct_def) + " = {} -- the module\n"; + code += "local " + NormalizedMetaName(struct_def) + + " = {} -- the class metatable\n"; + code += "\n"; + } + + // Begin enum code with a class declaration. + void BeginEnum(const std::string &class_name, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "local " + class_name + " = {\n"; + } + + std::string EscapeKeyword(const std::string &name) const { + return keywords_.find(name) == keywords_.end() ? name : "_" + name; + } + + std::string NormalizedName(const Definition &definition) const { + return EscapeKeyword(definition.name); + } + + std::string NormalizedName(const EnumVal &ev) const { + return EscapeKeyword(ev.name); + } + + std::string NormalizedMetaName(const Definition &definition) const { + return EscapeKeyword(definition.name) + "_mt"; + } + + // A single enum member. + void EnumMember(const EnumDef &enum_def, const EnumVal &ev, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += std::string(Indent) + NormalizedName(ev) + " = " + + enum_def.ToString(ev) + ",\n"; + } + + // End enum code. + void EndEnum(std::string *code_ptr) { + std::string &code = *code_ptr; + code += "}\n"; + } + + void GenerateNewObjectPrototype(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "function " + NormalizedName(struct_def) + ".New()\n"; + code += std::string(Indent) + "local o = {}\n"; + code += std::string(Indent) + + "setmetatable(o, {__index = " + NormalizedMetaName(struct_def) + + "})\n"; + code += std::string(Indent) + "return o\n"; + code += EndFunc; + } + + // Initialize a new struct or table from existing data. + void NewRootTypeFromBuffer(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + + code += "function " + NormalizedName(struct_def) + ".GetRootAs" + + NormalizedName(struct_def) + "(buf, offset)\n"; + code += std::string(Indent) + + "local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n"; + code += std::string(Indent) + "local o = " + NormalizedName(struct_def) + + ".New()\n"; + code += std::string(Indent) + "o:Init(buf, n + offset)\n"; + code += std::string(Indent) + "return o\n"; + code += EndFunc; + } + + // Initialize an existing object with other data, to avoid an allocation. + void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + + GenReceiver(struct_def, code_ptr); + code += "Init(buf, pos)\n"; + code += + std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n"; + code += EndFunc; + } + + // Get the length of a vector. + void GetVectorLen(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)) + "Length()\n"; + code += OffsetPrefix(field); + code += + std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n"; + code += std::string(Indent) + End; + code += std::string(Indent) + "return 0\n"; + code += EndFunc; + } + + // Get the value of a struct's scalar. + void GetScalarFieldOfStruct(const StructDef &struct_def, + const FieldDef &field, std::string *code_ptr) { + std::string &code = *code_ptr; + std::string getter = GenGetter(field.value.type); + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)); + code += "()\n"; + code += std::string(Indent) + "return " + getter; + code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) + + ")\n"; + code += EndFunc; + } + + // Get the value of a table's scalar. + void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string getter = GenGetter(field.value.type); + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)); + code += "()\n"; + code += OffsetPrefix(field); + getter += std::string("o + ") + SelfDataPos + ")"; + auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL; + if (is_bool) { getter = "(" + getter + " ~= 0)"; } + code += std::string(Indent) + Indent + "return " + getter + "\n"; + code += std::string(Indent) + End; + std::string default_value; + if (is_bool) { + default_value = field.value.constant == "0" ? "false" : "true"; + } else { + default_value = field.value.constant; } + code += std::string(Indent) + "return " + default_value + "\n"; + code += EndFunc; + } - // Most field accessors need to retrieve and test the field offset first, - // this is the prefix code for that. - std::string OffsetPrefix(const FieldDef &field) { - return std::string(Indent) + - "local o = " + SelfData + ":Offset(" + NumToString(field.value.offset) + ")\n" + - Indent + "if o ~= 0 then\n"; + // Get a struct by initializing an existing struct. + // Specific to Struct. + void GetStructFieldOfStruct(const StructDef &struct_def, + const FieldDef &field, std::string *code_ptr) { + std::string &code = *code_ptr; + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)); + code += "(obj)\n"; + code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " + + SelfDataPos + " + "; + code += NumToString(field.value.offset) + ")\n"; + code += std::string(Indent) + "return obj\n"; + code += EndFunc; + } + + // Get a struct by initializing an existing struct. + // Specific to Table. + void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)); + code += "()\n"; + code += OffsetPrefix(field); + if (field.value.type.struct_def->fixed) { + code += + std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n"; + } else { + code += std::string(Indent) + Indent + "local x = " + SelfData + + ":Indirect(o + " + SelfDataPos + ")\n"; } + code += std::string(Indent) + Indent + "local obj = require('" + + TypeNameWithNamespace(field) + "').New()\n"; + code += + std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n"; + code += std::string(Indent) + Indent + "return obj\n"; + code += std::string(Indent) + End; + code += EndFunc; + } - // Begin a class declaration. - void BeginClass(const StructDef &struct_def, std::string *code_ptr) { - std::string &code = *code_ptr; - code += "local " + NormalizedName(struct_def) + " = {} -- the module\n"; - code += "local " + NormalizedMetaName(struct_def) + " = {} -- the class metatable\n"; - code += "\n"; + // Get the value of a string. + void GetStringField(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)); + code += "()\n"; + code += OffsetPrefix(field); + code += + std::string(Indent) + Indent + "return " + GenGetter(field.value.type); + code += std::string("o + ") + SelfDataPos + ")\n"; + code += std::string(Indent) + End; + code += EndFunc; + } + + // Get the value of a union from an object. + void GetUnionField(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)) + "()\n"; + code += OffsetPrefix(field); + + // TODO(rw): this works and is not the good way to it: + // bool is_native_table = TypeName(field) == "*flatbuffers.Table"; + // if (is_native_table) { + // code += std::string(Indent) + Indent + "from flatbuffers.table import + // Table\n"; + //} else { + // code += std::string(Indent) + Indent + + // code += "from ." + TypeName(field) + " import " + TypeName(field) + + // "\n"; + //} + code += + std::string(Indent) + Indent + + "local obj = " + "flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n"; + code += std::string(Indent) + Indent + GenGetter(field.value.type) + + "obj, o)\n"; + code += std::string(Indent) + Indent + "return obj\n"; + code += std::string(Indent) + End; + code += EndFunc; + } + + // Get the value of a vector's struct member. + void GetMemberOfVectorOfStruct(const StructDef &struct_def, + const FieldDef &field, std::string *code_ptr) { + std::string &code = *code_ptr; + auto vectortype = field.value.type.VectorType(); + + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)); + code += "(j)\n"; + code += OffsetPrefix(field); + code += + std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n"; + code += std::string(Indent) + Indent + "x = x + ((j-1) * "; + code += NumToString(InlineSize(vectortype)) + ")\n"; + if (!(vectortype.struct_def->fixed)) { + code += + std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n"; } + code += std::string(Indent) + Indent + "local obj = require('" + + TypeNameWithNamespace(field) + "').New()\n"; + code += + std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n"; + code += std::string(Indent) + Indent + "return obj\n"; + code += std::string(Indent) + End; + code += EndFunc; + } - // Begin enum code with a class declaration. - void BeginEnum(const std::string &class_name, std::string *code_ptr) { - std::string &code = *code_ptr; - code += "local " + class_name + " = {\n"; - } + // Get the value of a vector's non-struct member. Uses a named return + // argument to conveniently set the zero value for the result. + void GetMemberOfVectorOfNonStruct(const StructDef &struct_def, + const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + auto vectortype = field.value.type.VectorType(); - std::string EscapeKeyword(const std::string &name) const { - return keywords_.find(name) == keywords_.end() ? name : "_" + name; - } - - std::string NormalizedName(const Definition &definition) const { - return EscapeKeyword(definition.name); - } - - std::string NormalizedName(const EnumVal &ev) const { - return EscapeKeyword(ev.name); - } - - std::string NormalizedMetaName(const Definition &definition) const { - return EscapeKeyword(definition.name) + "_mt"; - } - - // A single enum member. - void EnumMember(const EnumDef &enum_def, const EnumVal &ev, std::string *code_ptr) { - std::string &code = *code_ptr; - code += std::string(Indent) + NormalizedName(ev) + " = " + - enum_def.ToString(ev) + ",\n"; - } - - // End enum code. - void EndEnum(std::string *code_ptr) { - std::string &code = *code_ptr; - code += "}\n"; - } - - void GenerateNewObjectPrototype(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - - code += "function " + NormalizedName(struct_def) + ".New()\n"; - code += std::string(Indent) + "local o = {}\n"; - code += std::string(Indent) + "setmetatable(o, {__index = " + NormalizedMetaName(struct_def) + "})\n"; - code += std::string(Indent) + "return o\n"; - code += EndFunc; - } - - // Initialize a new struct or table from existing data. - void NewRootTypeFromBuffer(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - - code += "function " + NormalizedName(struct_def) + ".GetRootAs" + NormalizedName(struct_def) + "(buf, offset)\n"; - code += std::string(Indent) + "local n = flatbuffers.N.UOffsetT:Unpack(buf, offset)\n"; - code += std::string(Indent) + "local o = " + NormalizedName(struct_def) + ".New()\n"; - code += std::string(Indent) + "o:Init(buf, n + offset)\n"; - code += std::string(Indent) + "return o\n"; - code += EndFunc; - } - - // Initialize an existing object with other data, to avoid an allocation. - void InitializeExisting(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - - GenReceiver(struct_def, code_ptr); - code += "Init(buf, pos)\n"; - code += std::string(Indent) + SelfData + " = flatbuffers.view.New(buf, pos)\n"; - code += EndFunc; - } - - // Get the length of a vector. - void GetVectorLen(const StructDef &struct_def, const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)) + "Length()\n"; - code += OffsetPrefix(field); - code += std::string(Indent) + Indent + "return " + SelfData + ":VectorLen(o)\n"; - code += std::string(Indent) + End; + GenReceiver(struct_def, code_ptr); + code += MakeCamel(NormalizedName(field)); + code += "(j)\n"; + code += OffsetPrefix(field); + code += + std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n"; + code += std::string(Indent) + Indent; + code += "return " + GenGetter(field.value.type); + code += "a + ((j-1) * "; + code += NumToString(InlineSize(vectortype)) + "))\n"; + code += std::string(Indent) + End; + if (vectortype.base_type == BASE_TYPE_STRING) { + code += std::string(Indent) + "return ''\n"; + } else { code += std::string(Indent) + "return 0\n"; - code += EndFunc; } + code += EndFunc; + } - // Get the value of a struct's scalar. - void GetScalarFieldOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - std::string getter = GenGetter(field.value.type); - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)); - code += "()\n"; - code += std::string(Indent) + "return " + getter; - code += std::string(SelfDataPos) + " + " + NumToString(field.value.offset) + ")\n"; - code += EndFunc; - } + // Begin the creator function signature. + void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; - // Get the value of a table's scalar. - void GetScalarFieldOfTable(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - std::string getter = GenGetter(field.value.type); - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)); - code += "()\n"; - code += OffsetPrefix(field); - getter += std::string("o + ") + SelfDataPos + ")"; - auto is_bool = field.value.type.base_type == BASE_TYPE_BOOL; - if (is_bool) { - getter = "(" + getter + " ~= 0)"; - } - code += std::string(Indent) + Indent + "return " + getter + "\n"; - code += std::string(Indent) + End; - std::string default_value; - if (is_bool) { - default_value = field.value.constant == "0" ? "false" : "true"; - } - else { - default_value = field.value.constant; - } - code += std::string(Indent) + "return " + default_value + "\n"; - code += EndFunc; - } + code += "function " + NormalizedName(struct_def) + ".Create" + + NormalizedName(struct_def); + code += "(builder"; + } - // Get a struct by initializing an existing struct. - // Specific to Struct. - void GetStructFieldOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)); - code += "(obj)\n"; - code += std::string(Indent) + "obj:Init(" + SelfDataBytes + ", " + SelfDataPos + " + "; - code += NumToString(field.value.offset) + ")\n"; - code += std::string(Indent) + "return obj\n"; - code += EndFunc; - } - - // Get a struct by initializing an existing struct. - // Specific to Table. - void GetStructFieldOfTable(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)); - code += "()\n"; - code += OffsetPrefix(field); - if (field.value.type.struct_def->fixed) { - code += std::string(Indent) + Indent + "local x = o + " + SelfDataPos + "\n"; - } - else { - code += std::string(Indent) + Indent + "local x = " + SelfData + ":Indirect(o + " + SelfDataPos + ")\n"; - } - code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n"; - code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n"; - code += std::string(Indent) + Indent + "return obj\n"; - code += std::string(Indent) + End; - code += EndFunc; - } - - // Get the value of a string. - void GetStringField(const StructDef &struct_def, const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)); - code += "()\n"; - code += OffsetPrefix(field); - code += std::string(Indent) + Indent + "return " + GenGetter(field.value.type); - code += std::string("o + ") + SelfDataPos + ")\n"; - code += std::string(Indent) + End; - code += EndFunc; - } - - // Get the value of a union from an object. - void GetUnionField(const StructDef &struct_def, const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)) + "()\n"; - code += OffsetPrefix(field); - - // TODO(rw): this works and is not the good way to it: - //bool is_native_table = TypeName(field) == "*flatbuffers.Table"; - //if (is_native_table) { - // code += std::string(Indent) + Indent + "from flatbuffers.table import Table\n"; - //} else { - // code += std::string(Indent) + Indent + - // code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n"; - //} - code += std::string(Indent) + Indent + "local obj = flatbuffers.view.New(require('flatbuffers.binaryarray').New(0), 0)\n"; - code += std::string(Indent) + Indent + GenGetter(field.value.type) + "obj, o)\n"; - code += std::string(Indent) + Indent + "return obj\n"; - code += std::string(Indent) + End; - code += EndFunc; - } - - // Get the value of a vector's struct member. - void GetMemberOfVectorOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - auto vectortype = field.value.type.VectorType(); - - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)); - code += "(j)\n"; - code += OffsetPrefix(field); - code += std::string(Indent) + Indent + "local x = " + SelfData + ":Vector(o)\n"; - code += std::string(Indent) + Indent + "x = x + ((j-1) * "; - code += NumToString(InlineSize(vectortype)) + ")\n"; - if (!(vectortype.struct_def->fixed)) { - code += std::string(Indent) + Indent + "x = " + SelfData + ":Indirect(x)\n"; - } - code += std::string(Indent) + Indent + "local obj = require('" + TypeNameWithNamespace(field) + "').New()\n"; - code += std::string(Indent) + Indent + "obj:Init(" + SelfDataBytes + ", x)\n"; - code += std::string(Indent) + Indent + "return obj\n"; - code += std::string(Indent) + End; - code += EndFunc; - } - - // Get the value of a vector's non-struct member. Uses a named return - // argument to conveniently set the zero value for the result. - void GetMemberOfVectorOfNonStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - auto vectortype = field.value.type.VectorType(); - - GenReceiver(struct_def, code_ptr); - code += MakeCamel(NormalizedName(field)); - code += "(j)\n"; - code += OffsetPrefix(field); - code += std::string(Indent) + Indent + "local a = " + SelfData + ":Vector(o)\n"; - code += std::string(Indent) + Indent; - code += "return " + GenGetter(field.value.type); - code += "a + ((j-1) * "; - code += NumToString(InlineSize(vectortype)) + "))\n"; - code += std::string(Indent) + End; - if (vectortype.base_type == BASE_TYPE_STRING) { - code += std::string(Indent) + "return ''\n"; - } - else { - code += std::string(Indent) + "return 0\n"; - } - code += EndFunc; - } - - // Begin the creator function signature. - void BeginBuilderArgs(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - - code += "function " + NormalizedName(struct_def) + ".Create" + NormalizedName(struct_def); - code += "(builder"; - } - - // Recursively generate arguments for a constructor, to deal with nested - // structs. - void StructBuilderArgs(const StructDef &struct_def, - const char *nameprefix, std::string *code_ptr) { - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (IsStruct(field.value.type)) { - // Generate arguments for a struct inside a struct. To ensure names - // don't clash, and to make it obvious these arguments are constructing - // a nested struct, prefix the name with the field name. - StructBuilderArgs(*field.value.type.struct_def, - (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr); - } - else { - std::string &code = *code_ptr; - code += std::string(", ") + nameprefix; - code += MakeCamel(NormalizedName(field), false); - } + // Recursively generate arguments for a constructor, to deal with nested + // structs. + void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix, + std::string *code_ptr) { + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (IsStruct(field.value.type)) { + // Generate arguments for a struct inside a struct. To ensure names + // don't clash, and to make it obvious these arguments are constructing + // a nested struct, prefix the name with the field name. + StructBuilderArgs(*field.value.type.struct_def, + (nameprefix + (NormalizedName(field) + "_")).c_str(), + code_ptr); + } else { + std::string &code = *code_ptr; + code += std::string(", ") + nameprefix; + code += MakeCamel(NormalizedName(field), false); } } + } - // End the creator function signature. - void EndBuilderArgs(std::string *code_ptr) { - std::string &code = *code_ptr; - code += ")\n"; - } + // End the creator function signature. + void EndBuilderArgs(std::string *code_ptr) { + std::string &code = *code_ptr; + code += ")\n"; + } - // Recursively generate struct construction statements and instert manual - // padding. - void StructBuilderBody(const StructDef &struct_def, - const char *nameprefix, std::string *code_ptr) { - std::string &code = *code_ptr; - code += std::string(Indent) + "builder:Prep(" + NumToString(struct_def.minalign) + ", "; - code += NumToString(struct_def.bytesize) + ")\n"; - for (auto it = struct_def.fields.vec.rbegin(); - it != struct_def.fields.vec.rend(); ++it) { - auto &field = **it; - if (field.padding) - code += std::string(Indent) + "builder:Pad(" + NumToString(field.padding) + ")\n"; - if (IsStruct(field.value.type)) { - StructBuilderBody(*field.value.type.struct_def, - (nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr); - } - else { - code += std::string(Indent) + "builder:Prepend" + GenMethod(field) + "("; - code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n"; - } + // Recursively generate struct construction statements and instert manual + // padding. + void StructBuilderBody(const StructDef &struct_def, const char *nameprefix, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += std::string(Indent) + "builder:Prep(" + + NumToString(struct_def.minalign) + ", "; + code += NumToString(struct_def.bytesize) + ")\n"; + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); ++it) { + auto &field = **it; + if (field.padding) + code += std::string(Indent) + "builder:Pad(" + + NumToString(field.padding) + ")\n"; + if (IsStruct(field.value.type)) { + StructBuilderBody(*field.value.type.struct_def, + (nameprefix + (NormalizedName(field) + "_")).c_str(), + code_ptr); + } else { + code += + std::string(Indent) + "builder:Prepend" + GenMethod(field) + "("; + code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n"; } } + } - void EndBuilderBody(std::string *code_ptr) { - std::string &code = *code_ptr; - code += std::string(Indent) + "return builder:Offset()\n"; - code += EndFunc; - } + void EndBuilderBody(std::string *code_ptr) { + std::string &code = *code_ptr; + code += std::string(Indent) + "return builder:Offset()\n"; + code += EndFunc; + } - // Get the value of a table's starting offset. - void GetStartOfTable(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += "function " + NormalizedName(struct_def) + ".Start"; - code += "(builder) "; - code += "builder:StartObject("; - code += NumToString(struct_def.fields.vec.size()); - code += ") end\n"; - } + // Get the value of a table's starting offset. + void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "function " + NormalizedName(struct_def) + ".Start"; + code += "(builder) "; + code += "builder:StartObject("; + code += NumToString(struct_def.fields.vec.size()); + code += ") end\n"; + } - // Set the value of a table's field. - void BuildFieldOfTable(const StructDef &struct_def, - const FieldDef &field, const size_t offset, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += "function " + NormalizedName(struct_def) + ".Add" + MakeCamel(NormalizedName(field)); - code += "(builder, "; - code += MakeCamel(NormalizedName(field), false); - code += ") "; - code += "builder:Prepend"; - code += GenMethod(field) + "Slot("; - code += NumToString(offset) + ", "; - // todo: i don't need to cast in Lua, but am I missing something? + // Set the value of a table's field. + void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field, + const size_t offset, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "function " + NormalizedName(struct_def) + ".Add" + + MakeCamel(NormalizedName(field)); + code += "(builder, "; + code += MakeCamel(NormalizedName(field), false); + code += ") "; + code += "builder:Prepend"; + code += GenMethod(field) + "Slot("; + code += NumToString(offset) + ", "; + // todo: i don't need to cast in Lua, but am I missing something? // if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) { // code += "flatbuffers.N.UOffsetTFlags.py_type"; // code += "("; // code += MakeCamel(NormalizedName(field), false) + ")"; // } else { - code += MakeCamel(NormalizedName(field), false); - // } - code += ", " + field.value.constant; - code += ") end\n"; - } + code += MakeCamel(NormalizedName(field), false); + // } + code += ", " + field.value.constant; + code += ") end\n"; + } - // Set the value of one of the members of a table's vector. - void BuildVectorOfTable(const StructDef &struct_def, - const FieldDef &field, std::string *code_ptr) { - std::string &code = *code_ptr; - code += "function " + NormalizedName(struct_def) + ".Start"; - code += MakeCamel(NormalizedName(field)); - code += "Vector(builder, numElems) return builder:StartVector("; - auto vector_type = field.value.type.VectorType(); - auto alignment = InlineAlignment(vector_type); - auto elem_size = InlineSize(vector_type); - code += NumToString(elem_size); - code += ", numElems, " + NumToString(alignment); - code += ") end\n"; - } + // Set the value of one of the members of a table's vector. + void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += "function " + NormalizedName(struct_def) + ".Start"; + code += MakeCamel(NormalizedName(field)); + code += "Vector(builder, numElems) return builder:StartVector("; + auto vector_type = field.value.type.VectorType(); + auto alignment = InlineAlignment(vector_type); + auto elem_size = InlineSize(vector_type); + code += NumToString(elem_size); + code += ", numElems, " + NumToString(alignment); + code += ") end\n"; + } - // Get the offset of the end of a table. - void GetEndOffsetOnTable(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += "function " + NormalizedName(struct_def) + ".End"; - code += "(builder) "; - code += "return builder:EndObject() end\n"; - } + // Get the offset of the end of a table. + void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "function " + NormalizedName(struct_def) + ".End"; + code += "(builder) "; + code += "return builder:EndObject() end\n"; + } - // Generate the receiver for function signatures. - void GenReceiver(const StructDef &struct_def, std::string *code_ptr) { - std::string &code = *code_ptr; - code += "function " + NormalizedMetaName(struct_def) + ":"; - } + // Generate the receiver for function signatures. + void GenReceiver(const StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "function " + NormalizedMetaName(struct_def) + ":"; + } - // Generate a struct field, conditioned on its child type(s). - void GenStructAccessor(const StructDef &struct_def, - const FieldDef &field, std::string *code_ptr) { - GenComment(field.doc_comment, code_ptr, &def_comment); - if (IsScalar(field.value.type.base_type)) { - if (struct_def.fixed) { - GetScalarFieldOfStruct(struct_def, field, code_ptr); - } - else { - GetScalarFieldOfTable(struct_def, field, code_ptr); - } + // Generate a struct field, conditioned on its child type(s). + void GenStructAccessor(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { + GenComment(field.doc_comment, code_ptr, &def_comment); + if (IsScalar(field.value.type.base_type)) { + if (struct_def.fixed) { + GetScalarFieldOfStruct(struct_def, field, code_ptr); + } else { + GetScalarFieldOfTable(struct_def, field, code_ptr); } - else { - switch (field.value.type.base_type) { + } else { + switch (field.value.type.base_type) { case BASE_TYPE_STRUCT: if (struct_def.fixed) { GetStructFieldOfStruct(struct_def, field, code_ptr); - } - else { + } else { GetStructFieldOfTable(struct_def, field, code_ptr); } break; - case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break; + case BASE_TYPE_STRING: + GetStringField(struct_def, field, code_ptr); + break; case BASE_TYPE_VECTOR: { auto vectortype = field.value.type.VectorType(); if (vectortype.base_type == BASE_TYPE_STRUCT) { GetMemberOfVectorOfStruct(struct_def, field, code_ptr); - } - else { + } else { GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr); } break; } case BASE_TYPE_UNION: GetUnionField(struct_def, field, code_ptr); break; default: FLATBUFFERS_ASSERT(0); - } } + } + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + GetVectorLen(struct_def, field, code_ptr); + } + } + + // Generate table constructors, conditioned on its members' types. + void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { + GetStartOfTable(struct_def, code_ptr); + + 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(); + BuildFieldOfTable(struct_def, field, offset, code_ptr); if (field.value.type.base_type == BASE_TYPE_VECTOR) { - GetVectorLen(struct_def, field, code_ptr); + BuildVectorOfTable(struct_def, field, code_ptr); } } - // Generate table constructors, conditioned on its members' types. - void GenTableBuilders(const StructDef &struct_def, - std::string *code_ptr) { - GetStartOfTable(struct_def, code_ptr); + GetEndOffsetOnTable(struct_def, code_ptr); + } - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; + // Generate struct or table methods. + void GenStruct(const StructDef &struct_def, std::string *code_ptr) { + if (struct_def.generated) return; - auto offset = it - struct_def.fields.vec.begin(); - BuildFieldOfTable(struct_def, field, offset, code_ptr); - if (field.value.type.base_type == BASE_TYPE_VECTOR) { - BuildVectorOfTable(struct_def, field, code_ptr); - } - } + GenComment(struct_def.doc_comment, code_ptr, &def_comment); + BeginClass(struct_def, code_ptr); - GetEndOffsetOnTable(struct_def, code_ptr); + GenerateNewObjectPrototype(struct_def, code_ptr); + + if (!struct_def.fixed) { + // Generate a special accessor for the table that has been declared as + // the root type. + NewRootTypeFromBuffer(struct_def, code_ptr); } - // Generate struct or table methods. - void GenStruct(const StructDef &struct_def, std::string *code_ptr) { - if (struct_def.generated) return; + // Generate the Init method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + InitializeExisting(struct_def, code_ptr); + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; - GenComment(struct_def.doc_comment, code_ptr, &def_comment); - BeginClass(struct_def, code_ptr); - - GenerateNewObjectPrototype(struct_def, code_ptr); - - if (!struct_def.fixed) { - // Generate a special accessor for the table that has been declared as - // the root type. - NewRootTypeFromBuffer(struct_def, code_ptr); - } - - // Generate the Init method that sets the field in a pre-existing - // accessor object. This is to allow object reuse. - InitializeExisting(struct_def, code_ptr); - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - - GenStructAccessor(struct_def, field, code_ptr); - } - - if (struct_def.fixed) { - // create a struct constructor function - GenStructBuilder(struct_def, code_ptr); - } - else { - // Create a set of functions that allow table construction. - GenTableBuilders(struct_def, code_ptr); - } + GenStructAccessor(struct_def, field, code_ptr); } - // Generate enum declarations. - void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { - if (enum_def.generated) return; - - GenComment(enum_def.doc_comment, code_ptr, &def_comment); - BeginEnum(NormalizedName(enum_def), code_ptr); - for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); - ++it) { - auto &ev = **it; - GenComment(ev.doc_comment, code_ptr, &def_comment, Indent); - EnumMember(enum_def, ev, code_ptr); - } - EndEnum(code_ptr); + if (struct_def.fixed) { + // create a struct constructor function + GenStructBuilder(struct_def, code_ptr); + } else { + // Create a set of functions that allow table construction. + GenTableBuilders(struct_def, code_ptr); } + } - // Returns the function name that is able to read a value of the given type. - std::string GenGetter(const Type &type) { - switch (type.base_type) { + // Generate enum declarations. + void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { + if (enum_def.generated) return; + + GenComment(enum_def.doc_comment, code_ptr, &def_comment); + BeginEnum(NormalizedName(enum_def), code_ptr); + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &ev = **it; + GenComment(ev.doc_comment, code_ptr, &def_comment, Indent); + EnumMember(enum_def, ev, code_ptr); + } + EndEnum(code_ptr); + } + + // Returns the function name that is able to read a value of the given type. + std::string GenGetter(const Type &type) { + switch (type.base_type) { case BASE_TYPE_STRING: return std::string(SelfData) + ":String("; - case BASE_TYPE_UNION: return std::string(SelfData) + ":Union("; + case BASE_TYPE_UNION: return std::string(SelfData) + ":Union("; case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); default: return std::string(SelfData) + ":Get(flatbuffers.N." + - MakeCamel(GenTypeGet(type)) + ", "; - } + MakeCamel(GenTypeGet(type)) + ", "; } + } - // Returns the method name for use with add/put calls. - std::string GenMethod(const FieldDef &field) { - return IsScalar(field.value.type.base_type) - ? MakeCamel(GenTypeBasic(field.value.type)) - : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative"); - } + // Returns the method name for use with add/put calls. + std::string GenMethod(const FieldDef &field) { + return IsScalar(field.value.type.base_type) + ? MakeCamel(GenTypeBasic(field.value.type)) + : (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative"); + } - std::string GenTypeBasic(const Type &type) { - static const char *ctypename[] = { - // clang-format off + std::string GenTypeBasic(const Type &type) { + static const char *ctypename[] = { + // clang-format off #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ #PTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on - }; - return ctypename[type.base_type]; - } + // clang-format on + }; + return ctypename[type.base_type]; + } - std::string GenTypePointer(const Type &type) { - switch (type.base_type) { + std::string GenTypePointer(const Type &type) { + switch (type.base_type) { case BASE_TYPE_STRING: return "string"; case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType()); case BASE_TYPE_STRUCT: return type.struct_def->name; case BASE_TYPE_UNION: // fall through default: return "*flatbuffers.Table"; - } + } + } + + std::string GenTypeGet(const Type &type) { + return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type); + } + + std::string GetNamespace(const Type &type) { + return type.struct_def->defined_namespace->GetFullyQualifiedName( + type.struct_def->name); + } + + std::string TypeName(const FieldDef &field) { + return GenTypeGet(field.value.type); + } + + std::string TypeNameWithNamespace(const FieldDef &field) { + return GetNamespace(field.value.type); + } + + // Create a struct with a builder and the struct's arguments. + void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) { + BeginBuilderArgs(struct_def, code_ptr); + StructBuilderArgs(struct_def, "", code_ptr); + EndBuilderArgs(code_ptr); + + StructBuilderBody(struct_def, "", code_ptr); + EndBuilderBody(code_ptr); + } + + bool generate() { + if (!generateEnums()) return false; + if (!generateStructs()) return false; + return true; + } + + private: + bool generateEnums() { + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + auto &enum_def = **it; + std::string enumcode; + GenEnum(enum_def, &enumcode); + if (!SaveType(enum_def, enumcode, false)) return false; + } + return true; + } + + bool generateStructs() { + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + std::string declcode; + GenStruct(struct_def, &declcode); + if (!SaveType(struct_def, declcode, true)) return false; + } + return true; + } + + // Begin by declaring namespace and imports. + void BeginFile(const std::string &name_space_name, const bool needs_imports, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n"; + code += std::string(Comment) + "namespace: " + name_space_name + "\n\n"; + if (needs_imports) { + code += "local flatbuffers = require('flatbuffers')\n\n"; + } + } + + // Save out the generated code for a Lua Table type. + bool SaveType(const Definition &def, const std::string &classcode, + bool needs_imports) { + if (!classcode.length()) return true; + + std::string namespace_dir = path_; + auto &namespaces = def.defined_namespace->components; + for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { + if (it != namespaces.begin()) namespace_dir += kPathSeparator; + namespace_dir += *it; + // std::string init_py_filename = namespace_dir + "/__init__.py"; + // SaveFile(init_py_filename.c_str(), "", false); } - std::string GenTypeGet(const Type &type) { - return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type); - } - - std::string GetNamespace(const Type &type) { - return type.struct_def->defined_namespace->GetFullyQualifiedName(type.struct_def->name); - } - - std::string TypeName(const FieldDef &field) { - return GenTypeGet(field.value.type); - } - - std::string TypeNameWithNamespace(const FieldDef &field) { - return GetNamespace(field.value.type); - } - - // Create a struct with a builder and the struct's arguments. - void GenStructBuilder(const StructDef &struct_def, - std::string *code_ptr) { - BeginBuilderArgs(struct_def, code_ptr); - StructBuilderArgs(struct_def, "", code_ptr); - EndBuilderArgs(code_ptr); - - StructBuilderBody(struct_def, "", code_ptr); - EndBuilderBody(code_ptr); - } - - bool generate() { - if (!generateEnums()) return false; - if (!generateStructs()) return false; - return true; - } - - private: - bool generateEnums() { - for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); - ++it) { - auto &enum_def = **it; - std::string enumcode; - GenEnum(enum_def, &enumcode); - if (!SaveType(enum_def, enumcode, false)) return false; - } - return true; - } - - bool generateStructs() { - for (auto it = parser_.structs_.vec.begin(); - it != parser_.structs_.vec.end(); ++it) { - auto &struct_def = **it; - std::string declcode; - GenStruct(struct_def, &declcode); - if (!SaveType(struct_def, declcode, true)) return false; - } - return true; - } - - // Begin by declaring namespace and imports. - void BeginFile(const std::string &name_space_name, const bool needs_imports, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += std::string(Comment) + FlatBuffersGeneratedWarning() + "\n\n"; - code += std::string(Comment) + "namespace: " + name_space_name + "\n\n"; - if (needs_imports) { - code += "local flatbuffers = require('flatbuffers')\n\n"; - } - } - - // Save out the generated code for a Lua Table type. - bool SaveType(const Definition &def, const std::string &classcode, - bool needs_imports) { - if (!classcode.length()) return true; - - std::string namespace_dir = path_; - auto &namespaces = def.defined_namespace->components; - for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { - if (it != namespaces.begin()) namespace_dir += kPathSeparator; - namespace_dir += *it; - //std::string init_py_filename = namespace_dir + "/__init__.py"; - //SaveFile(init_py_filename.c_str(), "", false); - } - - std::string code = ""; - BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code); - code += classcode; - code += "\n"; - code += "return " + NormalizedName(def) + " " + Comment + "return the module"; - std::string filename = + std::string code = ""; + BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code); + code += classcode; + code += "\n"; + code += + "return " + NormalizedName(def) + " " + Comment + "return the module"; + std::string filename = NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".lua"; - return SaveFile(filename.c_str(), code, false); - } - private: - std::unordered_set keywords_; - }; + return SaveFile(filename.c_str(), code, false); + } + + private: + std::unordered_set keywords_; +}; } // namespace lua bool GenerateLua(const Parser &parser, const std::string &path, - const std::string &file_name) { + const std::string &file_name) { lua::LuaGenerator generator(parser, path, file_name); return generator.generate(); } diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index 9d8141595..16e47816c 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -826,7 +826,8 @@ class PhpGenerator : public BaseGenerator { code += Indent + "private static $names = array(\n"; for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { auto &ev = **it; - code += Indent + Indent + enum_def.name + "::" + ev.name + "=>" + "\"" + ev.name + "\",\n"; + code += Indent + Indent + enum_def.name + "::" + ev.name + "=>" + "\"" + + ev.name + "\",\n"; } code += Indent + ");\n\n"; diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index c8db35973..bff0d8492 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -17,14 +17,13 @@ // independent from idl_parser, since this code is not needed for most clients #include +#include #include "flatbuffers/code_generators.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" -#include - namespace flatbuffers { namespace python { @@ -39,40 +38,12 @@ class PythonGenerator : public BaseGenerator { : BaseGenerator(parser, path, file_name, "" /* not used */, "" /* not used */), float_const_gen_("float('nan')", "float('inf')", "float('-inf')") { - static const char * const keywords[] = { - "False", - "None", - "True", - "and", - "as", - "assert", - "break", - "class", - "continue", - "def", - "del", - "elif", - "else", - "except", - "finally", - "for", - "from", - "global", - "if", - "import", - "in", - "is", - "lambda", - "nonlocal", - "not", - "or", - "pass", - "raise", - "return", - "try", - "while", - "with", - "yield" + static const char *const keywords[] = { + "False", "None", "True", "and", "as", "assert", "break", + "class", "continue", "def", "del", "elif", "else", "except", + "finally", "for", "from", "global", "if", "import", "in", + "is", "lambda", "nonlocal", "not", "or", "pass", "raise", + "return", "try", "while", "with", "yield" }; keywords_.insert(std::begin(keywords), std::end(keywords)); } @@ -81,9 +52,9 @@ class PythonGenerator : public BaseGenerator { // this is the prefix code for that. std::string OffsetPrefix(const FieldDef &field) { return "\n" + Indent + Indent + - "o = flatbuffers.number_types.UOffsetTFlags.py_type" + - "(self._tab.Offset(" + NumToString(field.value.offset) + "))\n" + - Indent + Indent + "if o != 0:\n"; + "o = flatbuffers.number_types.UOffsetTFlags.py_type" + + "(self._tab.Offset(" + NumToString(field.value.offset) + "))\n" + + Indent + Indent + "if o != 0:\n"; } // Begin a class declaration. @@ -148,8 +119,7 @@ class PythonGenerator : public BaseGenerator { } // Initialize an existing object with other data, to avoid an allocation. - void InitializeExisting(const StructDef &struct_def, - std::string *code_ptr) { + void InitializeExisting(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; GenReceiver(struct_def, code_ptr); @@ -172,8 +142,7 @@ class PythonGenerator : public BaseGenerator { // Get the value of a struct's scalar. void GetScalarFieldOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; std::string getter = GenGetter(field.value.type); GenReceiver(struct_def, code_ptr); @@ -184,8 +153,7 @@ class PythonGenerator : public BaseGenerator { } // Get the value of a table's scalar. - void GetScalarFieldOfTable(const StructDef &struct_def, - const FieldDef &field, + void GetScalarFieldOfTable(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; std::string getter = GenGetter(field.value.type); @@ -195,9 +163,7 @@ class PythonGenerator : public BaseGenerator { code += OffsetPrefix(field); getter += "o + self._tab.Pos)"; auto is_bool = IsBool(field.value.type.base_type); - if (is_bool) { - getter = "bool(" + getter + ")"; - } + if (is_bool) { getter = "bool(" + getter + ")"; } code += Indent + Indent + Indent + "return " + getter + "\n"; std::string default_value; if (is_bool) { @@ -213,8 +179,7 @@ class PythonGenerator : public BaseGenerator { // Get a struct by initializing an existing struct. // Specific to Struct. void GetStructFieldOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; GenReceiver(struct_def, code_ptr); code += MakeCamel(NormalizedName(field)); @@ -250,8 +215,7 @@ class PythonGenerator : public BaseGenerator { // Get a struct by initializing an existing struct. // Specific to Table. - void GetStructFieldOfTable(const StructDef &struct_def, - const FieldDef &field, + void GetStructFieldOfTable(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; GenReceiver(struct_def, code_ptr); @@ -296,7 +260,8 @@ class PythonGenerator : public BaseGenerator { // TODO(rw): this works and is not the good way to it: bool is_native_table = TypeName(field) == "*flatbuffers.Table"; if (is_native_table) { - code += Indent + Indent + Indent + "from flatbuffers.table import Table\n"; + code += + Indent + Indent + Indent + "from flatbuffers.table import Table\n"; } else { code += Indent + Indent + Indent; code += "from ." + TypeName(field) + " import " + TypeName(field) + "\n"; @@ -309,8 +274,7 @@ class PythonGenerator : public BaseGenerator { // Get the value of a vector's struct member. void GetMemberOfVectorOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; auto vectortype = field.value.type.VectorType(); @@ -388,8 +352,7 @@ class PythonGenerator : public BaseGenerator { } // Begin the creator function signature. - void BeginBuilderArgs(const StructDef &struct_def, - std::string *code_ptr) { + void BeginBuilderArgs(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; code += "\n"; @@ -399,10 +362,10 @@ class PythonGenerator : public BaseGenerator { // Recursively generate arguments for a constructor, to deal with nested // structs. - void StructBuilderArgs(const StructDef &struct_def, - const char *nameprefix, std::string *code_ptr) { + void StructBuilderArgs(const StructDef &struct_def, const char *nameprefix, + std::string *code_ptr) { for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { + it != struct_def.fields.vec.end(); ++it) { auto &field = **it; const auto &field_type = field.value.type; const auto &type = @@ -439,7 +402,7 @@ class PythonGenerator : public BaseGenerator { indent + " builder.Prep(" + NumToString(struct_def.minalign) + ", "; code += NumToString(struct_def.bytesize) + ")\n"; for (auto it = struct_def.fields.vec.rbegin(); - it != struct_def.fields.vec.rend(); ++it) { + it != struct_def.fields.vec.rend(); ++it) { auto &field = **it; const auto &field_type = field.value.type; const auto &type = @@ -484,8 +447,7 @@ class PythonGenerator : public BaseGenerator { } // Get the value of a table's starting offset. - void GetStartOfTable(const StructDef &struct_def, - std::string *code_ptr) { + void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; code += "def " + NormalizedName(struct_def) + "Start"; code += "(builder): "; @@ -495,11 +457,11 @@ class PythonGenerator : public BaseGenerator { } // Set the value of a table's field. - void BuildFieldOfTable(const StructDef &struct_def, - const FieldDef &field, const size_t offset, - std::string *code_ptr) { + void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field, + const size_t offset, std::string *code_ptr) { std::string &code = *code_ptr; - code += "def " + NormalizedName(struct_def) + "Add" + MakeCamel(NormalizedName(field)); + code += "def " + NormalizedName(struct_def) + "Add" + + MakeCamel(NormalizedName(field)); code += "(builder, "; code += MakeCamel(NormalizedName(field), false); code += "): "; @@ -521,8 +483,8 @@ class PythonGenerator : public BaseGenerator { } // Set the value of one of the members of a table's vector. - void BuildVectorOfTable(const StructDef &struct_def, - const FieldDef &field, std::string *code_ptr) { + void BuildVectorOfTable(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { std::string &code = *code_ptr; code += "def " + NormalizedName(struct_def) + "Start"; code += MakeCamel(NormalizedName(field)); @@ -536,8 +498,7 @@ class PythonGenerator : public BaseGenerator { } // Get the offset of the end of a table. - void GetEndOffsetOnTable(const StructDef &struct_def, - std::string *code_ptr) { + void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; code += "def " + NormalizedName(struct_def) + "End"; code += "(builder): "; @@ -552,8 +513,8 @@ class PythonGenerator : public BaseGenerator { } // Generate a struct field, conditioned on its child type(s). - void GenStructAccessor(const StructDef &struct_def, - const FieldDef &field, std::string *code_ptr) { + void GenStructAccessor(const StructDef &struct_def, const FieldDef &field, + std::string *code_ptr) { GenComment(field.doc_comment, code_ptr, &def_comment, Indent.c_str()); if (IsScalar(field.value.type.base_type)) { if (struct_def.fixed) { @@ -572,7 +533,9 @@ class PythonGenerator : public BaseGenerator { GetStructFieldOfTable(struct_def, field, code_ptr); } break; - case BASE_TYPE_STRING: GetStringField(struct_def, field, code_ptr); break; + case BASE_TYPE_STRING: + GetStringField(struct_def, field, code_ptr); + break; case BASE_TYPE_VECTOR: { auto vectortype = field.value.type.VectorType(); if (vectortype.base_type == BASE_TYPE_STRUCT) { @@ -593,12 +556,11 @@ class PythonGenerator : public BaseGenerator { } // Generate table constructors, conditioned on its members' types. - void GenTableBuilders(const StructDef &struct_def, - std::string *code_ptr) { + void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { GetStartOfTable(struct_def, code_ptr); for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { + it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (field.deprecated) continue; @@ -635,7 +597,7 @@ class PythonGenerator : public BaseGenerator { code += "\", size_prefixed=size_prefixed)\n"; code += "\n"; } - + // Generate struct or table methods. void GenStruct(const StructDef &struct_def, std::string *code_ptr) { if (struct_def.generated) return; @@ -646,7 +608,7 @@ class PythonGenerator : public BaseGenerator { // Generate a special accessor for the table that has been declared as // the root type. NewRootTypeFromBuffer(struct_def, code_ptr); - if (parser_.file_identifier_.length()){ + if (parser_.file_identifier_.length()) { // Generate a special function to test file_identifier GenHasFileIdentifier(struct_def, code_ptr); } @@ -655,7 +617,7 @@ class PythonGenerator : public BaseGenerator { // accessor object. This is to allow object reuse. InitializeExisting(struct_def, code_ptr); for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { + it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (field.deprecated) continue; @@ -693,7 +655,7 @@ class PythonGenerator : public BaseGenerator { case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); default: return "self._tab.Get(flatbuffers.number_types." + - MakeCamel(GenTypeGet(type)) + "Flags, "; + MakeCamel(GenTypeGet(type)) + "Flags, "; } } @@ -738,8 +700,7 @@ class PythonGenerator : public BaseGenerator { } // Create a struct with a builder and the struct's arguments. - void GenStructBuilder(const StructDef &struct_def, - std::string *code_ptr) { + void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) { BeginBuilderArgs(struct_def, code_ptr); StructBuilderArgs(struct_def, "", code_ptr); EndBuilderArgs(code_ptr); @@ -807,6 +768,7 @@ class PythonGenerator : public BaseGenerator { NamespaceDir(*def.defined_namespace) + NormalizedName(def) + ".py"; return SaveFile(filename.c_str(), code, false); } + private: std::unordered_set keywords_; const SimpleFloatConstantGenerator float_const_gen_; diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 936ac8369..3c23f2f9d 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -40,9 +40,7 @@ std::string MakeSnakeCase(const std::string &in) { } else if (!islower(in[i])) { // Prevent duplicate underscores for Upper_Snake_Case strings // and UPPERCASE strings. - if (islower(in[i - 1])) { - s += '_'; - } + if (islower(in[i - 1])) { s += '_'; } s += static_cast(tolower(in[i])); } else { s += in[i]; @@ -200,77 +198,19 @@ class RustGenerator : public BaseGenerator { // changes to that webpage in the future. // currently-used keywords - "as", - "break", - "const", - "continue", - "crate", - "else", - "enum", - "extern", - "false", - "fn", - "for", - "if", - "impl", - "in", - "let", - "loop", - "match", - "mod", - "move", - "mut", - "pub", - "ref", - "return", - "Self", - "self", - "static", - "struct", - "super", - "trait", - "true", - "type", - "unsafe", - "use", - "where", - "while", + "as", "break", "const", "continue", "crate", "else", "enum", "extern", + "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", + "move", "mut", "pub", "ref", "return", "Self", "self", "static", "struct", + "super", "trait", "true", "type", "unsafe", "use", "where", "while", // future possible keywords - "abstract", - "alignof", - "become", - "box", - "do", - "final", - "macro", - "offsetof", - "override", - "priv", - "proc", - "pure", - "sizeof", - "typeof", - "unsized", - "virtual", - "yield", + "abstract", "alignof", "become", "box", "do", "final", "macro", + "offsetof", "override", "priv", "proc", "pure", "sizeof", "typeof", + "unsized", "virtual", "yield", // other rust terms we should not use - "std", - "usize", - "isize", - "u8", - "i8", - "u16", - "i16", - "u32", - "i32", - "u64", - "i64", - "u128", - "i128", - "f32", - "f64", + "std", "usize", "isize", "u8", "i8", "u16", "i16", "u32", "i32", "u64", + "i64", "u128", "i128", "f32", "f64", // These are terms the code generator can implement on types. // @@ -281,13 +221,9 @@ class RustGenerator : public BaseGenerator { // implementation detail, and how we implement methods could change in // the future. as a result, we proactively block these out as reserved // words. - "follow", - "push", - "size", - "alignment", - "to_little_endian", - "from_little_endian", - nullptr }; + "follow", "push", "size", "alignment", "to_little_endian", + "from_little_endian", nullptr + }; for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw); } @@ -310,8 +246,7 @@ class RustGenerator : public BaseGenerator { // TODO(rw): Use a set data structure to reduce namespace evaluations from // O(n**2) to O(n). for (auto ns_it = parser_.namespaces_.begin(); - ns_it != parser_.namespaces_.end(); - ++ns_it) { + ns_it != parser_.namespaces_.end(); ++ns_it) { const auto &ns = *ns_it; // Generate code for all the enum declarations. @@ -381,8 +316,12 @@ class RustGenerator : public BaseGenerator { case ftBool: case ftEnumKey: case ftUnionKey: - case ftUnionValue: { return false; } - default: { return true; } + case ftUnionValue: { + return false; + } + default: { + return true; + } } } @@ -393,13 +332,9 @@ class RustGenerator : public BaseGenerator { for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; - if (field.deprecated) { - continue; - } + if (field.deprecated) { continue; } - if (TableBuilderTypeNeedsLifetime(field.value.type)) { - return true; - } + if (TableBuilderTypeNeedsLifetime(field.value.type)) { return true; } } return false; @@ -410,14 +345,18 @@ class RustGenerator : public BaseGenerator { bool StructMemberAccessNeedsCopy(const Type &type) const { switch (GetFullType(type)) { case ftInteger: // requires endian swap - case ftFloat: // requires endian swap - case ftBool: // no endian-swap, but do the copy for UX consistency - case ftEnumKey: { return true; } // requires endian swap - case ftStruct: { return false; } // no endian swap + case ftFloat: // requires endian swap + case ftBool: // no endian-swap, but do the copy for UX consistency + case ftEnumKey: { + return true; + } // requires endian swap + case ftStruct: { + return false; + } // no endian swap default: { // logic error: no other types can be struct members. FLATBUFFERS_ASSERT(false && "invalid struct member type"); - return false; // only to satisfy compiler's return analysis + return false; // only to satisfy compiler's return analysis } } } @@ -477,7 +416,7 @@ class RustGenerator : public BaseGenerator { auto s = src->components.begin(); auto d = dst->components.begin(); - for(;;) { + for (;;) { if (s == src->components.end()) { break; } if (d == dst->components.end()) { break; } if (*s != *d) { break; } @@ -486,9 +425,7 @@ class RustGenerator : public BaseGenerator { ++i; } - for (; s != src->components.end(); ++s) { - stream << "super::"; - } + for (; s != src->components.end(); ++s) { stream << "super::"; } for (; d != dst->components.end(); ++d) { stream << MakeSnakeCase(*d) + "::"; } @@ -509,8 +446,12 @@ class RustGenerator : public BaseGenerator { case ftFloat: case ftBool: case ftEnumKey: - case ftUnionKey: { break; } - default: { FLATBUFFERS_ASSERT(false && "incorrect type given");} + case ftUnionKey: { + break; + } + default: { + FLATBUFFERS_ASSERT(false && "incorrect type given"); + } } // clang-format off @@ -560,13 +501,17 @@ class RustGenerator : public BaseGenerator { case ftBool: case ftEnumKey: case ftUnionKey: { - return GetTypeBasic(type); } + return GetTypeBasic(type); + } case ftTable: { return WrapInNameSpace(type.struct_def->defined_namespace, - type.struct_def->name) + "<'a>"; } + type.struct_def->name) + + "<'a>"; + } default: { return WrapInNameSpace(type.struct_def->defined_namespace, - type.struct_def->name); } + type.struct_def->name); + } } } @@ -586,7 +531,8 @@ class RustGenerator : public BaseGenerator { GenComment(enum_def.doc_comment); code_ += "#[allow(non_camel_case_types)]"; code_ += "#[repr({{BASE_TYPE}})]"; - code_ += "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]"; + code_ += + "#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]"; code_ += "pub enum " + Name(enum_def) + " {"; for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { @@ -644,8 +590,9 @@ class RustGenerator : public BaseGenerator { code_ += " type Output = {{ENUM_NAME}};"; code_ += " #[inline]"; code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {"; - code_ += " flatbuffers::emplace_scalar::<{{ENUM_NAME}}>" - "(dst, *self);"; + code_ += + " flatbuffers::emplace_scalar::<{{ENUM_NAME}}>" + "(dst, *self);"; code_ += " }"; code_ += "}"; code_ += ""; @@ -654,7 +601,7 @@ class RustGenerator : public BaseGenerator { auto num_fields = NumToString(enum_def.size()); code_ += "#[allow(non_camel_case_types)]"; code_ += "const ENUM_VALUES_{{ENUM_NAME_CAPS}}:[{{ENUM_NAME}}; " + - num_fields + "] = ["; + num_fields + "] = ["; for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { const auto &ev = **it; auto value = GetEnumValUse(enum_def, ev); @@ -727,8 +674,12 @@ class RustGenerator : public BaseGenerator { std::string GetDefaultScalarValue(const FieldDef &field) { switch (GetFullType(field.value.type)) { - case ftInteger: { return GetDefaultConstant(field); } - case ftFloat: { return GetDefaultConstant(field); } + case ftInteger: { + return GetDefaultConstant(field); + } + case ftFloat: { + return GetDefaultConstant(field); + } case ftBool: { return field.value.constant == "0" ? "false" : "true"; } @@ -742,7 +693,9 @@ class RustGenerator : public BaseGenerator { // All pointer-ish types have a default value of None, because they are // wrapped in Option. - default: { return "None"; } + default: { + return "None"; + } } } @@ -759,7 +712,7 @@ class RustGenerator : public BaseGenerator { // 3) return a hardcoded value because the vtable field value is set to zero. std::string TableBuilderArgsDefnType(const FieldDef &field, const std::string &lifetime) { - const Type& type = field.value.type; + const Type &type = field.value.type; switch (GetFullType(type)) { case ftInteger: @@ -774,7 +727,7 @@ class RustGenerator : public BaseGenerator { } case ftTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return "Option>>"; } case ftString: { @@ -792,43 +745,43 @@ class RustGenerator : public BaseGenerator { case ftVectorOfInteger: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); - return "Option>>"; + return "Option>>"; } case ftVectorOfBool: { - return "Option>>"; + return "Option>>"; } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); - return "Option>>"; + return "Option>>"; } case ftVectorOfStruct: { const auto typname = WrapInNameSpace(*type.struct_def); - return "Option>>"; + return "Option>>"; } case ftVectorOfTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return "Option>>>>"; + return "Option>>>>"; } case ftVectorOfString: { - return "Option>>>"; + return "Option>>>"; } case ftVectorOfUnionValue: { - const auto typname = WrapInNameSpace(*type.enum_def) + \ - "UnionTableOffset"; - return "Option>>>"; + const auto typname = + WrapInNameSpace(*type.enum_def) + "UnionTableOffset"; + return "Option>>>"; } } - return "INVALID_CODE_GENERATION"; // for return analysis + return "INVALID_CODE_GENERATION"; // for return analysis } std::string TableBuilderArgsDefaultValue(const FieldDef &field) { @@ -839,53 +792,56 @@ class RustGenerator : public BaseGenerator { switch (GetFullType(field.value.type)) { case ftUnionKey: case ftEnumKey: { - const std::string basetype = GetTypeBasic(field.value.type); //<- never used + const std::string basetype = + GetTypeBasic(field.value.type); //<- never used return GetDefaultScalarValue(field); } - default: { return GetDefaultScalarValue(field); } + default: { + return GetDefaultScalarValue(field); + } } } std::string TableBuilderArgsAddFuncType(const FieldDef &field, const std::string &lifetime) { - const Type& type = field.value.type; + const Type &type = field.value.type; switch (GetFullType(field.value.type)) { case ftVectorOfStruct: { const auto typname = WrapInNameSpace(*type.struct_def); - return "flatbuffers::WIPOffset>"; + return "flatbuffers::WIPOffset>"; } case ftVectorOfTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return "flatbuffers::WIPOffset>>>"; + return "flatbuffers::WIPOffset>>>"; } case ftVectorOfInteger: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); - return "flatbuffers::WIPOffset>"; + return "flatbuffers::WIPOffset>"; } case ftVectorOfBool: { - return "flatbuffers::WIPOffset>"; } case ftVectorOfString: { - return "flatbuffers::WIPOffset>>"; } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); - return "flatbuffers::WIPOffset>"; + return "flatbuffers::WIPOffset>"; } case ftVectorOfUnionValue: { - return "flatbuffers::WIPOffset>>"; + return "flatbuffers::WIPOffset>>"; } case ftEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); @@ -919,11 +875,11 @@ class RustGenerator : public BaseGenerator { } } - return "INVALID_CODE_GENERATION"; // for return analysis + return "INVALID_CODE_GENERATION"; // for return analysis } std::string TableBuilderArgsAddFuncBody(const FieldDef &field) { - const Type& type = field.value.type; + const Type &type = field.value.type; switch (GetFullType(field.value.type)) { case ftInteger: @@ -947,8 +903,8 @@ class RustGenerator : public BaseGenerator { } case ftTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return "self.fbb_.push_slot_always::>"; + return "self.fbb_.push_slot_always::>"; } case ftUnionValue: @@ -964,12 +920,12 @@ class RustGenerator : public BaseGenerator { return "self.fbb_.push_slot_always::>"; } } - return "INVALID_CODE_GENERATION"; // for return analysis + return "INVALID_CODE_GENERATION"; // for return analysis } std::string GenTableAccessorFuncReturnType(const FieldDef &field, const std::string &lifetime) { - const Type& type = field.value.type; + const Type &type = field.value.type; switch (GetFullType(field.value.type)) { case ftInteger: @@ -982,11 +938,13 @@ class RustGenerator : public BaseGenerator { } case ftStruct: { const auto typname = WrapInNameSpace(*type.struct_def); - return WrapInOptionIfNotRequired("&" + lifetime + " " + typname, field.required); + return WrapInOptionIfNotRequired("&" + lifetime + " " + typname, + field.required); } case ftTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return WrapInOptionIfNotRequired(typname + "<" + lifetime + ">", field.required); + return WrapInOptionIfNotRequired(typname + "<" + lifetime + ">", + field.required); } case ftEnumKey: case ftUnionKey: { @@ -995,55 +953,68 @@ class RustGenerator : public BaseGenerator { } case ftUnionValue: { - return WrapInOptionIfNotRequired("flatbuffers::Table<" + lifetime + ">", field.required); + return WrapInOptionIfNotRequired("flatbuffers::Table<" + lifetime + ">", + field.required); } case ftString: { - return WrapInOptionIfNotRequired("&" + lifetime + " str", field.required); + return WrapInOptionIfNotRequired("&" + lifetime + " str", + field.required); } case ftVectorOfInteger: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); if (IsOneByte(type.VectorType().base_type)) { - return WrapInOptionIfNotRequired("&" + lifetime + " [" + typname + "]", field.required); + return WrapInOptionIfNotRequired( + "&" + lifetime + " [" + typname + "]", field.required); } - return WrapInOptionIfNotRequired("flatbuffers::Vector<" + lifetime + ", " + typname + ">", field.required); + return WrapInOptionIfNotRequired( + "flatbuffers::Vector<" + lifetime + ", " + typname + ">", + field.required); } case ftVectorOfBool: { - return WrapInOptionIfNotRequired("&" + lifetime + " [bool]", field.required); + return WrapInOptionIfNotRequired("&" + lifetime + " [bool]", + field.required); } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); - return WrapInOptionIfNotRequired("flatbuffers::Vector<" + lifetime + ", " + typname + ">", field.required); + return WrapInOptionIfNotRequired( + "flatbuffers::Vector<" + lifetime + ", " + typname + ">", + field.required); } case ftVectorOfStruct: { const auto typname = WrapInNameSpace(*type.struct_def); - return WrapInOptionIfNotRequired("&" + lifetime + " [" + typname + "]", field.required); + return WrapInOptionIfNotRequired("&" + lifetime + " [" + typname + "]", + field.required); } case ftVectorOfTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return WrapInOptionIfNotRequired("flatbuffers::Vector<" + lifetime + ", flatbuffers::ForwardsUOffset<" + \ - typname + "<" + lifetime + ">>>", field.required); + return WrapInOptionIfNotRequired("flatbuffers::Vector<" + lifetime + + ", flatbuffers::ForwardsUOffset<" + + typname + "<" + lifetime + ">>>", + field.required); } case ftVectorOfString: { - return WrapInOptionIfNotRequired("flatbuffers::Vector<" + lifetime + ", flatbuffers::ForwardsUOffset<&" + \ - lifetime + " str>>", field.required); + return WrapInOptionIfNotRequired( + "flatbuffers::Vector<" + lifetime + + ", flatbuffers::ForwardsUOffset<&" + lifetime + " str>>", + field.required); } case ftVectorOfUnionValue: { FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported"); // TODO(rw): when we do support these, we should consider using the // Into trait to convert tables to typesafe union values. - return "INVALID_CODE_GENERATION"; // for return analysis + return "INVALID_CODE_GENERATION"; // for return analysis } } - return "INVALID_CODE_GENERATION"; // for return analysis + return "INVALID_CODE_GENERATION"; // for return analysis } std::string GenTableAccessorFuncBody(const FieldDef &field, const std::string &lifetime, const std::string &offset_prefix) { - const std::string offset_name = offset_prefix + "::" + \ - GetFieldOffsetName(field); - const Type& type = field.value.type; + const std::string offset_name = + offset_prefix + "::" + GetFieldOffsetName(field); + const Type &type = field.value.type; switch (GetFullType(field.value.type)) { case ftInteger: @@ -1051,42 +1022,51 @@ class RustGenerator : public BaseGenerator { case ftBool: { const auto typname = GetTypeBasic(type); const auto default_value = GetDefaultScalarValue(field); - return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" + \ + return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" + default_value + ")).unwrap()"; } case ftStruct: { const auto typname = WrapInNameSpace(*type.struct_def); - return AddUnwrapIfRequired("self._tab.get::<" + typname + ">(" + offset_name + ", None)", field.required); + return AddUnwrapIfRequired( + "self._tab.get::<" + typname + ">(" + offset_name + ", None)", + field.required); } case ftTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return AddUnwrapIfRequired("self._tab.get::>>(" + offset_name + ", None)", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>>(" + offset_name + ", None)", + field.required); } case ftUnionValue: { - return AddUnwrapIfRequired("self._tab.get::>>(" + offset_name + \ - ", None)", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>>(" + offset_name + ", None)", + field.required); } case ftUnionKey: case ftEnumKey: { - const auto underlying_typname = GetTypeBasic(type); //<- never used + const auto underlying_typname = GetTypeBasic(type); //<- never used const auto typname = WrapInNameSpace(*type.enum_def); const auto default_value = GetDefaultScalarValue(field); - return "self._tab.get::<" + typname + ">(" + offset_name + \ - ", Some(" + default_value + ")).unwrap()"; + return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" + + default_value + ")).unwrap()"; } case ftString: { - return AddUnwrapIfRequired("self._tab.get::>(" + \ - offset_name + ", None)", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>(" + + offset_name + ", None)", + field.required); } case ftVectorOfInteger: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); - std::string s = "self._tab.get::>>(" + offset_name + ", None)"; + std::string s = + "self._tab.get::>>(" + offset_name + ", None)"; // single-byte values are safe to slice if (IsOneByte(type.VectorType().base_type)) { s += ".map(|v| v.safe_slice())"; @@ -1094,49 +1074,60 @@ class RustGenerator : public BaseGenerator { return AddUnwrapIfRequired(s, field.required); } case ftVectorOfBool: { - return AddUnwrapIfRequired("self._tab.get::>>(" + \ - offset_name + ", None).map(|v| v.safe_slice())", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>>(" + offset_name + + ", None).map(|v| v.safe_slice())", + field.required); } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); - return AddUnwrapIfRequired("self._tab.get::>>(" + \ - offset_name + ", None)", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>>(" + offset_name + ", None)", + field.required); } case ftVectorOfStruct: { const auto typname = WrapInNameSpace(*type.struct_def); - return AddUnwrapIfRequired("self._tab.get::>>(" + \ - offset_name + ", None).map(|v| v.safe_slice() )", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>>(" + offset_name + + ", None).map(|v| v.safe_slice() )", + field.required); } case ftVectorOfTable: { const auto typname = WrapInNameSpace(*type.struct_def); - return AddUnwrapIfRequired("self._tab.get::>>>>(" + offset_name + ", None)", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>>>>(" + offset_name + ", None)", + field.required); } case ftVectorOfString: { - return AddUnwrapIfRequired("self._tab.get::>>>(" + offset_name + ", None)", field.required); + return AddUnwrapIfRequired( + "self._tab.get::>>>(" + offset_name + ", None)", + field.required); } case ftVectorOfUnionValue: { FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported"); - return "INVALID_CODE_GENERATION"; // for return analysis + return "INVALID_CODE_GENERATION"; // for return analysis } } - return "INVALID_CODE_GENERATION"; // for return analysis + return "INVALID_CODE_GENERATION"; // for return analysis } - bool TableFieldReturnsOption(const Type& type) { + bool TableFieldReturnsOption(const Type &type) { switch (GetFullType(type)) { case ftInteger: case ftFloat: case ftBool: case ftEnumKey: - case ftUnionKey: - return false; + case ftUnionKey: return false; default: return true; } } @@ -1172,8 +1163,9 @@ class RustGenerator : public BaseGenerator { code_ += ""; code_ += "impl<'a> {{STRUCT_NAME}}<'a> {"; code_ += " #[inline]"; - code_ += " pub fn init_from_table(table: flatbuffers::Table<'a>) -> " - "Self {"; + code_ += + " pub fn init_from_table(table: flatbuffers::Table<'a>) -> " + "Self {"; code_ += " {{STRUCT_NAME}} {"; code_ += " _tab: table,"; code_ += " }"; @@ -1181,16 +1173,17 @@ class RustGenerator : public BaseGenerator { // Generate a convenient create* function that uses the above builder // to create a table in one function call. - code_.SetValue("MAYBE_US", - struct_def.fields.vec.size() == 0 ? "_" : ""); + code_.SetValue("MAYBE_US", struct_def.fields.vec.size() == 0 ? "_" : ""); code_.SetValue("MAYBE_LT", - TableBuilderArgsNeedsLifetime(struct_def) ? "<'args>" : ""); + TableBuilderArgsNeedsLifetime(struct_def) ? "<'args>" : ""); code_ += " #[allow(unused_mut)]"; code_ += " pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>("; - code_ += " _fbb: " - "&'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,"; - code_ += " {{MAYBE_US}}args: &'args {{STRUCT_NAME}}Args{{MAYBE_LT}})" - " -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'bldr>> {"; + code_ += + " _fbb: " + "&'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>,"; + code_ += + " {{MAYBE_US}}args: &'args {{STRUCT_NAME}}Args{{MAYBE_LT}})" + " -> flatbuffers::WIPOffset<{{STRUCT_NAME}}<'bldr>> {"; code_ += " let mut builder = {{STRUCT_NAME}}Builder::new(_fbb);"; for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; @@ -1203,8 +1196,9 @@ class RustGenerator : public BaseGenerator { size == SizeOf(field.value.type.base_type))) { code_.SetValue("FIELD_NAME", Name(field)); if (TableFieldReturnsOption(field.value.type)) { - code_ += " if let Some(x) = args.{{FIELD_NAME}} " - "{ builder.add_{{FIELD_NAME}}(x); }"; + code_ += + " if let Some(x) = args.{{FIELD_NAME}} " + "{ builder.add_{{FIELD_NAME}}(x); }"; } else { code_ += " builder.add_{{FIELD_NAME}}(args.{{FIELD_NAME}});"; } @@ -1227,8 +1221,9 @@ class RustGenerator : public BaseGenerator { code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field)); code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset)); - code_ += " pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = " - "{{OFFSET_VALUE}};"; + code_ += + " pub const {{OFFSET_NAME}}: flatbuffers::VOffsetT = " + "{{OFFSET_VALUE}};"; } code_ += ""; } @@ -1266,9 +1261,7 @@ class RustGenerator : public BaseGenerator { code_ += " }"; // Generate a comparison function for this field if it is a key. - if (field.key) { - GenKeyFieldMethods(field); - } + if (field.key) { GenKeyFieldMethods(field); } // Generate a nested flatbuffer field, if applicable. auto nested = field.attributes.Lookup("nested_flatbuffer"); @@ -1285,14 +1278,16 @@ class RustGenerator : public BaseGenerator { code_.SetValue("OFFSET_NAME", offset_prefix + "::" + GetFieldOffsetName(field)); - code_ += " pub fn {{FIELD_NAME}}_nested_flatbuffer(&'a self) -> " - " Option<{{STRUCT_NAME}}<'a>> {"; + code_ += + " pub fn {{FIELD_NAME}}_nested_flatbuffer(&'a self) -> " + " Option<{{STRUCT_NAME}}<'a>> {"; code_ += " match self.{{FIELD_NAME}}() {"; code_ += " None => { None }"; code_ += " Some(data) => {"; code_ += " use self::flatbuffers::Follow;"; - code_ += " Some(>>::follow(data, 0))"; + code_ += + " Some(>>::follow(data, 0))"; code_ += " },"; code_ += " }"; code_ += " }"; @@ -1315,22 +1310,26 @@ class RustGenerator : public BaseGenerator { auto &ev = **u_it; if (ev.union_type.base_type == BASE_TYPE_NONE) { continue; } - auto table_init_type = WrapInNameSpace( - ev.union_type.struct_def->defined_namespace, - ev.union_type.struct_def->name); + auto table_init_type = + WrapInNameSpace(ev.union_type.struct_def->defined_namespace, + ev.union_type.struct_def->name); - code_.SetValue("U_ELEMENT_ENUM_TYPE", - WrapInNameSpace(u->defined_namespace, GetEnumValUse(*u, ev))); + code_.SetValue( + "U_ELEMENT_ENUM_TYPE", + WrapInNameSpace(u->defined_namespace, GetEnumValUse(*u, ev))); code_.SetValue("U_ELEMENT_TABLE_TYPE", table_init_type); code_.SetValue("U_ELEMENT_NAME", MakeSnakeCase(Name(ev))); code_ += " #[inline]"; code_ += " #[allow(non_snake_case)]"; - code_ += " pub fn {{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}(&self) -> " - "Option<{{U_ELEMENT_TABLE_TYPE}}<'a>> {"; - code_ += " if self.{{FIELD_NAME}}_type() == {{U_ELEMENT_ENUM_TYPE}} {"; - code_ += " self.{{FIELD_NAME}}().map(|u| " - "{{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))"; + code_ += + " pub fn {{FIELD_NAME}}_as_{{U_ELEMENT_NAME}}(&self) -> " + "Option<{{U_ELEMENT_TABLE_TYPE}}<'a>> {"; + code_ += + " if self.{{FIELD_NAME}}_type() == {{U_ELEMENT_ENUM_TYPE}} {"; + code_ += + " self.{{FIELD_NAME}}().map(|u| " + "{{U_ELEMENT_TABLE_TYPE}}::init_from_table(u))"; code_ += " } else {"; code_ += " None"; code_ += " }"; @@ -1344,7 +1343,7 @@ class RustGenerator : public BaseGenerator { // Generate an args struct: code_.SetValue("MAYBE_LT", - TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : ""); + TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : ""); code_ += "pub struct {{STRUCT_NAME}}Args{{MAYBE_LT}} {"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { @@ -1363,7 +1362,7 @@ class RustGenerator : public BaseGenerator { code_ += " fn default() -> Self {"; code_ += " {{STRUCT_NAME}}Args {"; for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { + it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; if (!field.deprecated) { code_.SetValue("PARAM_VALUE", TableBuilderArgsDefaultValue(field)); @@ -1379,8 +1378,9 @@ class RustGenerator : public BaseGenerator { // Generate a builder struct: code_ += "pub struct {{STRUCT_NAME}}Builder<'a: 'b, 'b> {"; code_ += " fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>,"; - code_ += " start_: flatbuffers::WIPOffset<" - "flatbuffers::TableUnfinishedWIPOffset>,"; + code_ += + " start_: flatbuffers::WIPOffset<" + "flatbuffers::TableUnfinishedWIPOffset>,"; code_ += "}"; // Generate builder functions: @@ -1409,13 +1409,15 @@ class RustGenerator : public BaseGenerator { code_.SetValue("FIELD_TYPE", TableBuilderArgsAddFuncType(field, "'b ")); code_.SetValue("FUNC_BODY", TableBuilderArgsAddFuncBody(field)); code_ += " #[inline]"; - code_ += " pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: " - "{{FIELD_TYPE}}) {"; + code_ += + " pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: " + "{{FIELD_TYPE}}) {"; if (is_scalar) { code_.SetValue("FIELD_DEFAULT_VALUE", TableBuilderAddFuncDefaultValue(field)); - code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, " - "{{FIELD_DEFAULT_VALUE}});"; + code_ += + " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}}, " + "{{FIELD_DEFAULT_VALUE}});"; } else { code_ += " {{FUNC_BODY}}({{FIELD_OFFSET}}, {{FIELD_NAME}});"; } @@ -1438,8 +1440,9 @@ class RustGenerator : public BaseGenerator { // finish() function. code_ += " #[inline]"; - code_ += " pub fn finish(self) -> " - "flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>> {"; + code_ += + " pub fn finish(self) -> " + "flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>> {"; code_ += " let o = self.fbb_.end_table(self.start_);"; for (auto it = struct_def.fields.vec.begin(); @@ -1448,8 +1451,9 @@ class RustGenerator : public BaseGenerator { if (!field.deprecated && field.required) { code_.SetValue("FIELD_NAME", MakeSnakeCase(Name(field))); code_.SetValue("OFFSET_NAME", GetFieldOffsetName(field)); - code_ += " self.fbb_.required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}}," - "\"{{FIELD_NAME}}\");"; + code_ += + " self.fbb_.required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}}," + "\"{{FIELD_NAME}}\");"; } } code_ += " flatbuffers::WIPOffset::new(o.value())"; @@ -1466,14 +1470,16 @@ class RustGenerator : public BaseGenerator { code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, "")); code_ += " #[inline]"; - code_ += " pub fn key_compare_less_than(&self, o: &{{STRUCT_NAME}}) -> " - " bool {"; + code_ += + " pub fn key_compare_less_than(&self, o: &{{STRUCT_NAME}}) -> " + " bool {"; code_ += " self.{{FIELD_NAME}}() < o.{{FIELD_NAME}}()"; code_ += " }"; code_ += ""; code_ += " #[inline]"; - code_ += " pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> " - " ::std::cmp::Ordering {"; + code_ += + " pub fn key_compare_with_value(&self, val: {{KEY_TYPE}}) -> " + " ::std::cmp::Ordering {"; code_ += " let key = self.{{FIELD_NAME}}();"; code_ += " key.cmp(&val)"; code_ += " }"; @@ -1499,10 +1505,12 @@ class RustGenerator : public BaseGenerator { code_ += ""; code_ += "#[inline]"; - code_ += "pub fn get_size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}" - "<'a>(buf: &'a [u8]) -> {{STRUCT_NAME}}<'a> {"; - code_ += " flatbuffers::get_size_prefixed_root::<{{STRUCT_NAME}}<'a>>" - "(buf)"; + code_ += + "pub fn get_size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}" + "<'a>(buf: &'a [u8]) -> {{STRUCT_NAME}}<'a> {"; + code_ += + " flatbuffers::get_size_prefixed_root::<{{STRUCT_NAME}}<'a>>" + "(buf)"; code_ += "}"; code_ += ""; @@ -1550,13 +1558,15 @@ class RustGenerator : public BaseGenerator { code_ += "}"; code_ += ""; code_ += "#[inline]"; - code_ += "pub fn finish_size_prefixed_{{STRUCT_NAME_SNAKECASE}}_buffer" - "<'a, 'b>(" - "fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, " - "root: flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>>) {"; + code_ += + "pub fn finish_size_prefixed_{{STRUCT_NAME_SNAKECASE}}_buffer" + "<'a, 'b>(" + "fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, " + "root: flatbuffers::WIPOffset<{{STRUCT_NAME}}<'a>>) {"; if (parser_.file_identifier_.length()) { - code_ += " fbb.finish_size_prefixed(root, " - "Some({{STRUCT_NAME_CAPS}}_IDENTIFIER));"; + code_ += + " fbb.finish_size_prefixed(root, " + "Some({{STRUCT_NAME_CAPS}}_IDENTIFIER));"; } else { code_ += " fbb.finish_size_prefixed(root, None);"; } @@ -1577,8 +1587,8 @@ class RustGenerator : public BaseGenerator { } static void PaddingDefinition(int bits, std::string *code_ptr, int *id) { - *code_ptr += " padding" + NumToString((*id)++) + "__: u" + \ - NumToString(bits) + ","; + *code_ptr += + " padding" + NumToString((*id)++) + "__: u" + NumToString(bits) + ","; } static void PaddingInitializer(int bits, std::string *code_ptr, int *id) { @@ -1644,8 +1654,9 @@ class RustGenerator : public BaseGenerator { code_ += " #[inline]"; code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {"; code_ += " let src = unsafe {"; - code_ += " ::std::slice::from_raw_parts(" - "self as *const {{STRUCT_NAME}} as *const u8, Self::size())"; + code_ += + " ::std::slice::from_raw_parts(" + "self as *const {{STRUCT_NAME}} as *const u8, Self::size())"; code_ += " };"; code_ += " dst.copy_from_slice(src);"; code_ += " }"; @@ -1656,8 +1667,9 @@ class RustGenerator : public BaseGenerator { code_ += " #[inline]"; code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {"; code_ += " let src = unsafe {"; - code_ += " ::std::slice::from_raw_parts(" - "*self as *const {{STRUCT_NAME}} as *const u8, Self::size())"; + code_ += + " ::std::slice::from_raw_parts(" + "*self as *const {{STRUCT_NAME}} as *const u8, Self::size())"; code_ += " };"; code_ += " dst.copy_from_slice(src);"; code_ += " }"; @@ -1674,14 +1686,12 @@ class RustGenerator : public BaseGenerator { it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; const auto member_name = Name(field) + "_"; - const auto reference = StructMemberAccessNeedsCopy(field.value.type) - ? "" : "&'a "; + const auto reference = + StructMemberAccessNeedsCopy(field.value.type) ? "" : "&'a "; const auto arg_name = "_" + Name(field); const auto arg_type = reference + GetTypeGet(field.value.type); - if (it != struct_def.fields.vec.begin()) { - arg_list += ", "; - } + if (it != struct_def.fields.vec.begin()) { arg_list += ", "; } arg_list += arg_name + ": "; arg_list += arg_type; init_list += " " + member_name; @@ -1717,8 +1727,9 @@ class RustGenerator : public BaseGenerator { auto field_type = TableBuilderArgsAddFuncType(field, "'a"); auto member = "self." + Name(field) + "_"; - auto value = StructMemberAccessNeedsCopy(field.value.type) ? - member + ".from_little_endian()" : member; + auto value = StructMemberAccessNeedsCopy(field.value.type) + ? member + ".from_little_endian()" + : member; code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("FIELD_TYPE", field_type); @@ -1731,22 +1742,20 @@ class RustGenerator : public BaseGenerator { code_ += " }"; // Generate a comparison function for this field if it is a key. - if (field.key) { - GenKeyFieldMethods(field); - } + if (field.key) { GenKeyFieldMethods(field); } } code_ += "}"; code_ += ""; } void GenNamespaceImports(const int white_spaces) { - std::string indent = std::string(white_spaces, ' '); - code_ += ""; - code_ += indent + "use std::mem;"; - code_ += indent + "use std::cmp::Ordering;"; - code_ += ""; - code_ += indent + "extern crate flatbuffers;"; - code_ += indent + "use self::flatbuffers::EndianScalar;"; + std::string indent = std::string(white_spaces, ' '); + code_ += ""; + code_ += indent + "use std::mem;"; + code_ += indent + "use std::cmp::Ordering;"; + code_ += ""; + code_ += indent + "extern crate flatbuffers;"; + code_ += indent + "use self::flatbuffers::EndianScalar;"; } // Set up the correct namespace. This opens a namespace if the current diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp index 66926a605..1d0a3caaf 100644 --- a/src/idl_gen_text.cpp +++ b/src/idl_gen_text.cpp @@ -142,8 +142,8 @@ bool Print(const void *val, Type type, int indent, FLATBUFFERS_ASSERT(prev_val); auto union_type_byte = *prev_val; // Always a uint8_t. if (vector_index >= 0) { - auto type_vec = reinterpret_cast *>(prev_val + - ReadScalar(prev_val)); + auto type_vec = reinterpret_cast *>( + prev_val + ReadScalar(prev_val)); union_type_byte = type_vec->Get(static_cast(vector_index)); } auto enum_val = type.enum_def->ReverseLookup(union_type_byte, true); @@ -205,9 +205,7 @@ bool Print(const void *val, Type type, int indent, // clang-format on return true; } - default: - FLATBUFFERS_ASSERT(0); - return false; + default: FLATBUFFERS_ASSERT(0); return false; } } @@ -287,7 +285,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, text += ":"; text += " "; switch (fd.value.type.base_type) { - // clang-format off + // clang-format off #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ case BASE_TYPE_ ## ENUM: \ @@ -310,7 +308,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, return false; } break; - // clang-format on + // clang-format on } // Track prev val for use with union types. if (struct_def.fixed) { @@ -330,15 +328,11 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, bool GenerateTextFromTable(const Parser &parser, const void *table, const std::string &table_name, std::string *_text) { auto struct_def = parser.LookupStruct(table_name); - if (struct_def == nullptr) { - return false; - } + if (struct_def == nullptr) { return false; } auto &text = *_text; text.reserve(1024); // Reduce amount of inevitable reallocs. auto root = static_cast(table); - if (!GenStruct(*struct_def, root, 0, parser.opts, &text)) { - return false; - } + if (!GenStruct(*struct_def, root, 0, parser.opts, &text)) { return false; } text += NewLine(parser.opts); return true; } @@ -348,9 +342,9 @@ bool GenerateText(const Parser &parser, const void *flatbuffer, std::string *_text) { std::string &text = *_text; FLATBUFFERS_ASSERT(parser.root_struct_def_); // call SetRootType() - text.reserve(1024); // Reduce amount of inevitable reallocs. - auto root = parser.opts.size_prefixed ? - GetSizePrefixedRoot(flatbuffer) : GetRoot
(flatbuffer); + text.reserve(1024); // Reduce amount of inevitable reallocs. + auto root = parser.opts.size_prefixed ? GetSizePrefixedRoot
(flatbuffer) + : GetRoot
(flatbuffer); if (!GenStruct(*parser.root_struct_def_, root, 0, parser.opts, _text)) { return false; } diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 37692f981..56b1547ca 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -15,12 +15,11 @@ */ #include +#include #include #include #include -#include - #include "flatbuffers/idl.h" #include "flatbuffers/util.h" @@ -114,8 +113,8 @@ std::string MakeScreamingCamel(const std::string &in) { return s; } -void DeserializeDoc( std::vector &doc, - const Vector> *documentation) { +void DeserializeDoc(std::vector &doc, + const Vector> *documentation) { if (documentation == nullptr) return; for (uoffset_t index = 0; index < documentation->size(); index++) doc.push_back(documentation->Get(index)->str()); @@ -399,7 +398,8 @@ CheckedError Parser::Next() { "illegal Unicode sequence (unpaired high surrogate)"); } // reset if non-printable - attr_is_trivial_ascii_string_ &= check_ascii_range(*cursor_, ' ', '~'); + attr_is_trivial_ascii_string_ &= + check_ascii_range(*cursor_, ' ', '~'); attribute_ += *cursor_++; } @@ -437,7 +437,7 @@ CheckedError Parser::Next() { cursor_ += 2; break; } - FLATBUFFERS_FALLTHROUGH(); // else fall thru + FLATBUFFERS_FALLTHROUGH(); // else fall thru default: const auto has_sign = (c == '+') || (c == '-'); // '-'/'+' and following identifier - can be a predefined constant like: @@ -451,14 +451,15 @@ CheckedError Parser::Next() { return NoError(); } - auto dot_lvl = (c == '.') ? 0 : 1; // dot_lvl==0 <=> exactly one '.' seen - if (!dot_lvl && !is_digit(*cursor_)) return NoError(); // enum? + auto dot_lvl = + (c == '.') ? 0 : 1; // dot_lvl==0 <=> exactly one '.' seen + if (!dot_lvl && !is_digit(*cursor_)) return NoError(); // enum? // Parser accepts hexadecimal-floating-literal (see C++ 5.13.4). if (is_digit(c) || has_sign || !dot_lvl) { const auto start = cursor_ - 1; auto start_digits = !is_digit(c) ? cursor_ : cursor_ - 1; - if (!is_digit(c) && is_digit(*cursor_)){ - start_digits = cursor_; // see digit in cursor_ position + if (!is_digit(c) && is_digit(*cursor_)) { + start_digits = cursor_; // see digit in cursor_ position c = *cursor_++; } // hex-float can't begind with '.' @@ -501,7 +502,8 @@ CheckedError Parser::Next() { } std::string ch; ch = c; - if (false == check_ascii_range(c, ' ', '~')) ch = "code: " + NumToString(c); + if (false == check_ascii_range(c, ' ', '~')) + ch = "code: " + NumToString(c); return Error("illegal character: " + ch); } } @@ -730,7 +732,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { if (!IsScalar(type.base_type) || (struct_def.fixed && field->value.constant != "0")) return Error( - "default values currently only supported for scalars in tables"); + "default values currently only supported for scalars in tables"); } // Append .0 if the value has not it (skip hex and scientific floats). // This suffix needed for generated C++ code. @@ -738,7 +740,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { auto &text = field->value.constant; FLATBUFFERS_ASSERT(false == text.empty()); auto s = text.c_str(); - while(*s == ' ') s++; + while (*s == ' ') s++; if (*s == '-' || *s == '+') s++; // 1) A float constants (nan, inf, pi, etc) is a kind of identifier. // 2) A float number needn't ".0" at the end if it has exponent. @@ -774,7 +776,8 @@ CheckedError Parser::ParseField(StructDef &struct_def) { field->deprecated = field->attributes.Lookup("deprecated") != nullptr; auto hash_name = field->attributes.Lookup("hash"); if (hash_name) { - switch ((type.base_type == BASE_TYPE_VECTOR) ? type.element : type.base_type) { + switch ((type.base_type == BASE_TYPE_VECTOR) ? type.element + : type.base_type) { case BASE_TYPE_SHORT: case BASE_TYPE_USHORT: { if (FindHashFunction16(hash_name->constant.c_str()) == nullptr) @@ -798,7 +801,8 @@ CheckedError Parser::ParseField(StructDef &struct_def) { } default: return Error( - "only short, ushort, int, uint, long and ulong data types support hashing."); + "only short, ushort, int, uint, long and ulong data types support " + "hashing."); } } auto cpp_type = field->attributes.Lookup("cpp_type"); @@ -817,8 +821,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { if (field->deprecated && struct_def.fixed) return Error("can't deprecate fields in a struct"); field->required = field->attributes.Lookup("required") != nullptr; - if (field->required && - (struct_def.fixed || IsScalar(type.base_type))) + if (field->required && (struct_def.fixed || IsScalar(type.base_type))) return Error("only non-scalar fields in tables may be 'required'"); field->key = field->attributes.Lookup("key") != nullptr; if (field->key) { @@ -861,8 +864,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { if (field->attributes.Lookup("flexbuffer")) { field->flexbuffer = true; uses_flexbuffers_ = true; - if (type.base_type != BASE_TYPE_VECTOR || - type.element != BASE_TYPE_UCHAR) + if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR) return Error("flexbuffer attribute may only apply to a vector of ubyte"); } @@ -902,8 +904,7 @@ CheckedError Parser::ParseComma() { CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, size_t parent_fieldn, const StructDef *parent_struct_def, - uoffset_t count, - bool inside_vector) { + uoffset_t count, bool inside_vector) { switch (val.type.base_type) { case BASE_TYPE_UNION: { FLATBUFFERS_ASSERT(field); @@ -921,8 +922,8 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, uoffset_t offset; ECHECK(atot(elem->first.constant.c_str(), *this, &offset)); vector_of_union_types = reinterpret_cast *>( - builder_.GetCurrentBufferPointer() + - builder_.GetSize() - offset); + builder_.GetCurrentBufferPointer() + builder_.GetSize() - + offset); break; } } else { @@ -964,8 +965,7 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, } } if (constant.empty() && !vector_of_union_types) { - return Error("missing type field for this union value: " + - field->name); + return Error("missing type field for this union value: " + field->name); } uint8_t enum_idx; if (vector_of_union_types) { @@ -1040,10 +1040,9 @@ void Parser::SerializeStruct(FlatBufferBuilder &builder, builder.AddStructOffset(val.offset, builder.GetSize()); } -template +template CheckedError Parser::ParseTableDelimiters(size_t &fieldn, - const StructDef *struct_def, - F body) { + const StructDef *struct_def, F body) { // We allow tables both as JSON object{ .. } with field names // or vector[..] with all fields in order char terminator = '}'; @@ -1217,7 +1216,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, reinterpret_cast(field_value.constant.c_str()), InlineSize(field_value.type)); break; - // clang-format on + // clang-format on } } } @@ -1243,7 +1242,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, return NoError(); } -template +template CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) { EXPECT('['); for (;;) { @@ -1259,12 +1258,11 @@ CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) { static bool CompareType(const uint8_t *a, const uint8_t *b, BaseType ftype) { switch (ftype) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE, RTYPE, KTYPE) \ - case BASE_TYPE_ ## ENUM: \ - return ReadScalar(a) < ReadScalar(b); +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ + RTYPE, KTYPE) \ + case BASE_TYPE_##ENUM: return ReadScalar(a) < ReadScalar(b); FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD +#undef FLATBUFFERS_TD case BASE_TYPE_STRING: // Indirect offset pointer to string pointer. a += ReadScalar(a); @@ -1278,21 +1276,21 @@ static bool CompareType(const uint8_t *a, const uint8_t *b, BaseType ftype) { // See below for why we need our own sort :( template void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) { - if (end - begin <= static_cast(width)) return; - auto l = begin + width; - auto r = end; - while (l < r) { - if (comparator(begin, l)) { - r -= width; - swapper(l, r); - } else { - l++; - } + if (end - begin <= static_cast(width)) return; + auto l = begin + width; + auto r = end; + while (l < r) { + if (comparator(begin, l)) { + r -= width; + swapper(l, r); + } else { + l++; } - l -= width; - swapper(begin, l); - SimpleQsort(begin, l, width, comparator, swapper); - SimpleQsort(r, end, width, comparator, swapper); + } + l -= width; + swapper(begin, l); + SimpleQsort(begin, l, width, comparator, swapper); + SimpleQsort(r, end, width, comparator, swapper); } CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue, @@ -1359,46 +1357,49 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue, static BaseType ftype = key->value.type.base_type; if (type.struct_def->fixed) { - auto v = reinterpret_cast( - builder_.GetCurrentBufferPointer()); - SimpleQsort(v->Data(), - v->Data() + v->size() * type.struct_def->bytesize, - type.struct_def->bytesize, - [](const uint8_t *a, const uint8_t *b) -> bool { - return CompareType(a + offset, b + offset, ftype); - }, [&](uint8_t *a, uint8_t *b) { - // FIXME: faster? - for (size_t i = 0; i < type.struct_def->bytesize; i++) { - std::swap(a[i], b[i]); - } - }); + auto v = + reinterpret_cast(builder_.GetCurrentBufferPointer()); + SimpleQsort( + v->Data(), v->Data() + v->size() * type.struct_def->bytesize, + type.struct_def->bytesize, + [](const uint8_t *a, const uint8_t *b) -> bool { + return CompareType(a + offset, b + offset, ftype); + }, + [&](uint8_t *a, uint8_t *b) { + // FIXME: faster? + for (size_t i = 0; i < type.struct_def->bytesize; i++) { + std::swap(a[i], b[i]); + } + }); } else { auto v = reinterpret_cast> *>( - builder_.GetCurrentBufferPointer()); + builder_.GetCurrentBufferPointer()); // Here also can't use std::sort. We do have an iterator type for it, // but it is non-standard as it will dereference the offsets, and thus // can't be used to swap elements. - SimpleQsort>(v->data(), v->data() + v->size(), 1, - [](const Offset
*_a, const Offset
*_b) -> bool { - // Indirect offset pointer to table pointer. - auto a = reinterpret_cast(_a) + - ReadScalar(_a); - auto b = reinterpret_cast(_b) + - ReadScalar(_b); - // Fetch field address from table. - a = reinterpret_cast(a)->GetAddressOf(offset); - b = reinterpret_cast(b)->GetAddressOf(offset); - return CompareType(a, b, ftype); - }, [&](Offset
*a, Offset
*b) { - // These are serialized offsets, so are relative where they are - // stored in memory, so compute the distance between these pointers: - ptrdiff_t diff = (b - a) * sizeof(Offset
); - assert(diff >= 0); // Guaranteed by SimpleQsort. - auto udiff = static_cast(diff); - a->o = EndianScalar(ReadScalar(a) - udiff); - b->o = EndianScalar(ReadScalar(b) + udiff); - std::swap(*a, *b); - }); + SimpleQsort>( + v->data(), v->data() + v->size(), 1, + [](const Offset
*_a, const Offset
*_b) -> bool { + // Indirect offset pointer to table pointer. + auto a = reinterpret_cast(_a) + + ReadScalar(_a); + auto b = reinterpret_cast(_b) + + ReadScalar(_b); + // Fetch field address from table. + a = reinterpret_cast(a)->GetAddressOf(offset); + b = reinterpret_cast(b)->GetAddressOf(offset); + return CompareType(a, b, ftype); + }, + [&](Offset
*a, Offset
*b) { + // These are serialized offsets, so are relative where they are + // stored in memory, so compute the distance between these pointers: + ptrdiff_t diff = (b - a) * sizeof(Offset
); + assert(diff >= 0); // Guaranteed by SimpleQsort. + auto udiff = static_cast(diff); + a->o = EndianScalar(ReadScalar(a) - udiff); + b->o = EndianScalar(ReadScalar(b) + udiff); + std::swap(*a, *b); + }); } } return NoError(); @@ -1478,12 +1479,11 @@ CheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field, nested_parser.enums_.dict.clear(); nested_parser.enums_.vec.clear(); - if (!ok) { - ECHECK(Error(nested_parser.error_)); - } + if (!ok) { ECHECK(Error(nested_parser.error_)); } // Force alignment for nested flatbuffer - builder_.ForceVectorAlignment(nested_parser.builder_.GetSize(), sizeof(uint8_t), - nested_parser.builder_.GetBufferMinAlignment()); + builder_.ForceVectorAlignment( + nested_parser.builder_.GetSize(), sizeof(uint8_t), + nested_parser.builder_.GetBufferMinAlignment()); auto off = builder_.CreateVector(nested_parser.builder_.GetBufferPointer(), nested_parser.builder_.GetSize()); @@ -1499,7 +1499,7 @@ CheckedError Parser::ParseMetaData(SymbolTable *attributes) { auto name = attribute_; if (false == (Is(kTokenIdentifier) || Is(kTokenStringConstant))) return Error("attribute name must be either identifier or string: " + - name); + name); if (known_attributes_.find(name) == known_attributes_.end()) return Error("user define attributes must be declared before use: " + name); @@ -1648,10 +1648,10 @@ template inline void SingleValueRepack(Value &e, T val) { } #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) // Normilaze defaults NaN to unsigned quiet-NaN(0). -static inline void SingleValueRepack(Value& e, float val) { +static inline void SingleValueRepack(Value &e, float val) { if (val != val) e.constant = "nan"; } -static inline void SingleValueRepack(Value& e, double val) { +static inline void SingleValueRepack(Value &e, double val) { if (val != val) e.constant = "nan"; } #endif @@ -1774,7 +1774,7 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e, "' to value of <" + std::string(kTypeNames[in_type]) + "> type."; return Error(msg); } - const auto match_type = e.type.base_type; // may differ from in_type + const auto match_type = e.type.base_type; // may differ from in_type // The check_now flag must be true when parse a fbs-schema. // This flag forces to check default scalar values or metadata of field. // For JSON parser the flag should be false. @@ -2210,11 +2210,10 @@ CheckedError Parser::CheckClash(std::vector &fields, bool Parser::SupportsAdvancedUnionFeatures() const { return opts.lang_to_generate != 0 && - (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kJs | - IDLOptions::kTs | IDLOptions::kPhp | - IDLOptions::kJava | IDLOptions::kCSharp | - IDLOptions::kKotlin | - IDLOptions::kBinary)) == 0; + (opts.lang_to_generate & + ~(IDLOptions::kCpp | IDLOptions::kJs | IDLOptions::kTs | + IDLOptions::kPhp | IDLOptions::kJava | IDLOptions::kCSharp | + IDLOptions::kKotlin | IDLOptions::kBinary)) == 0; } bool Parser::SupportsAdvancedArrayFeatures() const { @@ -2486,8 +2485,8 @@ CheckedError Parser::StartEnum(const std::string &enum_name, bool is_union, if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name), &enum_def)) return Error("enum already exists: " + enum_name); - enum_def.underlying_type.base_type = is_union ? BASE_TYPE_UTYPE - : BASE_TYPE_INT; + enum_def.underlying_type.base_type = + is_union ? BASE_TYPE_UTYPE : BASE_TYPE_INT; enum_def.underlying_type.enum_def = &enum_def; if (dest) *dest = &enum_def; return NoError(); @@ -2623,8 +2622,8 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend, if (oneof_type.base_type != BASE_TYPE_STRUCT || !oneof_type.struct_def || oneof_type.struct_def->fixed) return Error("oneof '" + name + - "' cannot be mapped to a union because member '" + - oneof_field.name + "' is not a table type."); + "' cannot be mapped to a union because member '" + + oneof_field.name + "' is not a table type."); EnumValBuilder evb(*this, *oneof_union); auto ev = evb.CreateEnumerator(oneof_type.struct_def->name); ev->union_type = oneof_type; @@ -2989,9 +2988,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, // entered into included_files_. // This is recursive, but only go as deep as the number of include // statements. - if (source_filename) { - included_files_.erase(source_filename); - } + if (source_filename) { included_files_.erase(source_filename); } return DoParse(source, include_paths, source_filename, include_filename); } @@ -3015,9 +3012,9 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, uoffset_t toff; ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); if (opts.size_prefixed) { - builder_.FinishSizePrefixed(Offset
(toff), file_identifier_.length() - ? file_identifier_.c_str() - : nullptr); + builder_.FinishSizePrefixed( + Offset
(toff), + file_identifier_.length() ? file_identifier_.c_str() : nullptr); } else { builder_.Finish(Offset
(toff), file_identifier_.length() ? file_identifier_.c_str() @@ -3038,8 +3035,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, if (opts.root_type.empty()) { if (!SetRootType(root_type.c_str())) return Error("unknown root type: " + root_type); - if (root_struct_def_->fixed) - return Error("root type must be a table"); + if (root_struct_def_->fixed) return Error("root type must be a table"); } EXPECT(';'); } else if (IsIdent("file_identifier")) { @@ -3144,10 +3140,9 @@ void Parser::Serialize() { auto fiid__ = builder_.CreateString(file_identifier_); auto fext__ = builder_.CreateString(file_extension_); auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets); - auto schema_offset = - reflection::CreateSchema(builder_, objs__, enum__, fiid__, fext__, - (root_struct_def_ ? root_struct_def_->serialized_location : 0), - serv__); + auto schema_offset = reflection::CreateSchema( + builder_, objs__, enum__, fiid__, fext__, + (root_struct_def_ ? root_struct_def_->serialized_location : 0), serv__); if (opts.size_prefixed) { builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier()); } else { @@ -3193,22 +3188,20 @@ Offset StructDef::Serialize(FlatBufferBuilder *builder, auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets); auto attr__ = SerializeAttributes(builder, parser); auto docs__ = parser.opts.binary_schema_comments - ? builder->CreateVectorOfStrings(doc_comment) - : 0; + ? builder->CreateVectorOfStrings(doc_comment) + : 0; return reflection::CreateObject(*builder, name__, flds__, fixed, static_cast(minalign), - static_cast(bytesize), - attr__, docs__); + static_cast(bytesize), attr__, docs__); } bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) { - if (!DeserializeAttributes(parser, object->attributes())) - return false; + if (!DeserializeAttributes(parser, object->attributes())) return false; DeserializeDoc(doc_comment, object->documentation()); name = parser.UnqualifiedName(object->name()->str()); predecl = false; sortbysize = attributes.Lookup("original_order") == nullptr && !fixed; - const auto& of = *(object->fields()); + const auto &of = *(object->fields()); auto indexes = std::vector(of.size()); for (uoffset_t i = 0; i < of.size(); i++) indexes[of.Get(i)->id()] = i; size_t tmp_struct_size = 0; @@ -3224,9 +3217,7 @@ bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) { // Recompute padding since that's currently not serialized. auto size = InlineSize(field_def->value.type); auto next_field = - i + 1 < indexes.size() - ? of.Get(indexes[i+1]) - : nullptr; + i + 1 < indexes.size() ? of.Get(indexes[i + 1]) : nullptr; tmp_struct_size += size; field_def->padding = next_field ? (next_field->offset() - field_def->value.offset) - size @@ -3245,9 +3236,10 @@ Offset FieldDef::Serialize(FlatBufferBuilder *builder, auto type__ = value.type.Serialize(builder); auto attr__ = SerializeAttributes(builder, parser); auto docs__ = parser.opts.binary_schema_comments - ? builder->CreateVectorOfStrings(doc_comment) - : 0; - return reflection::CreateField(*builder, name__, type__, id, value.offset, + ? builder->CreateVectorOfStrings(doc_comment) + : 0; + return reflection::CreateField( + *builder, name__, type__, id, value.offset, // Is uint64>max(int64) tested? IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0, // result may be platform-dependent if underlying is float (not double) @@ -3261,8 +3253,7 @@ Offset FieldDef::Serialize(FlatBufferBuilder *builder, bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) { name = field->name()->str(); defined_namespace = parser.current_namespace_; - if (!value.type.Deserialize(parser, field->type())) - return false; + if (!value.type.Deserialize(parser, field->type())) return false; value.offset = field->offset(); if (IsInteger(value.type.base_type)) { value.constant = NumToString(field->default_integer()); @@ -3276,8 +3267,7 @@ bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) { deprecated = field->deprecated(); required = field->required(); key = field->key(); - if (!DeserializeAttributes(parser, field->attributes())) - return false; + if (!DeserializeAttributes(parser, field->attributes())) return false; // TODO: this should probably be handled by a separate attribute if (attributes.Lookup("flexbuffer")) { flexbuffer = true; @@ -3301,18 +3291,16 @@ Offset RPCCall::Serialize(FlatBufferBuilder *builder, auto name__ = builder->CreateString(name); auto attr__ = SerializeAttributes(builder, parser); auto docs__ = parser.opts.binary_schema_comments - ? builder->CreateVectorOfStrings(doc_comment) - : 0; - return reflection::CreateRPCCall(*builder, name__, - request->serialized_location, - response->serialized_location, - attr__, docs__); + ? builder->CreateVectorOfStrings(doc_comment) + : 0; + return reflection::CreateRPCCall( + *builder, name__, request->serialized_location, + response->serialized_location, attr__, docs__); } bool RPCCall::Deserialize(Parser &parser, const reflection::RPCCall *call) { name = call->name()->str(); - if (!DeserializeAttributes(parser, call->attributes())) - return false; + if (!DeserializeAttributes(parser, call->attributes())) return false; DeserializeDoc(doc_comment, call->documentation()); request = parser.structs_.Lookup(call->request()->name()->str()); response = parser.structs_.Lookup(call->response()->name()->str()); @@ -3331,8 +3319,8 @@ Offset ServiceDef::Serialize(FlatBufferBuilder *builder, auto call__ = builder->CreateVector(servicecall_offsets); auto attr__ = SerializeAttributes(builder, parser); auto docs__ = parser.opts.binary_schema_comments - ? builder->CreateVectorOfStrings(doc_comment) - : 0; + ? builder->CreateVectorOfStrings(doc_comment) + : 0; return reflection::CreateService(*builder, name__, call__, attr__, docs__); } @@ -3349,8 +3337,7 @@ bool ServiceDef::Deserialize(Parser &parser, } } } - if (!DeserializeAttributes(parser, service->attributes())) - return false; + if (!DeserializeAttributes(parser, service->attributes())) return false; DeserializeDoc(doc_comment, service->documentation()); return true; } @@ -3367,8 +3354,8 @@ Offset EnumDef::Serialize(FlatBufferBuilder *builder, auto type__ = underlying_type.Serialize(builder); auto attr__ = SerializeAttributes(builder, parser); auto docs__ = parser.opts.binary_schema_comments - ? builder->CreateVectorOfStrings(doc_comment) - : 0; + ? builder->CreateVectorOfStrings(doc_comment) + : 0; return reflection::CreateEnum(*builder, name__, vals__, is_union, type__, attr__, docs__); } @@ -3387,8 +3374,7 @@ bool EnumDef::Deserialize(Parser &parser, const reflection::Enum *_enum) { if (!underlying_type.Deserialize(parser, _enum->underlying_type())) { return false; } - if (!DeserializeAttributes(parser, _enum->attributes())) - return false; + if (!DeserializeAttributes(parser, _enum->attributes())) return false; DeserializeDoc(doc_comment, _enum->documentation()); return true; } @@ -3398,9 +3384,10 @@ Offset EnumVal::Serialize(FlatBufferBuilder *builder, auto name__ = builder->CreateString(name); auto type__ = union_type.Serialize(builder); auto docs__ = parser.opts.binary_schema_comments - ? builder->CreateVectorOfStrings(doc_comment) - : 0; - return reflection::CreateEnumVal(*builder, name__, value, + ? builder->CreateVectorOfStrings(doc_comment) + : 0; + return reflection::CreateEnumVal( + *builder, name__, value, union_type.struct_def ? union_type.struct_def->serialized_location : 0, type__, docs__); } @@ -3409,8 +3396,7 @@ bool EnumVal::Deserialize(const Parser &parser, const reflection::EnumVal *val) { name = val->name()->str(); value = val->value(); - if (!union_type.Deserialize(parser, val->union_type())) - return false; + if (!union_type.Deserialize(parser, val->union_type())) return false; DeserializeDoc(doc_comment, val->documentation()); return true; } @@ -3432,8 +3418,7 @@ bool Type::Deserialize(const Parser &parser, const reflection::Type *type) { bool is_series = type->base_type() == reflection::Vector || type->base_type() == reflection::Array; if (type->base_type() == reflection::Obj || - (is_series && - type->element() == reflection::Obj)) { + (is_series && type->element() == reflection::Obj)) { if (static_cast(type->index()) < parser.structs_.vec.size()) { struct_def = parser.structs_.vec[type->index()]; struct_def->refcount++; @@ -3474,8 +3459,7 @@ Definition::SerializeAttributes(FlatBufferBuilder *builder, bool Definition::DeserializeAttributes( Parser &parser, const Vector> *attrs) { - if (attrs == nullptr) - return true; + if (attrs == nullptr) return true; for (uoffset_t i = 0; i < attrs->size(); ++i) { auto kv = attrs->Get(i); auto value = new Value(); @@ -3495,7 +3479,7 @@ bool Definition::DeserializeAttributes( bool Parser::Deserialize(const uint8_t *buf, const size_t size) { flatbuffers::Verifier verifier(reinterpret_cast(buf), size); bool size_prefixed = false; - if(!reflection::SchemaBufferHasIdentifier(buf)) { + if (!reflection::SchemaBufferHasIdentifier(buf)) { if (!flatbuffers::BufferHasIdentifier(buf, reflection::SchemaIdentifier(), true)) return false; @@ -3504,9 +3488,7 @@ bool Parser::Deserialize(const uint8_t *buf, const size_t size) { } auto verify_fn = size_prefixed ? &reflection::VerifySizePrefixedSchemaBuffer : &reflection::VerifySchemaBuffer; - if (!verify_fn(verifier)) { - return false; - } + if (!verify_fn(verifier)) { return false; } auto schema = size_prefixed ? reflection::GetSizePrefixedSchema(buf) : reflection::GetSchema(buf); return Deserialize(schema); @@ -3555,7 +3537,7 @@ bool Parser::Deserialize(const reflection::Schema *schema) { auto struct_def = structs_.Lookup(qualified_name); struct_def->defined_namespace = GetNamespace(qualified_name, namespaces_, namespaces_index); - if (!struct_def->Deserialize(*this, * it)) { return false; } + if (!struct_def->Deserialize(*this, *it)) { return false; } if (schema->root_table() == *it) { root_struct_def_ = struct_def; } } for (auto it = schema->enums()->begin(); it != schema->enums()->end(); ++it) { diff --git a/src/reflection.cpp b/src/reflection.cpp index fc211c5fa..409dbd038 100644 --- a/src/reflection.cpp +++ b/src/reflection.cpp @@ -15,6 +15,7 @@ */ #include "flatbuffers/reflection.h" + #include "flatbuffers/util.h" // Helper functionality for reflection. @@ -431,8 +432,8 @@ Offset CopyTable(FlatBufferBuilder &fbb, break; } } - FLATBUFFERS_FALLTHROUGH(); // fall thru - default: { // Scalars and structs. + FLATBUFFERS_FALLTHROUGH(); // fall thru + default: { // Scalars and structs. auto element_size = GetTypeSize(element_base_type); if (elemobjectdef && elemobjectdef->is_struct()) element_size = elemobjectdef->bytesize(); @@ -466,7 +467,7 @@ Offset CopyTable(FlatBufferBuilder &fbb, break; } } - FLATBUFFERS_FALLTHROUGH(); // fall thru + FLATBUFFERS_FALLTHROUGH(); // fall thru case reflection::Union: case reflection::String: case reflection::Vector: @@ -495,9 +496,8 @@ bool VerifyStruct(flatbuffers::Verifier &v, auto offset = parent_table.GetOptionalFieldOffset(field_offset); if (required && !offset) { return false; } - return !offset || - v.Verify(reinterpret_cast(&parent_table), offset, - obj.bytesize()); + return !offset || v.Verify(reinterpret_cast(&parent_table), + offset, obj.bytesize()); } bool VerifyVectorOfStructs(flatbuffers::Verifier &v, @@ -535,9 +535,8 @@ bool VerifyUnion(flatbuffers::Verifier &v, const reflection::Schema &schema, } case reflection::String: return v.VerifyString( - reinterpret_cast(elem)); - default: - return false; + reinterpret_cast(elem)); + default: return false; } } @@ -597,27 +596,24 @@ bool VerifyVector(flatbuffers::Verifier &v, const reflection::Schema &schema, } } case reflection::Union: { - auto vec = flatbuffers::GetFieldV>(table, - vec_field); + auto vec = flatbuffers::GetFieldV>( + table, vec_field); if (!v.VerifyVector(vec)) return false; if (!vec) return true; - auto type_vec = table.GetPointer *> - (vec_field.offset() - sizeof(voffset_t)); + auto type_vec = table.GetPointer *>(vec_field.offset() - + sizeof(voffset_t)); if (!v.VerifyVector(type_vec)) return false; for (uoffset_t j = 0; j < vec->size(); j++) { // get union type from the prev field auto utype = type_vec->Get(j); auto elem = vec->Get(j); - if (!VerifyUnion(v, schema, utype, elem, vec_field)) - return false; + if (!VerifyUnion(v, schema, utype, elem, vec_field)) return false; } return true; } case reflection::Vector: case reflection::None: - default: - FLATBUFFERS_ASSERT(false); - return false; + default: FLATBUFFERS_ASSERT(false); return false; } } @@ -663,8 +659,7 @@ bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema, } break; case reflection::Vector: - if (!VerifyVector(v, schema, *table, *field_def)) - return false; + if (!VerifyVector(v, schema, *table, *field_def)) return false; break; case reflection::Obj: { auto child_obj = schema.objects()->Get(field_def->type()->index()); @@ -687,15 +682,11 @@ bool VerifyObject(flatbuffers::Verifier &v, const reflection::Schema &schema, voffset_t utype_offset = field_def->offset() - sizeof(voffset_t); auto utype = table->GetField(utype_offset, 0); auto uval = reinterpret_cast( - flatbuffers::GetFieldT(*table, *field_def)); - if (!VerifyUnion(v, schema, utype, uval, *field_def)) { - return false; - } + flatbuffers::GetFieldT(*table, *field_def)); + if (!VerifyUnion(v, schema, utype, uval, *field_def)) { return false; } break; } - default: - FLATBUFFERS_ASSERT(false); - break; + default: FLATBUFFERS_ASSERT(false); break; } } diff --git a/src/util.cpp b/src/util.cpp index b80bed250..08b779189 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -242,9 +242,9 @@ bool SetGlobalTestLocale(const char *locale_name, std::string *_value) { } bool ReadEnvironmentVariable(const char *var_name, std::string *_value) { - #ifdef _MSC_VER - __pragma(warning(disable : 4996)); // _CRT_SECURE_NO_WARNINGS - #endif +#ifdef _MSC_VER + __pragma(warning(disable : 4996)); // _CRT_SECURE_NO_WARNINGS +#endif auto env_str = std::getenv(var_name); if (!env_str) return false; if (_value) *_value = std::string(env_str); diff --git a/tests/native_type_test_impl.cpp b/tests/native_type_test_impl.cpp index 04ddb9632..edf23ebf7 100644 --- a/tests/native_type_test_impl.cpp +++ b/tests/native_type_test_impl.cpp @@ -1,13 +1,13 @@ #include "native_type_test_impl.h" + #include "native_type_test_generated.h" namespace flatbuffers { - Geometry::Vector3D Pack(const Native::Vector3D &obj) { - return Geometry::Vector3D(obj.x, obj.y, obj.z); - } - - const Native::Vector3D UnPack(const Geometry::Vector3D &obj) { - return Native::Vector3D(obj.x(), obj.y(), obj.z()); - } +Geometry::Vector3D Pack(const Native::Vector3D &obj) { + return Geometry::Vector3D(obj.x, obj.y, obj.z); } +const Native::Vector3D UnPack(const Geometry::Vector3D &obj) { + return Native::Vector3D(obj.x(), obj.y(), obj.z()); +} +} // namespace flatbuffers diff --git a/tests/native_type_test_impl.h b/tests/native_type_test_impl.h index 2473ad3c7..fb35e0fce 100644 --- a/tests/native_type_test_impl.h +++ b/tests/native_type_test_impl.h @@ -2,23 +2,31 @@ #define NATIVE_TYPE_TEST_IMPL_H namespace Native { - struct Vector3D { - float x; - float y; - float z; +struct Vector3D { + float x; + float y; + float z; - Vector3D() { x = 0; y = 0; z = 0; }; - Vector3D(float _x, float _y, float _z) { this->x = _x; this->y = _y; this->z = _z; } + Vector3D() { + x = 0; + y = 0; + z = 0; }; -} + Vector3D(float _x, float _y, float _z) { + this->x = _x; + this->y = _y; + this->z = _z; + } +}; +} // namespace Native -namespace Geometry { - struct Vector3D; +namespace Geometry { +struct Vector3D; } namespace flatbuffers { - Geometry::Vector3D Pack(const Native::Vector3D &obj); - const Native::Vector3D UnPack(const Geometry::Vector3D &obj); -} +Geometry::Vector3D Pack(const Native::Vector3D &obj); +const Native::Vector3D UnPack(const Geometry::Vector3D &obj); +} // namespace flatbuffers -#endif // VECTOR3D_PACK_H +#endif // VECTOR3D_PACK_H diff --git a/tests/test.cpp b/tests/test.cpp index 6e2dc546c..abfae0d59 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ #include + #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/minireflect.h" @@ -35,7 +36,7 @@ #include "union_vector/union_vector_generated.h" #include "monster_extra_generated.h" #if !defined(_MSC_VER) || _MSC_VER >= 1700 -#include "arrays_test_generated.h" +# include "arrays_test_generated.h" #endif #include "native_type_test_generated.h" @@ -43,7 +44,6 @@ #include "flatbuffers/flexbuffers.h" - // clang-format off // Check that char* and uint8_t* are interoperable types. // The reinterpret_cast<> between the pointers are used to simplify data loading. @@ -72,7 +72,8 @@ void FlatBufferBuilderTest(); // http://en.wikipedia.org/wiki/Park%E2%80%93Miller_random_number_generator uint32_t lcg_seed = 48271; uint32_t lcg_rand() { - return lcg_seed = (static_cast(lcg_seed) * 279470273UL) % 4294967291UL; + return lcg_seed = + (static_cast(lcg_seed) * 279470273UL) % 4294967291UL; } void lcg_reset() { lcg_seed = 48271; } @@ -200,14 +201,13 @@ flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string &buffer) { auto vecofcolors = builder.CreateVectorScalarCast(colors, 2); // shortcut for creating monster with all fields set: - auto mloc = CreateMonster(builder, &vec, 150, 80, name, inventory, Color_Blue, - Any_Monster, mlocs[1].Union(), // Store a union. - testv, vecofstrings, vecoftables, 0, - nested_flatbuffer_vector, 0, false, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3.14159f, 3.0f, 0.0f, vecofstrings2, - vecofstructs, flex, testv2, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, AnyUniqueAliases_NONE, 0, - AnyAmbiguousAliases_NONE, 0, vecofcolors); + auto mloc = CreateMonster( + builder, &vec, 150, 80, name, inventory, Color_Blue, Any_Monster, + mlocs[1].Union(), // Store a union. + testv, vecofstrings, vecoftables, 0, nested_flatbuffer_vector, 0, false, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.14159f, 3.0f, 0.0f, vecofstrings2, + vecofstructs, flex, testv2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + AnyUniqueAliases_NONE, 0, AnyAmbiguousAliases_NONE, 0, vecofcolors); FinishMonsterBuffer(builder, mloc); @@ -567,8 +567,7 @@ void SizePrefixedTest() { // Create size prefixed buffer. flatbuffers::FlatBufferBuilder fbb; FinishSizePrefixedMonsterBuffer( - fbb, - CreateMonster(fbb, 0, 200, 300, fbb.CreateString("bob"))); + fbb, CreateMonster(fbb, 0, 200, 300, fbb.CreateString("bob"))); // Verify it. flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize()); @@ -598,7 +597,8 @@ void JsonDefaultTest() { // load FlatBuffer schema (.fbs) from disk std::string schemafile; TEST_EQ(flatbuffers::LoadFile((test_data_path + "monster_test.fbs").c_str(), - false, &schemafile), true); + false, &schemafile), + true); // parse schema first, so we can use it to parse the data after flatbuffers::Parser parser; auto include_test_path = @@ -771,7 +771,7 @@ void ParseAndGenerateTextTest(bool binary) { true); auto include_test_path = - flatbuffers::ConCatPathFileName(test_data_path, "include_test"); + flatbuffers::ConCatPathFileName(test_data_path, "include_test"); const char *include_directories[] = { test_data_path.c_str(), include_test_path.c_str(), nullptr }; @@ -782,8 +782,10 @@ void ParseAndGenerateTextTest(bool binary) { reinterpret_cast(schemafile.c_str()), schemafile.size()); TEST_EQ(reflection::VerifySchemaBuffer(verifier), true); - //auto schema = reflection::GetSchema(schemafile.c_str()); - TEST_EQ(parser.Deserialize((const uint8_t *)schemafile.c_str(), schemafile.size()), true); + // auto schema = reflection::GetSchema(schemafile.c_str()); + TEST_EQ(parser.Deserialize((const uint8_t *)schemafile.c_str(), + schemafile.size()), + true); } else { TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true); } @@ -1029,7 +1031,8 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { } void MiniReflectFlatBuffersTest(uint8_t *flatbuf) { - auto s = flatbuffers::FlatBufferToString(flatbuf, Monster::MiniReflectTypeTable()); + auto s = + flatbuffers::FlatBufferToString(flatbuf, Monster::MiniReflectTypeTable()); TEST_EQ_STR( s.c_str(), "{ " @@ -1060,15 +1063,15 @@ void MiniReflectFlatBuffersTest(uint8_t *flatbuf) { "}"); Test test(16, 32); - Vec3 vec(1,2,3, 1.5, Color_Red, test); + Vec3 vec(1, 2, 3, 1.5, Color_Red, test); flatbuffers::FlatBufferBuilder vec_builder; vec_builder.Finish(vec_builder.CreateStruct(vec)); auto vec_buffer = vec_builder.Release(); auto vec_str = flatbuffers::FlatBufferToString(vec_buffer.data(), Vec3::MiniReflectTypeTable()); - TEST_EQ_STR( - vec_str.c_str(), - "{ x: 1.0, y: 2.0, z: 3.0, test1: 1.5, test2: Red, test3: { a: 16, b: 32 } }"); + TEST_EQ_STR(vec_str.c_str(), + "{ x: 1.0, y: 2.0, z: 3.0, test1: 1.5, test2: Red, test3: { a: " + "16, b: 32 } }"); } // Parse a .proto schema, output as .fbs @@ -1085,11 +1088,10 @@ void ParseProtoTest() { flatbuffers::LoadFile((test_data_path + "prototest/test.golden").c_str(), false, &goldenfile), true); - TEST_EQ( - flatbuffers::LoadFile((test_data_path + - "prototest/test_union.golden").c_str(), - false, &goldenunionfile), - true); + TEST_EQ(flatbuffers::LoadFile( + (test_data_path + "prototest/test_union.golden").c_str(), false, + &goldenunionfile), + true); flatbuffers::IDLOptions opts; opts.include_dependence_headers = false; @@ -1526,9 +1528,9 @@ bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; } // Additional parser testing not covered elsewhere. void ValueTest() { // Test scientific notation numbers. - TEST_EQ(FloatCompare(TestValue("{ Y:0.0314159e+2 }", "float"), - 3.14159f), - true); + TEST_EQ( + FloatCompare(TestValue("{ Y:0.0314159e+2 }", "float"), 3.14159f), + true); // number in string TEST_EQ(FloatCompare(TestValue("{ Y:\"0.0314159e+2\" }", "float"), 3.14159f), @@ -1566,7 +1568,6 @@ void ValueTest() { // check comments before and after json object TEST_EQ(TestValue("/*before*/ { Y:1 } /*after*/", "int"), 1); TEST_EQ(TestValue("//before \n { Y:1 } //after", "int"), 1); - } void NestedListTest() { @@ -1608,8 +1609,8 @@ void EnumNamesTest() { // For details see C++17 standard or explanation on the SO: // stackoverflow.com/questions/18195312/what-happens-if-you-static-cast-invalid-value-to-enum-class TEST_EQ_STR("", EnumNameColor(static_cast(0))); - TEST_EQ_STR("", EnumNameColor(static_cast(Color_ANY-1))); - TEST_EQ_STR("", EnumNameColor(static_cast(Color_ANY+1))); + TEST_EQ_STR("", EnumNameColor(static_cast(Color_ANY - 1))); + TEST_EQ_STR("", EnumNameColor(static_cast(Color_ANY + 1))); } void EnumOutOfRangeTest() { @@ -1629,12 +1630,14 @@ void EnumOutOfRangeTest() { TestError("enum X:uint { Y = -1 }", "enum value does not fit"); TestError("enum X:uint { Y = 4294967297 }", "enum value does not fit"); TestError("enum X:long { Y = 9223372036854775808 }", "does not fit"); - TestError("enum X:long { Y = 9223372036854775807, Z }", "enum value does not fit"); + TestError("enum X:long { Y = 9223372036854775807, Z }", + "enum value does not fit"); TestError("enum X:ulong { Y = -1 }", "does not fit"); TestError("enum X:ubyte (bit_flags) { Y=8 }", "bit flag out"); - TestError("enum X:byte (bit_flags) { Y=7 }", "must be unsigned"); // -128 + TestError("enum X:byte (bit_flags) { Y=7 }", "must be unsigned"); // -128 // bit_flgs out of range - TestError("enum X:ubyte (bit_flags) { Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8 }", "out of range"); + TestError("enum X:ubyte (bit_flags) { Y0,Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8 }", + "out of range"); } void EnumValueTest() { @@ -1734,11 +1737,12 @@ void IntegerOutOfRangeTest() { void IntegerBoundaryTest() { // Check numerical compatibility with non-C++ languages. - // By the C++ standard, std::numerical_limits::min() == -9223372036854775807 (-2^63+1) or less* - // The Flatbuffers grammar and most of the languages (C#, Java, Rust) expect - // that minimum values are: -128, -32768,.., -9223372036854775808. - // Since C++20, static_cast(0x8000000000000000ULL) is well-defined two's complement cast. - // Therefore -9223372036854775808 should be valid negative value. + // By the C++ standard, std::numerical_limits::min() == + // -9223372036854775807 (-2^63+1) or less* The Flatbuffers grammar and most of + // the languages (C#, Java, Rust) expect that minimum values are: -128, + // -32768,.., -9223372036854775808. Since C++20, + // static_cast(0x8000000000000000ULL) is well-defined two's complement + // cast. Therefore -9223372036854775808 should be valid negative value. TEST_EQ(flatbuffers::numeric_limits::min(), -128); TEST_EQ(flatbuffers::numeric_limits::max(), 127); TEST_EQ(flatbuffers::numeric_limits::min(), -32768); @@ -1810,11 +1814,11 @@ void ValidFloatTest() { TEST_EQ(TestValue("{ Y:5 }", "float"), 5.0f); TEST_EQ(TestValue("{ Y:\"5\" }", "float"), 5.0f); - #if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) +#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) // Old MSVC versions may have problem with this check. // https://www.exploringbinary.com/visual-c-plus-plus-strtod-still-broken/ TEST_EQ(TestValue("{ Y:6.9294956446009195e15 }", "double"), - 6929495644600920.0); + 6929495644600920.0); // check nan's TEST_EQ(std::isnan(TestValue("{ Y:nan }", "double")), true); TEST_EQ(std::isnan(TestValue("{ Y:nan }", "float")), true); @@ -1936,8 +1940,8 @@ void GenerateTableTextTest() { TEST_EQ(ok, true); auto include_test_path = flatbuffers::ConCatPathFileName(test_data_path, "include_test"); - const char *include_directories[] = {test_data_path.c_str(), - include_test_path.c_str(), nullptr}; + const char *include_directories[] = { test_data_path.c_str(), + include_test_path.c_str(), nullptr }; flatbuffers::IDLOptions opt; opt.indent_step = -1; flatbuffers::Parser parser(opt); @@ -2237,7 +2241,7 @@ void InvalidUTF8Test() { // Check independence of identifier from locale. std::string locale_ident; locale_ident += "table T { F"; - locale_ident += static_cast(-32); // unsigned 0xE0 + locale_ident += static_cast(-32); // unsigned 0xE0 locale_ident += " :string; }"; locale_ident += "root_type T;"; locale_ident += "{}"; @@ -2311,8 +2315,8 @@ void UnionVectorTest() { // load FlatBuffer fbs schema and json. std::string schemafile, jsonfile; TEST_EQ(flatbuffers::LoadFile( - (test_data_path + "union_vector/union_vector.fbs").c_str(), - false, &schemafile), + (test_data_path + "union_vector/union_vector.fbs").c_str(), false, + &schemafile), true); TEST_EQ(flatbuffers::LoadFile( (test_data_path + "union_vector/union_vector.json").c_str(), @@ -2420,70 +2424,67 @@ void UnionVectorTest() { "characters: [ { books_read: 7 }, { sword_attack_damage: 5 }, " "{ books_read: 2 }, \"Other\", \"Unused\" ] }"); - flatbuffers::ToStringVisitor visitor("\n", true, " "); IterateFlatBuffer(fbb.GetBufferPointer(), MovieTypeTable(), &visitor); - TEST_EQ_STR( - visitor.s.c_str(), - "{\n" - " \"main_character_type\": \"Rapunzel\",\n" - " \"main_character\": {\n" - " \"hair_length\": 6\n" - " },\n" - " \"characters_type\": [\n" - " \"Belle\",\n" - " \"MuLan\",\n" - " \"BookFan\",\n" - " \"Other\",\n" - " \"Unused\"\n" - " ],\n" - " \"characters\": [\n" - " {\n" - " \"books_read\": 7\n" - " },\n" - " {\n" - " \"sword_attack_damage\": 5\n" - " },\n" - " {\n" - " \"books_read\": 2\n" - " },\n" - " \"Other\",\n" - " \"Unused\"\n" - " ]\n" - "}"); + TEST_EQ_STR(visitor.s.c_str(), + "{\n" + " \"main_character_type\": \"Rapunzel\",\n" + " \"main_character\": {\n" + " \"hair_length\": 6\n" + " },\n" + " \"characters_type\": [\n" + " \"Belle\",\n" + " \"MuLan\",\n" + " \"BookFan\",\n" + " \"Other\",\n" + " \"Unused\"\n" + " ],\n" + " \"characters\": [\n" + " {\n" + " \"books_read\": 7\n" + " },\n" + " {\n" + " \"sword_attack_damage\": 5\n" + " },\n" + " {\n" + " \"books_read\": 2\n" + " },\n" + " \"Other\",\n" + " \"Unused\"\n" + " ]\n" + "}"); // Generate text using parsed schema. std::string jsongen; auto result = GenerateText(parser, fbb.GetBufferPointer(), &jsongen); TEST_EQ(result, true); - TEST_EQ_STR( - jsongen.c_str(), - "{\n" - " main_character_type: \"Rapunzel\",\n" - " main_character: {\n" - " hair_length: 6\n" - " },\n" - " characters_type: [\n" - " \"Belle\",\n" - " \"MuLan\",\n" - " \"BookFan\",\n" - " \"Other\",\n" - " \"Unused\"\n" - " ],\n" - " characters: [\n" - " {\n" - " books_read: 7\n" - " },\n" - " {\n" - " sword_attack_damage: 5\n" - " },\n" - " {\n" - " books_read: 2\n" - " },\n" - " \"Other\",\n" - " \"Unused\"\n" - " ]\n" - "}\n"); + TEST_EQ_STR(jsongen.c_str(), + "{\n" + " main_character_type: \"Rapunzel\",\n" + " main_character: {\n" + " hair_length: 6\n" + " },\n" + " characters_type: [\n" + " \"Belle\",\n" + " \"MuLan\",\n" + " \"BookFan\",\n" + " \"Other\",\n" + " \"Unused\"\n" + " ],\n" + " characters: [\n" + " {\n" + " books_read: 7\n" + " },\n" + " {\n" + " sword_attack_damage: 5\n" + " },\n" + " {\n" + " books_read: 2\n" + " },\n" + " \"Other\",\n" + " \"Unused\"\n" + " ]\n" + "}\n"); // Simple test with reflection. parser.Serialize(); @@ -2496,7 +2497,8 @@ void UnionVectorTest() { TEST_EQ(parser2.Parse("struct Bool { b:bool; }" "union Any { Bool }" "table Root { a:Any; }" - "root_type Root;"), true); + "root_type Root;"), + true); TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true); } @@ -2703,7 +2705,7 @@ void TypeAliasesTest() { TEST_EQ(ta->u64(), flatbuffers::numeric_limits::max()); TEST_EQ(ta->f32(), 2.3f); TEST_EQ(ta->f64(), 2.3); - using namespace flatbuffers; // is_same + using namespace flatbuffers; // is_same static_assert(is_samei8()), int8_t>::value, "invalid type"); static_assert(is_samei16()), int16_t>::value, "invalid type"); static_assert(is_samei32()), int32_t>::value, "invalid type"); @@ -2729,14 +2731,16 @@ void UninitializedVectorTest() { flatbuffers::FlatBufferBuilder builder; Test *buf = nullptr; - auto vector_offset = builder.CreateUninitializedVectorOfStructs(2, &buf); + auto vector_offset = + builder.CreateUninitializedVectorOfStructs(2, &buf); TEST_NOTNULL(buf); buf[0] = Test(10, 20); buf[1] = Test(30, 40); auto required_name = builder.CreateString("myMonster"); auto monster_builder = MonsterBuilder(builder); - monster_builder.add_name(required_name); // required field mandated for monster. + monster_builder.add_name( + required_name); // required field mandated for monster. monster_builder.add_test4(vector_offset); builder.Finish(monster_builder.Finish()); @@ -2781,11 +2785,11 @@ void EqualOperatorTest() { // For testing any binaries, e.g. from fuzzing. void LoadVerifyBinaryTest() { std::string binary; - if (flatbuffers::LoadFile((test_data_path + - "fuzzer/your-filename-here").c_str(), - true, &binary)) { + if (flatbuffers::LoadFile( + (test_data_path + "fuzzer/your-filename-here").c_str(), true, + &binary)) { flatbuffers::Verifier verifier( - reinterpret_cast(binary.data()), binary.size()); + reinterpret_cast(binary.data()), binary.size()); TEST_EQ(VerifyMonsterBuffer(verifier), true); } } @@ -2801,24 +2805,28 @@ void CreateSharedStringTest() { TEST_EQ(onetwo.o != two.o, true); // Support for embedded nulls - const char chars_b[] = {'a', '\0', 'b'}; - const char chars_c[] = {'a', '\0', 'c'}; + const char chars_b[] = { 'a', '\0', 'b' }; + const char chars_c[] = { 'a', '\0', 'c' }; const auto null_b1 = builder.CreateSharedString(chars_b, sizeof(chars_b)); const auto null_c = builder.CreateSharedString(chars_c, sizeof(chars_c)); const auto null_b2 = builder.CreateSharedString(chars_b, sizeof(chars_b)); - TEST_EQ(null_b1.o != null_c.o, true); // Issue#5058 repro + TEST_EQ(null_b1.o != null_c.o, true); // Issue#5058 repro TEST_EQ(null_b1.o, null_b2.o); // Put the strings into an array for round trip verification. - const flatbuffers::Offset array[7] = { one1, two, one2, onetwo, null_b1, null_c, null_b2 }; - const auto vector_offset = builder.CreateVector(array, flatbuffers::uoffset_t(7)); + const flatbuffers::Offset array[7] = { + one1, two, one2, onetwo, null_b1, null_c, null_b2 + }; + const auto vector_offset = + builder.CreateVector(array, flatbuffers::uoffset_t(7)); MonsterBuilder monster_builder(builder); monster_builder.add_name(two); monster_builder.add_testarrayofstring(vector_offset); builder.Finish(monster_builder.Finish()); // Read the Monster back. - const auto *monster = flatbuffers::GetRoot(builder.GetBufferPointer()); + const auto *monster = + flatbuffers::GetRoot(builder.GetBufferPointer()); TEST_EQ_STR(monster->name()->c_str(), "two"); const auto *testarrayofstring = monster->testarrayofstring(); TEST_EQ(testarrayofstring->size(), flatbuffers::uoffset_t(7)); @@ -2831,7 +2839,8 @@ void CreateSharedStringTest() { TEST_EQ(a[5]->str(), (std::string(chars_c, sizeof(chars_c)))); TEST_EQ(a[6]->str(), (std::string(chars_b, sizeof(chars_b)))); - // Make sure String::operator< works, too, since it is related to StringOffsetCompare. + // Make sure String::operator< works, too, since it is related to + // StringOffsetCompare. TEST_EQ((*a[0]) < (*a[1]), true); TEST_EQ((*a[1]) < (*a[0]), false); TEST_EQ((*a[1]) < (*a[2]), false); @@ -2943,16 +2952,17 @@ void NativeTypeTest() { src_data.vectors.reserve(N); for (int i = 0; i < N; ++i) { - src_data.vectors.push_back (Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f)); + src_data.vectors.push_back( + Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f)); } flatbuffers::FlatBufferBuilder fbb; fbb.Finish(Geometry::ApplicationData::Pack(fbb, &src_data)); - auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer()); + auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer()); for (int i = 0; i < N; ++i) { - Native::Vector3D& v = dstDataT->vectors[i]; + Native::Vector3D &v = dstDataT->vectors[i]; TEST_EQ(v.x, 10 * i + 0.1f); TEST_EQ(v.y, 10 * i + 0.2f); TEST_EQ(v.z, 10 * i + 0.3f); @@ -3107,7 +3117,7 @@ int FlatBufferTests() { return 0; } -int main(int /*argc*/, const char * /*argv*/ []) { +int main(int /*argc*/, const char * /*argv*/[]) { InitTestEngine(); std::string req_locale; diff --git a/tests/test_assert.cpp b/tests/test_assert.cpp index 794ffe7d9..eec777972 100644 --- a/tests/test_assert.cpp +++ b/tests/test_assert.cpp @@ -31,7 +31,7 @@ void TestEqStr(const char *expval, const char *val, const char *exp, #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && defined(_MSC_VER) && \ defined(_DEBUG) -#define FLATBUFFERS_MEMORY_LEAK_TRACKING_MSVC +# define FLATBUFFERS_MEMORY_LEAK_TRACKING_MSVC #endif void InitTestEngine(TestFailEventListener listener) { @@ -58,12 +58,12 @@ void InitTestEngine(TestFailEventListener listener) { int CloseTestEngine(bool force_report) { if (!testing_fails || force_report) { - #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING_MSVC) - auto flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - flags &= ~_CRTDBG_DELAY_FREE_MEM_DF; - flags |= _CRTDBG_LEAK_CHECK_DF; - _CrtSetDbgFlag(flags); - #endif +#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING_MSVC) + auto flags = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flags &= ~_CRTDBG_DELAY_FREE_MEM_DF; + flags |= _CRTDBG_LEAK_CHECK_DF; + _CrtSetDbgFlag(flags); +#endif } return (0 != testing_fails); } diff --git a/tests/test_builder.cpp b/tests/test_builder.cpp index 8c070c115..685c643cc 100644 --- a/tests/test_builder.cpp +++ b/tests/test_builder.cpp @@ -1,8 +1,8 @@ -#include "flatbuffers/stl_emulation.h" - -#include "monster_test_generated.h" #include "test_builder.h" +#include "flatbuffers/stl_emulation.h" +#include "monster_test_generated.h" + using namespace MyGame::Example; const std::string m1_name = "Cyberdemon"; @@ -13,7 +13,7 @@ const Color m2_color = Color_Green; struct OwnedAllocator : public flatbuffers::DefaultAllocator {}; class TestHeapBuilder : public flatbuffers::FlatBufferBuilder { -private: + private: // clang-format off #if !defined(FLATBUFFERS_CPP98_STL) TestHeapBuilder(const TestHeapBuilder &); @@ -21,15 +21,15 @@ private: #endif // !defined(FLATBUFFERS_CPP98_STL) // clang-format on -public: + public: TestHeapBuilder() - : flatbuffers::FlatBufferBuilder(2048, new OwnedAllocator(), true) {} + : flatbuffers::FlatBufferBuilder(2048, new OwnedAllocator(), true) {} // clang-format off #if !defined(FLATBUFFERS_CPP98_STL) // clang-format on TestHeapBuilder(TestHeapBuilder &&other) - : FlatBufferBuilder(std::move(other)) { } + : FlatBufferBuilder(std::move(other)) {} TestHeapBuilder &operator=(TestHeapBuilder &&other) { FlatBufferBuilder::operator=(std::move(other)); @@ -47,16 +47,16 @@ struct AllocatorMember { struct GrpcLikeMessageBuilder : private AllocatorMember, public flatbuffers::FlatBufferBuilder { -private: + private: GrpcLikeMessageBuilder(const GrpcLikeMessageBuilder &); GrpcLikeMessageBuilder &operator=(const GrpcLikeMessageBuilder &); -public: + public: GrpcLikeMessageBuilder() - : flatbuffers::FlatBufferBuilder(1024, &member_allocator_, false) {} + : flatbuffers::FlatBufferBuilder(1024, &member_allocator_, false) {} GrpcLikeMessageBuilder(GrpcLikeMessageBuilder &&other) - : FlatBufferBuilder(1024, &member_allocator_, false) { + : FlatBufferBuilder(1024, &member_allocator_, false) { // Default construct and swap idiom. Swap(other); } @@ -77,53 +77,63 @@ public: void Swap(GrpcLikeMessageBuilder &other) { // No need to swap member_allocator_ because it's stateless. FlatBufferBuilder::Swap(other); - // After swapping the FlatBufferBuilder, we swap back the allocator, which restores - // the original allocator back in place. This is necessary because MessageBuilder's - // allocator is its own member (SliceAllocatorMember). The allocator passed to - // FlatBufferBuilder::vector_downward must point to this member. + // After swapping the FlatBufferBuilder, we swap back the allocator, which + // restores the original allocator back in place. This is necessary because + // MessageBuilder's allocator is its own member (SliceAllocatorMember). The + // allocator passed to FlatBufferBuilder::vector_downward must point to this + // member. buf_.swap_allocator(other.buf_); } }; -flatbuffers::Offset populate1(flatbuffers::FlatBufferBuilder &builder) { +flatbuffers::Offset populate1( + flatbuffers::FlatBufferBuilder &builder) { auto name_offset = builder.CreateString(m1_name); return CreateMonster(builder, nullptr, 0, 0, name_offset, 0, m1_color); } -flatbuffers::Offset populate2(flatbuffers::FlatBufferBuilder &builder) { +flatbuffers::Offset populate2( + flatbuffers::FlatBufferBuilder &builder) { auto name_offset = builder.CreateString(m2_name); return CreateMonster(builder, nullptr, 0, 0, name_offset, 0, m2_color); } -uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size, size_t &offset) { +uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size, + size_t &offset) { return fbb.ReleaseRaw(size, offset); } void free_raw(flatbuffers::grpc::MessageBuilder &, uint8_t *) { - // release_raw_base calls FlatBufferBuilder::ReleaseRaw on the argument MessageBuilder. - // It's semantically wrong as MessageBuilder has its own ReleaseRaw member function that - // takes three arguments. In such cases though, ~MessageBuilder() invokes - // ~SliceAllocator() that takes care of deleting memory as it calls grpc_slice_unref. - // Obviously, this behavior is very surprising as the pointer returned by - // FlatBufferBuilder::ReleaseRaw is not valid as soon as MessageBuilder goes out of scope. - // This problem does not occur with FlatBufferBuilder. + // release_raw_base calls FlatBufferBuilder::ReleaseRaw on the argument + // MessageBuilder. It's semantically wrong as MessageBuilder has its own + // ReleaseRaw member function that takes three arguments. In such cases + // though, ~MessageBuilder() invokes ~SliceAllocator() that takes care of + // deleting memory as it calls grpc_slice_unref. Obviously, this behavior is + // very surprising as the pointer returned by FlatBufferBuilder::ReleaseRaw is + // not valid as soon as MessageBuilder goes out of scope. This problem does + // not occur with FlatBufferBuilder. } void free_raw(flatbuffers::FlatBufferBuilder &, uint8_t *buf) { flatbuffers::DefaultAllocator().deallocate(buf, 0); } -bool verify(const flatbuffers::DetachedBuffer &buf, const std::string &expected_name, Color color) { +bool verify(const flatbuffers::DetachedBuffer &buf, + const std::string &expected_name, Color color) { const Monster *monster = flatbuffers::GetRoot(buf.data()); - return (monster->name()->str() == expected_name) && (monster->color() == color); + return (monster->name()->str() == expected_name) && + (monster->color() == color); } -bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name, Color color) { - const Monster *monster = flatbuffers::GetRoot(buf+offset); - return (monster->name()->str() == expected_name) && (monster->color() == color); +bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name, + Color color) { + const Monster *monster = flatbuffers::GetRoot(buf + offset); + return (monster->name()->str() == expected_name) && + (monster->color() == color); } -bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb, const std::string &expected_name, Color color) { +bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb, + const std::string &expected_name, Color color) { flatbuffers::DetachedBuffer buf = fbb.Release(); return verify(buf, expected_name, color); } @@ -136,13 +146,15 @@ void FlatBufferBuilderTest() { BuilderTests::all_tests(); BuilderReuseTestSelector tests[4] = { - REUSABLE_AFTER_RELEASE, - REUSABLE_AFTER_RELEASE_RAW, + REUSABLE_AFTER_RELEASE, REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN }; - BuilderReuseTests::run_tests(TestSelector(tests, tests+4)); - BuilderReuseTests::run_tests(TestSelector(tests, tests+4)); - BuilderReuseTests::run_tests(TestSelector(tests, tests+4)); + BuilderReuseTests::run_tests( + TestSelector(tests, tests + 4)); + BuilderReuseTests::run_tests( + TestSelector(tests, tests + 4)); + BuilderReuseTests::run_tests( + TestSelector(tests, tests + 4)); } diff --git a/tests/test_builder.h b/tests/test_builder.h index 1e2fa0adb..eb719a80c 100644 --- a/tests/test_builder.h +++ b/tests/test_builder.h @@ -3,8 +3,9 @@ #include #include -#include "monster_test_generated.h" + #include "flatbuffers/flatbuffers.h" +#include "monster_test_generated.h" #include "test_assert.h" using MyGame::Example::Color; @@ -14,17 +15,11 @@ namespace flatbuffers { namespace grpc { class MessageBuilder; } -} +} // namespace flatbuffers -template -struct is_same { - static const bool value = false; -}; +template struct is_same { static const bool value = false; }; -template -struct is_same { - static const bool value = true; -}; +template struct is_same { static const bool value = true; }; extern const std::string m1_name; extern const Color m1_color; @@ -34,30 +29,36 @@ extern const Color m2_color; flatbuffers::Offset populate1(flatbuffers::FlatBufferBuilder &builder); flatbuffers::Offset populate2(flatbuffers::FlatBufferBuilder &builder); -uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size, size_t &offset); +uint8_t *release_raw_base(flatbuffers::FlatBufferBuilder &fbb, size_t &size, + size_t &offset); void free_raw(flatbuffers::grpc::MessageBuilder &mbb, uint8_t *buf); void free_raw(flatbuffers::FlatBufferBuilder &fbb, uint8_t *buf); -bool verify(const flatbuffers::DetachedBuffer &buf, const std::string &expected_name, Color color); -bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name, Color color); +bool verify(const flatbuffers::DetachedBuffer &buf, + const std::string &expected_name, Color color); +bool verify(const uint8_t *buf, size_t offset, const std::string &expected_name, + Color color); -bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb, const std::string &expected_name, Color color); -bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, const std::string &expected_name, Color color); +bool release_n_verify(flatbuffers::FlatBufferBuilder &fbb, + const std::string &expected_name, Color color); +bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, + const std::string &expected_name, Color color); // clang-format off #if !defined(FLATBUFFERS_CPP98_STL) // clang-format on // Invokes this function when testing the following Builder types // FlatBufferBuilder, TestHeapBuilder, and GrpcLikeMessageBuilder -template +template void builder_move_assign_after_releaseraw_test(Builder b1) { auto root_offset1 = populate1(b1); b1.Finish(root_offset1); size_t size, offset; - std::shared_ptr raw(b1.ReleaseRaw(size, offset), [size](uint8_t *ptr) { - flatbuffers::DefaultAllocator::dealloc(ptr, size); - }); + std::shared_ptr raw( + b1.ReleaseRaw(size, offset), [size](uint8_t *ptr) { + flatbuffers::DefaultAllocator::dealloc(ptr, size); + }); Builder src; auto root_offset2 = populate2(src); src.Finish(root_offset2); @@ -72,9 +73,10 @@ void builder_move_assign_after_releaseraw_test(Builder b1) { #endif // !defined(FLATBUFFERS_CPP98_STL) // clang-format on -void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder b1); +void builder_move_assign_after_releaseraw_test( + flatbuffers::grpc::MessageBuilder b1); -template +template struct BuilderTests { // clang-format off #if !defined(FLATBUFFERS_CPP98_STL) @@ -164,9 +166,10 @@ struct BuilderTests { #endif // !defined(FLATBUFFERS_CPP98_STL) // clang-format on - static void builder_swap_before_finish_test(bool run = is_same::value) { + static void builder_swap_before_finish_test( + bool run = is_same::value) { /// Swap is allowed only when lhs and rhs are the same concrete type. - if(run) { + if (run) { SrcBuilder src; auto root_offset1 = populate1(src); auto size1 = src.GetSize(); @@ -183,9 +186,10 @@ struct BuilderTests { } } - static void builder_swap_after_finish_test(bool run = is_same::value) { + static void builder_swap_after_finish_test( + bool run = is_same::value) { /// Swap is allowed only when lhs and rhs are the same concrete type. - if(run) { + if (run) { SrcBuilder src; auto root_offset1 = populate1(src); src.Finish(root_offset1); @@ -233,12 +237,9 @@ enum BuilderReuseTestSelector { typedef std::set TestSelector; -template -struct BuilderReuseTests { +template struct BuilderReuseTests { static void builder_reusable_after_release_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE)) { - return; - } + if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; } DestBuilder fbb; std::vector buffers; @@ -251,9 +252,7 @@ struct BuilderReuseTests { } static void builder_reusable_after_releaseraw_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { - return; - } + if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; } DestBuilder fbb; for (int i = 0; i < 5; ++i) { @@ -269,10 +268,9 @@ struct BuilderReuseTests { // clang-format off #if !defined(FLATBUFFERS_CPP98_STL) // clang-format on - static void builder_reusable_after_release_and_move_assign_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { - return; - } + static void builder_reusable_after_release_and_move_assign_test( + TestSelector selector) { + if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; } DestBuilder dst; std::vector buffers; @@ -287,10 +285,9 @@ struct BuilderReuseTests { } } - static void builder_reusable_after_releaseraw_and_move_assign_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { - return; - } + static void builder_reusable_after_releaseraw_and_move_assign_test( + TestSelector selector) { + if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; } DestBuilder dst; for (int i = 0; i < 5; ++i) { @@ -323,4 +320,4 @@ struct BuilderReuseTests { } }; -#endif // TEST_BUILDER_H +#endif // TEST_BUILDER_H From 105dd528e9e0f5a42da1d63839980ed5d49ed0d4 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Thu, 7 Nov 2019 14:10:41 -0800 Subject: [PATCH 12/28] Change monster_extra generation to use flatbuffers::unique_ptr (#5612) --- tests/generate_code.bat | 2 +- tests/generate_code.sh | 2 +- tests/monster_extra_generated.h | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/generate_code.bat b/tests/generate_code.bat index 59033b8ea..8b78a5d89 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -26,7 +26,7 @@ if "%1"=="-b" set buildtype=%2 IF NOT "%MONSTER_EXTRA%"=="skip" ( @echo Generate MosterExtra - ..\%buildtype%\flatc.exe --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs monsterdata_extra.json || goto FAIL + ..\%buildtype%\flatc.exe --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --cpp-ptr-type flatbuffers::unique_ptr monster_extra.fbs monsterdata_extra.json || goto FAIL ) else ( @echo monster_extra.fbs skipped (the strtod function from MSVC2013 or older doesn't support NaN/Inf arguments) ) diff --git a/tests/generate_code.sh b/tests/generate_code.sh index d0247cb59..37b405851 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -21,7 +21,7 @@ set -e ../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs ../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs ../flatc --jsonschema --schema -I include_test monster_test.fbs -../flatc --cpp --java --kotlin --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs monsterdata_extra.json +../flatc --cpp --java --kotlin --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --cpp-ptr-type flatbuffers::unique_ptr monster_extra.fbs monsterdata_extra.json ../flatc --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --scoped-enums --jsonschema --cpp-ptr-type flatbuffers::unique_ptr arrays_test.fbs cd ../samples ../flatc --cpp --lobster --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr monster.fbs diff --git a/tests/monster_extra_generated.h b/tests/monster_extra_generated.h index 2a4c8f3a7..284249444 100644 --- a/tests/monster_extra_generated.h +++ b/tests/monster_extra_generated.h @@ -389,16 +389,16 @@ inline void FinishSizePrefixedMonsterExtraBuffer( fbb.FinishSizePrefixed(root, MonsterExtraIdentifier()); } -inline std::unique_ptr UnPackMonsterExtra( +inline flatbuffers::unique_ptr UnPackMonsterExtra( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr(GetMonsterExtra(buf)->UnPack(res)); + return flatbuffers::unique_ptr(GetMonsterExtra(buf)->UnPack(res)); } -inline std::unique_ptr UnPackSizePrefixedMonsterExtra( +inline flatbuffers::unique_ptr UnPackSizePrefixedMonsterExtra( const void *buf, const flatbuffers::resolver_function_t *res = nullptr) { - return std::unique_ptr(GetSizePrefixedMonsterExtra(buf)->UnPack(res)); + return flatbuffers::unique_ptr(GetSizePrefixedMonsterExtra(buf)->UnPack(res)); } } // namespace MyGame From 33d5dd9bdd99baf7a0005be36ca468977fdef46d Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Thu, 7 Nov 2019 14:35:42 -0800 Subject: [PATCH 13/28] Improved pull request & clang-format instructions. Change-Id: Ia439bcc61bac5788792244d10e573b1fba54b347 --- .github/PULL_REQUEST_TEMPLATE.md | 6 +++++- src/clang-format-all.sh | 6 ++++++ src/clang-format-git.sh | 6 ++++++ src/clang-format.sh | 2 -- 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/clang-format-all.sh create mode 100644 src/clang-format-git.sh delete mode 100644 src/clang-format.sh diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 819946532..4cbb292f3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,8 @@ Thank you for submitting a PR! -Please make sure you include the names of the affected language(s) in your PR title. +Please delete this standard text once you've created your own description. + +Make sure you include the names of the affected language(s) in your PR title. This helps us get the correct maintainers to look at your issue. If you make changes to any of the code generators, be sure to run @@ -11,6 +13,8 @@ If your PR includes C++ code, please adhere to the Google C++ Style Guide, and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3), so only some C++11 support is available. +For any C++ changes, please make sure to run `sh src/clang-format-git.sh` + Include other details as appropriate. Thanks! diff --git a/src/clang-format-all.sh b/src/clang-format-all.sh new file mode 100644 index 000000000..3fd9e3375 --- /dev/null +++ b/src/clang-format-all.sh @@ -0,0 +1,6 @@ +# Running it twice corrects some bugs in clang-format. +for run in {1..2} +do + clang-format -i -style=file include/flatbuffers/* src/*.cpp tests/*.cpp samples/*.cpp grpc/src/compiler/schema_interface.h grpc/tests/*.cpp +done +git checkout include/flatbuffers/reflection_generated.h diff --git a/src/clang-format-git.sh b/src/clang-format-git.sh new file mode 100644 index 000000000..0611cbba2 --- /dev/null +++ b/src/clang-format-git.sh @@ -0,0 +1,6 @@ +# Running it twice corrects some bugs in clang-format. +for run in {1..2} +do + git clang-format HEAD^ -- include/flatbuffers/* src/*.cpp tests/*.cpp samples/*.cpp grpc/src/compiler/schema_interface.h grpc/tests/*.cpp +done +git checkout include/flatbuffers/reflection_generated.h diff --git a/src/clang-format.sh b/src/clang-format.sh deleted file mode 100644 index fbce6b9e4..000000000 --- a/src/clang-format.sh +++ /dev/null @@ -1,2 +0,0 @@ -clang-format -i -style=file include/flatbuffers/* src/*.cpp tests/test.cpp samples/*.cpp grpc/src/compiler/schema_interface.h grpc/tests/*.cpp -git checkout include/flatbuffers/reflection_generated.h From 42c08cbca601688af921eaa9384844a632e2cde8 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Mon, 11 Nov 2019 09:29:37 -0800 Subject: [PATCH 14/28] Ran src/clang-format-all.sh (#5617) --- grpc/src/compiler/schema_interface.h | 4 +- grpc/tests/grpctest.cpp | 16 +-- grpc/tests/message_builder_test.cpp | 167 +++++++++++++++------------ include/flatbuffers/reflection.h | 2 +- samples/sample_bfbs.cpp | 6 +- samples/sample_binary.cpp | 2 +- samples/sample_text.cpp | 3 +- src/idl_gen_js_ts.cpp | 3 +- tests/test.cpp | 1 - 9 files changed, 110 insertions(+), 94 deletions(-) diff --git a/grpc/src/compiler/schema_interface.h b/grpc/src/compiler/schema_interface.h index 2be2ed738..638448d3a 100644 --- a/grpc/src/compiler/schema_interface.h +++ b/grpc/src/compiler/schema_interface.h @@ -34,11 +34,11 @@ #ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H #define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H -#include "src/compiler/config.h" - #include #include +#include "src/compiler/config.h" + #ifndef GRPC_CUSTOM_STRING # include # define GRPC_CUSTOM_STRING std::string diff --git a/grpc/tests/grpctest.cpp b/grpc/tests/grpctest.cpp index 7e5c6e6cb..decf5e513 100644 --- a/grpc/tests/grpctest.cpp +++ b/grpc/tests/grpctest.cpp @@ -14,17 +14,17 @@ * limitations under the License. */ -#include - #include +#include + #include "monster_test.grpc.fb.h" #include "monster_test_generated.h" #include "test_assert.h" using namespace MyGame::Example; -using flatbuffers::grpc::MessageBuilder; using flatbuffers::FlatBufferBuilder; +using flatbuffers::grpc::MessageBuilder; void message_builder_tests(); @@ -97,8 +97,7 @@ void RunServer() { server_instance->Wait(); } -template -void StoreRPC(MonsterStorage::Stub *stub) { +template void StoreRPC(MonsterStorage::Stub *stub) { Builder fbb; grpc::ClientContext context; // Build a request with the name set. @@ -119,8 +118,7 @@ void StoreRPC(MonsterStorage::Stub *stub) { } } -template -void RetrieveRPC(MonsterStorage::Stub *stub) { +template void RetrieveRPC(MonsterStorage::Stub *stub) { Builder fbb; grpc::ClientContext context; fbb.Clear(); @@ -155,7 +153,6 @@ int grpc_server_test() { RetrieveRPC(stub.get()); RetrieveRPC(stub.get()); - #if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION { // Test that an invalid request errors out correctly @@ -181,7 +178,7 @@ int grpc_server_test() { return 0; } -int main(int /*argc*/, const char * /*argv*/ []) { +int main(int /*argc*/, const char * /*argv*/[]) { message_builder_tests(); grpc_server_test(); @@ -193,4 +190,3 @@ int main(int /*argc*/, const char * /*argv*/ []) { return 1; } } - diff --git a/grpc/tests/message_builder_test.cpp b/grpc/tests/message_builder_test.cpp index 36f5bc2ed..04153f1b9 100644 --- a/grpc/tests/message_builder_test.cpp +++ b/grpc/tests/message_builder_test.cpp @@ -3,22 +3,27 @@ #include "test_assert.h" #include "test_builder.h" -using MyGame::Example::Vec3; -using MyGame::Example::CreateStat; using MyGame::Example::Any_NONE; +using MyGame::Example::CreateStat; +using MyGame::Example::Vec3; -bool verify(flatbuffers::grpc::Message &msg, const std::string &expected_name, Color color) { +bool verify(flatbuffers::grpc::Message &msg, + const std::string &expected_name, Color color) { const Monster *monster = msg.GetRoot(); - return (monster->name()->str() == expected_name) && (monster->color() == color); + return (monster->name()->str() == expected_name) && + (monster->color() == color); } -bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, const std::string &expected_name, Color color) { +bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, + const std::string &expected_name, Color color) { flatbuffers::grpc::Message msg = mbb.ReleaseMessage(); const Monster *monster = msg.GetRoot(); - return (monster->name()->str() == expected_name) && (monster->color() == color); + return (monster->name()->str() == expected_name) && + (monster->color() == color); } -void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder dst) { +void builder_move_assign_after_releaseraw_test( + flatbuffers::grpc::MessageBuilder dst) { auto root_offset1 = populate1(dst); dst.Finish(root_offset1); size_t size, offset; @@ -36,12 +41,11 @@ void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder grpc_slice_unref(slice); } -template +template struct BuilderReuseTests { - static void builder_reusable_after_release_message_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { - return; - } + static void builder_reusable_after_release_message_test( + TestSelector selector) { + if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { return; } flatbuffers::grpc::MessageBuilder mb; std::vector> buffers; @@ -54,12 +58,10 @@ struct BuilderReuseTests { } static void builder_reusable_after_release_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE)) { - return; - } + if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; } - // FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in SliceAllocator::allocate - // in the second iteration. + // FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in + // SliceAllocator::allocate in the second iteration. flatbuffers::grpc::MessageBuilder mb; std::vector buffers; @@ -72,9 +74,7 @@ struct BuilderReuseTests { } static void builder_reusable_after_releaseraw_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { - return; - } + if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; } flatbuffers::grpc::MessageBuilder mb; for (int i = 0; i < 5; ++i) { @@ -88,13 +88,13 @@ struct BuilderReuseTests { } } - static void builder_reusable_after_release_and_move_assign_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { - return; - } + static void builder_reusable_after_release_and_move_assign_test( + TestSelector selector) { + if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; } - // FIXME: Release-move_assign loop fails assert(p == GRPC_SLICE_START_PTR(slice_)) - // in DetachedBuffer destructor after all the iterations + // FIXME: Release-move_assign loop fails assert(p == + // GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the + // iterations flatbuffers::grpc::MessageBuilder dst; std::vector buffers; @@ -113,7 +113,8 @@ struct BuilderReuseTests { } } - static void builder_reusable_after_release_message_and_move_assign_test(TestSelector selector) { + static void builder_reusable_after_release_message_and_move_assign_test( + TestSelector selector) { if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN)) { return; } @@ -135,10 +136,9 @@ struct BuilderReuseTests { } } - static void builder_reusable_after_releaseraw_and_move_assign_test(TestSelector selector) { - if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { - return; - } + static void builder_reusable_after_releaseraw_and_move_assign_test( + TestSelector selector) { + if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; } flatbuffers::grpc::MessageBuilder dst; for (int i = 0; i < 5; ++i) { @@ -175,11 +175,11 @@ void slice_allocator_tests() { uint8_t *buf = sa1.allocate(size); TEST_ASSERT_FUNC(buf != 0); buf[0] = 100; - buf[size-1] = 200; + buf[size - 1] = 200; flatbuffers::grpc::SliceAllocator sa2(std::move(sa1)); // buf should not be deleted after move-construct TEST_EQ_FUNC(buf[0], 100); - TEST_EQ_FUNC(buf[size-1], 200); + TEST_EQ_FUNC(buf[size - 1], 200); // buf is freed here } @@ -194,13 +194,16 @@ void slice_allocator_tests() { } } -/// This function does not populate exactly the first half of the table. But it could. -void populate_first_half(MyGame::Example::MonsterBuilder &wrapper, flatbuffers::Offset name_offset) { +/// This function does not populate exactly the first half of the table. But it +/// could. +void populate_first_half(MyGame::Example::MonsterBuilder &wrapper, + flatbuffers::Offset name_offset) { wrapper.add_name(name_offset); wrapper.add_color(m1_color); } -/// This function does not populate exactly the second half of the table. But it could. +/// This function does not populate exactly the second half of the table. But it +/// could. void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) { wrapper.add_hp(77); wrapper.add_mana(88); @@ -208,83 +211,97 @@ void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) { wrapper.add_pos(&vec3); } -/// This function is a hack to update the FlatBufferBuilder reference (fbb_) in the MonsterBuilder object. -/// This function will break if fbb_ is not the first member in MonsterBuilder. In that case, some offset must be added. -/// This function is used exclusively for testing correctness of move operations between FlatBufferBuilders. -/// If MonsterBuilder had a fbb_ pointer, this hack would be unnecessary. That involves a code-generator change though. -void test_only_hack_update_fbb_reference(MyGame::Example::MonsterBuilder &monsterBuilder, - flatbuffers::grpc::MessageBuilder &mb) { +/// This function is a hack to update the FlatBufferBuilder reference (fbb_) in +/// the MonsterBuilder object. This function will break if fbb_ is not the first +/// member in MonsterBuilder. In that case, some offset must be added. This +/// function is used exclusively for testing correctness of move operations +/// between FlatBufferBuilders. If MonsterBuilder had a fbb_ pointer, this hack +/// would be unnecessary. That involves a code-generator change though. +void test_only_hack_update_fbb_reference( + MyGame::Example::MonsterBuilder &monsterBuilder, + flatbuffers::grpc::MessageBuilder &mb) { *reinterpret_cast(&monsterBuilder) = &mb; } -/// This test validates correctness of move conversion of FlatBufferBuilder to a MessageBuilder DURING -/// a table construction. Half of the table is constructed using FlatBufferBuilder and the other half -/// of the table is constructed using a MessageBuilder. +/// This test validates correctness of move conversion of FlatBufferBuilder to a +/// MessageBuilder DURING a table construction. Half of the table is constructed +/// using FlatBufferBuilder and the other half of the table is constructed using +/// a MessageBuilder. void builder_move_ctor_conversion_before_finish_half_n_half_table_test() { - for (size_t initial_size = 4 ; initial_size <= 2048; initial_size *= 2) { + for (size_t initial_size = 4; initial_size <= 2048; initial_size *= 2) { flatbuffers::FlatBufferBuilder fbb(initial_size); auto name_offset = fbb.CreateString(m1_name); - MyGame::Example::MonsterBuilder monsterBuilder(fbb); // starts a table in FlatBufferBuilder + MyGame::Example::MonsterBuilder monsterBuilder( + fbb); // starts a table in FlatBufferBuilder populate_first_half(monsterBuilder, name_offset); flatbuffers::grpc::MessageBuilder mb(std::move(fbb)); - test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack + test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack populate_second_half(monsterBuilder); - mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder + mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color)); TEST_EQ_FUNC(fbb.GetSize(), 0); } } -/// This test populates a COMPLETE inner table before move conversion and later populates more members in the outer table. +/// This test populates a COMPLETE inner table before move conversion and later +/// populates more members in the outer table. void builder_move_ctor_conversion_before_finish_test() { - for (size_t initial_size = 4 ; initial_size <= 2048; initial_size *= 2) { + for (size_t initial_size = 4; initial_size <= 2048; initial_size *= 2) { flatbuffers::FlatBufferBuilder fbb(initial_size); auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0); flatbuffers::grpc::MessageBuilder mb(std::move(fbb)); - auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset); + auto monster_offset = + CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, + Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset); mb.Finish(monster_offset); TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color)); TEST_EQ_FUNC(fbb.GetSize(), 0); } } -/// This test validates correctness of move conversion of FlatBufferBuilder to a MessageBuilder DURING -/// a table construction. Half of the table is constructed using FlatBufferBuilder and the other half -/// of the table is constructed using a MessageBuilder. +/// This test validates correctness of move conversion of FlatBufferBuilder to a +/// MessageBuilder DURING a table construction. Half of the table is constructed +/// using FlatBufferBuilder and the other half of the table is constructed using +/// a MessageBuilder. void builder_move_assign_conversion_before_finish_half_n_half_table_test() { flatbuffers::FlatBufferBuilder fbb; flatbuffers::grpc::MessageBuilder mb; - for (int i = 0;i < 5; ++i) { + for (int i = 0; i < 5; ++i) { flatbuffers::FlatBufferBuilder fbb; auto name_offset = fbb.CreateString(m1_name); - MyGame::Example::MonsterBuilder monsterBuilder(fbb); // starts a table in FlatBufferBuilder + MyGame::Example::MonsterBuilder monsterBuilder( + fbb); // starts a table in FlatBufferBuilder populate_first_half(monsterBuilder, name_offset); mb = std::move(fbb); - test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack + test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack populate_second_half(monsterBuilder); - mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder + mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color)); TEST_EQ_FUNC(fbb.GetSize(), 0); } } -/// This test populates a COMPLETE inner table before move conversion and later populates more members in the outer table. +/// This test populates a COMPLETE inner table before move conversion and later +/// populates more members in the outer table. void builder_move_assign_conversion_before_finish_test() { flatbuffers::FlatBufferBuilder fbb; flatbuffers::grpc::MessageBuilder mb; - for (int i = 0;i < 5; ++i) { + for (int i = 0; i < 5; ++i) { auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0); mb = std::move(fbb); - auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset); + auto monster_offset = + CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, + Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset); mb.Finish(monster_offset); TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color)); TEST_EQ_FUNC(fbb.GetSize(), 0); } } -/// This test populates data, finishes the buffer, and does move conversion after. +/// This test populates data, finishes the buffer, and does move conversion +/// after. void builder_move_ctor_conversion_after_finish_test() { flatbuffers::FlatBufferBuilder fbb; fbb.Finish(populate1(fbb)); @@ -293,12 +310,13 @@ void builder_move_ctor_conversion_after_finish_test() { TEST_EQ_FUNC(fbb.GetSize(), 0); } -/// This test populates data, finishes the buffer, and does move conversion after. +/// This test populates data, finishes the buffer, and does move conversion +/// after. void builder_move_assign_conversion_after_finish_test() { flatbuffers::FlatBufferBuilder fbb; flatbuffers::grpc::MessageBuilder mb; - for (int i = 0;i < 5; ++i) { + for (int i = 0; i < 5; ++i) { fbb.Finish(populate1(fbb)); mb = std::move(fbb); TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color)); @@ -307,15 +325,15 @@ void builder_move_assign_conversion_after_finish_test() { } void message_builder_tests() { - using flatbuffers::grpc::MessageBuilder; using flatbuffers::FlatBufferBuilder; + using flatbuffers::grpc::MessageBuilder; slice_allocator_tests(); #ifndef __APPLE__ builder_move_ctor_conversion_before_finish_half_n_half_table_test(); builder_move_assign_conversion_before_finish_half_n_half_table_test(); -#endif // __APPLE__ +#endif // __APPLE__ builder_move_ctor_conversion_before_finish_test(); builder_move_assign_conversion_before_finish_test(); @@ -326,15 +344,18 @@ void message_builder_tests() { BuilderTests::all_tests(); BuilderReuseTestSelector tests[6] = { - //REUSABLE_AFTER_RELEASE, // Assertion failed: (GRPC_SLICE_IS_EMPTY(slice_)) - //REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p == GRPC_SLICE_START_PTR(slice_) + // REUSABLE_AFTER_RELEASE, // Assertion failed: + // (GRPC_SLICE_IS_EMPTY(slice_)) + // REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p == + // GRPC_SLICE_START_PTR(slice_) - REUSABLE_AFTER_RELEASE_RAW, - REUSABLE_AFTER_RELEASE_MESSAGE, + REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE, REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN, REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN }; - BuilderReuseTests::run_tests(TestSelector(tests, tests+6)); - BuilderReuseTests::run_tests(TestSelector(tests, tests+6)); + BuilderReuseTests::run_tests( + TestSelector(tests, tests + 6)); + BuilderReuseTests::run_tests( + TestSelector(tests, tests + 6)); } diff --git a/include/flatbuffers/reflection.h b/include/flatbuffers/reflection.h index 580ae624b..052e6d927 100644 --- a/include/flatbuffers/reflection.h +++ b/include/flatbuffers/reflection.h @@ -228,7 +228,7 @@ inline std::string GetAnyVectorElemS(const VectorOfAny *vec, template T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) { auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i; - return reinterpret_cast(elem_ptr + ReadScalar(elem_ptr)); + return reinterpret_cast(elem_ptr + ReadScalar(elem_ptr)); } // Get the inline-address of a vector element. Useful for Structs (pass Struct diff --git a/samples/sample_bfbs.cpp b/samples/sample_bfbs.cpp index 131f85bce..0e1769078 100644 --- a/samples/sample_bfbs.cpp +++ b/samples/sample_bfbs.cpp @@ -16,8 +16,7 @@ #include "flatbuffers/idl.h" #include "flatbuffers/util.h" - -#include "monster_generated.h" // Already includes "flatbuffers/flatbuffers.h". +#include "monster_generated.h" // Already includes "flatbuffers/flatbuffers.h". using namespace MyGame::Sample; @@ -30,7 +29,8 @@ int main(int /*argc*/, const char * /*argv*/[]) { std::string bfbs_file; bool ok = flatbuffers::LoadFile("tests/monster_test.fbs", false, &schema_file) && - flatbuffers::LoadFile("tests/monsterdata_test.golden", false, &json_file) && + flatbuffers::LoadFile("tests/monsterdata_test.golden", false, + &json_file) && flatbuffers::LoadFile("tests/monster_test.bfbs", true, &bfbs_file); if (!ok) { printf("couldn't load files!\n"); diff --git a/samples/sample_binary.cpp b/samples/sample_binary.cpp index 46f08bb17..b8f4f1f6c 100644 --- a/samples/sample_binary.cpp +++ b/samples/sample_binary.cpp @@ -20,7 +20,7 @@ using namespace MyGame::Sample; // Example how to use FlatBuffers to create and read binary buffers. -int main(int /*argc*/, const char * /*argv*/ []) { +int main(int /*argc*/, const char * /*argv*/[]) { // Build up a serialized buffer algorithmically: flatbuffers::FlatBufferBuilder builder; diff --git a/samples/sample_text.cpp b/samples/sample_text.cpp index aca0189c6..d46185b36 100644 --- a/samples/sample_text.cpp +++ b/samples/sample_text.cpp @@ -16,14 +16,13 @@ #include "flatbuffers/idl.h" #include "flatbuffers/util.h" - #include "monster_generated.h" // Already includes "flatbuffers/flatbuffers.h". using namespace MyGame::Sample; // This is an example of parsing text straight into a buffer and then // generating flatbuffer (JSON) text from the buffer. -int main(int /*argc*/, const char * /*argv*/ []) { +int main(int /*argc*/, const char * /*argv*/[]) { // load FlatBuffer schema (.fbs) and JSON from disk std::string schemafile; std::string jsonfile; diff --git a/src/idl_gen_js_ts.cpp b/src/idl_gen_js_ts.cpp index 8d86d3022..0a88d9ad3 100644 --- a/src/idl_gen_js_ts.cpp +++ b/src/idl_gen_js_ts.cpp @@ -1014,7 +1014,8 @@ class JsTsGenerator : public BaseGenerator { } // Adds the mutable scalar value to the output - if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer && !IsUnion(field.value.type)) { + if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer && + !IsUnion(field.value.type)) { std::string annotations = GenTypeAnnotation( kParam, GenTypeName(field.value.type, true), "value"); GenDocComment( diff --git a/tests/test.cpp b/tests/test.cpp index abfae0d59..361b83547 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -2308,7 +2308,6 @@ void InvalidNestedFlatbufferTest() { TEST_EQ(parser1.Parse("{ name: \"Bender\", testnestedflatbuffer: { name: " "\"Leela\", color: \"nonexistent\"}}"), false); - // Check that Parser is destroyed correctly after parsing invalid json } void UnionVectorTest() { From 405c64e07dae6efc7689e5b7d58898a4234a26c1 Mon Sep 17 00:00:00 2001 From: messense Date: Tue, 12 Nov 2019 01:52:26 +0800 Subject: [PATCH 15/28] [Rust] Bump smallvec version to 1.0 (#5621) See https://github.com/servo/rust-smallvec/pull/175 for changelog. --- rust/flatbuffers/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/flatbuffers/Cargo.toml b/rust/flatbuffers/Cargo.toml index 32d9b1b80..34ae82668 100644 --- a/rust/flatbuffers/Cargo.toml +++ b/rust/flatbuffers/Cargo.toml @@ -10,4 +10,4 @@ keywords = ["flatbuffers", "serialization", "zero-copy"] categories = ["encoding", "data-structures", "memory-management"] [dependencies] -smallvec = "0.6" +smallvec = "1.0" From cbbd6aca04676ac7484d53fb56131bbb1943a225 Mon Sep 17 00:00:00 2001 From: Dmitry Date: Mon, 11 Nov 2019 22:33:27 +0300 Subject: [PATCH 16/28] add check for root_type specified for json schema generation (#5622) --- src/idl_gen_json_schema.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/idl_gen_json_schema.cpp b/src/idl_gen_json_schema.cpp index 5d7bad6d8..b152fb202 100644 --- a/src/idl_gen_json_schema.cpp +++ b/src/idl_gen_json_schema.cpp @@ -122,6 +122,7 @@ class JsonSchemaGenerator : public BaseGenerator { : BaseGenerator(base_generator) {} bool generate() { + if (parser_.root_struct_def_ == nullptr) { return false; } code_.Clear(); code_ += "{"; code_ += " \"$schema\": \"http://json-schema.org/draft-04/schema#\","; From adbcbba5d14771e4e4f2d2377cc05b59d43c1764 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Mon, 11 Nov 2019 11:37:55 -0800 Subject: [PATCH 17/28] [C++, C#, Java] Separated C# and Java generators into their own classes (#5618) * Cloned idl_gen_general.cpp to idl_gen_csharp.cpp and removed java references * Java generator changes --- BUILD | 2 + CMakeLists.txt | 2 + include/flatbuffers/idl.h | 10 + src/flatc_main.cpp | 4 +- src/idl_gen_csharp.cpp | 1182 +++++++++++++++++++++++++ src/idl_gen_general.cpp | 1737 +------------------------------------ src/idl_gen_java.cpp | 1242 ++++++++++++++++++++++++++ 7 files changed, 2445 insertions(+), 1734 deletions(-) create mode 100644 src/idl_gen_csharp.cpp create mode 100644 src/idl_gen_java.cpp diff --git a/BUILD b/BUILD index 84d043235..210e104ed 100644 --- a/BUILD +++ b/BUILD @@ -86,10 +86,12 @@ cc_binary( "grpc/src/compiler/schema_interface.h", "src/flatc_main.cpp", "src/idl_gen_cpp.cpp", + "src/idl_gen_csharp.cpp", "src/idl_gen_dart.cpp", "src/idl_gen_general.cpp", "src/idl_gen_go.cpp", "src/idl_gen_grpc.cpp", + "src/idl_gen_java.cpp", "src/idl_gen_js_ts.cpp", "src/idl_gen_json_schema.cpp", "src/idl_gen_kotlin.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index 961d0bba0..60ebe2606 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,10 +81,12 @@ set(FlatBuffers_Library_SRCS set(FlatBuffers_Compiler_SRCS ${FlatBuffers_Library_SRCS} src/idl_gen_cpp.cpp + src/idl_gen_csharp.cpp src/idl_gen_dart.cpp src/idl_gen_general.cpp src/idl_gen_kotlin.cpp src/idl_gen_go.cpp + src/idl_gen_java.cpp src/idl_gen_js_ts.cpp src/idl_gen_php.cpp src/idl_gen_python.cpp diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index a4ad4964c..005134ccd 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -976,9 +976,19 @@ extern bool GenerateBinary(const Parser &parser, const std::string &path, extern bool GenerateCPP(const Parser &parser, const std::string &path, const std::string &file_name); +// Generate C# files from the definitions in the Parser object. +// See idl_gen_csharp.cpp. +extern bool GenerateCSharp(const Parser &parser, const std::string &path, + const std::string &file_name); + extern bool GenerateDart(const Parser &parser, const std::string &path, const std::string &file_name); +// Generate Java files from the definitions in the Parser object. +// See idl_gen_java.cpp. +extern bool GenerateJava(const Parser &parser, const std::string &path, + const std::string &file_name); + // Generate JavaScript or TypeScript code from the definitions in the Parser // object. See idl_gen_js. extern bool GenerateJSTS(const Parser &parser, const std::string &path, diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index 352c31454..786a1b1e5 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -55,7 +55,7 @@ int main(int argc, const char *argv[]) { { flatbuffers::GenerateGo, "-g", "--go", "Go", true, flatbuffers::GenerateGoGRPC, flatbuffers::IDLOptions::kGo, "Generate Go files for tables/structs", flatbuffers::GeneralMakeRule }, - { flatbuffers::GenerateGeneral, "-j", "--java", "Java", true, + { flatbuffers::GenerateJava, "-j", "--java", "Java", true, flatbuffers::GenerateJavaGRPC, flatbuffers::IDLOptions::kJava, "Generate Java classes for tables/structs", flatbuffers::GeneralMakeRule }, @@ -70,7 +70,7 @@ int main(int argc, const char *argv[]) { flatbuffers::IDLOptions::kTs, "Generate TypeScript code for tables/structs", flatbuffers::JSTSMakeRule }, - { flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", true, nullptr, + { flatbuffers::GenerateCSharp, "-n", "--csharp", "C#", true, nullptr, flatbuffers::IDLOptions::kCSharp, "Generate C# classes for tables/structs", flatbuffers::GeneralMakeRule }, { flatbuffers::GeneratePython, "-p", "--python", "Python", true, nullptr, diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp new file mode 100644 index 000000000..5045bd95d --- /dev/null +++ b/src/idl_gen_csharp.cpp @@ -0,0 +1,1182 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// independent from idl_parser, since this code is not needed for most clients + +#include "flatbuffers/code_generators.h" +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" + +#if defined(FLATBUFFERS_CPP98_STL) +# include +#endif // defined(FLATBUFFERS_CPP98_STL) + +namespace flatbuffers { + +static TypedFloatConstantGenerator CSharpFloatGen("Double.", "Single.", "NaN", + "PositiveInfinity", + "NegativeInfinity"); +static CommentConfig comment_config = { + nullptr, + "///", + nullptr, +}; + +namespace csharp { +class CSharpGenerator : public BaseGenerator { + public: + CSharpGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) + : BaseGenerator(parser, path, file_name, "", "."), + cur_name_space_(nullptr) {} + + CSharpGenerator &operator=(const CSharpGenerator &); + + bool generate() { + std::string one_file_code; + cur_name_space_ = parser_.current_namespace_; + + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + std::string enumcode; + auto &enum_def = **it; + if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace; + GenEnum(enum_def, &enumcode); + if (parser_.opts.one_file) { + one_file_code += enumcode; + } else { + if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode, + false)) + return false; + } + } + + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + std::string declcode; + auto &struct_def = **it; + if (!parser_.opts.one_file) + cur_name_space_ = struct_def.defined_namespace; + GenStruct(struct_def, &declcode); + if (parser_.opts.one_file) { + one_file_code += declcode; + } else { + if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode, + true)) + return false; + } + } + + if (parser_.opts.one_file) { + return SaveType(file_name_, *parser_.current_namespace_, one_file_code, + true); + } + return true; + } + + // Save out the generated code for a single class while adding + // declaration boilerplate. + bool SaveType(const std::string &defname, const Namespace &ns, + const std::string &classcode, bool needs_includes) const { + if (!classcode.length()) return true; + + std::string code = + "// \n" + "// " + + std::string(FlatBuffersGeneratedWarning()) + + "\n" + "// \n\n"; + + std::string namespace_name = FullNamespace(".", ns); + if (!namespace_name.empty()) { + code += "namespace " + namespace_name + "\n{\n\n"; + } + if (needs_includes) { + code += "using global::System;\nusing global::FlatBuffers;\n\n"; + } + code += classcode; + if (!namespace_name.empty()) { code += "\n}\n"; } + auto filename = NamespaceDir(ns) + defname + ".cs"; + return SaveFile(filename.c_str(), code, false); + } + + const Namespace *CurrentNameSpace() const { return cur_name_space_; } + + std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const { + // clang-format off + static const char * const csharp_typename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ + CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #NTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + }; + // clang-format on + + if (enableLangOverrides) { + if (IsEnum(type)) return WrapInNameSpace(*type.enum_def); + if (type.base_type == BASE_TYPE_STRUCT) { + return "Offset<" + WrapInNameSpace(*type.struct_def) + ">"; + } + } + + return csharp_typename[type.base_type]; + } + + inline std::string GenTypeBasic(const Type &type) const { + return GenTypeBasic(type, true); + } + + std::string GenTypePointer(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "string"; + case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType()); + case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def); + case BASE_TYPE_UNION: return "TTable"; + default: return "Table"; + } + } + + std::string GenTypeGet(const Type &type) const { + return IsScalar(type.base_type) + ? GenTypeBasic(type) + : (IsArray(type) ? GenTypeGet(type.VectorType()) + : GenTypePointer(type)); + } + + std::string GenOffsetType(const StructDef &struct_def) const { + return "Offset<" + WrapInNameSpace(struct_def) + ">"; + } + + std::string GenOffsetConstruct(const StructDef &struct_def, + const std::string &variable_name) const { + return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name + + ")"; + } + + // Casts necessary to correctly read serialized data + std::string DestinationCast(const Type &type) const { + if (IsSeries(type)) { + return DestinationCast(type.VectorType()); + } else { + if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")"; + } + return ""; + } + + // Cast statements for mutator method parameters. + // In Java, parameters representing unsigned numbers need to be cast down to + // their respective type. For example, a long holding an unsigned int value + // would be cast down to int before being put onto the buffer. In C#, one cast + // directly cast an Enum to its underlying type, which is essential before + // putting it onto the buffer. + std::string SourceCast(const Type &type) const { + if (IsSeries(type)) { + return SourceCast(type.VectorType()); + } else { + if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")"; + } + return ""; + } + + std::string SourceCastBasic(const Type &type) const { + return IsScalar(type.base_type) ? SourceCast(type) : ""; + } + + std::string GenEnumDefaultValue(const FieldDef &field) const { + auto &value = field.value; + FLATBUFFERS_ASSERT(value.type.enum_def); + auto &enum_def = *value.type.enum_def; + auto enum_val = enum_def.FindByValue(value.constant); + return enum_val ? (WrapInNameSpace(enum_def) + "." + enum_val->name) + : value.constant; + } + + std::string GenDefaultValue(const FieldDef &field, + bool enableLangOverrides) const { + auto &value = field.value; + if (enableLangOverrides) { + // handles both enum case and vector of enum case + if (value.type.enum_def != nullptr && + value.type.base_type != BASE_TYPE_UNION) { + return GenEnumDefaultValue(field); + } + } + + auto longSuffix = ""; + switch (value.type.base_type) { + case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true"; + case BASE_TYPE_ULONG: return value.constant; + case BASE_TYPE_UINT: + case BASE_TYPE_LONG: return value.constant + longSuffix; + default: + if (IsFloat(value.type.base_type)) + return CSharpFloatGen.GenFloatConstant(field); + else + return value.constant; + } + } + + std::string GenDefaultValue(const FieldDef &field) const { + return GenDefaultValue(field, true); + } + + std::string GenDefaultValueBasic(const FieldDef &field, + bool enableLangOverrides) const { + auto &value = field.value; + if (!IsScalar(value.type.base_type)) { + if (enableLangOverrides) { + switch (value.type.base_type) { + case BASE_TYPE_STRING: return "default(StringOffset)"; + case BASE_TYPE_STRUCT: + return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) + + ">)"; + case BASE_TYPE_VECTOR: return "default(VectorOffset)"; + default: break; + } + } + return "0"; + } + return GenDefaultValue(field, enableLangOverrides); + } + + std::string GenDefaultValueBasic(const FieldDef &field) const { + return GenDefaultValueBasic(field, true); + } + + void GenEnum(EnumDef &enum_def, std::string *code_ptr) const { + std::string &code = *code_ptr; + if (enum_def.generated) return; + + // Generate enum definitions of the form: + // public static (final) int name = value; + // In Java, we use ints rather than the Enum feature, because we want them + // to map directly to how they're used in C/C++ and file formats. + // That, and Java Enums are expensive, and not universally liked. + GenComment(enum_def.doc_comment, code_ptr, &comment_config); + + // In C# this indicates enumeration values can be treated as bit flags. + if (enum_def.attributes.Lookup("bit_flags")) { + code += "[System.FlagsAttribute]\n"; + } + if (enum_def.attributes.Lookup("private")) { + code += "internal "; + } else { + code += "public "; + } + code += "enum " + enum_def.name; + code += " : " + GenTypeBasic(enum_def.underlying_type, false); + code += "\n{\n"; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &ev = **it; + GenComment(ev.doc_comment, code_ptr, &comment_config, " "); + code += " "; + code += ev.name + " = "; + code += enum_def.ToString(ev); + code += ",\n"; + } + // Close the class + code += "};\n\n"; + } + + // Returns the function name that is able to read a value of the given type. + std::string GenGetter(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "__p.__string"; + case BASE_TYPE_STRUCT: return "__p.__struct"; + case BASE_TYPE_UNION: return "__p.__union"; + case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); + case BASE_TYPE_ARRAY: return GenGetter(type.VectorType()); + default: { + std::string getter = "__p.bb.Get"; + if (type.base_type == BASE_TYPE_BOOL) { + getter = "0!=" + getter; + } else if (GenTypeBasic(type, false) != "byte") { + getter += MakeCamel(GenTypeBasic(type, false)); + } + return getter; + } + } + } + + // Returns the function name that is able to read a value of the given type. + std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field, + const std::string &data_buffer, + const char *num = nullptr) const { + auto type = key_field->value.type; + auto dest_mask = ""; + auto dest_cast = DestinationCast(type); + auto getter = data_buffer + ".Get"; + if (GenTypeBasic(type, false) != "byte") { + getter += MakeCamel(GenTypeBasic(type, false)); + } + getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" + + dest_mask; + return getter; + } + + // Direct mutation is only allowed for scalar fields. + // Hence a setter method will only be generated for such fields. + std::string GenSetter(const Type &type) const { + if (IsScalar(type.base_type)) { + std::string setter = "__p.bb.Put"; + if (GenTypeBasic(type, false) != "byte" && + type.base_type != BASE_TYPE_BOOL) { + setter += MakeCamel(GenTypeBasic(type, false)); + } + return setter; + } else { + return ""; + } + } + + // Returns the method name for use with add/put calls. + std::string GenMethod(const Type &type) const { + return IsScalar(type.base_type) ? MakeCamel(GenTypeBasic(type, false)) + : (IsStruct(type) ? "Struct" : "Offset"); + } + + // Recursively generate arguments for a constructor, to deal with nested + // structs. + void GenStructArgs(const StructDef &struct_def, std::string *code_ptr, + const char *nameprefix, size_t array_count = 0) const { + std::string &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; + const auto array_field = IsArray(field_type); + const auto &type = array_field ? field_type.VectorType() : field_type; + const auto array_cnt = array_field ? (array_count + 1) : array_count; + if (IsStruct(type)) { + // Generate arguments for a struct inside a struct. To ensure names + // don't clash, and to make it obvious these arguments are constructing + // a nested struct, prefix the name with the field name. + GenStructArgs(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), array_cnt); + } else { + code += ", "; + code += GenTypeBasic(type); + if (array_cnt > 0) { + code += "["; + for (size_t i = 1; i < array_cnt; i++) code += ","; + code += "]"; + } + code += " "; + code += nameprefix; + code += MakeCamel(field.name, true); + } + } + } + + // Recusively generate struct construction statements of the form: + // builder.putType(name); + // and insert manual padding. + void GenStructBody(const StructDef &struct_def, std::string *code_ptr, + const char *nameprefix, size_t index = 0, + bool in_array = false) const { + std::string &code = *code_ptr; + std::string indent((index + 1) * 2, ' '); + code += indent + " builder.Prep("; + code += NumToString(struct_def.minalign) + ", "; + code += NumToString(struct_def.bytesize) + ");\n"; + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); ++it) { + auto &field = **it; + const auto &field_type = field.value.type; + if (field.padding) { + code += indent + " builder.Pad("; + code += NumToString(field.padding) + ");\n"; + } + if (IsStruct(field_type)) { + GenStructBody(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), index, + in_array); + } else { + const auto &type = + IsArray(field_type) ? field_type.VectorType() : field_type; + const auto index_var = "_idx" + NumToString(index); + if (IsArray(field_type)) { + code += indent + " for (int " + index_var + " = "; + code += NumToString(field_type.fixed_length); + code += "; " + index_var + " > 0; " + index_var + "--) {\n"; + in_array = true; + } + if (IsStruct(type)) { + GenStructBody(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), index + 1, + in_array); + } else { + code += IsArray(field_type) ? " " : ""; + code += indent + " builder.Put"; + code += GenMethod(type) + "("; + code += SourceCast(type); + auto argname = nameprefix + MakeCamel(field.name, true); + code += argname; + size_t array_cnt = index + (IsArray(field_type) ? 1 : 0); + if (array_cnt > 0) { + code += "["; + for (size_t i = 0; in_array && i < array_cnt; i++) { + code += "_idx" + NumToString(i) + "-1"; + if (i != (array_cnt - 1)) code += ","; + } + code += "]"; + } + code += ");\n"; + } + if (IsArray(field_type)) { code += indent + " }\n"; } + } + } + } + std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, + const char *num = nullptr) const { + std::string key_offset = + "Table.__offset(" + NumToString(key_field->value.offset) + ", "; + if (num) { + key_offset += num; + key_offset += ".Value, builder.DataBuffer)"; + } else { + key_offset += "bb.Length"; + key_offset += " - tableOffset, bb)"; + } + return key_offset; + } + + std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) const { + std::string key_getter = " "; + key_getter += "int tableOffset = Table."; + key_getter += "__indirect(vectorLocation + 4 * (start + middle)"; + key_getter += ", bb);\n "; + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + key_getter += "int comp = Table."; + key_getter += "CompareStrings("; + key_getter += GenOffsetGetter(key_field); + key_getter += ", byteKey, bb);\n"; + } else { + auto get_val = GenGetterForLookupByKey(key_field, "bb"); + key_getter += "int comp = " + get_val + ".CompareTo(key);\n"; + } + return key_getter; + } + + std::string GenKeyGetter(flatbuffers::FieldDef *key_field) const { + std::string key_getter = ""; + auto data_buffer = "builder.DataBuffer"; + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + key_getter += "Table.CompareStrings("; + key_getter += GenOffsetGetter(key_field, "o1") + ", "; + key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")"; + } else { + auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1"); + key_getter += field_getter; + field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2"); + key_getter += ".CompareTo(" + field_getter + ")"; + } + return key_getter; + } + + void GenStruct(StructDef &struct_def, std::string *code_ptr) const { + if (struct_def.generated) return; + std::string &code = *code_ptr; + + // Generate a struct accessor class, with methods of the form: + // public type name() { return bb.getType(i + offset); } + // or for tables of the form: + // public type name() { + // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default; + // } + GenComment(struct_def.doc_comment, code_ptr, &comment_config); + 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 "; + } + code += "struct " + struct_def.name; + code += " : IFlatbufferObject"; + code += "\n{\n"; + code += " private "; + code += struct_def.fixed ? "Struct" : "Table"; + code += " __p;\n"; + + code += " public ByteBuffer ByteBuffer { get { return __p.bb; } }\n"; + + if (!struct_def.fixed) { + // Generate verson check method. + // Force compile time error if not using the same version runtime. + code += " public static void ValidateVersion() {"; + code += " FlatBufferConstants."; + code += "FLATBUFFERS_1_11_1(); "; + code += "}\n"; + + // Generate a special accessor for the table that when used as the root + // of a FlatBuffer + std::string method_name = "GetRootAs" + struct_def.name; + std::string method_signature = + " public static " + struct_def.name + " " + method_name; + + // create convenience method that doesn't require an existing object + code += method_signature + "(ByteBuffer _bb) "; + code += "{ return " + method_name + "(_bb, new " + struct_def.name + + "()); }\n"; + + // create method that allows object reuse + code += + method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { "; + code += "return (obj.__assign(_bb.GetInt(_bb.Position"; + code += ") + _bb.Position"; + code += ", _bb)); }\n"; + if (parser_.root_struct_def_ == &struct_def) { + if (parser_.file_identifier_.length()) { + // Check if a buffer has the identifier. + code += " public static "; + code += "bool " + struct_def.name; + code += "BufferHasIdentifier(ByteBuffer _bb) { return "; + code += "Table.__has_identifier(_bb, \""; + code += parser_.file_identifier_; + code += "\"); }\n"; + } + } + } + // Generate the __init method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + code += " public void __init(int _i, ByteBuffer _bb) "; + code += "{ "; + code += "__p = new "; + code += struct_def.fixed ? "Struct" : "Table"; + code += "(_i, _bb); "; + code += "}\n"; + code += + " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) "; + code += "{ __init(_i, _bb); return this; }\n\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + GenComment(field.doc_comment, code_ptr, &comment_config, " "); + std::string type_name = GenTypeGet(field.value.type); + std::string type_name_dest = GenTypeGet(field.value.type); + std::string conditional_cast = ""; + std::string optional = ""; + if (!struct_def.fixed && + (field.value.type.base_type == BASE_TYPE_STRUCT || + field.value.type.base_type == BASE_TYPE_UNION || + (field.value.type.base_type == BASE_TYPE_VECTOR && + (field.value.type.element == BASE_TYPE_STRUCT || + field.value.type.element == BASE_TYPE_UNION)))) { + optional = "?"; + conditional_cast = "(" + type_name_dest + optional + ")"; + } + std::string dest_mask = ""; + std::string dest_cast = DestinationCast(field.value.type); + std::string src_cast = SourceCast(field.value.type); + std::string method_start = " public " + type_name_dest + optional + " " + + MakeCamel(field.name, true); + std::string obj = "(new " + type_name + "())"; + + // Most field accessors need to retrieve and test the field offset first, + // this is the prefix code for that: + auto offset_prefix = + IsArray(field.value.type) + ? " { return " + : (" { int o = __p.__offset(" + NumToString(field.value.offset) + + "); return o != 0 ? "); + // Generate the accessors that don't do object reuse. + if (field.value.type.base_type == BASE_TYPE_STRUCT) { + } else if (field.value.type.base_type == BASE_TYPE_VECTOR && + field.value.type.element == BASE_TYPE_STRUCT) { + } else if (field.value.type.base_type == BASE_TYPE_UNION || + (field.value.type.base_type == BASE_TYPE_VECTOR && + field.value.type.VectorType().base_type == BASE_TYPE_UNION)) { + method_start += ""; + type_name = type_name_dest; + } + std::string getter = dest_cast + GenGetter(field.value.type); + code += method_start; + std::string default_cast = ""; + // only create default casts for c# scalars or vectors of scalars + if ((IsScalar(field.value.type.base_type) || + (field.value.type.base_type == BASE_TYPE_VECTOR && + IsScalar(field.value.type.element)))) { + // For scalars, default value will be returned by GetDefaultValue(). + // If the scalar is an enum, GetDefaultValue() returns an actual c# enum + // that doesn't need to be casted. However, default values for enum + // elements of vectors are integer literals ("0") and are still casted + // for clarity. + if (field.value.type.enum_def == nullptr || + field.value.type.base_type == BASE_TYPE_VECTOR) { + default_cast = "(" + type_name_dest + ")"; + } + } + std::string member_suffix = "; "; + if (IsScalar(field.value.type.base_type)) { + code += " { get"; + member_suffix += "} "; + if (struct_def.fixed) { + code += " { return " + getter; + code += "(__p.bb_pos + "; + code += NumToString(field.value.offset) + ")"; + code += dest_mask; + } else { + code += offset_prefix + getter; + code += "(o + __p.bb_pos)" + dest_mask; + code += " : " + default_cast; + code += GenDefaultValue(field); + } + } else { + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: + code += " { get"; + member_suffix += "} "; + if (struct_def.fixed) { + code += " { return " + obj + ".__assign(" + "__p."; + code += "bb_pos + " + NumToString(field.value.offset) + ", "; + code += "__p.bb)"; + } else { + code += offset_prefix + conditional_cast; + code += obj + ".__assign("; + code += field.value.type.struct_def->fixed + ? "o + __p.bb_pos" + : "__p.__indirect(o + __p.bb_pos)"; + code += ", __p.bb) : null"; + } + break; + case BASE_TYPE_STRING: + code += " { get"; + member_suffix += "} "; + code += offset_prefix + getter + "(o + " + "__p."; + code += "bb_pos) : null"; + break; + case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_VECTOR: { + auto vectortype = field.value.type.VectorType(); + if (vectortype.base_type == BASE_TYPE_UNION) { + conditional_cast = "(TTable?)"; + getter += ""; + } + code += "("; + if (vectortype.base_type == BASE_TYPE_STRUCT) { + getter = obj + ".__assign"; + } else if (vectortype.base_type == BASE_TYPE_UNION) { + } + code += "int j)"; + const auto body = offset_prefix + conditional_cast + getter + "("; + if (vectortype.base_type == BASE_TYPE_UNION) { + code += " where TTable : struct, IFlatbufferObject" + body; + } else { + code += body; + } + std::string index = "__p."; + if (IsArray(field.value.type)) { + index += "bb_pos + " + NumToString(field.value.offset) + " + "; + } else { + index += "__vector(o) + "; + } + index += "j * " + NumToString(InlineSize(vectortype)); + if (vectortype.base_type == BASE_TYPE_STRUCT) { + code += vectortype.struct_def->fixed + ? index + : "__p.__indirect(" + index + ")"; + code += ", __p.bb"; + } else { + code += index; + } + code += ")" + dest_mask; + if (!IsArray(field.value.type)) { + code += " : "; + code += + field.value.type.element == BASE_TYPE_BOOL + ? "false" + : (IsScalar(field.value.type.element) ? default_cast + "0" + : "null"); + } + + break; + } + case BASE_TYPE_UNION: + code += "() where TTable : struct, IFlatbufferObject"; + code += offset_prefix + "(TTable?)" + getter; + code += "(o + __p.bb_pos) : null"; + break; + default: FLATBUFFERS_ASSERT(0); + } + } + code += member_suffix; + code += "}\n"; + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + code += " public int " + MakeCamel(field.name, true); + code += "Length"; + code += " { get"; + code += offset_prefix; + code += "__p.__vector_len(o) : 0; "; + code += "} "; + code += "}\n"; + // See if we should generate a by-key accessor. + if (field.value.type.element == BASE_TYPE_STRUCT && + !field.value.type.struct_def->fixed) { + auto &sd = *field.value.type.struct_def; + auto &fields = sd.fields.vec; + for (auto kit = fields.begin(); kit != fields.end(); ++kit) { + auto &key_field = **kit; + if (key_field.key) { + auto qualified_name = WrapInNameSpace(sd); + code += " public " + qualified_name + "? "; + code += MakeCamel(field.name, true) + "ByKey("; + code += GenTypeGet(key_field.value.type) + " key)"; + code += offset_prefix; + code += qualified_name + ".__lookup_by_key("; + code += "__p.__vector(o), key, "; + code += "__p.bb) : null; "; + code += "}\n"; + break; + } + } + } + } + // Generate a ByteBuffer accessor for strings & vectors of scalars. + if ((field.value.type.base_type == BASE_TYPE_VECTOR && + IsScalar(field.value.type.VectorType().base_type)) || + field.value.type.base_type == BASE_TYPE_STRING) { + code += "#if ENABLE_SPAN_T\n"; + code += " public Span<" + GenTypeBasic(field.value.type.VectorType()) + + "> Get"; + code += MakeCamel(field.name, true); + code += "Bytes() { return "; + code += "__p.__vector_as_span<" + + GenTypeBasic(field.value.type.VectorType()) + ">("; + code += NumToString(field.value.offset); + code += + ", " + NumToString(SizeOf(field.value.type.VectorType().base_type)); + code += "); }\n"; + code += "#else\n"; + code += " public ArraySegment? Get"; + code += MakeCamel(field.name, true); + code += "Bytes() { return "; + code += "__p.__vector_as_arraysegment("; + code += NumToString(field.value.offset); + code += "); }\n"; + code += "#endif\n"; + + // For direct blockcopying the data into a typed array + code += " public "; + code += GenTypeBasic(field.value.type.VectorType()); + code += "[] Get"; + code += MakeCamel(field.name, true); + code += "Array() { "; + if (IsEnum(field.value.type.VectorType())) { + // Since __vector_as_array does not work for enum types, + // fill array using an explicit loop. + code += "int o = __p.__offset("; + code += NumToString(field.value.offset); + code += "); if (o == 0) return null; int p = "; + code += "__p.__vector(o); int l = "; + code += "__p.__vector_len(o); "; + code += GenTypeBasic(field.value.type.VectorType()); + code += "[] a = new "; + code += GenTypeBasic(field.value.type.VectorType()); + code += "[l]; for (int i = 0; i < l; i++) { a[i] = " + getter; + code += "(p + i * "; + code += NumToString(InlineSize(field.value.type.VectorType())); + code += "); } return a;"; + } else { + code += "return "; + code += "__p.__vector_as_array<"; + code += GenTypeBasic(field.value.type.VectorType()); + code += ">("; + code += NumToString(field.value.offset); + code += ");"; + } + code += " }\n"; + } + // generate object accessors if is nested_flatbuffer + if (field.nested_flatbuffer) { + auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer); + auto nested_method_name = + MakeCamel(field.name, true) + "As" + field.nested_flatbuffer->name; + auto get_nested_method_name = nested_method_name; + get_nested_method_name = "Get" + nested_method_name; + conditional_cast = "(" + nested_type_name + "?)"; + obj = "(new " + nested_type_name + "())"; + code += " public " + nested_type_name + "? "; + code += get_nested_method_name + "("; + code += ") { int o = __p.__offset("; + code += NumToString(field.value.offset) + "); "; + code += "return o != 0 ? " + conditional_cast + obj + ".__assign("; + code += "__p."; + code += "__indirect(__p.__vector(o)), "; + code += "__p.bb) : null; }\n"; + } + // Generate mutators for scalar fields or vectors of scalars. + if (parser_.opts.mutable_buffer) { + auto is_series = (IsSeries(field.value.type)); + const auto &underlying_type = + is_series ? field.value.type.VectorType() : field.value.type; + // Boolean parameters have to be explicitly converted to byte + // representation. + auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL + ? "(byte)(" + field.name + " ? 1 : 0)" + : field.name; + auto mutator_prefix = MakeCamel("mutate", true); + // A vector mutator also needs the index of the vector element it should + // mutate. + auto mutator_params = (is_series ? "(int j, " : "(") + + GenTypeGet(underlying_type) + " " + field.name + + ") { "; + auto setter_index = + is_series + ? "__p." + + (IsArray(field.value.type) + ? "bb_pos + " + NumToString(field.value.offset) + : "__vector(o)") + + +" + j * " + NumToString(InlineSize(underlying_type)) + : (struct_def.fixed + ? "__p.bb_pos + " + NumToString(field.value.offset) + : "o + __p.bb_pos"); + if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) { + code += " public "; + code += struct_def.fixed ? "void " : "bool "; + code += mutator_prefix + MakeCamel(field.name, true); + code += mutator_params; + if (struct_def.fixed) { + code += GenSetter(underlying_type) + "(" + setter_index + ", "; + code += src_cast + setter_parameter + "); }\n"; + } else { + code += "int o = __p.__offset("; + code += NumToString(field.value.offset) + ");"; + code += " if (o != 0) { " + GenSetter(underlying_type); + code += "(" + setter_index + ", " + src_cast + setter_parameter + + "); return true; } else { return false; } }\n"; + } + } + } + if (parser_.opts.java_primitive_has_method && + IsScalar(field.value.type.base_type) && !struct_def.fixed) { + auto vt_offset_constant = " public static final int VT_" + + MakeScreamingCamel(field.name) + " = " + + NumToString(field.value.offset) + ";"; + + code += vt_offset_constant; + code += "\n"; + } + } + code += "\n"; + flatbuffers::FieldDef *key_field = nullptr; + if (struct_def.fixed) { + // create a struct constructor function + code += " public static " + GenOffsetType(struct_def) + " "; + code += "Create"; + code += struct_def.name + "(FlatBufferBuilder builder"; + GenStructArgs(struct_def, code_ptr, ""); + code += ") {\n"; + GenStructBody(struct_def, code_ptr, ""); + code += " return "; + code += GenOffsetConstruct(struct_def, "builder.Offset"); + code += ";\n }\n"; + } else { + // Generate a method that creates a table in one go. This is only possible + // when the table has no struct fields, since those have to be created + // inline, and there's no way to do so in Java. + bool has_no_struct_fields = true; + int num_fields = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (IsStruct(field.value.type)) { + has_no_struct_fields = false; + } else { + num_fields++; + } + } + // 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) { + // Generate a table constructor of the form: + // public static int createName(FlatBufferBuilder builder, args...) + code += " public static " + GenOffsetType(struct_def) + " "; + code += "Create" + struct_def.name; + code += "(FlatBufferBuilder builder"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + code += ",\n "; + code += GenTypeBasic(field.value.type); + code += " "; + code += field.name; + if (!IsScalar(field.value.type.base_type)) code += "Offset"; + + code += " = "; + code += GenDefaultValueBasic(field); + } + code += ") {\n builder."; + code += "StartTable("; + code += NumToString(struct_def.fields.vec.size()) + ");\n"; + for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; + size; size /= 2) { + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); ++it) { + auto &field = **it; + if (!field.deprecated && + (!struct_def.sortbysize || + size == SizeOf(field.value.type.base_type))) { + code += " " + struct_def.name + "."; + code += "Add"; + code += MakeCamel(field.name) + "(builder, " + field.name; + if (!IsScalar(field.value.type.base_type)) code += "Offset"; + code += ");\n"; + } + } + } + code += " return " + struct_def.name + "."; + code += "End" + struct_def.name; + code += "(builder);\n }\n\n"; + } + // Generate a set of static methods that allow table construction, + // of the form: + // public static void addName(FlatBufferBuilder builder, short name) + // { builder.addShort(id, name, default); } + // Unlike the Create function, these always work. + code += " public static void Start"; + code += struct_def.name; + code += "(FlatBufferBuilder builder) { builder."; + code += "StartTable("; + code += NumToString(struct_def.fields.vec.size()) + "); }\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.key) key_field = &field; + code += " public static void Add"; + code += MakeCamel(field.name); + code += "(FlatBufferBuilder builder, "; + code += GenTypeBasic(field.value.type); + auto argname = MakeCamel(field.name, false); + if (!IsScalar(field.value.type.base_type)) argname += "Offset"; + code += " " + argname + ") { builder.Add"; + code += GenMethod(field.value.type) + "("; + code += NumToString(it - struct_def.fields.vec.begin()) + ", "; + code += SourceCastBasic(field.value.type); + code += argname; + if (!IsScalar(field.value.type.base_type) && + field.value.type.base_type != BASE_TYPE_UNION) { + code += ".Value"; + } + code += ", "; + code += GenDefaultValue(field, false); + code += "); }\n"; + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + auto vector_type = field.value.type.VectorType(); + auto alignment = InlineAlignment(vector_type); + auto elem_size = InlineSize(vector_type); + if (!IsStruct(vector_type)) { + code += " public static VectorOffset "; + code += "Create"; + code += MakeCamel(field.name); + code += "Vector(FlatBufferBuilder builder, "; + code += GenTypeBasic(vector_type) + "[] data) "; + code += "{ builder.StartVector("; + code += NumToString(elem_size); + code += ", data.Length, "; + code += NumToString(alignment); + code += "); for (int i = data."; + code += "Length - 1; i >= 0; i--) builder."; + code += "Add"; + code += GenMethod(vector_type); + code += "("; + code += SourceCastBasic(vector_type); + code += "data[i]"; + if ((vector_type.base_type == BASE_TYPE_STRUCT || + vector_type.base_type == BASE_TYPE_STRING)) + code += ".Value"; + code += "); return "; + code += "builder.EndVector(); }\n"; + + code += " public static VectorOffset "; + code += "Create"; + code += MakeCamel(field.name); + code += "VectorBlock(FlatBufferBuilder builder, "; + code += GenTypeBasic(vector_type) + "[] data) "; + code += "{ builder.StartVector("; + code += NumToString(elem_size); + code += ", data.Length, "; + code += NumToString(alignment); + code += "); builder.Add(data); return builder.EndVector(); }\n"; + } + // Generate a method to start a vector, data to be added manually + // after. + code += " public static void Start"; + code += MakeCamel(field.name); + code += "Vector(FlatBufferBuilder builder, int numElems) "; + code += "{ builder.StartVector("; + code += NumToString(elem_size); + code += ", numElems, " + NumToString(alignment); + code += "); }\n"; + } + } + code += " public static " + GenOffsetType(struct_def) + " "; + code += "End" + struct_def.name; + code += "(FlatBufferBuilder builder) {\n int o = builder."; + code += "EndTable();\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated && field.required) { + code += " builder.Required(o, "; + code += NumToString(field.value.offset); + code += "); // " + field.name + "\n"; + } + } + code += " return " + GenOffsetConstruct(struct_def, "o") + ";\n }\n"; + if (parser_.root_struct_def_ == &struct_def) { + std::string size_prefix[] = { "", "SizePrefixed" }; + for (int i = 0; i < 2; ++i) { + code += " public static void "; + code += "Finish" + size_prefix[i] + struct_def.name; + code += + "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def); + code += " offset) {"; + code += " builder.Finish" + size_prefix[i] + "(offset"; + code += ".Value"; + + if (parser_.file_identifier_.length()) + code += ", \"" + parser_.file_identifier_ + "\""; + code += "); }\n"; + } + } + } + // Only generate key compare function for table, + // because `key_field` is not set for struct + if (struct_def.has_key && !struct_def.fixed) { + FLATBUFFERS_ASSERT(key_field); + code += "\n public static VectorOffset "; + code += "CreateSortedVectorOf" + struct_def.name; + code += "(FlatBufferBuilder builder, "; + code += "Offset<" + struct_def.name + ">"; + code += "[] offsets) {\n"; + code += " Array.Sort(offsets, (Offset<" + struct_def.name + + "> o1, Offset<" + struct_def.name + "> o2) => " + + GenKeyGetter(key_field); + code += ");\n"; + code += " return builder.CreateVectorOfTables(offsets);\n }\n"; + + code += "\n public static " + struct_def.name + "?"; + code += " __lookup_by_key("; + code += "int vectorLocation, "; + code += GenTypeGet(key_field->value.type); + code += " key, ByteBuffer bb) {\n"; + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + code += " byte[] byteKey = "; + code += "System.Text.Encoding.UTF8.GetBytes(key);\n"; + } + code += " int span = "; + code += "bb.GetInt(vectorLocation - 4);\n"; + code += " int start = 0;\n"; + code += " while (span != 0) {\n"; + code += " int middle = span / 2;\n"; + code += GenLookupKeyGetter(key_field); + code += " if (comp > 0) {\n"; + code += " span = middle;\n"; + code += " } else if (comp < 0) {\n"; + code += " middle++;\n"; + code += " start += middle;\n"; + code += " span -= middle;\n"; + code += " } else {\n"; + code += " return "; + code += "new " + struct_def.name + "()"; + code += ".__assign(tableOffset, bb);\n"; + code += " }\n }\n"; + code += " return null;\n"; + code += " }\n"; + } + code += "};\n\n"; + } + + void GenVectorAccessObject(StructDef &struct_def, + std::string *code_ptr) const { + auto &code = *code_ptr; + // Generate a vector of structs accessor class. + code += "\n"; + code += " "; + if (!struct_def.attributes.Lookup("private")) code += "public "; + code += "static struct Vector : BaseVector\n{\n"; + + // Generate the __assign method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + std::string method_indent = " "; + code += method_indent + "public Vector "; + code += "__assign(int _vector, int _element_size, ByteBuffer _bb) { "; + code += "__reset(_vector, _element_size, _bb); return this; }\n\n"; + + auto type_name = struct_def.name; + auto method_start = method_indent + "public " + type_name + " Get"; + // Generate the accessors that don't do object reuse. + code += method_start + "(int j) { return Get"; + code += "(new " + type_name + "(), j); }\n"; + code += method_start + "(" + type_name + " obj, int j) { "; + code += " return obj.__assign("; + code += struct_def.fixed ? "__p.__element(j)" + : "__p.__indirect(__p.__element(j), bb)"; + code += ", __p.bb); }\n"; + // See if we should generate a by-key accessor. + if (!struct_def.fixed) { + auto &fields = struct_def.fields.vec; + for (auto kit = fields.begin(); kit != fields.end(); ++kit) { + auto &key_field = **kit; + if (key_field.key) { + auto nullable_annotation = + parser_.opts.gen_nullable ? "@Nullable " : ""; + code += method_indent + nullable_annotation; + code += "public " + type_name + "? "; + code += "GetByKey("; + code += GenTypeGet(key_field.value.type) + " key) { "; + code += " return __lookup_by_key(null, "; + code += "__p.__vector(), key, "; + code += "__p.bb); "; + code += "}\n"; + code += method_indent + nullable_annotation; + code += "public " + type_name + "?" + " "; + code += "GetByKey("; + code += type_name + "? obj, "; + code += GenTypeGet(key_field.value.type) + " key) { "; + code += " return __lookup_by_key(obj, "; + code += "__p.__vector(), key, "; + code += "__p.bb); "; + code += "}\n"; + break; + } + } + } + code += " }\n"; + } + + // This tracks the current namespace used to determine if a type need to be + // prefixed by its namespace + const Namespace *cur_name_space_; +}; +} // namespace csharp + +bool GenerateCSharp(const Parser &parser, const std::string &path, + const std::string &file_name) { + csharp::CSharpGenerator generator(parser, path, file_name); + return generator.generate(); +} + +} // namespace flatbuffers diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 48ec2b73e..a12719bfd 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -26,1739 +26,12 @@ #endif // defined(FLATBUFFERS_CPP98_STL) namespace flatbuffers { - -// These arrays need to correspond to the IDLOptions::k enum. - -struct LanguageParameters { - IDLOptions::Language language; - // Whether function names in the language typically start with uppercase. - bool first_camel_upper; - std::string file_extension; - std::string string_type; - std::string bool_type; - std::string open_curly; - std::string accessor_type; - std::string const_decl; - std::string unsubclassable_decl; - std::string enum_decl; - std::string enum_separator; - std::string getter_prefix; - std::string getter_suffix; - std::string inheritance_marker; - std::string namespace_ident; - std::string namespace_begin; - std::string namespace_end; - std::string set_bb_byteorder; - std::string get_bb_position; - std::string get_fbb_offset; - std::string accessor_prefix; - std::string accessor_prefix_static; - std::string optional_suffix; - std::string includes; - std::string class_annotation; - std::string generated_type_annotation; - CommentConfig comment_config; - const FloatConstantGenerator *float_gen; -}; - -const LanguageParameters &GetLangParams(IDLOptions::Language lang) { - static TypedFloatConstantGenerator CSharpFloatGen( - "Double.", "Single.", "NaN", "PositiveInfinity", "NegativeInfinity"); - - static TypedFloatConstantGenerator JavaFloatGen( - "Double.", "Float.", "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY"); - - static const 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.*;\nimport com.google.flatbuffers.*;\n", - "\n@SuppressWarnings(\"unused\")\n", - "\n@javax.annotation.Generated(value=\"flatc\")\n", - { - "/**", - " *", - " */", - }, - &JavaFloatGen }, - { IDLOptions::kCSharp, - true, - ".cs", - "string", - "bool ", - "\n{\n", - "struct ", - " readonly ", - "", - "enum ", - ",\n", - " { get", - "} ", - " : ", - "namespace ", - "\n{", - "\n}\n", - "", - "Position", - "Offset", - "__p.", - "Table.", - "?", - "using global::System;\nusing global::FlatBuffers;\n\n", - "", - "", - { - nullptr, - "///", - nullptr, - }, - &CSharpFloatGen }, - }; - - if (lang == IDLOptions::kJava) { - return language_parameters[0]; - } else { - FLATBUFFERS_ASSERT(lang == IDLOptions::kCSharp); - return language_parameters[1]; - } -} - -namespace general { -class GeneralGenerator : public BaseGenerator { - public: - GeneralGenerator(const Parser &parser, const std::string &path, - const std::string &file_name) - : BaseGenerator(parser, path, file_name, "", "."), - lang_(GetLangParams(parser_.opts.lang)), - cur_name_space_(nullptr) {} - - GeneralGenerator &operator=(const GeneralGenerator &); - bool generate() { - std::string one_file_code; - cur_name_space_ = parser_.current_namespace_; - - for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); - ++it) { - std::string enumcode; - auto &enum_def = **it; - if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace; - GenEnum(enum_def, &enumcode); - if (parser_.opts.one_file) { - one_file_code += enumcode; - } else { - if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode, - false)) - return false; - } - } - - for (auto it = parser_.structs_.vec.begin(); - it != parser_.structs_.vec.end(); ++it) { - std::string declcode; - auto &struct_def = **it; - if (!parser_.opts.one_file) - cur_name_space_ = struct_def.defined_namespace; - GenStruct(struct_def, &declcode); - if (parser_.opts.one_file) { - one_file_code += declcode; - } else { - if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode, - true)) - return false; - } - } - - if (parser_.opts.one_file) { - return SaveType(file_name_, *parser_.current_namespace_, one_file_code, - true); - } - return true; - } - - // Save out the generated code for a single class while adding - // declaration boilerplate. - bool SaveType(const std::string &defname, const Namespace &ns, - const std::string &classcode, bool needs_includes) const { - if (!classcode.length()) return true; - - std::string code; - if (lang_.language == IDLOptions::kCSharp) { - code = - "// \n" - "// " + - std::string(FlatBuffersGeneratedWarning()) + - "\n" - "// \n\n"; - } else { - code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; - } - - std::string namespace_name = FullNamespace(".", ns); - if (!namespace_name.empty()) { - code += lang_.namespace_ident + namespace_name + lang_.namespace_begin; - code += "\n\n"; - } - if (needs_includes) { - code += lang_.includes; - if (parser_.opts.gen_nullable) { - code += "\nimport javax.annotation.Nullable;\n"; - } - if (parser_.opts.java_checkerframework) { - code += "\nimport org.checkerframework.dataflow.qual.Pure;\n"; - } - code += lang_.class_annotation; - } - if (parser_.opts.gen_generated) { code += lang_.generated_type_annotation; } - code += classcode; - if (!namespace_name.empty()) code += lang_.namespace_end; - auto filename = NamespaceDir(ns) + defname + lang_.file_extension; - return SaveFile(filename.c_str(), code, false); - } - - const Namespace *CurrentNameSpace() const { return cur_name_space_; } - - std::string FunctionStart(char upper) const { - return std::string() + (lang_.language == IDLOptions::kJava - ? static_cast(tolower(upper)) - : upper); - } - - std::string GenNullableAnnotation(const Type &t) const { - return lang_.language == IDLOptions::kJava && parser_.opts.gen_nullable && - !IsScalar(DestinationType(t, true).base_type) && - t.base_type != BASE_TYPE_VECTOR - ? " @Nullable " - : ""; - } - - std::string GenPureAnnotation(const Type &t) const { - return lang_.language == IDLOptions::kJava && - parser_.opts.java_checkerframework && - !IsScalar(DestinationType(t, true).base_type) - ? " @Pure " - : ""; - } - - std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const { - // clang-format off - static const char * const java_typename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - #JTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - }; - - static const char * const csharp_typename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - #NTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - }; - // clang-format on - - if (enableLangOverrides) { - if (lang_.language == IDLOptions::kCSharp) { - if (IsEnum(type)) return WrapInNameSpace(*type.enum_def); - if (type.base_type == BASE_TYPE_STRUCT) { - return "Offset<" + WrapInNameSpace(*type.struct_def) + ">"; - } - } - } - - if (lang_.language == IDLOptions::kJava) { - return java_typename[type.base_type]; - } else { - FLATBUFFERS_ASSERT(lang_.language == IDLOptions::kCSharp); - return csharp_typename[type.base_type]; - } - } - - std::string GenTypeBasic(const Type &type) const { - return GenTypeBasic(type, true); - } - - std::string GenTypePointer(const Type &type) const { - switch (type.base_type) { - case BASE_TYPE_STRING: return lang_.string_type; - case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType()); - case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def); - case BASE_TYPE_UNION: - // Unions in C# use a generic Table-derived type for better type safety - if (lang_.language == IDLOptions::kCSharp) return "TTable"; - FLATBUFFERS_FALLTHROUGH(); // else fall thru - default: return "Table"; - } - } - - std::string GenTypeGet(const Type &type) const { - return IsScalar(type.base_type) - ? GenTypeBasic(type) - : (IsArray(type) ? GenTypeGet(type.VectorType()) - : GenTypePointer(type)); - } - - // Find the destination type the user wants to receive the value in (e.g. - // one size higher signed types for unsigned serialized values in Java). - Type DestinationType(const Type &type, bool vectorelem) const { - if (lang_.language != IDLOptions::kJava) return type; - switch (type.base_type) { - // We use int for both uchar/ushort, since that generally means less - // casting than using short for uchar. - case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT); - case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT); - case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG); - case BASE_TYPE_ARRAY: - case BASE_TYPE_VECTOR: - if (vectorelem) return DestinationType(type.VectorType(), vectorelem); - FLATBUFFERS_FALLTHROUGH(); // else fall thru - default: return type; - } - } - - std::string GenOffsetType(const StructDef &struct_def) const { - if (lang_.language == IDLOptions::kCSharp) { - return "Offset<" + WrapInNameSpace(struct_def) + ">"; - } else { - return "int"; - } - } - - std::string GenOffsetConstruct(const StructDef &struct_def, - const std::string &variable_name) const { - if (lang_.language == IDLOptions::kCSharp) { - return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + - variable_name + ")"; - } - return variable_name; - } - - std::string GenVectorOffsetType() const { - if (lang_.language == IDLOptions::kCSharp) { - return "VectorOffset"; - } else { - return "int"; - } - } - - // Generate destination type name - std::string GenTypeNameDest(const Type &type) const { - return GenTypeGet(DestinationType(type, true)); - } - - // Mask to turn serialized value into destination type value. - std::string DestinationMask(const Type &type, bool vectorelem) const { - if (lang_.language != IDLOptions::kJava) return ""; - switch (type.base_type) { - case BASE_TYPE_UCHAR: return " & 0xFF"; - case BASE_TYPE_USHORT: return " & 0xFFFF"; - case BASE_TYPE_UINT: return " & 0xFFFFFFFFL"; - case BASE_TYPE_VECTOR: - if (vectorelem) return DestinationMask(type.VectorType(), vectorelem); - FLATBUFFERS_FALLTHROUGH(); // else fall thru - default: return ""; - } - } - - // Casts necessary to correctly read serialized data - std::string DestinationCast(const Type &type) const { - if (IsSeries(type)) { - return DestinationCast(type.VectorType()); - } else { - switch (lang_.language) { - case IDLOptions::kJava: - // Cast necessary to correctly read serialized unsigned values. - if (type.base_type == BASE_TYPE_UINT) return "(long)"; - break; - - case IDLOptions::kCSharp: - // Cast from raw integral types to enum. - if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")"; - break; - - default: break; - } - } - return ""; - } - - // Cast statements for mutator method parameters. - // In Java, parameters representing unsigned numbers need to be cast down to - // their respective type. For example, a long holding an unsigned int value - // would be cast down to int before being put onto the buffer. In C#, one cast - // directly cast an Enum to its underlying type, which is essential before - // putting it onto the buffer. - std::string SourceCast(const Type &type, bool castFromDest) const { - if (IsSeries(type)) { - return SourceCast(type.VectorType(), castFromDest); - } else { - switch (lang_.language) { - case IDLOptions::kJava: - if (castFromDest) { - if (type.base_type == BASE_TYPE_UINT) - return "(int)"; - else if (type.base_type == BASE_TYPE_USHORT) - return "(short)"; - else if (type.base_type == BASE_TYPE_UCHAR) - return "(byte)"; - } - break; - case IDLOptions::kCSharp: - if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")"; - break; - default: break; - } - } - return ""; - } - - std::string SourceCast(const Type &type) const { - return SourceCast(type, true); - } - - std::string SourceCastBasic(const Type &type, bool castFromDest) const { - return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : ""; - } - - std::string SourceCastBasic(const Type &type) const { - return SourceCastBasic(type, true); - } - - std::string GenEnumDefaultValue(const FieldDef &field) const { - auto &value = field.value; - FLATBUFFERS_ASSERT(value.type.enum_def); - auto &enum_def = *value.type.enum_def; - auto enum_val = enum_def.FindByValue(value.constant); - return enum_val ? (WrapInNameSpace(enum_def) + "." + enum_val->name) - : value.constant; - } - - std::string GenDefaultValue(const FieldDef &field, - bool enableLangOverrides) const { - auto &value = field.value; - if (enableLangOverrides) { - // handles both enum case and vector of enum case - if (lang_.language == IDLOptions::kCSharp && - value.type.enum_def != nullptr && - value.type.base_type != BASE_TYPE_UNION) { - return GenEnumDefaultValue(field); - } - } - - auto longSuffix = lang_.language == IDLOptions::kJava ? "L" : ""; - switch (value.type.base_type) { - case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true"; - case BASE_TYPE_ULONG: { - if (lang_.language != IDLOptions::kJava) return value.constant; - // Converts the ulong into its bits signed equivalent - uint64_t defaultValue = StringToUInt(value.constant.c_str()); - return NumToString(static_cast(defaultValue)) + longSuffix; - } - case BASE_TYPE_UINT: - case BASE_TYPE_LONG: return value.constant + longSuffix; - default: - if (IsFloat(value.type.base_type)) - return lang_.float_gen->GenFloatConstant(field); - else - return value.constant; - } - } - - std::string GenDefaultValue(const FieldDef &field) const { - return GenDefaultValue(field, true); - } - - std::string GenDefaultValueBasic(const FieldDef &field, - bool enableLangOverrides) const { - auto &value = field.value; - if (!IsScalar(value.type.base_type)) { - if (enableLangOverrides) { - if (lang_.language == IDLOptions::kCSharp) { - switch (value.type.base_type) { - case BASE_TYPE_STRING: return "default(StringOffset)"; - case BASE_TYPE_STRUCT: - return "default(Offset<" + - WrapInNameSpace(*value.type.struct_def) + ">)"; - case BASE_TYPE_VECTOR: return "default(VectorOffset)"; - default: break; - } - } - } - return "0"; - } - return GenDefaultValue(field, enableLangOverrides); - } - - std::string GenDefaultValueBasic(const FieldDef &field) const { - return GenDefaultValueBasic(field, true); - } - - void GenEnum(EnumDef &enum_def, std::string *code_ptr) const { - std::string &code = *code_ptr; - if (enum_def.generated) return; - - // Generate enum definitions of the form: - // public static (final) int name = value; - // In Java, we use ints rather than the Enum feature, because we want them - // to map directly to how they're used in C/C++ and file formats. - // That, and Java Enums are expensive, and not universally liked. - GenComment(enum_def.doc_comment, code_ptr, &lang_.comment_config); - - // In C# this indicates enumeration values can be treated as bit flags. - if (lang_.language == IDLOptions::kCSharp && - enum_def.attributes.Lookup("bit_flags")) { - code += "[System.FlagsAttribute]\n"; - } - if (enum_def.attributes.Lookup("private")) { - // For Java, we leave the enum unmarked to indicate package-private - // For C# we mark the enum as internal - if (lang_.language == IDLOptions::kCSharp) { code += "internal "; } - } else { - code += "public "; - } - code += lang_.enum_decl + enum_def.name; - if (lang_.language == IDLOptions::kCSharp) { - code += lang_.inheritance_marker + - GenTypeBasic(enum_def.underlying_type, false); - } - code += lang_.open_curly; - if (lang_.language == IDLOptions::kJava) { - code += " private " + enum_def.name + "() { }\n"; - } - for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { - auto &ev = **it; - GenComment(ev.doc_comment, code_ptr, &lang_.comment_config, " "); - if (lang_.language != IDLOptions::kCSharp) { - code += " public static"; - code += lang_.const_decl; - code += GenTypeBasic(enum_def.underlying_type, false); - } - code += (lang_.language == IDLOptions::kJava) ? " " : " "; - code += ev.name + " = "; - code += enum_def.ToString(ev); - code += lang_.enum_separator; - } - - // Generate a generate string table for enum values. - // We do not do that for C# where this functionality is native. - if (lang_.language != IDLOptions::kCSharp) { - // Problem is, if values are very sparse that could generate really big - // tables. Ideally in that case we generate a map lookup instead, but for - // the moment we simply don't output a table at all. - auto range = enum_def.Distance(); - // Average distance between values above which we consider a table - // "too sparse". Change at will. - static const uint64_t kMaxSparseness = 5; - if (range / static_cast(enum_def.size()) < kMaxSparseness) { - code += "\n public static"; - code += lang_.const_decl; - code += lang_.string_type; - code += "[] names = { "; - auto val = enum_def.Vals().front(); - for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); - ++it) { - auto ev = *it; - for (auto k = enum_def.Distance(val, ev); k > 1; --k) - code += "\"\", "; - val = ev; - code += "\"" + (*it)->name + "\", "; - } - code += "};\n\n"; - code += " public static "; - code += lang_.string_type; - code += " " + MakeCamel("name", lang_.first_camel_upper); - code += "(int e) { return names[e"; - if (enum_def.MinValue()->IsNonZero()) - code += " - " + enum_def.MinValue()->name; - code += "]; }\n"; - } - } - - // Close the class - code += "}"; - // Java does not need the closing semi-colon on class definitions. - code += (lang_.language != IDLOptions::kJava) ? ";" : ""; - code += "\n\n"; - } - - // Returns the function name that is able to read a value of the given type. - std::string GenGetter(const Type &type) const { - switch (type.base_type) { - case BASE_TYPE_STRING: return lang_.accessor_prefix + "__string"; - case BASE_TYPE_STRUCT: return lang_.accessor_prefix + "__struct"; - case BASE_TYPE_UNION: return lang_.accessor_prefix + "__union"; - case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); - case BASE_TYPE_ARRAY: return GenGetter(type.VectorType()); - default: { - std::string getter = - lang_.accessor_prefix + "bb." + FunctionStart('G') + "et"; - if (type.base_type == BASE_TYPE_BOOL) { - getter = "0!=" + getter; - } else if (GenTypeBasic(type, false) != "byte") { - getter += MakeCamel(GenTypeBasic(type, false)); - } - return getter; - } - } - } - - // Returns the function name that is able to read a value of the given type. - std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field, - const std::string &data_buffer, - const char *num = nullptr) const { - auto type = key_field->value.type; - auto dest_mask = DestinationMask(type, true); - auto dest_cast = DestinationCast(type); - auto getter = data_buffer + "." + FunctionStart('G') + "et"; - if (GenTypeBasic(type, false) != "byte") { - getter += MakeCamel(GenTypeBasic(type, false)); - } - getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" + - dest_mask; - return getter; - } - - // Direct mutation is only allowed for scalar fields. - // Hence a setter method will only be generated for such fields. - std::string GenSetter(const Type &type) const { - if (IsScalar(type.base_type)) { - std::string setter = - lang_.accessor_prefix + "bb." + FunctionStart('P') + "ut"; - if (GenTypeBasic(type, false) != "byte" && - type.base_type != BASE_TYPE_BOOL) { - setter += MakeCamel(GenTypeBasic(type, false)); - } - return setter; - } else { - return ""; - } - } - - // Returns the method name for use with add/put calls. - std::string GenMethod(const Type &type) const { - return IsScalar(type.base_type) ? MakeCamel(GenTypeBasic(type, false)) - : (IsStruct(type) ? "Struct" : "Offset"); - } - - // Recursively generate arguments for a constructor, to deal with nested - // structs. - void GenStructArgs(const StructDef &struct_def, std::string *code_ptr, - const char *nameprefix, size_t array_count = 0) const { - std::string &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; - const auto array_field = IsArray(field_type); - const auto &type = array_field ? field_type.VectorType() - : DestinationType(field_type, false); - const auto array_cnt = array_field ? (array_count + 1) : array_count; - if (IsStruct(type)) { - // Generate arguments for a struct inside a struct. To ensure names - // don't clash, and to make it obvious these arguments are constructing - // a nested struct, prefix the name with the field name. - GenStructArgs(*field_type.struct_def, code_ptr, - (nameprefix + (field.name + "_")).c_str(), array_cnt); - } else { - code += ", "; - code += GenTypeBasic(type); - if (lang_.language == IDLOptions::kJava) { - for (size_t i = 0; i < array_cnt; i++) code += "[]"; - } else if (lang_.language == IDLOptions::kCSharp) { - if (array_cnt > 0) { - code += "["; - for (size_t i = 1; i < array_cnt; i++) code += ","; - code += "]"; - } - } else { - FLATBUFFERS_ASSERT(0); - } - code += " "; - code += nameprefix; - code += MakeCamel(field.name, lang_.first_camel_upper); - } - } - } - - // Recusively generate struct construction statements of the form: - // builder.putType(name); - // and insert manual padding. - void GenStructBody(const StructDef &struct_def, std::string *code_ptr, - const char *nameprefix, size_t index = 0, - bool in_array = false) const { - std::string &code = *code_ptr; - std::string indent((index + 1) * 2, ' '); - code += indent + " builder." + FunctionStart('P') + "rep("; - code += NumToString(struct_def.minalign) + ", "; - code += NumToString(struct_def.bytesize) + ");\n"; - for (auto it = struct_def.fields.vec.rbegin(); - it != struct_def.fields.vec.rend(); ++it) { - auto &field = **it; - const auto &field_type = field.value.type; - if (field.padding) { - code += indent + " builder." + FunctionStart('P') + "ad("; - code += NumToString(field.padding) + ");\n"; - } - if (IsStruct(field_type)) { - GenStructBody(*field_type.struct_def, code_ptr, - (nameprefix + (field.name + "_")).c_str(), index, - in_array); - } else { - const auto &type = - IsArray(field_type) ? field_type.VectorType() : field_type; - const auto index_var = "_idx" + NumToString(index); - if (IsArray(field_type)) { - code += indent + " for (int " + index_var + " = "; - code += NumToString(field_type.fixed_length); - code += "; " + index_var + " > 0; " + index_var + "--) {\n"; - in_array = true; - } - if (IsStruct(type)) { - GenStructBody(*field_type.struct_def, code_ptr, - (nameprefix + (field.name + "_")).c_str(), index + 1, - in_array); - } else { - code += IsArray(field_type) ? " " : ""; - code += indent + " builder." + FunctionStart('P') + "ut"; - code += GenMethod(type) + "("; - code += SourceCast(type); - auto argname = - nameprefix + MakeCamel(field.name, lang_.first_camel_upper); - code += argname; - size_t array_cnt = index + (IsArray(field_type) ? 1 : 0); - if (lang_.language == IDLOptions::kJava) { - for (size_t i = 0; in_array && i < array_cnt; i++) { - code += "[_idx" + NumToString(i) + "-1]"; - } - } else if (lang_.language == IDLOptions::kCSharp) { - if (array_cnt > 0) { - code += "["; - for (size_t i = 0; in_array && i < array_cnt; i++) { - code += "_idx" + NumToString(i) + "-1"; - if (i != (array_cnt - 1)) code += ","; - } - code += "]"; - } - } else { - FLATBUFFERS_ASSERT(0); - } - code += ");\n"; - } - if (IsArray(field_type)) { code += indent + " }\n"; } - } - } - } - - std::string GenByteBufferLength(const char *bb_name) const { - std::string bb_len = bb_name; - if (lang_.language == IDLOptions::kCSharp) - bb_len += ".Length"; - else - bb_len += ".capacity()"; - return bb_len; - } - - std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, - const char *num = nullptr) const { - std::string key_offset = ""; - key_offset += lang_.accessor_prefix_static + "__offset(" + - NumToString(key_field->value.offset) + ", "; - if (num) { - key_offset += num; - key_offset += - (lang_.language == IDLOptions::kCSharp ? ".Value, builder.DataBuffer)" - : ", _bb)"); - } else { - key_offset += GenByteBufferLength("bb"); - key_offset += " - tableOffset, bb)"; - } - return key_offset; - } - - std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) const { - std::string key_getter = " "; - key_getter += "int tableOffset = " + lang_.accessor_prefix_static; - key_getter += "__indirect(vectorLocation + 4 * (start + middle)"; - key_getter += ", bb);\n "; - if (key_field->value.type.base_type == BASE_TYPE_STRING) { - key_getter += "int comp = " + lang_.accessor_prefix_static; - key_getter += FunctionStart('C') + "ompareStrings("; - key_getter += GenOffsetGetter(key_field); - key_getter += ", byteKey, bb);\n"; - } else { - auto get_val = GenGetterForLookupByKey(key_field, "bb"); - if (lang_.language == IDLOptions::kCSharp) { - key_getter += "int comp = " + get_val + ".CompareTo(key);\n"; - } else { - key_getter += GenTypeNameDest(key_field->value.type) + " val = "; - key_getter += get_val + ";\n"; - key_getter += " int comp = val > key ? 1 : val < key ? -1 : 0;\n"; - } - } - return key_getter; - } - - std::string GenKeyGetter(flatbuffers::FieldDef *key_field) const { - std::string key_getter = ""; - auto data_buffer = - (lang_.language == IDLOptions::kCSharp) ? "builder.DataBuffer" : "_bb"; - if (key_field->value.type.base_type == BASE_TYPE_STRING) { - if (lang_.language == IDLOptions::kJava) key_getter += " return "; - key_getter += lang_.accessor_prefix_static; - key_getter += FunctionStart('C') + "ompareStrings("; - key_getter += GenOffsetGetter(key_field, "o1") + ", "; - key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")"; - if (lang_.language == IDLOptions::kJava) key_getter += ";"; - } else { - auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1"); - if (lang_.language == IDLOptions::kCSharp) { - key_getter += field_getter; - field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2"); - key_getter += ".CompareTo(" + field_getter + ")"; - } else { - key_getter += - "\n " + GenTypeNameDest(key_field->value.type) + " val_1 = "; - key_getter += - field_getter + ";\n " + GenTypeNameDest(key_field->value.type); - key_getter += " val_2 = "; - field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2"); - key_getter += field_getter + ";\n"; - key_getter += - " return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n "; - } - } - return key_getter; - } - - void GenStruct(StructDef &struct_def, std::string *code_ptr) const { - if (struct_def.generated) return; - std::string &code = *code_ptr; - - // Generate a struct accessor class, with methods of the form: - // public type name() { return bb.getType(i + offset); } - // or for tables of the form: - // public type name() { - // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default; - // } - GenComment(struct_def.doc_comment, code_ptr, &lang_.comment_config); - if (struct_def.attributes.Lookup("private")) { - // For Java, we leave the struct unmarked to indicate package-private - // For C# we mark the struct as internal - if (lang_.language == IDLOptions::kCSharp) { code += "internal "; } - } else { - code += "public "; - } - if (lang_.language == IDLOptions::kCSharp && - struct_def.attributes.Lookup("csharp_partial")) { - // generate a partial class for this C# struct/table - code += "partial "; - } else { - code += lang_.unsubclassable_decl; - } - code += lang_.accessor_type + struct_def.name; - if (lang_.language == IDLOptions::kCSharp) { - code += " : IFlatbufferObject"; - code += lang_.open_curly; - code += " private "; - code += struct_def.fixed ? "Struct" : "Table"; - code += " __p;\n"; - - if (lang_.language == IDLOptions::kCSharp) { - code += " public ByteBuffer ByteBuffer { get { return __p.bb; } }\n"; - } - - } else { - code += lang_.inheritance_marker; - code += struct_def.fixed ? "Struct" : "Table"; - code += lang_.open_curly; - } - - if (!struct_def.fixed) { - // Generate verson check method. - // Force compile time error if not using the same version runtime. - code += " public static void ValidateVersion() {"; - if (lang_.language == IDLOptions::kCSharp) - code += " FlatBufferConstants."; - else - code += " Constants."; - code += "FLATBUFFERS_1_11_1(); "; - code += "}\n"; - - // Generate a special accessor for the table that when used as the root - // of a FlatBuffer - std::string method_name = - FunctionStart('G') + "etRootAs" + struct_def.name; - std::string method_signature = - " public static " + struct_def.name + " " + method_name; - - // create convenience method that doesn't require an existing object - code += method_signature + "(ByteBuffer _bb) "; - code += "{ return " + method_name + "(_bb, new " + struct_def.name + - "()); }\n"; - - // create method that allows object reuse - code += - method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { "; - code += lang_.set_bb_byteorder; - code += "return (obj.__assign(_bb." + FunctionStart('G') + "etInt(_bb."; - code += lang_.get_bb_position; - code += ") + _bb."; - code += lang_.get_bb_position; - code += ", _bb)); }\n"; - if (parser_.root_struct_def_ == &struct_def) { - if (parser_.file_identifier_.length()) { - // Check if a buffer has the identifier. - code += " public static "; - code += lang_.bool_type + struct_def.name; - code += "BufferHasIdentifier(ByteBuffer _bb) { return "; - code += lang_.accessor_prefix_static + "__has_identifier(_bb, \""; - code += parser_.file_identifier_; - code += "\"); }\n"; - } - } - } - // Generate the __init method that sets the field in a pre-existing - // accessor object. This is to allow object reuse. - code += " public void __init(int _i, ByteBuffer _bb) "; - code += "{ "; - if (lang_.language == IDLOptions::kCSharp) { - code += "__p = new "; - code += struct_def.fixed ? "Struct" : "Table"; - code += "(_i, _bb); "; - } else { - code += "__reset(_i, _bb); "; - } - code += "}\n"; - code += - " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) "; - code += "{ __init(_i, _bb); return this; }\n\n"; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - GenComment(field.doc_comment, code_ptr, &lang_.comment_config, " "); - std::string type_name = GenTypeGet(field.value.type); - std::string type_name_dest = GenTypeNameDest(field.value.type); - std::string conditional_cast = ""; - std::string optional = ""; - if (lang_.language == IDLOptions::kCSharp && !struct_def.fixed && - (field.value.type.base_type == BASE_TYPE_STRUCT || - field.value.type.base_type == BASE_TYPE_UNION || - (field.value.type.base_type == BASE_TYPE_VECTOR && - (field.value.type.element == BASE_TYPE_STRUCT || - field.value.type.element == BASE_TYPE_UNION)))) { - optional = lang_.optional_suffix; - conditional_cast = "(" + type_name_dest + optional + ")"; - } - std::string dest_mask = DestinationMask(field.value.type, true); - std::string dest_cast = DestinationCast(field.value.type); - std::string src_cast = SourceCast(field.value.type); - std::string method_start = - " public " + - (field.required ? "" : GenNullableAnnotation(field.value.type)) + - GenPureAnnotation(field.value.type) + type_name_dest + optional + - " " + MakeCamel(field.name, lang_.first_camel_upper); - std::string obj = lang_.language == IDLOptions::kCSharp - ? "(new " + type_name + "())" - : "obj"; - - // Most field accessors need to retrieve and test the field offset first, - // this is the prefix code for that: - auto offset_prefix = - IsArray(field.value.type) - ? " { return " - : (" { int o = " + lang_.accessor_prefix + "__offset(" + - NumToString(field.value.offset) + "); return o != 0 ? "); - // Generate the accessors that don't do object reuse. - if (field.value.type.base_type == BASE_TYPE_STRUCT) { - // Calls the accessor that takes an accessor object with a new object. - if (lang_.language != IDLOptions::kCSharp) { - code += method_start + "() { return "; - code += MakeCamel(field.name, lang_.first_camel_upper); - code += "(new "; - code += type_name + "()); }\n"; - } - } else if (field.value.type.base_type == BASE_TYPE_VECTOR && - field.value.type.element == BASE_TYPE_STRUCT) { - // Accessors for vectors of structs also take accessor objects, this - // generates a variant without that argument. - if (lang_.language != IDLOptions::kCSharp) { - code += method_start + "(int j) { return "; - code += MakeCamel(field.name, lang_.first_camel_upper); - code += "(new " + type_name + "(), j); }\n"; - } - } else if (field.value.type.base_type == BASE_TYPE_UNION || - (field.value.type.base_type == BASE_TYPE_VECTOR && - field.value.type.VectorType().base_type == BASE_TYPE_UNION)) { - if (lang_.language == IDLOptions::kCSharp) { - // Union types in C# use generic Table-derived type for better type - // safety. - method_start += ""; - type_name = type_name_dest; - } - } - std::string getter = dest_cast + GenGetter(field.value.type); - code += method_start; - std::string default_cast = ""; - // only create default casts for c# scalars or vectors of scalars - if (lang_.language == IDLOptions::kCSharp && - (IsScalar(field.value.type.base_type) || - (field.value.type.base_type == BASE_TYPE_VECTOR && - IsScalar(field.value.type.element)))) { - // For scalars, default value will be returned by GetDefaultValue(). - // If the scalar is an enum, GetDefaultValue() returns an actual c# enum - // that doesn't need to be casted. However, default values for enum - // elements of vectors are integer literals ("0") and are still casted - // for clarity. - if (field.value.type.enum_def == nullptr || - field.value.type.base_type == BASE_TYPE_VECTOR) { - default_cast = "(" + type_name_dest + ")"; - } - } - std::string member_suffix = "; "; - if (IsScalar(field.value.type.base_type)) { - code += lang_.getter_prefix; - member_suffix += lang_.getter_suffix; - if (struct_def.fixed) { - code += " { return " + getter; - code += "(" + lang_.accessor_prefix + "bb_pos + "; - code += NumToString(field.value.offset) + ")"; - code += dest_mask; - } else { - code += offset_prefix + getter; - code += "(o + " + lang_.accessor_prefix + "bb_pos)" + dest_mask; - code += " : " + default_cast; - code += GenDefaultValue(field); - } - } else { - switch (field.value.type.base_type) { - case BASE_TYPE_STRUCT: - if (lang_.language != IDLOptions::kCSharp) { - code += "(" + type_name + " obj" + ")"; - } else { - code += lang_.getter_prefix; - member_suffix += lang_.getter_suffix; - } - if (struct_def.fixed) { - code += " { return " + obj + ".__assign(" + lang_.accessor_prefix; - code += "bb_pos + " + NumToString(field.value.offset) + ", "; - code += lang_.accessor_prefix + "bb)"; - } else { - code += offset_prefix + conditional_cast; - code += obj + ".__assign("; - code += field.value.type.struct_def->fixed - ? "o + " + lang_.accessor_prefix + "bb_pos" - : lang_.accessor_prefix + "__indirect(o + " + - lang_.accessor_prefix + "bb_pos)"; - code += ", " + lang_.accessor_prefix + "bb) : null"; - } - break; - case BASE_TYPE_STRING: - code += lang_.getter_prefix; - member_suffix += lang_.getter_suffix; - code += offset_prefix + getter + "(o + " + lang_.accessor_prefix; - code += "bb_pos) : null"; - break; - case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru - case BASE_TYPE_VECTOR: { - auto vectortype = field.value.type.VectorType(); - if (vectortype.base_type == BASE_TYPE_UNION && - lang_.language == IDLOptions::kCSharp) { - conditional_cast = "(TTable?)"; - getter += ""; - } - code += "("; - if (vectortype.base_type == BASE_TYPE_STRUCT) { - if (lang_.language != IDLOptions::kCSharp) - code += type_name + " obj, "; - getter = obj + ".__assign"; - } else if (vectortype.base_type == BASE_TYPE_UNION) { - if (lang_.language != IDLOptions::kCSharp) - code += type_name + " obj, "; - } - code += "int j)"; - const auto body = offset_prefix + conditional_cast + getter + "("; - if (vectortype.base_type == BASE_TYPE_UNION) { - if (lang_.language != IDLOptions::kCSharp) - code += body + "obj, "; - else - code += " where TTable : struct, IFlatbufferObject" + body; - } else { - code += body; - } - auto index = lang_.accessor_prefix; - if (IsArray(field.value.type)) { - index += "bb_pos + " + NumToString(field.value.offset) + " + "; - } else { - index += "__vector(o) + "; - } - index += "j * " + NumToString(InlineSize(vectortype)); - if (vectortype.base_type == BASE_TYPE_STRUCT) { - code += vectortype.struct_def->fixed - ? index - : lang_.accessor_prefix + "__indirect(" + index + ")"; - code += ", " + lang_.accessor_prefix + "bb"; - } else { - code += index; - } - code += ")" + dest_mask; - if (!IsArray(field.value.type)) { - code += " : "; - code += - field.value.type.element == BASE_TYPE_BOOL - ? "false" - : (IsScalar(field.value.type.element) ? default_cast + "0" - : "null"); - } - - break; - } - case BASE_TYPE_UNION: - if (lang_.language == IDLOptions::kCSharp) { - code += "() where TTable : struct, IFlatbufferObject"; - code += offset_prefix + "(TTable?)" + getter; - code += - "(o + " + lang_.accessor_prefix + "bb_pos) : null"; - } else { - code += "(" + type_name + " obj)" + offset_prefix + getter; - code += "(obj, o + " + lang_.accessor_prefix + "bb_pos) : null"; - } - break; - default: FLATBUFFERS_ASSERT(0); - } - } - code += member_suffix; - code += "}\n"; - if (field.value.type.base_type == BASE_TYPE_VECTOR) { - code += - " public int " + MakeCamel(field.name, lang_.first_camel_upper); - code += "Length"; - code += lang_.getter_prefix; - code += offset_prefix; - code += lang_.accessor_prefix + "__vector_len(o) : 0; "; - code += lang_.getter_suffix; - code += "}\n"; - // See if we should generate a by-key accessor. - if (field.value.type.element == BASE_TYPE_STRUCT && - !field.value.type.struct_def->fixed) { - auto &sd = *field.value.type.struct_def; - auto &fields = sd.fields.vec; - for (auto kit = fields.begin(); kit != fields.end(); ++kit) { - auto &key_field = **kit; - if (key_field.key) { - auto qualified_name = WrapInNameSpace(sd); - code += - " public " + qualified_name + lang_.optional_suffix + " "; - code += MakeCamel(field.name, lang_.first_camel_upper) + "ByKey("; - code += GenTypeNameDest(key_field.value.type) + " key)"; - code += offset_prefix; - code += qualified_name + ".__lookup_by_key("; - if (lang_.language == IDLOptions::kJava) code += "null, "; - code += lang_.accessor_prefix + "__vector(o), key, "; - code += lang_.accessor_prefix + "bb) : null; "; - code += "}\n"; - if (lang_.language == IDLOptions::kJava) { - code += - " public " + qualified_name + lang_.optional_suffix + " "; - code += - MakeCamel(field.name, lang_.first_camel_upper) + "ByKey("; - code += qualified_name + lang_.optional_suffix + " obj, "; - code += GenTypeNameDest(key_field.value.type) + " key)"; - code += offset_prefix; - code += qualified_name + ".__lookup_by_key(obj, "; - code += lang_.accessor_prefix + "__vector(o), key, "; - code += lang_.accessor_prefix + "bb) : null; "; - code += "}\n"; - } - break; - } - } - } - } - // Generate the accessors for vector of structs with vector access object - if (lang_.language == IDLOptions::kJava && - field.value.type.base_type == BASE_TYPE_VECTOR) { - std::string vector_type_name; - const auto &element_base_type = field.value.type.VectorType().base_type; - if (IsScalar(element_base_type)) { - vector_type_name = MakeCamel(type_name, true) + "Vector"; - } else if (element_base_type == BASE_TYPE_STRING) { - vector_type_name = "StringVector"; - } else if (element_base_type == BASE_TYPE_UNION) { - vector_type_name = "UnionVector"; - } else { - vector_type_name = type_name + ".Vector"; - } - auto vector_method_start = - GenNullableAnnotation(field.value.type) + " public " + - vector_type_name + optional + " " + - MakeCamel(field.name, lang_.first_camel_upper) + "Vector"; - code += vector_method_start + "() { return "; - code += MakeCamel(field.name, lang_.first_camel_upper) + "Vector"; - code += "(new " + vector_type_name + "()); }\n"; - code += vector_method_start + "(" + vector_type_name + " obj)"; - code += offset_prefix + conditional_cast + obj + ".__assign" + "("; - code += lang_.accessor_prefix + "__vector(o), "; - if (!IsScalar(element_base_type)) { - auto vectortype = field.value.type.VectorType(); - code += NumToString(InlineSize(vectortype)) + ", "; - } - code += lang_.accessor_prefix + "bb) : null" + member_suffix + "}\n"; - } - // Generate a ByteBuffer accessor for strings & vectors of scalars. - if ((field.value.type.base_type == BASE_TYPE_VECTOR && - IsScalar(field.value.type.VectorType().base_type)) || - field.value.type.base_type == BASE_TYPE_STRING) { - switch (lang_.language) { - case IDLOptions::kJava: - code += " public ByteBuffer "; - code += MakeCamel(field.name, lang_.first_camel_upper); - code += "AsByteBuffer() { return "; - code += lang_.accessor_prefix + "__vector_as_bytebuffer("; - code += NumToString(field.value.offset) + ", "; - code += - NumToString(field.value.type.base_type == BASE_TYPE_STRING - ? 1 - : InlineSize(field.value.type.VectorType())); - code += "); }\n"; - code += " public ByteBuffer "; - code += MakeCamel(field.name, lang_.first_camel_upper); - code += "InByteBuffer(ByteBuffer _bb) { return "; - code += lang_.accessor_prefix + "__vector_in_bytebuffer(_bb, "; - code += NumToString(field.value.offset) + ", "; - code += - NumToString(field.value.type.base_type == BASE_TYPE_STRING - ? 1 - : InlineSize(field.value.type.VectorType())); - code += "); }\n"; - break; - case IDLOptions::kCSharp: - code += "#if ENABLE_SPAN_T\n"; - code += " public Span<" + - GenTypeBasic(field.value.type.VectorType()) + "> Get"; - code += MakeCamel(field.name, lang_.first_camel_upper); - code += "Bytes() { return "; - code += lang_.accessor_prefix + "__vector_as_span<" + - GenTypeBasic(field.value.type.VectorType()) + ">("; - code += NumToString(field.value.offset); - code += ", " + NumToString( - SizeOf(field.value.type.VectorType().base_type)); - code += "); }\n"; - code += "#else\n"; - code += " public ArraySegment? Get"; - code += MakeCamel(field.name, lang_.first_camel_upper); - code += "Bytes() { return "; - code += lang_.accessor_prefix + "__vector_as_arraysegment("; - code += NumToString(field.value.offset); - code += "); }\n"; - code += "#endif\n"; - - // For direct blockcopying the data into a typed array - code += " public "; - code += GenTypeBasic(field.value.type.VectorType()); - code += "[] Get"; - code += MakeCamel(field.name, lang_.first_camel_upper); - code += "Array() { "; - if (IsEnum(field.value.type.VectorType())) { - // Since __vector_as_array does not work for enum types, - // fill array using an explicit loop. - code += "int o = " + lang_.accessor_prefix + "__offset("; - code += NumToString(field.value.offset); - code += "); if (o == 0) return null; int p = "; - code += lang_.accessor_prefix + "__vector(o); int l = "; - code += lang_.accessor_prefix + "__vector_len(o); "; - code += GenTypeBasic(field.value.type.VectorType()); - code += "[] a = new "; - code += GenTypeBasic(field.value.type.VectorType()); - code += "[l]; for (int i = 0; i < l; i++) { a[i] = " + getter; - code += "(p + i * "; - code += NumToString(InlineSize(field.value.type.VectorType())); - code += "); } return a;"; - } else { - code += "return "; - code += lang_.accessor_prefix + "__vector_as_array<"; - code += GenTypeBasic(field.value.type.VectorType()); - code += ">("; - code += NumToString(field.value.offset); - code += ");"; - } - code += " }\n"; - break; - default: break; - } - } - // generate object accessors if is nested_flatbuffer - if (field.nested_flatbuffer) { - auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer); - auto nested_method_name = - MakeCamel(field.name, lang_.first_camel_upper) + "As" + - field.nested_flatbuffer->name; - auto get_nested_method_name = nested_method_name; - if (lang_.language == IDLOptions::kCSharp) { - get_nested_method_name = "Get" + nested_method_name; - conditional_cast = - "(" + nested_type_name + lang_.optional_suffix + ")"; - } - if (lang_.language != IDLOptions::kCSharp) { - code += " public " + nested_type_name + lang_.optional_suffix + " "; - code += nested_method_name + "() { return "; - code += - get_nested_method_name + "(new " + nested_type_name + "()); }\n"; - } else { - obj = "(new " + nested_type_name + "())"; - } - code += " public " + nested_type_name + lang_.optional_suffix + " "; - code += get_nested_method_name + "("; - if (lang_.language != IDLOptions::kCSharp) - code += nested_type_name + " obj"; - code += ") { int o = " + lang_.accessor_prefix + "__offset("; - code += NumToString(field.value.offset) + "); "; - code += "return o != 0 ? " + conditional_cast + obj + ".__assign("; - code += lang_.accessor_prefix; - code += "__indirect(" + lang_.accessor_prefix + "__vector(o)), "; - code += lang_.accessor_prefix + "bb) : null; }\n"; - } - // Generate mutators for scalar fields or vectors of scalars. - if (parser_.opts.mutable_buffer) { - auto is_series = (IsSeries(field.value.type)); - const auto &underlying_type = - is_series ? field.value.type.VectorType() : field.value.type; - // Boolean parameters have to be explicitly converted to byte - // representation. - auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL - ? "(byte)(" + field.name + " ? 1 : 0)" - : field.name; - auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper); - // A vector mutator also needs the index of the vector element it should - // mutate. - auto mutator_params = (is_series ? "(int j, " : "(") + - GenTypeNameDest(underlying_type) + " " + - field.name + ") { "; - auto setter_index = - is_series - ? lang_.accessor_prefix + - (IsArray(field.value.type) - ? "bb_pos + " + NumToString(field.value.offset) - : "__vector(o)") + - +" + j * " + NumToString(InlineSize(underlying_type)) - : (struct_def.fixed - ? lang_.accessor_prefix + "bb_pos + " + - NumToString(field.value.offset) - : "o + " + lang_.accessor_prefix + "bb_pos"); - if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) { - code += " public "; - code += struct_def.fixed ? "void " : lang_.bool_type; - code += mutator_prefix + MakeCamel(field.name, true); - code += mutator_params; - if (struct_def.fixed) { - code += GenSetter(underlying_type) + "(" + setter_index + ", "; - code += src_cast + setter_parameter + "); }\n"; - } else { - code += "int o = " + lang_.accessor_prefix + "__offset("; - code += NumToString(field.value.offset) + ");"; - code += " if (o != 0) { " + GenSetter(underlying_type); - code += "(" + setter_index + ", " + src_cast + setter_parameter + - "); return true; } else { return false; } }\n"; - } - } - } - if (parser_.opts.java_primitive_has_method && - IsScalar(field.value.type.base_type) && !struct_def.fixed) { - auto vt_offset_constant = " public static final int VT_" + - MakeScreamingCamel(field.name) + " = " + - NumToString(field.value.offset) + ";"; - - code += vt_offset_constant; - code += "\n"; - } - } - code += "\n"; - flatbuffers::FieldDef *key_field = nullptr; - if (struct_def.fixed) { - // create a struct constructor function - code += " public static " + GenOffsetType(struct_def) + " "; - code += FunctionStart('C') + "reate"; - code += struct_def.name + "(FlatBufferBuilder builder"; - GenStructArgs(struct_def, code_ptr, ""); - code += ") {\n"; - GenStructBody(struct_def, code_ptr, ""); - code += " return "; - code += GenOffsetConstruct( - struct_def, "builder." + std::string(lang_.get_fbb_offset)); - code += ";\n }\n"; - } else { - // Generate a method that creates a table in one go. This is only possible - // when the table has no struct fields, since those have to be created - // inline, and there's no way to do so in Java. - bool has_no_struct_fields = true; - int num_fields = 0; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - if (IsStruct(field.value.type)) { - has_no_struct_fields = false; - } else { - num_fields++; - } - } - // 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) { - // Generate a table constructor of the form: - // public static int createName(FlatBufferBuilder builder, args...) - code += " public static " + GenOffsetType(struct_def) + " "; - code += FunctionStart('C') + "reate" + struct_def.name; - code += "(FlatBufferBuilder builder"; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (field.deprecated) continue; - code += ",\n "; - code += GenTypeBasic(DestinationType(field.value.type, false)); - code += " "; - code += field.name; - if (!IsScalar(field.value.type.base_type)) code += "Offset"; - - // Java doesn't have defaults, which means this method must always - // supply all arguments, and thus won't compile when fields are added. - if (lang_.language != IDLOptions::kJava) { - code += " = "; - code += GenDefaultValueBasic(field); - } - } - code += ") {\n builder."; - code += FunctionStart('S') + "tartTable("; - code += NumToString(struct_def.fields.vec.size()) + ");\n"; - for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; - size; size /= 2) { - for (auto it = struct_def.fields.vec.rbegin(); - it != struct_def.fields.vec.rend(); ++it) { - auto &field = **it; - if (!field.deprecated && - (!struct_def.sortbysize || - size == SizeOf(field.value.type.base_type))) { - code += " " + struct_def.name + "."; - code += FunctionStart('A') + "dd"; - code += MakeCamel(field.name) + "(builder, " + field.name; - if (!IsScalar(field.value.type.base_type)) code += "Offset"; - code += ");\n"; - } - } - } - code += " return " + struct_def.name + "."; - code += FunctionStart('E') + "nd" + struct_def.name; - code += "(builder);\n }\n\n"; - } - // Generate a set of static methods that allow table construction, - // of the form: - // public static void addName(FlatBufferBuilder builder, short name) - // { builder.addShort(id, name, default); } - // Unlike the Create function, these always work. - code += " public static void " + FunctionStart('S') + "tart"; - code += struct_def.name; - code += "(FlatBufferBuilder builder) { builder."; - code += FunctionStart('S') + "tartTable("; - code += NumToString(struct_def.fields.vec.size()) + "); }\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.key) key_field = &field; - code += " public static void " + FunctionStart('A') + "dd"; - code += MakeCamel(field.name); - code += "(FlatBufferBuilder builder, "; - code += GenTypeBasic(DestinationType(field.value.type, false)); - auto argname = MakeCamel(field.name, false); - if (!IsScalar(field.value.type.base_type)) argname += "Offset"; - code += " " + argname + ") { builder." + FunctionStart('A') + "dd"; - code += GenMethod(field.value.type) + "("; - code += NumToString(it - struct_def.fields.vec.begin()) + ", "; - code += SourceCastBasic(field.value.type); - code += argname; - if (!IsScalar(field.value.type.base_type) && - field.value.type.base_type != BASE_TYPE_UNION && - lang_.language == IDLOptions::kCSharp) { - code += ".Value"; - } - code += ", "; - if (lang_.language == IDLOptions::kJava) - code += SourceCastBasic(field.value.type); - code += GenDefaultValue(field, false); - code += "); }\n"; - if (field.value.type.base_type == BASE_TYPE_VECTOR) { - auto vector_type = field.value.type.VectorType(); - auto alignment = InlineAlignment(vector_type); - auto elem_size = InlineSize(vector_type); - if (!IsStruct(vector_type)) { - // generate a method to create a vector from a java array. - if (lang_.language == IDLOptions::kJava && - (vector_type.base_type == BASE_TYPE_CHAR || - vector_type.base_type == BASE_TYPE_UCHAR)) { - // Handle byte[] and ByteBuffers separately for Java - code += " public static " + GenVectorOffsetType() + " "; - code += FunctionStart('C') + "reate"; - code += MakeCamel(field.name); - code += "Vector(FlatBufferBuilder builder, byte[] data) "; - code += "{ return builder.createByteVector(data); }\n"; - - code += " public static " + GenVectorOffsetType() + " "; - code += FunctionStart('C') + "reate"; - code += MakeCamel(field.name); - code += "Vector(FlatBufferBuilder builder, ByteBuffer data) "; - code += "{ return builder.createByteVector(data); }\n"; - } else { - code += " public static " + GenVectorOffsetType() + " "; - code += FunctionStart('C') + "reate"; - code += MakeCamel(field.name); - code += "Vector(FlatBufferBuilder builder, "; - code += GenTypeBasic(vector_type) + "[] data) "; - code += "{ builder." + FunctionStart('S') + "tartVector("; - code += NumToString(elem_size); - code += ", data." + FunctionStart('L') + "ength, "; - code += NumToString(alignment); - code += "); for (int i = data."; - code += FunctionStart('L') + "ength - 1; i >= 0; i--) builder."; - code += FunctionStart('A') + "dd"; - code += GenMethod(vector_type); - code += "("; - code += SourceCastBasic(vector_type, false); - code += "data[i]"; - if (lang_.language == IDLOptions::kCSharp && - (vector_type.base_type == BASE_TYPE_STRUCT || - vector_type.base_type == BASE_TYPE_STRING)) - code += ".Value"; - code += "); return "; - code += "builder." + FunctionStart('E') + "ndVector(); }\n"; - // For C#, include a block copy method signature. - if (lang_.language == IDLOptions::kCSharp) { - code += " public static " + GenVectorOffsetType() + " "; - code += FunctionStart('C') + "reate"; - code += MakeCamel(field.name); - code += "VectorBlock(FlatBufferBuilder builder, "; - code += GenTypeBasic(vector_type) + "[] data) "; - code += "{ builder." + FunctionStart('S') + "tartVector("; - code += NumToString(elem_size); - code += ", data." + FunctionStart('L') + "ength, "; - code += NumToString(alignment); - code += "); builder.Add(data); return builder.EndVector(); }\n"; - } - } - } - // Generate a method to start a vector, data to be added manually - // after. - code += " public static void " + FunctionStart('S') + "tart"; - code += MakeCamel(field.name); - code += "Vector(FlatBufferBuilder builder, int numElems) "; - code += "{ builder." + FunctionStart('S') + "tartVector("; - code += NumToString(elem_size); - code += ", numElems, " + NumToString(alignment); - code += "); }\n"; - } - } - code += " public static " + GenOffsetType(struct_def) + " "; - code += FunctionStart('E') + "nd" + struct_def.name; - code += "(FlatBufferBuilder builder) {\n int o = builder."; - code += FunctionStart('E') + "ndTable();\n"; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { - auto &field = **it; - if (!field.deprecated && field.required) { - code += " builder." + FunctionStart('R') + "equired(o, "; - code += NumToString(field.value.offset); - code += "); // " + field.name + "\n"; - } - } - code += " return " + GenOffsetConstruct(struct_def, "o") + ";\n }\n"; - if (parser_.root_struct_def_ == &struct_def) { - std::string size_prefix[] = { "", "SizePrefixed" }; - for (int i = 0; i < 2; ++i) { - code += " public static void "; - code += - FunctionStart('F') + "inish" + size_prefix[i] + struct_def.name; - code += - "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def); - code += " offset) {"; - code += " builder." + FunctionStart('F') + "inish" + size_prefix[i] + - "(offset"; - if (lang_.language == IDLOptions::kCSharp) { code += ".Value"; } - - if (parser_.file_identifier_.length()) - code += ", \"" + parser_.file_identifier_ + "\""; - code += "); }\n"; - } - } - } - // Only generate key compare function for table, - // because `key_field` is not set for struct - if (struct_def.has_key && !struct_def.fixed) { - FLATBUFFERS_ASSERT(key_field); - if (lang_.language == IDLOptions::kJava) { - code += "\n @Override\n protected int keysCompare("; - code += "Integer o1, Integer o2, ByteBuffer _bb) {"; - code += GenKeyGetter(key_field); - code += " }\n"; - } else { - code += "\n public static VectorOffset "; - code += "CreateSortedVectorOf" + struct_def.name; - code += "(FlatBufferBuilder builder, "; - code += "Offset<" + struct_def.name + ">"; - code += "[] offsets) {\n"; - code += " Array.Sort(offsets, (Offset<" + struct_def.name + - "> o1, Offset<" + struct_def.name + "> o2) => " + - GenKeyGetter(key_field); - code += ");\n"; - code += " return builder.CreateVectorOfTables(offsets);\n }\n"; - } - - code += "\n public static " + struct_def.name + lang_.optional_suffix; - code += " __lookup_by_key("; - if (lang_.language == IDLOptions::kJava) - code += struct_def.name + " obj, "; - code += "int vectorLocation, "; - code += GenTypeNameDest(key_field->value.type); - code += " key, ByteBuffer bb) {\n"; - if (key_field->value.type.base_type == BASE_TYPE_STRING) { - code += " byte[] byteKey = "; - if (lang_.language == IDLOptions::kJava) - code += "key.getBytes(Table.UTF8_CHARSET.get());\n"; - else - code += "System.Text.Encoding.UTF8.GetBytes(key);\n"; - } - code += " int span = "; - code += "bb." + FunctionStart('G') + "etInt(vectorLocation - 4);\n"; - code += " int start = 0;\n"; - code += " while (span != 0) {\n"; - code += " int middle = span / 2;\n"; - code += GenLookupKeyGetter(key_field); - code += " if (comp > 0) {\n"; - code += " span = middle;\n"; - code += " } else if (comp < 0) {\n"; - code += " middle++;\n"; - code += " start += middle;\n"; - code += " span -= middle;\n"; - code += " } else {\n"; - code += " return "; - if (lang_.language == IDLOptions::kJava) - code += "(obj == null ? new " + struct_def.name + "() : obj)"; - else - code += "new " + struct_def.name + "()"; - code += ".__assign(tableOffset, bb);\n"; - code += " }\n }\n"; - code += " return null;\n"; - code += " }\n"; - } - if (lang_.language == IDLOptions::kJava) - GenVectorAccessObject(struct_def, code_ptr); - code += "}"; - // Java does not need the closing semi-colon on class definitions. - code += (lang_.language != IDLOptions::kJava) ? ";" : ""; - code += "\n\n"; - } - - void GenVectorAccessObject(StructDef &struct_def, - std::string *code_ptr) const { - auto &code = *code_ptr; - // Generate a vector of structs accessor class. - code += "\n"; - code += " "; - if (!struct_def.attributes.Lookup("private")) code += "public "; - code += "static "; - code += lang_.unsubclassable_decl; - code += lang_.accessor_type + "Vector" + lang_.inheritance_marker; - code += "BaseVector" + lang_.open_curly; - - // Generate the __assign method that sets the field in a pre-existing - // accessor object. This is to allow object reuse. - std::string method_indent = " "; - code += method_indent + "public Vector "; - code += "__assign(int _vector, int _element_size, ByteBuffer _bb) { "; - code += "__reset(_vector, _element_size, _bb); return this; }\n\n"; - - auto type_name = struct_def.name; - auto method_start = - method_indent + "public " + type_name + " " + FunctionStart('G') + "et"; - // Generate the accessors that don't do object reuse. - code += method_start + "(int j) { return " + FunctionStart('G') + "et"; - code += "(new " + type_name + "(), j); }\n"; - code += method_start + "(" + type_name + " obj, int j) { "; - code += " return obj.__assign("; - auto index = lang_.accessor_prefix + "__element(j)"; - code += struct_def.fixed - ? index - : lang_.accessor_prefix + "__indirect(" + index + ", bb)"; - code += ", " + lang_.accessor_prefix + "bb); }\n"; - // See if we should generate a by-key accessor. - if (!struct_def.fixed) { - auto &fields = struct_def.fields.vec; - for (auto kit = fields.begin(); kit != fields.end(); ++kit) { - auto &key_field = **kit; - if (key_field.key) { - auto nullable_annotation = - parser_.opts.gen_nullable ? "@Nullable " : ""; - code += method_indent + nullable_annotation; - code += "public " + type_name + lang_.optional_suffix + " "; - code += FunctionStart('G') + "et" + "ByKey("; - code += GenTypeNameDest(key_field.value.type) + " key) { "; - code += " return __lookup_by_key(null, "; - code += lang_.accessor_prefix + "__vector(), key, "; - code += lang_.accessor_prefix + "bb); "; - code += "}\n"; - code += method_indent + nullable_annotation; - code += "public " + type_name + lang_.optional_suffix + " "; - code += FunctionStart('G') + "et" + "ByKey("; - code += type_name + lang_.optional_suffix + " obj, "; - code += GenTypeNameDest(key_field.value.type) + " key) { "; - code += " return __lookup_by_key(obj, "; - code += lang_.accessor_prefix + "__vector(), key, "; - code += lang_.accessor_prefix + "bb); "; - code += "}\n"; - break; - } - } - } - code += " }\n"; - } - - 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_; -}; -} // namespace general - -bool GenerateGeneral(const Parser &parser, const std::string &path, - const std::string &file_name) { - general::GeneralGenerator generator(parser, path, file_name); - return generator.generate(); -} - std::string GeneralMakeRule(const Parser &parser, const std::string &path, const std::string &file_name) { FLATBUFFERS_ASSERT(parser.opts.lang <= IDLOptions::kMAX); - const auto &lang = GetLangParams(parser.opts.lang); + + std::string file_extension = + (parser.opts.lang == IDLOptions::kJava) ? ".java" : ".cs"; std::string make_rule; @@ -1768,7 +41,7 @@ std::string GeneralMakeRule(const Parser &parser, const std::string &path, if (!make_rule.empty()) make_rule += " "; std::string directory = BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace); - make_rule += directory + enum_def.name + lang.file_extension; + make_rule += directory + enum_def.name + file_extension; } for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); @@ -1777,7 +50,7 @@ std::string GeneralMakeRule(const Parser &parser, const std::string &path, if (!make_rule.empty()) make_rule += " "; std::string directory = BaseGenerator::NamespaceDir( parser, path, *struct_def.defined_namespace); - make_rule += directory + struct_def.name + lang.file_extension; + make_rule += directory + struct_def.name + file_extension; } make_rule += ": "; diff --git a/src/idl_gen_java.cpp b/src/idl_gen_java.cpp new file mode 100644 index 000000000..123ebddc6 --- /dev/null +++ b/src/idl_gen_java.cpp @@ -0,0 +1,1242 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// independent from idl_parser, since this code is not needed for most clients + +#include "flatbuffers/code_generators.h" +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" + +#if defined(FLATBUFFERS_CPP98_STL) +# include +#endif // defined(FLATBUFFERS_CPP98_STL) + +namespace flatbuffers { +namespace java { + +static TypedFloatConstantGenerator JavaFloatGen("Double.", "Float.", "NaN", + "POSITIVE_INFINITY", + "NEGATIVE_INFINITY"); + +static CommentConfig comment_config = { + "/**", + " *", + " */", +}; + +class JavaGenerator : public BaseGenerator { + public: + JavaGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) + : BaseGenerator(parser, path, file_name, "", "."), + cur_name_space_(nullptr) {} + + JavaGenerator &operator=(const JavaGenerator &); + bool generate() { + std::string one_file_code; + cur_name_space_ = parser_.current_namespace_; + + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + std::string enumcode; + auto &enum_def = **it; + if (!parser_.opts.one_file) cur_name_space_ = enum_def.defined_namespace; + GenEnum(enum_def, &enumcode); + if (parser_.opts.one_file) { + one_file_code += enumcode; + } else { + if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode, + false)) + return false; + } + } + + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + std::string declcode; + auto &struct_def = **it; + if (!parser_.opts.one_file) + cur_name_space_ = struct_def.defined_namespace; + GenStruct(struct_def, &declcode); + if (parser_.opts.one_file) { + one_file_code += declcode; + } else { + if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode, + true)) + return false; + } + } + + if (parser_.opts.one_file) { + return SaveType(file_name_, *parser_.current_namespace_, one_file_code, + true); + } + return true; + } + + // Save out the generated code for a single class while adding + // declaration boilerplate. + bool SaveType(const std::string &defname, const Namespace &ns, + const std::string &classcode, bool needs_includes) const { + if (!classcode.length()) return true; + + std::string code; + code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n"; + + std::string namespace_name = FullNamespace(".", ns); + if (!namespace_name.empty()) { + code += "package " + namespace_name + ";"; + code += "\n\n"; + } + if (needs_includes) { + code += + "import java.nio.*;\nimport java.lang.*;\nimport " + "java.util.*;\nimport com.google.flatbuffers.*;\n"; + if (parser_.opts.gen_nullable) { + code += "\nimport javax.annotation.Nullable;\n"; + } + if (parser_.opts.java_checkerframework) { + code += "\nimport org.checkerframework.dataflow.qual.Pure;\n"; + } + code += "\n@SuppressWarnings(\"unused\")\n"; + } + if (parser_.opts.gen_generated) { + code += "\n@javax.annotation.Generated(value=\"flatc\")\n"; + } + code += classcode; + if (!namespace_name.empty()) code += ""; + auto filename = NamespaceDir(ns) + defname + ".java"; + return SaveFile(filename.c_str(), code, false); + } + + const Namespace *CurrentNameSpace() const { return cur_name_space_; } + + std::string GenNullableAnnotation(const Type &t) const { + return parser_.opts.gen_nullable && + !IsScalar(DestinationType(t, true).base_type) && + t.base_type != BASE_TYPE_VECTOR + ? " @Nullable " + : ""; + } + + std::string GenPureAnnotation(const Type &t) const { + return parser_.opts.java_checkerframework && + !IsScalar(DestinationType(t, true).base_type) + ? " @Pure " + : ""; + } + + std::string GenTypeBasic(const Type &type) const { + // clang-format off + static const char * const java_typename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ + CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #JTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + }; + // clang-format on + + return java_typename[type.base_type]; + } + + std::string GenTypePointer(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "String"; + case BASE_TYPE_VECTOR: return GenTypeGet(type.VectorType()); + case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def); + case BASE_TYPE_UNION: FLATBUFFERS_FALLTHROUGH(); // else fall thru + default: return "Table"; + } + } + + std::string GenTypeGet(const Type &type) const { + return IsScalar(type.base_type) + ? GenTypeBasic(type) + : (IsArray(type) ? GenTypeGet(type.VectorType()) + : GenTypePointer(type)); + } + + // Find the destination type the user wants to receive the value in (e.g. + // one size higher signed types for unsigned serialized values in Java). + Type DestinationType(const Type &type, bool vectorelem) const { + switch (type.base_type) { + // We use int for both uchar/ushort, since that generally means less + // casting than using short for uchar. + case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT); + case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT); + case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG); + case BASE_TYPE_ARRAY: + case BASE_TYPE_VECTOR: + if (vectorelem) return DestinationType(type.VectorType(), vectorelem); + FLATBUFFERS_FALLTHROUGH(); // else fall thru + default: return type; + } + } + + std::string GenOffsetType() const { return "int"; } + + std::string GenOffsetConstruct(const std::string &variable_name) const { + return variable_name; + } + + std::string GenVectorOffsetType() const { return "int"; } + + // Generate destination type name + std::string GenTypeNameDest(const Type &type) const { + return GenTypeGet(DestinationType(type, true)); + } + + // Mask to turn serialized value into destination type value. + std::string DestinationMask(const Type &type, bool vectorelem) const { + switch (type.base_type) { + case BASE_TYPE_UCHAR: return " & 0xFF"; + case BASE_TYPE_USHORT: return " & 0xFFFF"; + case BASE_TYPE_UINT: return " & 0xFFFFFFFFL"; + case BASE_TYPE_VECTOR: + if (vectorelem) return DestinationMask(type.VectorType(), vectorelem); + FLATBUFFERS_FALLTHROUGH(); // else fall thru + default: return ""; + } + } + + // Casts necessary to correctly read serialized data + std::string DestinationCast(const Type &type) const { + if (IsSeries(type)) { + return DestinationCast(type.VectorType()); + } else { + // Cast necessary to correctly read serialized unsigned values. + if (type.base_type == BASE_TYPE_UINT) return "(long)"; + } + return ""; + } + + // Cast statements for mutator method parameters. + // In Java, parameters representing unsigned numbers need to be cast down to + // their respective type. For example, a long holding an unsigned int value + // would be cast down to int before being put onto the buffer. In C#, one cast + // directly cast an Enum to its underlying type, which is essential before + // putting it onto the buffer. + std::string SourceCast(const Type &type, bool castFromDest) const { + if (IsSeries(type)) { + return SourceCast(type.VectorType(), castFromDest); + } else { + if (castFromDest) { + if (type.base_type == BASE_TYPE_UINT) + return "(int)"; + else if (type.base_type == BASE_TYPE_USHORT) + return "(short)"; + else if (type.base_type == BASE_TYPE_UCHAR) + return "(byte)"; + } + } + return ""; + } + + std::string SourceCast(const Type &type) const { + return SourceCast(type, true); + } + + std::string SourceCastBasic(const Type &type, bool castFromDest) const { + return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : ""; + } + + std::string SourceCastBasic(const Type &type) const { + return SourceCastBasic(type, true); + } + + std::string GenEnumDefaultValue(const FieldDef &field) const { + auto &value = field.value; + FLATBUFFERS_ASSERT(value.type.enum_def); + auto &enum_def = *value.type.enum_def; + auto enum_val = enum_def.FindByValue(value.constant); + return enum_val ? (WrapInNameSpace(enum_def) + "." + enum_val->name) + : value.constant; + } + + std::string GenDefaultValue(const FieldDef &field) const { + auto &value = field.value; + auto longSuffix = "L"; + switch (value.type.base_type) { + case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true"; + case BASE_TYPE_ULONG: { + // Converts the ulong into its bits signed equivalent + uint64_t defaultValue = StringToUInt(value.constant.c_str()); + return NumToString(static_cast(defaultValue)) + longSuffix; + } + case BASE_TYPE_UINT: + case BASE_TYPE_LONG: return value.constant + longSuffix; + default: + if (IsFloat(value.type.base_type)) + return JavaFloatGen.GenFloatConstant(field); + else + return value.constant; + } + } + + std::string GenDefaultValueBasic(const FieldDef &field) const { + auto &value = field.value; + if (!IsScalar(value.type.base_type)) { return "0"; } + return GenDefaultValue(field); + } + + void GenEnum(EnumDef &enum_def, std::string *code_ptr) const { + std::string &code = *code_ptr; + if (enum_def.generated) return; + + // Generate enum definitions of the form: + // public static (final) int name = value; + // In Java, we use ints rather than the Enum feature, because we want them + // to map directly to how they're used in C/C++ and file formats. + // That, and Java Enums are expensive, and not universally liked. + GenComment(enum_def.doc_comment, code_ptr, &comment_config); + + if (enum_def.attributes.Lookup("private")) { + // For Java, we leave the enum unmarked to indicate package-private + // For C# we mark the enum as internal + } else { + code += "public "; + } + code += "final class " + enum_def.name; + code += " {\n"; + code += " private " + enum_def.name + "() { }\n"; + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) { + auto &ev = **it; + GenComment(ev.doc_comment, code_ptr, &comment_config, " "); + code += " public static final "; + code += GenTypeBasic(enum_def.underlying_type); + code += " "; + code += ev.name + " = "; + code += enum_def.ToString(ev); + code += ";\n"; + } + + // Generate a generate string table for enum values. + // We do not do that for C# where this functionality is native. + // Problem is, if values are very sparse that could generate really big + // tables. Ideally in that case we generate a map lookup instead, but for + // the moment we simply don't output a table at all. + auto range = enum_def.Distance(); + // Average distance between values above which we consider a table + // "too sparse". Change at will. + static const uint64_t kMaxSparseness = 5; + if (range / static_cast(enum_def.size()) < kMaxSparseness) { + code += "\n public static final String"; + code += "[] names = { "; + auto val = enum_def.Vals().front(); + for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); + ++it) { + auto ev = *it; + for (auto k = enum_def.Distance(val, ev); k > 1; --k) code += "\"\", "; + val = ev; + code += "\"" + (*it)->name + "\", "; + } + code += "};\n\n"; + code += " public static "; + code += "String"; + code += " " + MakeCamel("name", false); + code += "(int e) { return names[e"; + if (enum_def.MinValue()->IsNonZero()) + code += " - " + enum_def.MinValue()->name; + code += "]; }\n"; + } + + // Close the class + code += "}"; + // Java does not need the closing semi-colon on class definitions. + code += ""; + code += "\n\n"; + } + + // Returns the function name that is able to read a value of the given type. + std::string GenGetter(const Type &type) const { + switch (type.base_type) { + case BASE_TYPE_STRING: return "__string"; + case BASE_TYPE_STRUCT: return "__struct"; + case BASE_TYPE_UNION: return "__union"; + case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); + case BASE_TYPE_ARRAY: return GenGetter(type.VectorType()); + default: { + std::string getter = "bb.get"; + if (type.base_type == BASE_TYPE_BOOL) { + getter = "0!=" + getter; + } else if (GenTypeBasic(type) != "byte") { + getter += MakeCamel(GenTypeBasic(type)); + } + return getter; + } + } + } + + // Returns the function name that is able to read a value of the given type. + std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field, + const std::string &data_buffer, + const char *num = nullptr) const { + auto type = key_field->value.type; + auto dest_mask = DestinationMask(type, true); + auto dest_cast = DestinationCast(type); + auto getter = data_buffer + ".get"; + if (GenTypeBasic(type) != "byte") { + getter += MakeCamel(GenTypeBasic(type)); + } + getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")" + + dest_mask; + return getter; + } + + // Direct mutation is only allowed for scalar fields. + // Hence a setter method will only be generated for such fields. + std::string GenSetter(const Type &type) const { + if (IsScalar(type.base_type)) { + std::string setter = "bb.put"; + if (GenTypeBasic(type) != "byte" && type.base_type != BASE_TYPE_BOOL) { + setter += MakeCamel(GenTypeBasic(type)); + } + return setter; + } else { + return ""; + } + } + + // Returns the method name for use with add/put calls. + std::string GenMethod(const Type &type) const { + return IsScalar(type.base_type) ? MakeCamel(GenTypeBasic(type)) + : (IsStruct(type) ? "Struct" : "Offset"); + } + + // Recursively generate arguments for a constructor, to deal with nested + // structs. + void GenStructArgs(const StructDef &struct_def, std::string *code_ptr, + const char *nameprefix, size_t array_count = 0) const { + std::string &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; + const auto array_field = IsArray(field_type); + const auto &type = array_field ? field_type.VectorType() + : DestinationType(field_type, false); + const auto array_cnt = array_field ? (array_count + 1) : array_count; + if (IsStruct(type)) { + // Generate arguments for a struct inside a struct. To ensure names + // don't clash, and to make it obvious these arguments are constructing + // a nested struct, prefix the name with the field name. + GenStructArgs(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), array_cnt); + } else { + code += ", "; + code += GenTypeBasic(type); + for (size_t i = 0; i < array_cnt; i++) code += "[]"; + code += " "; + code += nameprefix; + code += MakeCamel(field.name, false); + } + } + } + + // Recusively generate struct construction statements of the form: + // builder.putType(name); + // and insert manual padding. + void GenStructBody(const StructDef &struct_def, std::string *code_ptr, + const char *nameprefix, size_t index = 0, + bool in_array = false) const { + std::string &code = *code_ptr; + std::string indent((index + 1) * 2, ' '); + code += indent + " builder.prep("; + code += NumToString(struct_def.minalign) + ", "; + code += NumToString(struct_def.bytesize) + ");\n"; + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); ++it) { + auto &field = **it; + const auto &field_type = field.value.type; + if (field.padding) { + code += indent + " builder.pad("; + code += NumToString(field.padding) + ");\n"; + } + if (IsStruct(field_type)) { + GenStructBody(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), index, + in_array); + } else { + const auto &type = + IsArray(field_type) ? field_type.VectorType() : field_type; + const auto index_var = "_idx" + NumToString(index); + if (IsArray(field_type)) { + code += indent + " for (int " + index_var + " = "; + code += NumToString(field_type.fixed_length); + code += "; " + index_var + " > 0; " + index_var + "--) {\n"; + in_array = true; + } + if (IsStruct(type)) { + GenStructBody(*field_type.struct_def, code_ptr, + (nameprefix + (field.name + "_")).c_str(), index + 1, + in_array); + } else { + code += IsArray(field_type) ? " " : ""; + code += indent + " builder.put"; + code += GenMethod(type) + "("; + code += SourceCast(type); + auto argname = nameprefix + MakeCamel(field.name, false); + code += argname; + size_t array_cnt = index + (IsArray(field_type) ? 1 : 0); + for (size_t i = 0; in_array && i < array_cnt; i++) { + code += "[_idx" + NumToString(i) + "-1]"; + } + code += ");\n"; + } + if (IsArray(field_type)) { code += indent + " }\n"; } + } + } + } + + std::string GenByteBufferLength(const char *bb_name) const { + std::string bb_len = bb_name; + bb_len += ".capacity()"; + return bb_len; + } + + std::string GenOffsetGetter(flatbuffers::FieldDef *key_field, + const char *num = nullptr) const { + std::string key_offset = ""; + key_offset += "__offset(" + NumToString(key_field->value.offset) + ", "; + if (num) { + key_offset += num; + key_offset += ", _bb)"; + } else { + key_offset += GenByteBufferLength("bb"); + key_offset += " - tableOffset, bb)"; + } + return key_offset; + } + + std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) const { + std::string key_getter = " "; + key_getter += "int tableOffset = "; + key_getter += "__indirect(vectorLocation + 4 * (start + middle)"; + key_getter += ", bb);\n "; + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + key_getter += "int comp = "; + key_getter += "compareStrings("; + key_getter += GenOffsetGetter(key_field); + key_getter += ", byteKey, bb);\n"; + } else { + auto get_val = GenGetterForLookupByKey(key_field, "bb"); + key_getter += GenTypeNameDest(key_field->value.type) + " val = "; + key_getter += get_val + ";\n"; + key_getter += " int comp = val > key ? 1 : val < key ? -1 : 0;\n"; + } + return key_getter; + } + + std::string GenKeyGetter(flatbuffers::FieldDef *key_field) const { + std::string key_getter = ""; + auto data_buffer = "_bb"; + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + key_getter += " return "; + key_getter += ""; + key_getter += "compareStrings("; + key_getter += GenOffsetGetter(key_field, "o1") + ", "; + key_getter += GenOffsetGetter(key_field, "o2") + ", " + data_buffer + ")"; + key_getter += ";"; + } else { + auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1"); + key_getter += + "\n " + GenTypeNameDest(key_field->value.type) + " val_1 = "; + key_getter += + field_getter + ";\n " + GenTypeNameDest(key_field->value.type); + key_getter += " val_2 = "; + field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2"); + key_getter += field_getter + ";\n"; + key_getter += " return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n "; + } + return key_getter; + } + + void GenStruct(StructDef &struct_def, std::string *code_ptr) const { + if (struct_def.generated) return; + std::string &code = *code_ptr; + + // Generate a struct accessor class, with methods of the form: + // public type name() { return bb.getType(i + offset); } + // or for tables of the form: + // public type name() { + // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default; + // } + GenComment(struct_def.doc_comment, code_ptr, &comment_config); + if (struct_def.attributes.Lookup("private")) { + // For Java, we leave the struct unmarked to indicate package-private + // For C# we mark the struct as internal + } else { + code += "public "; + } + code += "final "; + code += "class " + struct_def.name; + code += " extends "; + code += struct_def.fixed ? "Struct" : "Table"; + code += " {\n"; + + if (!struct_def.fixed) { + // Generate verson check method. + // Force compile time error if not using the same version runtime. + code += " public static void ValidateVersion() {"; + code += " Constants."; + code += "FLATBUFFERS_1_11_1(); "; + code += "}\n"; + + // Generate a special accessor for the table that when used as the root + // of a FlatBuffer + std::string method_name = + "getRootAs" + struct_def.name; + std::string method_signature = + " public static " + struct_def.name + " " + method_name; + + // create convenience method that doesn't require an existing object + code += method_signature + "(ByteBuffer _bb) "; + code += "{ return " + method_name + "(_bb, new " + struct_def.name + + "()); }\n"; + + // create method that allows object reuse + code += + method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { "; + code += "_bb.order(ByteOrder.LITTLE_ENDIAN); "; + code += "return (obj.__assign(_bb.getInt(_bb."; + code += "position()"; + code += ") + _bb."; + code += "position()"; + code += ", _bb)); }\n"; + if (parser_.root_struct_def_ == &struct_def) { + if (parser_.file_identifier_.length()) { + // Check if a buffer has the identifier. + code += " public static "; + code += "boolean " + struct_def.name; + code += "BufferHasIdentifier(ByteBuffer _bb) { return "; + code += "__has_identifier(_bb, \""; + code += parser_.file_identifier_; + code += "\"); }\n"; + } + } + } + // Generate the __init method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + code += " public void __init(int _i, ByteBuffer _bb) "; + code += "{ "; + code += "__reset(_i, _bb); "; + code += "}\n"; + code += + " public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) "; + code += "{ __init(_i, _bb); return this; }\n\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + GenComment(field.doc_comment, code_ptr, &comment_config, " "); + std::string type_name = GenTypeGet(field.value.type); + std::string type_name_dest = GenTypeNameDest(field.value.type); + std::string conditional_cast = ""; + std::string optional = ""; + std::string dest_mask = DestinationMask(field.value.type, true); + std::string dest_cast = DestinationCast(field.value.type); + std::string src_cast = SourceCast(field.value.type); + std::string method_start = + " public " + + (field.required ? "" : GenNullableAnnotation(field.value.type)) + + GenPureAnnotation(field.value.type) + type_name_dest + optional + + " " + MakeCamel(field.name, false); + std::string obj = "obj"; + + // Most field accessors need to retrieve and test the field offset first, + // this is the prefix code for that: + auto offset_prefix = + IsArray(field.value.type) + ? " { return " + : (" { int o = __offset(" + NumToString(field.value.offset) + + "); return o != 0 ? "); + // Generate the accessors that don't do object reuse. + if (field.value.type.base_type == BASE_TYPE_STRUCT) { + // Calls the accessor that takes an accessor object with a new object. + code += method_start + "() { return "; + code += MakeCamel(field.name, false); + code += "(new "; + code += type_name + "()); }\n"; + } else if (field.value.type.base_type == BASE_TYPE_VECTOR && + field.value.type.element == BASE_TYPE_STRUCT) { + // Accessors for vectors of structs also take accessor objects, this + // generates a variant without that argument. + code += method_start + "(int j) { return "; + code += MakeCamel(field.name, false); + code += "(new " + type_name + "(), j); }\n"; + } + + std::string getter = dest_cast + GenGetter(field.value.type); + code += method_start; + std::string default_cast = ""; + std::string member_suffix = "; "; + if (IsScalar(field.value.type.base_type)) { + code += "()"; + member_suffix += ""; + if (struct_def.fixed) { + code += " { return " + getter; + code += "(bb_pos + "; + code += NumToString(field.value.offset) + ")"; + code += dest_mask; + } else { + code += offset_prefix + getter; + code += "(o + bb_pos)" + dest_mask; + code += " : " + default_cast; + code += GenDefaultValue(field); + } + } else { + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: + code += "(" + type_name + " obj)"; + if (struct_def.fixed) { + code += " { return " + obj + ".__assign("; + code += "bb_pos + " + NumToString(field.value.offset) + ", "; + code += "bb)"; + } else { + code += offset_prefix + conditional_cast; + code += obj + ".__assign("; + code += field.value.type.struct_def->fixed + ? "o + bb_pos" + : "__indirect(o + bb_pos)"; + code += ", bb) : null"; + } + break; + case BASE_TYPE_STRING: + code += "()"; + member_suffix += ""; + code += offset_prefix + getter + "(o + "; + code += "bb_pos) : null"; + break; + case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru + case BASE_TYPE_VECTOR: { + auto vectortype = field.value.type.VectorType(); + code += "("; + if (vectortype.base_type == BASE_TYPE_STRUCT) { + code += type_name + " obj, "; + getter = obj + ".__assign"; + } else if (vectortype.base_type == BASE_TYPE_UNION) { + code += type_name + " obj, "; + } + code += "int j)"; + const auto body = offset_prefix + conditional_cast + getter + "("; + if (vectortype.base_type == BASE_TYPE_UNION) { + code += body + "obj, "; + } else { + code += body; + } + std::string index; + if (IsArray(field.value.type)) { + index += "bb_pos + " + NumToString(field.value.offset) + " + "; + } else { + index += "__vector(o) + "; + } + index += "j * " + NumToString(InlineSize(vectortype)); + if (vectortype.base_type == BASE_TYPE_STRUCT) { + code += vectortype.struct_def->fixed + ? index + : "__indirect(" + index + ")"; + code += ", bb"; + } else { + code += index; + } + code += ")" + dest_mask; + if (!IsArray(field.value.type)) { + code += " : "; + code += + field.value.type.element == BASE_TYPE_BOOL + ? "false" + : (IsScalar(field.value.type.element) ? default_cast + "0" + : "null"); + } + + break; + } + case BASE_TYPE_UNION: + code += "(" + type_name + " obj)" + offset_prefix + getter; + code += "(obj, o + bb_pos) : null"; + break; + default: FLATBUFFERS_ASSERT(0); + } + } + code += member_suffix; + code += "}\n"; + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + code += " public int " + MakeCamel(field.name, false); + code += "Length"; + code += "()"; + code += offset_prefix; + code += "__vector_len(o) : 0; "; + code += ""; + code += "}\n"; + // See if we should generate a by-key accessor. + if (field.value.type.element == BASE_TYPE_STRUCT && + !field.value.type.struct_def->fixed) { + auto &sd = *field.value.type.struct_def; + auto &fields = sd.fields.vec; + for (auto kit = fields.begin(); kit != fields.end(); ++kit) { + auto &key_field = **kit; + if (key_field.key) { + auto qualified_name = WrapInNameSpace(sd); + code += " public " + qualified_name + " "; + code += MakeCamel(field.name, false) + "ByKey("; + code += GenTypeNameDest(key_field.value.type) + " key)"; + code += offset_prefix; + code += qualified_name + ".__lookup_by_key("; + code += "null, "; + code += "__vector(o), key, "; + code += "bb) : null; "; + code += "}\n"; + code += " public " + qualified_name + " "; + code += MakeCamel(field.name, false) + "ByKey("; + code += qualified_name + " obj, "; + code += GenTypeNameDest(key_field.value.type) + " key)"; + code += offset_prefix; + code += qualified_name + ".__lookup_by_key(obj, "; + code += "__vector(o), key, "; + code += "bb) : null; "; + code += "}\n"; + break; + } + } + } + } + // Generate the accessors for vector of structs with vector access object + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + std::string vector_type_name; + const auto &element_base_type = field.value.type.VectorType().base_type; + if (IsScalar(element_base_type)) { + vector_type_name = MakeCamel(type_name, true) + "Vector"; + } else if (element_base_type == BASE_TYPE_STRING) { + vector_type_name = "StringVector"; + } else if (element_base_type == BASE_TYPE_UNION) { + vector_type_name = "UnionVector"; + } else { + vector_type_name = type_name + ".Vector"; + } + auto vector_method_start = GenNullableAnnotation(field.value.type) + + " public " + vector_type_name + optional + + " " + MakeCamel(field.name, false) + + "Vector"; + code += vector_method_start + "() { return "; + code += MakeCamel(field.name, false) + "Vector"; + code += "(new " + vector_type_name + "()); }\n"; + code += vector_method_start + "(" + vector_type_name + " obj)"; + code += offset_prefix + conditional_cast + obj + ".__assign("; + code += "__vector(o), "; + if (!IsScalar(element_base_type)) { + auto vectortype = field.value.type.VectorType(); + code += NumToString(InlineSize(vectortype)) + ", "; + } + code += "bb) : null" + member_suffix + "}\n"; + } + // Generate a ByteBuffer accessor for strings & vectors of scalars. + if ((field.value.type.base_type == BASE_TYPE_VECTOR && + IsScalar(field.value.type.VectorType().base_type)) || + field.value.type.base_type == BASE_TYPE_STRING) { + code += " public ByteBuffer "; + code += MakeCamel(field.name, false); + code += "AsByteBuffer() { return "; + code += "__vector_as_bytebuffer("; + code += NumToString(field.value.offset) + ", "; + code += NumToString(field.value.type.base_type == BASE_TYPE_STRING + ? 1 + : InlineSize(field.value.type.VectorType())); + code += "); }\n"; + code += " public ByteBuffer "; + code += MakeCamel(field.name, false); + code += "InByteBuffer(ByteBuffer _bb) { return "; + code += "__vector_in_bytebuffer(_bb, "; + code += NumToString(field.value.offset) + ", "; + code += NumToString(field.value.type.base_type == BASE_TYPE_STRING + ? 1 + : InlineSize(field.value.type.VectorType())); + code += "); }\n"; + } + // generate object accessors if is nested_flatbuffer + if (field.nested_flatbuffer) { + auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer); + auto nested_method_name = + MakeCamel(field.name, false) + "As" + field.nested_flatbuffer->name; + auto get_nested_method_name = nested_method_name; + code += " public " + nested_type_name + " "; + code += nested_method_name + "() { return "; + code += + get_nested_method_name + "(new " + nested_type_name + "()); }\n"; + code += " public " + nested_type_name + " "; + code += get_nested_method_name + "("; + code += nested_type_name + " obj"; + code += ") { int o = __offset("; + code += NumToString(field.value.offset) + "); "; + code += "return o != 0 ? " + conditional_cast + obj + ".__assign("; + code += ""; + code += "__indirect(__vector(o)), "; + code += "bb) : null; }\n"; + } + // Generate mutators for scalar fields or vectors of scalars. + if (parser_.opts.mutable_buffer) { + auto is_series = (IsSeries(field.value.type)); + const auto &underlying_type = + is_series ? field.value.type.VectorType() : field.value.type; + // Boolean parameters have to be explicitly converted to byte + // representation. + auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL + ? "(byte)(" + field.name + " ? 1 : 0)" + : field.name; + auto mutator_prefix = MakeCamel("mutate", false); + // A vector mutator also needs the index of the vector element it should + // mutate. + auto mutator_params = (is_series ? "(int j, " : "(") + + GenTypeNameDest(underlying_type) + " " + + field.name + ") { "; + auto setter_index = + is_series + ? (IsArray(field.value.type) + ? "bb_pos + " + NumToString(field.value.offset) + : "__vector(o)") + + +" + j * " + NumToString(InlineSize(underlying_type)) + : (struct_def.fixed + ? "bb_pos + " + NumToString(field.value.offset) + : "o + bb_pos"); + if (IsScalar(underlying_type.base_type) && !IsUnion(field.value.type)) { + code += " public "; + code += struct_def.fixed ? "void " : "boolean "; + code += mutator_prefix + MakeCamel(field.name, true); + code += mutator_params; + if (struct_def.fixed) { + code += GenSetter(underlying_type) + "(" + setter_index + ", "; + code += src_cast + setter_parameter + "); }\n"; + } else { + code += "int o = __offset("; + code += NumToString(field.value.offset) + ");"; + code += " if (o != 0) { " + GenSetter(underlying_type); + code += "(" + setter_index + ", " + src_cast + setter_parameter + + "); return true; } else { return false; } }\n"; + } + } + } + if (parser_.opts.java_primitive_has_method && + IsScalar(field.value.type.base_type) && !struct_def.fixed) { + auto vt_offset_constant = " public static final int VT_" + + MakeScreamingCamel(field.name) + " = " + + NumToString(field.value.offset) + ";"; + + code += vt_offset_constant; + code += "\n"; + } + } + code += "\n"; + flatbuffers::FieldDef *key_field = nullptr; + if (struct_def.fixed) { + // create a struct constructor function + code += " public static " + GenOffsetType() + " "; + code += "create"; + code += struct_def.name + "(FlatBufferBuilder builder"; + GenStructArgs(struct_def, code_ptr, ""); + code += ") {\n"; + GenStructBody(struct_def, code_ptr, ""); + code += " return "; + code += GenOffsetConstruct("builder." + std::string("offset()")); + code += ";\n }\n"; + } else { + // Generate a method that creates a table in one go. This is only possible + // when the table has no struct fields, since those have to be created + // inline, and there's no way to do so in Java. + bool has_no_struct_fields = true; + int num_fields = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (IsStruct(field.value.type)) { + has_no_struct_fields = false; + } else { + num_fields++; + } + } + // 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) { + // Generate a table constructor of the form: + // public static int createName(FlatBufferBuilder builder, args...) + code += " public static " + GenOffsetType() + " "; + code += "create" + struct_def.name; + code += "(FlatBufferBuilder builder"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (field.deprecated) continue; + code += ",\n "; + code += GenTypeBasic(DestinationType(field.value.type, false)); + code += " "; + code += field.name; + if (!IsScalar(field.value.type.base_type)) code += "Offset"; + } + code += ") {\n builder."; + code += "startTable("; + code += NumToString(struct_def.fields.vec.size()) + ");\n"; + for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; + size; size /= 2) { + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); ++it) { + auto &field = **it; + if (!field.deprecated && + (!struct_def.sortbysize || + size == SizeOf(field.value.type.base_type))) { + code += " " + struct_def.name + "."; + code += "add"; + code += MakeCamel(field.name) + "(builder, " + field.name; + if (!IsScalar(field.value.type.base_type)) code += "Offset"; + code += ");\n"; + } + } + } + code += " return " + struct_def.name + "."; + code += "end" + struct_def.name; + code += "(builder);\n }\n\n"; + } + // Generate a set of static methods that allow table construction, + // of the form: + // public static void addName(FlatBufferBuilder builder, short name) + // { builder.addShort(id, name, default); } + // Unlike the Create function, these always work. + code += " public static void start"; + code += struct_def.name; + code += "(FlatBufferBuilder builder) { builder."; + code += "startTable("; + code += NumToString(struct_def.fields.vec.size()) + "); }\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.key) key_field = &field; + code += " public static void add"; + code += MakeCamel(field.name); + code += "(FlatBufferBuilder builder, "; + code += GenTypeBasic(DestinationType(field.value.type, false)); + auto argname = MakeCamel(field.name, false); + if (!IsScalar(field.value.type.base_type)) argname += "Offset"; + code += " " + argname + ") { builder.add"; + code += GenMethod(field.value.type) + "("; + code += NumToString(it - struct_def.fields.vec.begin()) + ", "; + code += SourceCastBasic(field.value.type); + code += argname; + code += ", "; + code += SourceCastBasic(field.value.type); + code += GenDefaultValue(field); + code += "); }\n"; + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + auto vector_type = field.value.type.VectorType(); + auto alignment = InlineAlignment(vector_type); + auto elem_size = InlineSize(vector_type); + if (!IsStruct(vector_type)) { + // generate a method to create a vector from a java array. + if ((vector_type.base_type == BASE_TYPE_CHAR || + vector_type.base_type == BASE_TYPE_UCHAR)) { + // Handle byte[] and ByteBuffers separately for Java + code += " public static " + GenVectorOffsetType() + " "; + code += "create"; + code += MakeCamel(field.name); + code += "Vector(FlatBufferBuilder builder, byte[] data) "; + code += "{ return builder.createByteVector(data); }\n"; + + code += " public static " + GenVectorOffsetType() + " "; + code += "create"; + code += MakeCamel(field.name); + code += "Vector(FlatBufferBuilder builder, ByteBuffer data) "; + code += "{ return builder.createByteVector(data); }\n"; + } else { + code += " public static " + GenVectorOffsetType() + " "; + code += "create"; + code += MakeCamel(field.name); + code += "Vector(FlatBufferBuilder builder, "; + code += GenTypeBasic(vector_type) + "[] data) "; + code += "{ builder.startVector("; + code += NumToString(elem_size); + code += ", data.length, "; + code += NumToString(alignment); + code += "); for (int i = data."; + code += "length - 1; i >= 0; i--) builder."; + code += "add"; + code += GenMethod(vector_type); + code += "("; + code += SourceCastBasic(vector_type, false); + code += "data[i]"; + code += "); return "; + code += "builder.endVector(); }\n"; + } + } + // Generate a method to start a vector, data to be added manually + // after. + code += " public static void start"; + code += MakeCamel(field.name); + code += "Vector(FlatBufferBuilder builder, int numElems) "; + code += "{ builder.startVector("; + code += NumToString(elem_size); + code += ", numElems, " + NumToString(alignment); + code += "); }\n"; + } + } + code += " public static " + GenOffsetType() + " "; + code += "end" + struct_def.name; + code += "(FlatBufferBuilder builder) {\n int o = builder."; + code += "endTable();\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated && field.required) { + code += " builder.required(o, "; + code += NumToString(field.value.offset); + code += "); // " + field.name + "\n"; + } + } + code += " return " + GenOffsetConstruct("o") + ";\n }\n"; + if (parser_.root_struct_def_ == &struct_def) { + std::string size_prefix[] = { "", "SizePrefixed" }; + for (int i = 0; i < 2; ++i) { + code += " public static void "; + code += "finish" + size_prefix[i] + struct_def.name; + code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(); + code += " offset) {"; + code += " builder.finish" + size_prefix[i] + + "(offset"; + + if (parser_.file_identifier_.length()) + code += ", \"" + parser_.file_identifier_ + "\""; + code += "); }\n"; + } + } + } + // Only generate key compare function for table, + // because `key_field` is not set for struct + if (struct_def.has_key && !struct_def.fixed) { + FLATBUFFERS_ASSERT(key_field); + code += "\n @Override\n protected int keysCompare("; + code += "Integer o1, Integer o2, ByteBuffer _bb) {"; + code += GenKeyGetter(key_field); + code += " }\n"; + + code += "\n public static " + struct_def.name; + code += " __lookup_by_key("; + code += struct_def.name + " obj, "; + code += "int vectorLocation, "; + code += GenTypeNameDest(key_field->value.type); + code += " key, ByteBuffer bb) {\n"; + if (key_field->value.type.base_type == BASE_TYPE_STRING) { + code += " byte[] byteKey = "; + code += "key.getBytes(Table.UTF8_CHARSET.get());\n"; + } + code += " int span = "; + code += "bb.getInt(vectorLocation - 4);\n"; + code += " int start = 0;\n"; + code += " while (span != 0) {\n"; + code += " int middle = span / 2;\n"; + code += GenLookupKeyGetter(key_field); + code += " if (comp > 0) {\n"; + code += " span = middle;\n"; + code += " } else if (comp < 0) {\n"; + code += " middle++;\n"; + code += " start += middle;\n"; + code += " span -= middle;\n"; + code += " } else {\n"; + code += " return "; + code += "(obj == null ? new " + struct_def.name + "() : obj)"; + code += ".__assign(tableOffset, bb);\n"; + code += " }\n }\n"; + code += " return null;\n"; + code += " }\n"; + } + GenVectorAccessObject(struct_def, code_ptr); + code += "}"; + code += "\n\n"; + } + + void GenVectorAccessObject(StructDef &struct_def, + std::string *code_ptr) const { + auto &code = *code_ptr; + // Generate a vector of structs accessor class. + code += "\n"; + code += " "; + if (!struct_def.attributes.Lookup("private")) code += "public "; + code += "static "; + code += "final "; + code += "class Vector extends "; + code += "BaseVector {\n"; + + // Generate the __assign method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + std::string method_indent = " "; + code += method_indent + "public Vector "; + code += "__assign(int _vector, int _element_size, ByteBuffer _bb) { "; + code += "__reset(_vector, _element_size, _bb); return this; }\n\n"; + + auto type_name = struct_def.name; + auto method_start = + method_indent + "public " + type_name + " get"; + // Generate the accessors that don't do object reuse. + code += method_start + "(int j) { return get"; + code += "(new " + type_name + "(), j); }\n"; + code += method_start + "(" + type_name + " obj, int j) { "; + code += " return obj.__assign("; + std::string index = "__element(j)"; + code += struct_def.fixed ? index : "__indirect(" + index + ", bb)"; + code += ", bb); }\n"; + // See if we should generate a by-key accessor. + if (!struct_def.fixed) { + auto &fields = struct_def.fields.vec; + for (auto kit = fields.begin(); kit != fields.end(); ++kit) { + auto &key_field = **kit; + if (key_field.key) { + auto nullable_annotation = + parser_.opts.gen_nullable ? "@Nullable " : ""; + code += method_indent + nullable_annotation; + code += "public " + type_name + " "; + code += "getByKey("; + code += GenTypeNameDest(key_field.value.type) + " key) { "; + code += " return __lookup_by_key(null, "; + code += "__vector(), key, "; + code += "bb); "; + code += "}\n"; + code += method_indent + nullable_annotation; + code += "public " + type_name + " "; + code += "getByKey("; + code += type_name + " obj, "; + code += GenTypeNameDest(key_field.value.type) + " key) { "; + code += " return __lookup_by_key(obj, "; + code += "__vector(), key, "; + code += "bb); "; + code += "}\n"; + break; + } + } + } + code += " }\n"; + } + + // This tracks the current namespace used to determine if a type need to be + // prefixed by its namespace + const Namespace *cur_name_space_; +}; +} // namespace java + +bool GenerateJava(const Parser &parser, const std::string &path, + const std::string &file_name) { + java::JavaGenerator generator(parser, path, file_name); + return generator.generate(); +} + +} // namespace flatbuffers From dda095023d9f2811c22519654f20e4027d301e9c Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Thu, 14 Nov 2019 15:44:18 -0800 Subject: [PATCH 18/28] [C++] Adds basic schema evolution tests (#5611) * Added basic schema evolution tests * Add BUILD targets for evolution tests. Added to test/generate_code scripts * Use vector.front() instead of vector.data() * Added --scoped-enums option for evolution test --- BUILD | 6 + tests/evolution_test/evolution_v1.fbs | 39 ++ tests/evolution_test/evolution_v1.json | 26 + tests/evolution_test/evolution_v1_generated.h | 453 ++++++++++++++ tests/evolution_test/evolution_v2.fbs | 50 ++ tests/evolution_test/evolution_v2.json | 34 ++ tests/evolution_test/evolution_v2_generated.h | 578 ++++++++++++++++++ tests/generate_code.bat | 1 + tests/generate_code.sh | 1 + tests/test.cpp | 73 +++ 10 files changed, 1261 insertions(+) create mode 100644 tests/evolution_test/evolution_v1.fbs create mode 100644 tests/evolution_test/evolution_v1.json create mode 100644 tests/evolution_test/evolution_v1_generated.h create mode 100644 tests/evolution_test/evolution_v2.fbs create mode 100644 tests/evolution_test/evolution_v2.json create mode 100644 tests/evolution_test/evolution_v2_generated.h diff --git a/BUILD b/BUILD index 210e104ed..b69760238 100644 --- a/BUILD +++ b/BUILD @@ -139,6 +139,8 @@ cc_test( "src/idl_parser.cpp", "src/reflection.cpp", "src/util.cpp", + "tests/evolution_test/evolution_v1_generated.h", + "tests/evolution_test/evolution_v2_generated.h", "tests/namespace_test/namespace_test1_generated.h", "tests/namespace_test/namespace_test2_generated.h", "tests/native_type_test_impl.cpp", @@ -159,6 +161,10 @@ cc_test( ":tests/arrays_test.bfbs", ":tests/arrays_test.fbs", ":tests/arrays_test.golden", + ":tests/evolution_test/evolution_v1.fbs", + ":tests/evolution_test/evolution_v1.json", + ":tests/evolution_test/evolution_v2.fbs", + ":tests/evolution_test/evolution_v2.json", ":tests/include_test/include_test1.fbs", ":tests/include_test/sub/include_test2.fbs", ":tests/monster_extra.fbs", diff --git a/tests/evolution_test/evolution_v1.fbs b/tests/evolution_test/evolution_v1.fbs new file mode 100644 index 000000000..2576c8791 --- /dev/null +++ b/tests/evolution_test/evolution_v1.fbs @@ -0,0 +1,39 @@ +namespace Evolution.V1; + +table TableA { + a:float; + b:int; +} + +table TableB { + a:int; +} + +enum Enum : byte { + King, + Queen +} + +union Union { + TableA, + TableB +} + +struct Struct { + a:int; + b:double; +} + +table Root { + a:int; + b:bool; + c:Union; + d:Enum; + e:TableA; + f:Struct; + g:[int]; + h:[TableB]; + i:int = 1234; +} + +root_type Root; \ No newline at end of file diff --git a/tests/evolution_test/evolution_v1.json b/tests/evolution_test/evolution_v1.json new file mode 100644 index 000000000..8b4b35222 --- /dev/null +++ b/tests/evolution_test/evolution_v1.json @@ -0,0 +1,26 @@ +{ + "a": 42, + "b": true, + "c_type": "TableB", + "c": { + "a": 15 + }, + "d": "King", + "e": { + "a": 3.1452, + "b": 325 + }, + "f":{ + "a": 16, + "b": 243.980943 + }, + "g": [ 7, 8, 9], + "h": [ + { + "a": 212 + }, + { + "a": 459 + } + ] +} \ No newline at end of file diff --git a/tests/evolution_test/evolution_v1_generated.h b/tests/evolution_test/evolution_v1_generated.h new file mode 100644 index 000000000..1d447ffc1 --- /dev/null +++ b/tests/evolution_test/evolution_v1_generated.h @@ -0,0 +1,453 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_EVOLUTIONV1_EVOLUTION_V1_H_ +#define FLATBUFFERS_GENERATED_EVOLUTIONV1_EVOLUTION_V1_H_ + +#include "flatbuffers/flatbuffers.h" + +namespace Evolution { +namespace V1 { + +struct TableA; + +struct TableB; + +struct Struct; + +struct Root; + +enum class Enum : int8_t { + King = 0, + Queen = 1, + MIN = King, + MAX = Queen +}; + +inline const Enum (&EnumValuesEnum())[2] { + static const Enum values[] = { + Enum::King, + Enum::Queen + }; + return values; +} + +inline const char * const *EnumNamesEnum() { + static const char * const names[3] = { + "King", + "Queen", + nullptr + }; + return names; +} + +inline const char *EnumNameEnum(Enum e) { + if (e < Enum::King || e > Enum::Queen) return ""; + const size_t index = static_cast(e); + return EnumNamesEnum()[index]; +} + +enum class Union : uint8_t { + NONE = 0, + TableA = 1, + TableB = 2, + MIN = NONE, + MAX = TableB +}; + +inline const Union (&EnumValuesUnion())[3] { + static const Union values[] = { + Union::NONE, + Union::TableA, + Union::TableB + }; + return values; +} + +inline const char * const *EnumNamesUnion() { + static const char * const names[4] = { + "NONE", + "TableA", + "TableB", + nullptr + }; + return names; +} + +inline const char *EnumNameUnion(Union e) { + if (e < Union::NONE || e > Union::TableB) return ""; + const size_t index = static_cast(e); + return EnumNamesUnion()[index]; +} + +template struct UnionTraits { + static const Union enum_value = Union::NONE; +}; + +template<> struct UnionTraits { + static const Union enum_value = Union::TableA; +}; + +template<> struct UnionTraits { + static const Union enum_value = Union::TableB; +}; + +bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type); +bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Struct FLATBUFFERS_FINAL_CLASS { + private: + int32_t a_; + int32_t padding0__; + double b_; + + public: + Struct() { + memset(static_cast(this), 0, sizeof(Struct)); + } + Struct(int32_t _a, double _b) + : a_(flatbuffers::EndianScalar(_a)), + padding0__(0), + b_(flatbuffers::EndianScalar(_b)) { + (void)padding0__; + } + int32_t a() const { + return flatbuffers::EndianScalar(a_); + } + double b() const { + return flatbuffers::EndianScalar(b_); + } +}; +FLATBUFFERS_STRUCT_END(Struct, 16); + +struct TableA FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4, + VT_B = 6 + }; + float a() const { + return GetField(VT_A, 0.0f); + } + int32_t b() const { + return GetField(VT_B, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_A) && + VerifyField(verifier, VT_B) && + verifier.EndTable(); + } +}; + +struct TableABuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_a(float a) { + fbb_.AddElement(TableA::VT_A, a, 0.0f); + } + void add_b(int32_t b) { + fbb_.AddElement(TableA::VT_B, b, 0); + } + explicit TableABuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + TableABuilder &operator=(const TableABuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTableA( + flatbuffers::FlatBufferBuilder &_fbb, + float a = 0.0f, + int32_t b = 0) { + TableABuilder builder_(_fbb); + builder_.add_b(b); + builder_.add_a(a); + return builder_.Finish(); +} + +struct TableB FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4 + }; + int32_t a() const { + return GetField(VT_A, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_A) && + verifier.EndTable(); + } +}; + +struct TableBBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_a(int32_t a) { + fbb_.AddElement(TableB::VT_A, a, 0); + } + explicit TableBBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + TableBBuilder &operator=(const TableBBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTableB( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t a = 0) { + TableBBuilder builder_(_fbb); + builder_.add_a(a); + return builder_.Finish(); +} + +struct Root FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4, + VT_B = 6, + VT_C_TYPE = 8, + VT_C = 10, + VT_D = 12, + VT_E = 14, + VT_F = 16, + VT_G = 18, + VT_H = 20, + VT_I = 22 + }; + int32_t a() const { + return GetField(VT_A, 0); + } + bool b() const { + return GetField(VT_B, 0) != 0; + } + Evolution::V1::Union c_type() const { + return static_cast(GetField(VT_C_TYPE, 0)); + } + const void *c() const { + return GetPointer(VT_C); + } + template const T *c_as() const; + const Evolution::V1::TableA *c_as_TableA() const { + return c_type() == Evolution::V1::Union::TableA ? static_cast(c()) : nullptr; + } + const Evolution::V1::TableB *c_as_TableB() const { + return c_type() == Evolution::V1::Union::TableB ? static_cast(c()) : nullptr; + } + Evolution::V1::Enum d() const { + return static_cast(GetField(VT_D, 0)); + } + const Evolution::V1::TableA *e() const { + return GetPointer(VT_E); + } + const Evolution::V1::Struct *f() const { + return GetStruct(VT_F); + } + const flatbuffers::Vector *g() const { + return GetPointer *>(VT_G); + } + const flatbuffers::Vector> *h() const { + return GetPointer> *>(VT_H); + } + int32_t i() const { + return GetField(VT_I, 1234); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_A) && + VerifyField(verifier, VT_B) && + VerifyField(verifier, VT_C_TYPE) && + VerifyOffset(verifier, VT_C) && + VerifyUnion(verifier, c(), c_type()) && + VerifyField(verifier, VT_D) && + VerifyOffset(verifier, VT_E) && + verifier.VerifyTable(e()) && + VerifyField(verifier, VT_F) && + VerifyOffset(verifier, VT_G) && + verifier.VerifyVector(g()) && + VerifyOffset(verifier, VT_H) && + verifier.VerifyVector(h()) && + verifier.VerifyVectorOfTables(h()) && + VerifyField(verifier, VT_I) && + verifier.EndTable(); + } +}; + +template<> inline const Evolution::V1::TableA *Root::c_as() const { + return c_as_TableA(); +} + +template<> inline const Evolution::V1::TableB *Root::c_as() const { + return c_as_TableB(); +} + +struct RootBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_a(int32_t a) { + fbb_.AddElement(Root::VT_A, a, 0); + } + void add_b(bool b) { + fbb_.AddElement(Root::VT_B, static_cast(b), 0); + } + void add_c_type(Evolution::V1::Union c_type) { + fbb_.AddElement(Root::VT_C_TYPE, static_cast(c_type), 0); + } + void add_c(flatbuffers::Offset c) { + fbb_.AddOffset(Root::VT_C, c); + } + void add_d(Evolution::V1::Enum d) { + fbb_.AddElement(Root::VT_D, static_cast(d), 0); + } + void add_e(flatbuffers::Offset e) { + fbb_.AddOffset(Root::VT_E, e); + } + void add_f(const Evolution::V1::Struct *f) { + fbb_.AddStruct(Root::VT_F, f); + } + void add_g(flatbuffers::Offset> g) { + fbb_.AddOffset(Root::VT_G, g); + } + void add_h(flatbuffers::Offset>> h) { + fbb_.AddOffset(Root::VT_H, h); + } + void add_i(int32_t i) { + fbb_.AddElement(Root::VT_I, i, 1234); + } + explicit RootBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + RootBuilder &operator=(const RootBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRoot( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t a = 0, + bool b = false, + Evolution::V1::Union c_type = Evolution::V1::Union::NONE, + flatbuffers::Offset c = 0, + Evolution::V1::Enum d = Evolution::V1::Enum::King, + flatbuffers::Offset e = 0, + const Evolution::V1::Struct *f = 0, + flatbuffers::Offset> g = 0, + flatbuffers::Offset>> h = 0, + int32_t i = 1234) { + RootBuilder builder_(_fbb); + builder_.add_i(i); + builder_.add_h(h); + builder_.add_g(g); + builder_.add_f(f); + builder_.add_e(e); + builder_.add_c(c); + builder_.add_a(a); + builder_.add_d(d); + builder_.add_c_type(c_type); + builder_.add_b(b); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateRootDirect( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t a = 0, + bool b = false, + Evolution::V1::Union c_type = Evolution::V1::Union::NONE, + flatbuffers::Offset c = 0, + Evolution::V1::Enum d = Evolution::V1::Enum::King, + flatbuffers::Offset e = 0, + const Evolution::V1::Struct *f = 0, + const std::vector *g = nullptr, + const std::vector> *h = nullptr, + int32_t i = 1234) { + auto g__ = g ? _fbb.CreateVector(*g) : 0; + auto h__ = h ? _fbb.CreateVector>(*h) : 0; + return Evolution::V1::CreateRoot( + _fbb, + a, + b, + c_type, + c, + d, + e, + f, + g__, + h__, + i); +} + +inline bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type) { + switch (type) { + case Union::NONE: { + return true; + } + case Union::TableA: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Union::TableB: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + default: return true; + } +} + +inline bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifyUnion( + verifier, values->Get(i), types->GetEnum(i))) { + return false; + } + } + return true; +} + +inline const Evolution::V1::Root *GetRoot(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const Evolution::V1::Root *GetSizePrefixedRoot(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline bool VerifyRootBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(nullptr); +} + +inline bool VerifySizePrefixedRootBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(nullptr); +} + +inline void FinishRootBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedRootBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +} // namespace V1 +} // namespace Evolution + +#endif // FLATBUFFERS_GENERATED_EVOLUTIONV1_EVOLUTION_V1_H_ diff --git a/tests/evolution_test/evolution_v2.fbs b/tests/evolution_test/evolution_v2.fbs new file mode 100644 index 000000000..5f4601e6e --- /dev/null +++ b/tests/evolution_test/evolution_v2.fbs @@ -0,0 +1,50 @@ +namespace Evolution.V2; + +table TableA { + b:int (id: 1); // swapped with 'a' + a:float (id: 0); // swapped with 'b' + c:string (id: 2); // new in v2 +} + +table TableB { + a:int; +} + +table TableC { // new in v2 + a:double; + b:string; +} + +enum Enum : byte { + King, + Queen, + Rook, // new in v2 + Bishop // new in v2 +} + +union Union { + TableA, + TableB, + TableC +} + +struct Struct { + a:int; + b:double; +} + +table Root { + a:int (deprecated); // deprecated in v2 + b:bool; + c:Union; + d:Enum; + e:TableA; + ff:Struct; // renamed from 'f' in v1 + g:[int]; + h:[TableB]; + i:uint = 1234; + j:TableC; // new in v2 + k:uint8 = 56; // new in v2 +} + +root_type Root; \ No newline at end of file diff --git a/tests/evolution_test/evolution_v2.json b/tests/evolution_test/evolution_v2.json new file mode 100644 index 000000000..625f50600 --- /dev/null +++ b/tests/evolution_test/evolution_v2.json @@ -0,0 +1,34 @@ +{ + "b": false, + "c_type": "TableC", + "c": { + "a": 984.2494 + }, + "d": "Bishop", + "e": { + "a": 3.1452, + "b": 435, + "c": "yummy yummy fig bar bar" + }, + "ff":{ + "a": 35, + "b": 243.980943 + }, + "g": [ 7, 8, 10], + "h": [ + { + "a": 212 + }, + { + "a": 459 + }, + { + "a": 333 + } + ], + "i": 4321, + "j": { + "a": 9874.342, + "b": "more please" + } +} diff --git a/tests/evolution_test/evolution_v2_generated.h b/tests/evolution_test/evolution_v2_generated.h new file mode 100644 index 000000000..4e1b8404d --- /dev/null +++ b/tests/evolution_test/evolution_v2_generated.h @@ -0,0 +1,578 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_EVOLUTIONV2_EVOLUTION_V2_H_ +#define FLATBUFFERS_GENERATED_EVOLUTIONV2_EVOLUTION_V2_H_ + +#include "flatbuffers/flatbuffers.h" + +namespace Evolution { +namespace V2 { + +struct TableA; + +struct TableB; + +struct TableC; + +struct Struct; + +struct Root; + +enum class Enum : int8_t { + King = 0, + Queen = 1, + Rook = 2, + Bishop = 3, + MIN = King, + MAX = Bishop +}; + +inline const Enum (&EnumValuesEnum())[4] { + static const Enum values[] = { + Enum::King, + Enum::Queen, + Enum::Rook, + Enum::Bishop + }; + return values; +} + +inline const char * const *EnumNamesEnum() { + static const char * const names[5] = { + "King", + "Queen", + "Rook", + "Bishop", + nullptr + }; + return names; +} + +inline const char *EnumNameEnum(Enum e) { + if (e < Enum::King || e > Enum::Bishop) return ""; + const size_t index = static_cast(e); + return EnumNamesEnum()[index]; +} + +enum class Union : uint8_t { + NONE = 0, + TableA = 1, + TableB = 2, + TableC = 3, + MIN = NONE, + MAX = TableC +}; + +inline const Union (&EnumValuesUnion())[4] { + static const Union values[] = { + Union::NONE, + Union::TableA, + Union::TableB, + Union::TableC + }; + return values; +} + +inline const char * const *EnumNamesUnion() { + static const char * const names[5] = { + "NONE", + "TableA", + "TableB", + "TableC", + nullptr + }; + return names; +} + +inline const char *EnumNameUnion(Union e) { + if (e < Union::NONE || e > Union::TableC) return ""; + const size_t index = static_cast(e); + return EnumNamesUnion()[index]; +} + +template struct UnionTraits { + static const Union enum_value = Union::NONE; +}; + +template<> struct UnionTraits { + static const Union enum_value = Union::TableA; +}; + +template<> struct UnionTraits { + static const Union enum_value = Union::TableB; +}; + +template<> struct UnionTraits { + static const Union enum_value = Union::TableC; +}; + +bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type); +bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Struct FLATBUFFERS_FINAL_CLASS { + private: + int32_t a_; + int32_t padding0__; + double b_; + + public: + Struct() { + memset(static_cast(this), 0, sizeof(Struct)); + } + Struct(int32_t _a, double _b) + : a_(flatbuffers::EndianScalar(_a)), + padding0__(0), + b_(flatbuffers::EndianScalar(_b)) { + (void)padding0__; + } + int32_t a() const { + return flatbuffers::EndianScalar(a_); + } + double b() const { + return flatbuffers::EndianScalar(b_); + } +}; +FLATBUFFERS_STRUCT_END(Struct, 16); + +struct TableA FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4, + VT_B = 6, + VT_C = 8 + }; + float a() const { + return GetField(VT_A, 0.0f); + } + int32_t b() const { + return GetField(VT_B, 0); + } + const flatbuffers::String *c() const { + return GetPointer(VT_C); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_A) && + VerifyField(verifier, VT_B) && + VerifyOffset(verifier, VT_C) && + verifier.VerifyString(c()) && + verifier.EndTable(); + } +}; + +struct TableABuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_a(float a) { + fbb_.AddElement(TableA::VT_A, a, 0.0f); + } + void add_b(int32_t b) { + fbb_.AddElement(TableA::VT_B, b, 0); + } + void add_c(flatbuffers::Offset c) { + fbb_.AddOffset(TableA::VT_C, c); + } + explicit TableABuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + TableABuilder &operator=(const TableABuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTableA( + flatbuffers::FlatBufferBuilder &_fbb, + float a = 0.0f, + int32_t b = 0, + flatbuffers::Offset c = 0) { + TableABuilder builder_(_fbb); + builder_.add_c(c); + builder_.add_b(b); + builder_.add_a(a); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTableADirect( + flatbuffers::FlatBufferBuilder &_fbb, + float a = 0.0f, + int32_t b = 0, + const char *c = nullptr) { + auto c__ = c ? _fbb.CreateString(c) : 0; + return Evolution::V2::CreateTableA( + _fbb, + a, + b, + c__); +} + +struct TableB FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4 + }; + int32_t a() const { + return GetField(VT_A, 0); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_A) && + verifier.EndTable(); + } +}; + +struct TableBBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_a(int32_t a) { + fbb_.AddElement(TableB::VT_A, a, 0); + } + explicit TableBBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + TableBBuilder &operator=(const TableBBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTableB( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t a = 0) { + TableBBuilder builder_(_fbb); + builder_.add_a(a); + return builder_.Finish(); +} + +struct TableC FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_A = 4, + VT_B = 6 + }; + double a() const { + return GetField(VT_A, 0.0); + } + const flatbuffers::String *b() const { + return GetPointer(VT_B); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_A) && + VerifyOffset(verifier, VT_B) && + verifier.VerifyString(b()) && + verifier.EndTable(); + } +}; + +struct TableCBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_a(double a) { + fbb_.AddElement(TableC::VT_A, a, 0.0); + } + void add_b(flatbuffers::Offset b) { + fbb_.AddOffset(TableC::VT_B, b); + } + explicit TableCBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + TableCBuilder &operator=(const TableCBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateTableC( + flatbuffers::FlatBufferBuilder &_fbb, + double a = 0.0, + flatbuffers::Offset b = 0) { + TableCBuilder builder_(_fbb); + builder_.add_a(a); + builder_.add_b(b); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateTableCDirect( + flatbuffers::FlatBufferBuilder &_fbb, + double a = 0.0, + const char *b = nullptr) { + auto b__ = b ? _fbb.CreateString(b) : 0; + return Evolution::V2::CreateTableC( + _fbb, + a, + b__); +} + +struct Root FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_B = 6, + VT_C_TYPE = 8, + VT_C = 10, + VT_D = 12, + VT_E = 14, + VT_FF = 16, + VT_G = 18, + VT_H = 20, + VT_I = 22, + VT_J = 24, + VT_K = 26 + }; + bool b() const { + return GetField(VT_B, 0) != 0; + } + Evolution::V2::Union c_type() const { + return static_cast(GetField(VT_C_TYPE, 0)); + } + const void *c() const { + return GetPointer(VT_C); + } + template const T *c_as() const; + const Evolution::V2::TableA *c_as_TableA() const { + return c_type() == Evolution::V2::Union::TableA ? static_cast(c()) : nullptr; + } + const Evolution::V2::TableB *c_as_TableB() const { + return c_type() == Evolution::V2::Union::TableB ? static_cast(c()) : nullptr; + } + const Evolution::V2::TableC *c_as_TableC() const { + return c_type() == Evolution::V2::Union::TableC ? static_cast(c()) : nullptr; + } + Evolution::V2::Enum d() const { + return static_cast(GetField(VT_D, 0)); + } + const Evolution::V2::TableA *e() const { + return GetPointer(VT_E); + } + const Evolution::V2::Struct *ff() const { + return GetStruct(VT_FF); + } + const flatbuffers::Vector *g() const { + return GetPointer *>(VT_G); + } + const flatbuffers::Vector> *h() const { + return GetPointer> *>(VT_H); + } + uint32_t i() const { + return GetField(VT_I, 1234); + } + const Evolution::V2::TableC *j() const { + return GetPointer(VT_J); + } + uint8_t k() const { + return GetField(VT_K, 56); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_B) && + VerifyField(verifier, VT_C_TYPE) && + VerifyOffset(verifier, VT_C) && + VerifyUnion(verifier, c(), c_type()) && + VerifyField(verifier, VT_D) && + VerifyOffset(verifier, VT_E) && + verifier.VerifyTable(e()) && + VerifyField(verifier, VT_FF) && + VerifyOffset(verifier, VT_G) && + verifier.VerifyVector(g()) && + VerifyOffset(verifier, VT_H) && + verifier.VerifyVector(h()) && + verifier.VerifyVectorOfTables(h()) && + VerifyField(verifier, VT_I) && + VerifyOffset(verifier, VT_J) && + verifier.VerifyTable(j()) && + VerifyField(verifier, VT_K) && + verifier.EndTable(); + } +}; + +template<> inline const Evolution::V2::TableA *Root::c_as() const { + return c_as_TableA(); +} + +template<> inline const Evolution::V2::TableB *Root::c_as() const { + return c_as_TableB(); +} + +template<> inline const Evolution::V2::TableC *Root::c_as() const { + return c_as_TableC(); +} + +struct RootBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_b(bool b) { + fbb_.AddElement(Root::VT_B, static_cast(b), 0); + } + void add_c_type(Evolution::V2::Union c_type) { + fbb_.AddElement(Root::VT_C_TYPE, static_cast(c_type), 0); + } + void add_c(flatbuffers::Offset c) { + fbb_.AddOffset(Root::VT_C, c); + } + void add_d(Evolution::V2::Enum d) { + fbb_.AddElement(Root::VT_D, static_cast(d), 0); + } + void add_e(flatbuffers::Offset e) { + fbb_.AddOffset(Root::VT_E, e); + } + void add_ff(const Evolution::V2::Struct *ff) { + fbb_.AddStruct(Root::VT_FF, ff); + } + void add_g(flatbuffers::Offset> g) { + fbb_.AddOffset(Root::VT_G, g); + } + void add_h(flatbuffers::Offset>> h) { + fbb_.AddOffset(Root::VT_H, h); + } + void add_i(uint32_t i) { + fbb_.AddElement(Root::VT_I, i, 1234); + } + void add_j(flatbuffers::Offset j) { + fbb_.AddOffset(Root::VT_J, j); + } + void add_k(uint8_t k) { + fbb_.AddElement(Root::VT_K, k, 56); + } + explicit RootBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + RootBuilder &operator=(const RootBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateRoot( + flatbuffers::FlatBufferBuilder &_fbb, + bool b = false, + Evolution::V2::Union c_type = Evolution::V2::Union::NONE, + flatbuffers::Offset c = 0, + Evolution::V2::Enum d = Evolution::V2::Enum::King, + flatbuffers::Offset e = 0, + const Evolution::V2::Struct *ff = 0, + flatbuffers::Offset> g = 0, + flatbuffers::Offset>> h = 0, + uint32_t i = 1234, + flatbuffers::Offset j = 0, + uint8_t k = 56) { + RootBuilder builder_(_fbb); + builder_.add_j(j); + builder_.add_i(i); + builder_.add_h(h); + builder_.add_g(g); + builder_.add_ff(ff); + builder_.add_e(e); + builder_.add_c(c); + builder_.add_k(k); + builder_.add_d(d); + builder_.add_c_type(c_type); + builder_.add_b(b); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateRootDirect( + flatbuffers::FlatBufferBuilder &_fbb, + bool b = false, + Evolution::V2::Union c_type = Evolution::V2::Union::NONE, + flatbuffers::Offset c = 0, + Evolution::V2::Enum d = Evolution::V2::Enum::King, + flatbuffers::Offset e = 0, + const Evolution::V2::Struct *ff = 0, + const std::vector *g = nullptr, + const std::vector> *h = nullptr, + uint32_t i = 1234, + flatbuffers::Offset j = 0, + uint8_t k = 56) { + auto g__ = g ? _fbb.CreateVector(*g) : 0; + auto h__ = h ? _fbb.CreateVector>(*h) : 0; + return Evolution::V2::CreateRoot( + _fbb, + b, + c_type, + c, + d, + e, + ff, + g__, + h__, + i, + j, + k); +} + +inline bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type) { + switch (type) { + case Union::NONE: { + return true; + } + case Union::TableA: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Union::TableB: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Union::TableC: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + default: return true; + } +} + +inline bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifyUnion( + verifier, values->Get(i), types->GetEnum(i))) { + return false; + } + } + return true; +} + +inline const Evolution::V2::Root *GetRoot(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const Evolution::V2::Root *GetSizePrefixedRoot(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline bool VerifyRootBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(nullptr); +} + +inline bool VerifySizePrefixedRootBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(nullptr); +} + +inline void FinishRootBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedRootBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +} // namespace V2 +} // namespace Evolution + +#endif // FLATBUFFERS_GENERATED_EVOLUTIONV2_EVOLUTION_V2_H_ diff --git a/tests/generate_code.bat b/tests/generate_code.bat index 8b78a5d89..29a029c67 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -18,6 +18,7 @@ if "%1"=="-b" set buildtype=%2 ..\%buildtype%\flatc.exe --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --grpc --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json || goto FAIL ..\%buildtype%\flatc.exe --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs || goto FAIL ..\%buildtype%\flatc.exe --cpp --java --csharp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs || goto FAIL +..\%buildtype%\flatc.exe --cpp --scoped-enums -o evolution_test ./evolution_test/evolution_v1.fbs ./evolution_test/evolution_v2.fbs|| goto FAIL ..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs || goto FAIL ..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs || goto FAIL ..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs || goto FAIL diff --git a/tests/generate_code.sh b/tests/generate_code.sh index 37b405851..14b621ccf 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -18,6 +18,7 @@ set -e ../flatc --cpp --java --kotlin --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --grpc --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json ../flatc --cpp --java --kotlin --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs ../flatc --cpp --java --kotlin --csharp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs +../flatc --cpp --scoped-enums -o evolution_test ./evolution_test/evolution_v*.fbs ../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs ../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs ../flatc --jsonschema --schema -I include_test monster_test.fbs diff --git a/tests/test.cpp b/tests/test.cpp index 361b83547..68716c67b 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -37,6 +37,8 @@ #include "monster_extra_generated.h" #if !defined(_MSC_VER) || _MSC_VER >= 1700 # include "arrays_test_generated.h" +# include "evolution_test/evolution_v1_generated.h" +# include "evolution_test/evolution_v2_generated.h" #endif #include "native_type_test_generated.h" @@ -2310,6 +2312,76 @@ void InvalidNestedFlatbufferTest() { false); } +void EvolutionTest() { + // VS10 does not support typed enums, exclude from tests +#if !defined(_MSC_VER) || _MSC_VER >= 1700 + const int NUM_VERSIONS = 2; + std::string schemas[NUM_VERSIONS]; + std::string jsonfiles[NUM_VERSIONS]; + std::vector binaries[NUM_VERSIONS]; + flatbuffers::Verifier *verifiers[NUM_VERSIONS]; + + flatbuffers::IDLOptions idl_opts; + idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary; + flatbuffers::Parser parser(idl_opts); + + // Load all the schema versions and their associated data. + for (int i = 0; i < NUM_VERSIONS; ++i) { + std::string schema = test_data_path + "evolution_test/evolution_v" + + flatbuffers::NumToString(i + 1) + ".fbs"; + TEST_ASSERT(flatbuffers::LoadFile(schema.c_str(), false, &schemas[i])); + std::string json = test_data_path + "evolution_test/evolution_v" + + flatbuffers::NumToString(i + 1) + ".json"; + TEST_ASSERT(flatbuffers::LoadFile(json.c_str(), false, &jsonfiles[i])); + + TEST_ASSERT(parser.Parse(schemas[i].c_str())); + TEST_ASSERT(parser.Parse(jsonfiles[i].c_str())); + + auto bufLen = parser.builder_.GetSize(); + auto buf = parser.builder_.GetBufferPointer(); + binaries[i].reserve(bufLen); + std::copy(buf, buf + bufLen, std::back_inserter(binaries[i])); + + verifiers[i] = new flatbuffers::Verifier(&binaries[i].front(), bufLen); + } + + // Assert that all the verifiers for the different schema versions properly verify any version data. + for (int i = 0; i < NUM_VERSIONS; ++i) { + TEST_ASSERT(Evolution::V1::VerifyRootBuffer(*verifiers[i])); + TEST_ASSERT(Evolution::V2::VerifyRootBuffer(*verifiers[i])); + } + + // Test backwards compatibility by reading old data with an evolved schema. + auto root_v1_viewed_from_v2 = Evolution::V2::GetRoot(&binaries[0].front()); + // field 'j' is new in version 2, so it should be null. + TEST_EQ(root_v1_viewed_from_v2->j(), NULL); + // field 'k' is new in version 2 with a default of 56. + TEST_EQ(root_v1_viewed_from_v2->k(), 56); + // field 'c' of 'TableA' is new in version 2, so it should be null. + TEST_EQ(root_v1_viewed_from_v2->e()->c(), NULL); + // 'TableC' was added to field 'c' union in version 2, so it should be null. + TEST_EQ(root_v1_viewed_from_v2->c_as_TableC(), NULL); + // The field 'c' union should be of type 'TableB' regardless of schema version + TEST_ASSERT(root_v1_viewed_from_v2->c_type() == Evolution::V2::Union::TableB); + // The field 'f' was renamed to 'ff' in version 2, it should still be readable. + TEST_EQ(root_v1_viewed_from_v2->ff()->a(), 16); + + // Test forwards compatibility by reading new data with an old schema. + auto root_v2_viewed_from_v1 = Evolution::V1::GetRoot(&binaries[1].front()); + // The field 'c' union in version 2 is a new table (index = 3) and should still be accessible, + // but not interpretable. + TEST_EQ(static_cast(root_v2_viewed_from_v1->c_type()), 3); + TEST_NOTNULL(root_v2_viewed_from_v1->c()); + // The field 'd' enum in verison 2 has new members and should still be accessible, but not interpretable. + TEST_EQ(static_cast(root_v2_viewed_from_v1->d()), 3); + // The field 'a' in version 2 is deprecated and should return the default value (0) instead of the value stored in + // the in the buffer (42). + TEST_EQ(root_v2_viewed_from_v1->a(), 0); + // The field 'ff' was originally named 'f' in version 1, it should still be readable. + TEST_EQ(root_v2_viewed_from_v1->f()->a(), 35); +#endif +} + void UnionVectorTest() { // load FlatBuffer fbs schema and json. std::string schemafile, jsonfile; @@ -3070,6 +3142,7 @@ int FlatBufferTests() { FixedLengthArrayJsonTest(true); ReflectionTest(flatbuf.data(), flatbuf.size()); ParseProtoTest(); + EvolutionTest(); UnionVectorTest(); LoadVerifyBinaryTest(); GenerateTableTextTest(); From 0f2ff7eaa96b58adbfcf58cb08e123c943f1ff01 Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Thu, 14 Nov 2019 15:46:47 -0800 Subject: [PATCH 19/28] Lua cleanup (#5624) --- lua/flatbuffers/builder.lua | 42 +++++++++++------------ lua/flatbuffers/numTypes.lua | 15 +++++++++ lua/flatbuffers/view.lua | 65 +++++++++++++++++++++--------------- tests/luatest.lua | 24 +++++-------- 4 files changed, 82 insertions(+), 64 deletions(-) diff --git a/lua/flatbuffers/builder.lua b/lua/flatbuffers/builder.lua index 19f214de5..4a0c4f6a2 100644 --- a/lua/flatbuffers/builder.lua +++ b/lua/flatbuffers/builder.lua @@ -29,12 +29,12 @@ local getAlignSize = compat.GetAlignSize local function vtableEqual(a, objectStart, b) UOffsetT:EnforceNumber(objectStart) - if (#a * VOffsetT.bytewidth) ~= #b then + if (#a * 2) ~= #b then return false end for i, elem in ipairs(a) do - local x = string.unpack(VOffsetT.packFmt, b, 1 + (i - 1) * VOffsetT.bytewidth) + local x = string.unpack(VOffsetT.packFmt, b, 1 + (i - 1) * 2) if x ~= 0 or elem ~= 0 then local y = objectStart - elem if x ~= y then @@ -121,7 +121,7 @@ function mt:WriteVtable() local vt2lenstr = self.bytes:Slice(vt2Start, vt2Start+1) local vt2Len = string.unpack(VOffsetT.packFmt, vt2lenstr, 1) - local metadata = VtableMetadataFields * VOffsetT.bytewidth + local metadata = VtableMetadataFields * 2 local vt2End = vt2Start + vt2Len local vt2 = self.bytes:Slice(vt2Start+metadata,vt2End) @@ -150,7 +150,7 @@ function mt:WriteVtable() self:PrependVOffsetT(objectSize) local vBytes = #self.currentVTable + VtableMetadataFields - vBytes = vBytes * VOffsetT.bytewidth + vBytes = vBytes * 2 self:PrependVOffsetT(vBytes) local objectStart = #self.bytes - objectOffset @@ -225,17 +225,17 @@ function mt:Prep(size, additionalBytes) end function mt:PrependSOffsetTRelative(off) - self:Prep(SOffsetT.bytewidth, 0) + self:Prep(4, 0) assert(off <= self:Offset(), "Offset arithmetic error") - local off2 = self:Offset() - off + SOffsetT.bytewidth + local off2 = self:Offset() - off + 4 self:Place(off2, SOffsetT) end function mt:PrependUOffsetTRelative(off) - self:Prep(UOffsetT.bytewidth, 0) + self:Prep(4, 0) local soffset = self:Offset() if off <= soffset then - local off2 = soffset - off + UOffsetT.bytewidth + local off2 = soffset - off + 4 self:Place(off2, UOffsetT) else error("Offset arithmetic error") @@ -245,8 +245,9 @@ end function mt:StartVector(elemSize, numElements, alignment) assert(not self.nested) self.nested = true - self:Prep(Uint32.bytewidth, elemSize * numElements) - self:Prep(alignment, elemSize * numElements) + local elementSize = elemSize * numElements + self:Prep(4, elementSize) -- Uint32 length + self:Prep(alignment, elementSize) return self:Offset() end @@ -263,7 +264,7 @@ function mt:CreateString(s) assert(type(s) == "string") - self:Prep(UOffsetT.bytewidth, (#s + 1)*Uint8.bytewidth) + self:Prep(4, #s + 1) self:Place(0, Uint8) local l = #s @@ -271,20 +272,21 @@ function mt:CreateString(s) self.bytes:Set(s, self.head, self.head + l) - return self:EndVector(#s) + return self:EndVector(l) end function mt:CreateByteVector(x) assert(not self.nested) self.nested = true - self:Prep(UOffsetT.bytewidth, #x*Uint8.bytewidth) local l = #x + self:Prep(4, l) + self.head = self.head - l self.bytes:Set(x, self.head, self.head + l) - return self:EndVector(#x) + return self:EndVector(l) end function mt:Slot(slotnum) @@ -295,12 +297,7 @@ end local function finish(self, rootTable, sizePrefix) UOffsetT:EnforceNumber(rootTable) - local prepSize = UOffsetT.bytewidth - if sizePrefix then - prepSize = prepSize + Int32.bytewidth - end - - self:Prep(self.minalign, prepSize) + self:Prep(self.minalign, sizePrefix and 8 or 4) self:PrependUOffsetTRelative(rootTable) if sizePrefix then local size = #self.bytes - self.head @@ -325,8 +322,9 @@ function mt:Prepend(flags, off) end function mt:PrependSlot(flags, o, x, d) - flags:EnforceNumber(x) - flags:EnforceNumber(d) + flags:EnforceNumbers(x,d) +-- flags:EnforceNumber(x) +-- flags:EnforceNumber(d) if x ~= d then self:Prepend(flags, x) self:Slot(o) diff --git a/lua/flatbuffers/numTypes.lua b/lua/flatbuffers/numTypes.lua index 8fec21c4d..01f419930 100644 --- a/lua/flatbuffers/numTypes.lua +++ b/lua/flatbuffers/numTypes.lua @@ -34,6 +34,20 @@ function type_mt:EnforceNumber(n) error("Number is not in the valid range") end +function type_mt:EnforceNumbers(a,b) + -- duplicate code since the overhead of function calls + -- for such a popular method is time consuming + if not self.min_value and not self.max_value then + return + end + + if self.min_value <= a and a <= self.max_value and self.min_value <= b and b <= self.max_value then + return + end + + error("Number is not in the valid range") +end + function type_mt:EnforceNumberAndPack(n) return bpack(self.packFmt, n) end @@ -58,6 +72,7 @@ local bool_mt = Unpack = function(self, buf, pos) return buf[pos] == "1" end, ValidNumber = function(self, n) return true end, -- anything is a valid boolean in Lua EnforceNumber = function(self, n) end, -- anything is a valid boolean in Lua + EnforceNumbers = function(self, a, b) end, -- anything is a valid boolean in Lua EnforceNumberAndPack = function(self, n) return self:Pack(value) end, } diff --git a/lua/flatbuffers/view.lua b/lua/flatbuffers/view.lua index da0f8bf7c..fde15c3d8 100644 --- a/lua/flatbuffers/view.lua +++ b/lua/flatbuffers/view.lua @@ -6,69 +6,83 @@ local mt_name = "flatbuffers.view.mt" local N = require("flatbuffers.numTypes") local binaryarray = require("flatbuffers.binaryarray") +local function enforceOffset(off) + if off < 0 or off > 42949672951 then + error("Offset is not valid") + end +end + +local unpack = string.unpack +local function unPackUoffset(bytes, off) + return unpack(" Date: Thu, 14 Nov 2019 15:47:58 -0800 Subject: [PATCH 20/28] Removed idl_gen_general.cpp and move contents to code_generators.cpp (#5625) --- BUILD | 3 -- CMakeLists.txt | 2 - android/jni/Android.mk | 3 +- include/flatbuffers/idl.h | 19 +++---- src/code_generators.cpp | 74 +++++++++++++++++++++++++++ src/flatc.cpp | 15 ++++-- src/flatc_main.cpp | 22 ++++---- src/idl_gen_general.cpp | 102 -------------------------------------- src/idl_gen_java.cpp | 9 ++-- 9 files changed, 105 insertions(+), 144 deletions(-) delete mode 100644 src/idl_gen_general.cpp diff --git a/BUILD b/BUILD index b69760238..c2f43d8df 100644 --- a/BUILD +++ b/BUILD @@ -22,7 +22,6 @@ cc_library( srcs = [ "src/code_generators.cpp", "src/idl_gen_fbs.cpp", - "src/idl_gen_general.cpp", "src/idl_gen_text.cpp", "src/idl_parser.cpp", "src/reflection.cpp", @@ -88,7 +87,6 @@ cc_binary( "src/idl_gen_cpp.cpp", "src/idl_gen_csharp.cpp", "src/idl_gen_dart.cpp", - "src/idl_gen_general.cpp", "src/idl_gen_go.cpp", "src/idl_gen_grpc.cpp", "src/idl_gen_java.cpp", @@ -134,7 +132,6 @@ cc_test( "include/flatbuffers/registry.h", "src/code_generators.cpp", "src/idl_gen_fbs.cpp", - "src/idl_gen_general.cpp", "src/idl_gen_text.cpp", "src/idl_parser.cpp", "src/reflection.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index 60ebe2606..a0f292ede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,6 @@ set(FlatBuffers_Compiler_SRCS src/idl_gen_cpp.cpp src/idl_gen_csharp.cpp src/idl_gen_dart.cpp - src/idl_gen_general.cpp src/idl_gen_kotlin.cpp src/idl_gen_go.cpp src/idl_gen_java.cpp @@ -148,7 +147,6 @@ set(FlatBuffers_Sample_Text_SRCS set(FlatBuffers_Sample_BFBS_SRCS ${FlatBuffers_Library_SRCS} - src/idl_gen_general.cpp samples/sample_bfbs.cpp # file generated by running compiler on samples/monster.fbs ${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h diff --git a/android/jni/Android.mk b/android/jni/Android.mk index e29c87289..5795a70f1 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -53,8 +53,7 @@ LOCAL_SRC_FILES := android/jni/main.cpp \ tests/test_builder.cpp \ tests/native_type_test_impl.h \ tests/native_type_test_impl.cpp \ - src/idl_gen_fbs.cpp \ - src/idl_gen_general.cpp + src/idl_gen_fbs.cpp LOCAL_LDLIBS := -llog -landroid -latomic LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra LOCAL_ARM_MODE := arm diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 005134ccd..4d567dc99 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -967,7 +967,7 @@ extern bool GenerateTextFile(const Parser &parser, const std::string &path, // Generate binary files from a given FlatBuffer, and a given Parser // object that has been populated with the corresponding schema. -// See idl_gen_general.cpp. +// See code_generators.cpp. extern bool GenerateBinary(const Parser &parser, const std::string &path, const std::string &file_name); @@ -1032,11 +1032,6 @@ extern bool GenerateJsonSchema(const Parser &parser, const std::string &path, extern bool GenerateKotlin(const Parser &parser, const std::string &path, const std::string &file_name); -// Generate Java/C#/.. files from the definitions in the Parser object. -// See idl_gen_general.cpp. -extern bool GenerateGeneral(const Parser &parser, const std::string &path, - const std::string &file_name); - // Generate a schema file from the internal representation, useful after // parsing a .proto schema. extern std::string GenerateFBS(const Parser &parser, @@ -1064,11 +1059,11 @@ extern std::string DartMakeRule(const Parser &parser, const std::string &path, extern std::string RustMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); -// Generate a make rule for the generated Java/C#/... files. -// See idl_gen_general.cpp. -extern std::string GeneralMakeRule(const Parser &parser, - const std::string &path, - const std::string &file_name); +// Generate a make rule for generated Java or C# files. +// See code_generators.cpp. +extern std::string JavaCSharpMakeRule(const Parser &parser, + const std::string &path, + const std::string &file_name); // Generate a make rule for the generated text (JSON) files. // See idl_gen_text.cpp. @@ -1076,7 +1071,7 @@ extern std::string TextMakeRule(const Parser &parser, const std::string &path, const std::string &file_names); // Generate a make rule for the generated binary files. -// See idl_gen_general.cpp. +// See code_generators.cpp. extern std::string BinaryMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); diff --git a/src/code_generators.cpp b/src/code_generators.cpp index a46c4b73d..ff4d61496 100644 --- a/src/code_generators.cpp +++ b/src/code_generators.cpp @@ -287,6 +287,80 @@ std::string SimpleFloatConstantGenerator::NaN(float v) const { return this->NaN(static_cast(v)); } +std::string JavaCSharpMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name) { + FLATBUFFERS_ASSERT(parser.opts.lang == IDLOptions::kJava || + parser.opts.lang == IDLOptions::kCSharp); + + std::string file_extension = + (parser.opts.lang == IDLOptions::kJava) ? ".java" : ".cs"; + + std::string make_rule; + + for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end(); + ++it) { + auto &enum_def = **it; + if (!make_rule.empty()) make_rule += " "; + std::string directory = + BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace); + make_rule += directory + enum_def.name + file_extension; + } + + for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); + ++it) { + auto &struct_def = **it; + if (!make_rule.empty()) make_rule += " "; + std::string directory = BaseGenerator::NamespaceDir( + parser, path, *struct_def.defined_namespace); + make_rule += directory + struct_def.name + file_extension; + } + + make_rule += ": "; + auto included_files = parser.GetIncludedFilesRecursive(file_name); + for (auto it = included_files.begin(); it != included_files.end(); ++it) { + make_rule += " " + *it; + } + return make_rule; +} + +std::string BinaryFileName(const Parser &parser, const std::string &path, + const std::string &file_name) { + auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin"; + return path + file_name + "." + ext; +} + +bool GenerateBinary(const Parser &parser, const std::string &path, + const std::string &file_name) { + if (parser.opts.use_flexbuffers) { + auto data_vec = parser.flex_builder_.GetBuffer(); + auto data_ptr = reinterpret_cast(data(data_vec)); + return !parser.flex_builder_.GetSize() || + flatbuffers::SaveFile( + BinaryFileName(parser, path, file_name).c_str(), data_ptr, + parser.flex_builder_.GetSize(), true); + } + return !parser.builder_.GetSize() || + flatbuffers::SaveFile( + BinaryFileName(parser, path, file_name).c_str(), + reinterpret_cast(parser.builder_.GetBufferPointer()), + parser.builder_.GetSize(), true); +} + +std::string BinaryMakeRule(const Parser &parser, const std::string &path, + const std::string &file_name) { + if (!parser.builder_.GetSize()) return ""; + std::string filebase = + flatbuffers::StripPath(flatbuffers::StripExtension(file_name)); + std::string make_rule = + BinaryFileName(parser, path, filebase) + ": " + file_name; + auto included_files = + parser.GetIncludedFilesRecursive(parser.root_struct_def_->file); + for (auto it = included_files.begin(); it != included_files.end(); ++it) { + make_rule += " " + *it; + } + return make_rule; +} + } // namespace flatbuffers #if defined(_MSC_VER) diff --git a/src/flatc.cpp b/src/flatc.cpp index 74f2e2381..257afa851 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -470,11 +470,16 @@ int FlatCompiler::Compile(int argc, const char **argv) { params_.generators[i].lang_name + " for " + filebase); } } else { - std::string make_rule = params_.generators[i].make_rule( - *parser.get(), output_path, filename); - if (!make_rule.empty()) - printf("%s\n", - flatbuffers::WordWrap(make_rule, 80, " ", " \\").c_str()); + if (params_.generators[i].make_rule == nullptr) { + Error(std::string("Cannot generate make rule for ") + + params_.generators[i].lang_name); + } else { + std::string make_rule = params_.generators[i].make_rule( + *parser.get(), output_path, filename); + if (!make_rule.empty()) + printf("%s\n", + flatbuffers::WordWrap(make_rule, 80, " ", " \\").c_str()); + } } if (grpc_enabled) { if (params_.generators[i].generateGRPC != nullptr) { diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index 786a1b1e5..1b02d2949 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -54,11 +54,11 @@ int main(int argc, const char *argv[]) { "Generate C++ headers for tables/structs", flatbuffers::CPPMakeRule }, { flatbuffers::GenerateGo, "-g", "--go", "Go", true, flatbuffers::GenerateGoGRPC, flatbuffers::IDLOptions::kGo, - "Generate Go files for tables/structs", flatbuffers::GeneralMakeRule }, + "Generate Go files for tables/structs", nullptr }, { flatbuffers::GenerateJava, "-j", "--java", "Java", true, flatbuffers::GenerateJavaGRPC, flatbuffers::IDLOptions::kJava, "Generate Java classes for tables/structs", - flatbuffers::GeneralMakeRule }, + flatbuffers::JavaCSharpMakeRule }, { flatbuffers::GenerateJSTS, "-s", "--js", "JavaScript", true, nullptr, flatbuffers::IDLOptions::kJs, "Generate JavaScript code for tables/structs", @@ -72,31 +72,29 @@ int main(int argc, const char *argv[]) { flatbuffers::JSTSMakeRule }, { flatbuffers::GenerateCSharp, "-n", "--csharp", "C#", true, nullptr, flatbuffers::IDLOptions::kCSharp, - "Generate C# classes for tables/structs", flatbuffers::GeneralMakeRule }, + "Generate C# classes for tables/structs", + flatbuffers::JavaCSharpMakeRule }, { flatbuffers::GeneratePython, "-p", "--python", "Python", true, nullptr, flatbuffers::IDLOptions::kPython, - "Generate Python files for tables/structs", - flatbuffers::GeneralMakeRule }, + "Generate Python files for tables/structs", nullptr }, { flatbuffers::GenerateLobster, nullptr, "--lobster", "Lobster", true, nullptr, flatbuffers::IDLOptions::kLobster, - "Generate Lobster files for tables/structs", - flatbuffers::GeneralMakeRule }, + "Generate Lobster files for tables/structs", nullptr }, { flatbuffers::GenerateLua, "-l", "--lua", "Lua", true, nullptr, flatbuffers::IDLOptions::kLua, "Generate Lua files for tables/structs", - flatbuffers::GeneralMakeRule }, + nullptr }, { flatbuffers::GenerateRust, "-r", "--rust", "Rust", true, nullptr, flatbuffers::IDLOptions::kRust, "Generate Rust files for tables/structs", flatbuffers::RustMakeRule }, { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true, nullptr, flatbuffers::IDLOptions::kPhp, "Generate PHP files for tables/structs", - flatbuffers::GeneralMakeRule }, + nullptr }, { flatbuffers::GenerateKotlin, nullptr, "--kotlin", "Kotlin", true, nullptr, flatbuffers::IDLOptions::kKotlin, - "Generate Kotlin classes for tables/structs", - flatbuffers::GeneralMakeRule }, + "Generate Kotlin classes for tables/structs", nullptr }, { flatbuffers::GenerateJsonSchema, nullptr, "--jsonschema", "JsonSchema", true, nullptr, flatbuffers::IDLOptions::kJsonSchema, - "Generate Json schema", flatbuffers::GeneralMakeRule }, + "Generate Json schema", nullptr }, }; flatbuffers::FlatCompiler::InitParams params; diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp deleted file mode 100644 index a12719bfd..000000000 --- a/src/idl_gen_general.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2014 Google Inc. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// independent from idl_parser, since this code is not needed for most clients - -#include "flatbuffers/code_generators.h" -#include "flatbuffers/flatbuffers.h" -#include "flatbuffers/idl.h" -#include "flatbuffers/util.h" - -#if defined(FLATBUFFERS_CPP98_STL) -# include -#endif // defined(FLATBUFFERS_CPP98_STL) - -namespace flatbuffers { -std::string GeneralMakeRule(const Parser &parser, const std::string &path, - const std::string &file_name) { - FLATBUFFERS_ASSERT(parser.opts.lang <= IDLOptions::kMAX); - - std::string file_extension = - (parser.opts.lang == IDLOptions::kJava) ? ".java" : ".cs"; - - std::string make_rule; - - for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end(); - ++it) { - auto &enum_def = **it; - if (!make_rule.empty()) make_rule += " "; - std::string directory = - BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace); - make_rule += directory + enum_def.name + file_extension; - } - - for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); - ++it) { - auto &struct_def = **it; - if (!make_rule.empty()) make_rule += " "; - std::string directory = BaseGenerator::NamespaceDir( - parser, path, *struct_def.defined_namespace); - make_rule += directory + struct_def.name + file_extension; - } - - make_rule += ": "; - auto included_files = parser.GetIncludedFilesRecursive(file_name); - for (auto it = included_files.begin(); it != included_files.end(); ++it) { - make_rule += " " + *it; - } - return make_rule; -} - -std::string BinaryFileName(const Parser &parser, const std::string &path, - const std::string &file_name) { - auto ext = parser.file_extension_.length() ? parser.file_extension_ : "bin"; - return path + file_name + "." + ext; -} - -bool GenerateBinary(const Parser &parser, const std::string &path, - const std::string &file_name) { - if (parser.opts.use_flexbuffers) { - auto data_vec = parser.flex_builder_.GetBuffer(); - auto data_ptr = reinterpret_cast(data(data_vec)); - return !parser.flex_builder_.GetSize() || - flatbuffers::SaveFile( - BinaryFileName(parser, path, file_name).c_str(), data_ptr, - parser.flex_builder_.GetSize(), true); - } - return !parser.builder_.GetSize() || - flatbuffers::SaveFile( - BinaryFileName(parser, path, file_name).c_str(), - reinterpret_cast(parser.builder_.GetBufferPointer()), - parser.builder_.GetSize(), true); -} - -std::string BinaryMakeRule(const Parser &parser, const std::string &path, - const std::string &file_name) { - if (!parser.builder_.GetSize()) return ""; - std::string filebase = - flatbuffers::StripPath(flatbuffers::StripExtension(file_name)); - std::string make_rule = - BinaryFileName(parser, path, filebase) + ": " + file_name; - auto included_files = - parser.GetIncludedFilesRecursive(parser.root_struct_def_->file); - for (auto it = included_files.begin(); it != included_files.end(); ++it) { - make_rule += " " + *it; - } - return make_rule; -} - -} // namespace flatbuffers diff --git a/src/idl_gen_java.cpp b/src/idl_gen_java.cpp index 123ebddc6..b257111f8 100644 --- a/src/idl_gen_java.cpp +++ b/src/idl_gen_java.cpp @@ -599,8 +599,7 @@ class JavaGenerator : public BaseGenerator { // Generate a special accessor for the table that when used as the root // of a FlatBuffer - std::string method_name = - "getRootAs" + struct_def.name; + std::string method_name = "getRootAs" + struct_def.name; std::string method_signature = " public static " + struct_def.name + " " + method_name; @@ -1112,8 +1111,7 @@ class JavaGenerator : public BaseGenerator { code += "finish" + size_prefix[i] + struct_def.name; code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(); code += " offset) {"; - code += " builder.finish" + size_prefix[i] + - "(offset"; + code += " builder.finish" + size_prefix[i] + "(offset"; if (parser_.file_identifier_.length()) code += ", \"" + parser_.file_identifier_ + "\""; @@ -1185,8 +1183,7 @@ class JavaGenerator : public BaseGenerator { code += "__reset(_vector, _element_size, _bb); return this; }\n\n"; auto type_name = struct_def.name; - auto method_start = - method_indent + "public " + type_name + " get"; + auto method_start = method_indent + "public " + type_name + " get"; // Generate the accessors that don't do object reuse. code += method_start + "(int j) { return get"; code += "(new " + type_name + "(), j); }\n"; From 6beb9f49cb44095c4c17be43f13906c6eb09d7c7 Mon Sep 17 00:00:00 2001 From: Malar Kannan Date: Fri, 15 Nov 2019 06:28:35 +0530 Subject: [PATCH 21/28] Support for python grpc - continuing the work from the pull request #4270 #4705 (#5613) * Support for python grpc * add few fixes * Fixes build * Fix python generator * Add tests * Fix grpc python test * Fix tests and add incomplete python generator * Fix python generator * Add python generator methods * Fix Appveyor build * grpc python support v0.1 * Update tests * update grpctest * Remove duplicated code and fix a brace * tests for flatbuffers grpc python * Updated tests + removed SerializeToString, From String * remove pickle import * include missing files in ci - BUILD and generated test result --- BUILD | 3 + CMakeLists.txt | 3 + grpc/src/compiler/python_generator.cc | 639 +++++++++++++++++++ grpc/src/compiler/python_generator.h | 55 ++ grpc/src/compiler/python_private_generator.h | 87 +++ grpc/src/compiler/schema_interface.h | 3 + grpc/tests/grpctest.py | 174 +++++ include/flatbuffers/idl.h | 6 + src/flatc_main.cpp | 4 +- src/idl_gen_grpc.cpp | 45 +- tests/MyGame/Example/monster_test_grpc_fb.py | 241 +++++++ 11 files changed, 1257 insertions(+), 3 deletions(-) create mode 100644 grpc/src/compiler/python_generator.cc create mode 100644 grpc/src/compiler/python_generator.h create mode 100644 grpc/src/compiler/python_private_generator.h create mode 100644 grpc/tests/grpctest.py create mode 100644 tests/MyGame/Example/monster_test_grpc_fb.py diff --git a/BUILD b/BUILD index c2f43d8df..5042553c4 100644 --- a/BUILD +++ b/BUILD @@ -80,6 +80,9 @@ cc_binary( "grpc/src/compiler/cpp_generator.h", "grpc/src/compiler/go_generator.cc", "grpc/src/compiler/go_generator.h", + "grpc/src/compiler/python_generator.cc", + "grpc/src/compiler/python_generator.h", + "grpc/src/compiler/python_private_generator.h", "grpc/src/compiler/java_generator.cc", "grpc/src/compiler/java_generator.h", "grpc/src/compiler/schema_interface.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index a0f292ede..1b02d45cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -104,6 +104,9 @@ set(FlatBuffers_Compiler_SRCS grpc/src/compiler/go_generator.cc grpc/src/compiler/java_generator.h grpc/src/compiler/java_generator.cc + grpc/src/compiler/python_generator.h + grpc/src/compiler/python_private_generator.h + grpc/src/compiler/python_generator.cc ) set(FlatHash_SRCS diff --git a/grpc/src/compiler/python_generator.cc b/grpc/src/compiler/python_generator.cc new file mode 100644 index 000000000..4bc2fb5eb --- /dev/null +++ b/grpc/src/compiler/python_generator.cc @@ -0,0 +1,639 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "flatbuffers/util.h" +#include "src/compiler/python_generator.h" +#include "src/compiler/python_private_generator.h" + +using std::make_pair; +using std::map; +using std::pair; +using std::replace; +using std::tuple; +using std::vector; +using std::set; + +namespace grpc_python_generator { + +grpc::string generator_file_name; + +typedef map StringMap; +typedef vector StringVector; +typedef tuple StringPair; +typedef set StringPairSet; + +// Provides RAII indentation handling. Use as: +// { +// IndentScope raii_my_indent_var_name_here(my_py_printer); +// // constructor indented my_py_printer +// ... +// // destructor called at end of scope, un-indenting my_py_printer +// } +class IndentScope { + public: + explicit IndentScope(grpc_generator::Printer* printer) : printer_(printer) { + printer_->Indent(); + } + + ~IndentScope() { printer_->Outdent(); } + + private: + grpc_generator::Printer* printer_; +}; + +inline grpc::string StringReplace(grpc::string str, const grpc::string& from, + const grpc::string& to, bool replace_all) { + size_t pos = 0; + + do { + pos = str.find(from, pos); + if (pos == grpc::string::npos) { + break; + } + str.replace(pos, from.length(), to); + pos += to.length(); + } while (replace_all); + + return str; +} + +inline grpc::string StringReplace(grpc::string str, const grpc::string& from, + const grpc::string& to) { + return StringReplace(str, from, to, true); +} + +grpc::string ModuleName(const grpc::string& filename, + const grpc::string& import_prefix) { + grpc::string basename = flatbuffers::StripExtension(filename); + basename = StringReplace(basename, "-", "_"); + basename = StringReplace(basename, "/", "."); + return import_prefix + basename + "_fb"; +} + +grpc::string ModuleAlias(const grpc::string& filename, + const grpc::string& import_prefix) { + grpc::string module_name = ModuleName(filename, import_prefix); + // We can't have dots in the module name, so we replace each with _dot_. + // But that could lead to a collision between a.b and a_dot_b, so we also + // duplicate each underscore. + module_name = StringReplace(module_name, "_", "__"); + module_name = StringReplace(module_name, ".", "_dot_"); + return module_name; +} + +PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config_, + const grpc_generator::File* file_) + : config(config_), file(file_) {} + +void PrivateGenerator::PrintBetaServicer(const grpc_generator::Service* service, + grpc_generator::Printer* out) { + StringMap service_dict; + service_dict["Service"] = service->name(); + out->Print("\n\n"); + out->Print(service_dict, "class Beta$Service$Servicer(object):\n"); + { + IndentScope raii_class_indent(out); + out->Print( + "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" + "\nIt is recommended to use the GA API (classes and functions in this\n" + "file not marked beta) for all further purposes. This class was " + "generated\n" + "only to ease transition from grpcio<0.15.0 to " + "grpcio>=0.15.0.\"\"\"\n"); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + grpc::string arg_name = + method->ClientStreaming() ? "request_iterator" : "request"; + StringMap method_dict; + method_dict["Method"] = method->name(); + method_dict["ArgName"] = arg_name; + out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n"); + { + IndentScope raii_method_indent(out); + out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n"); + } + } + } +} + +void PrivateGenerator::PrintBetaStub(const grpc_generator::Service* service, + grpc_generator::Printer* out) { + StringMap service_dict; + service_dict["Service"] = service->name(); + out->Print("\n\n"); + out->Print(service_dict, "class Beta$Service$Stub(object):\n"); + { + IndentScope raii_class_indent(out); + out->Print( + "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" + "\nIt is recommended to use the GA API (classes and functions in this\n" + "file not marked beta) for all further purposes. This class was " + "generated\n" + "only to ease transition from grpcio<0.15.0 to " + "grpcio>=0.15.0.\"\"\"\n"); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + grpc::string arg_name = + method->ClientStreaming() ? "request_iterator" : "request"; + StringMap method_dict; + method_dict["Method"] = method->name(); + method_dict["ArgName"] = arg_name; + out->Print(method_dict, + "def $Method$(self, $ArgName$, timeout, metadata=None, " + "with_call=False, protocol_options=None):\n"); + { + IndentScope raii_method_indent(out); + out->Print("raise NotImplementedError()\n"); + } + if (!method->ServerStreaming()) { + out->Print(method_dict, "$Method$.future = None\n"); + } + } + } +} + +void PrivateGenerator::PrintBetaServerFactory( + const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, grpc_generator::Printer* out) { + StringMap service_dict; + service_dict["Service"] = service->name(); + out->Print("\n\n"); + out->Print(service_dict, + "def beta_create_$Service$_server(servicer, pool=None, " + "pool_size=None, default_timeout=None, maximum_timeout=None):\n"); + { + IndentScope raii_create_server_indent(out); + out->Print( + "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" + "\nIt is recommended to use the GA API (classes and functions in this\n" + "file not marked beta) for all further purposes. This function was\n" + "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0" + "\"\"\"\n"); + StringMap method_implementation_constructors; + StringMap input_message_modules_and_classes; + StringMap output_message_modules_and_classes; + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + const grpc::string method_implementation_constructor = + grpc::string(method->ClientStreaming() ? "stream_" : "unary_") + + grpc::string(method->ServerStreaming() ? "stream_" : "unary_") + + "inline"; + grpc::string input_message_module_and_class = method->get_fb_builder(); + grpc::string output_message_module_and_class = method->get_fb_builder(); + method_implementation_constructors.insert( + make_pair(method->name(), method_implementation_constructor)); + input_message_modules_and_classes.insert( + make_pair(method->name(), input_message_module_and_class)); + output_message_modules_and_classes.insert( + make_pair(method->name(), output_message_module_and_class)); + } + StringMap method_dict; + method_dict["PackageQualifiedServiceName"] = package_qualified_service_name; +// out->Print("request_deserializers = {\n"); +// for (StringMap::iterator name_and_input_module_class_pair = +// input_message_modules_and_classes.begin(); +// name_and_input_module_class_pair != +// input_message_modules_and_classes.end(); +// name_and_input_module_class_pair++) { +// method_dict["MethodName"] = name_and_input_module_class_pair->first; +// method_dict["InputTypeModuleAndClass"] = +// name_and_input_module_class_pair->second; +// IndentScope raii_indent(out); +// out->Print(method_dict, +// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " +// "$InputTypeModuleAndClass$.FromString,\n"); +// } +// out->Print("}\n"); +// out->Print("response_serializers = {\n"); +// for (StringMap::iterator name_and_output_module_class_pair = +// output_message_modules_and_classes.begin(); +// name_and_output_module_class_pair != +// output_message_modules_and_classes.end(); +// name_and_output_module_class_pair++) { +// method_dict["MethodName"] = name_and_output_module_class_pair->first; +// method_dict["OutputTypeModuleAndClass"] = +// name_and_output_module_class_pair->second; +// IndentScope raii_indent(out); +// out->Print(method_dict, +// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " +// "$OutputTypeModuleAndClass$.SerializeToString,\n"); +// } +// out->Print("}\n"); + out->Print("method_implementations = {\n"); + for (StringMap::iterator name_and_implementation_constructor = + method_implementation_constructors.begin(); + name_and_implementation_constructor != + method_implementation_constructors.end(); + name_and_implementation_constructor++) { + method_dict["Method"] = name_and_implementation_constructor->first; + method_dict["Constructor"] = name_and_implementation_constructor->second; + IndentScope raii_descriptions_indent(out); + const grpc::string method_name = + name_and_implementation_constructor->first; + out->Print(method_dict, + "(\'$PackageQualifiedServiceName$\', \'$Method$\'): " + "face_utilities.$Constructor$(servicer.$Method$),\n"); + } + out->Print("}\n"); + out->Print( + "server_options = beta_implementations.server_options(" + "thread_pool=pool, thread_pool_size=pool_size, " + "default_timeout=default_timeout, " + "maximum_timeout=maximum_timeout)\n"); + out->Print( + "return beta_implementations.server(method_implementations, " + "options=server_options)\n"); + //"request_deserializers=request_deserializers, " + //"response_serializers=response_serializers, " + } +} + +void PrivateGenerator::PrintBetaStubFactory( + const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, grpc_generator::Printer* out) { + StringMap dict; + dict["Service"] = service->name(); + out->Print("\n\n"); + out->Print(dict, + "def beta_create_$Service$_stub(channel, host=None," + " metadata_transformer=None, pool=None, pool_size=None):\n"); + { + IndentScope raii_create_server_indent(out); + out->Print( + "\"\"\"The Beta API is deprecated for 0.15.0 and later.\n" + "\nIt is recommended to use the GA API (classes and functions in this\n" + "file not marked beta) for all further purposes. This function was\n" + "generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0" + "\"\"\"\n"); + StringMap method_cardinalities; + StringMap input_message_modules_and_classes; + StringMap output_message_modules_and_classes; + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + const grpc::string method_cardinality = + grpc::string(method->ClientStreaming() ? "STREAM" : "UNARY") + + "_" + + grpc::string(method->ServerStreaming() ? "STREAM" : "UNARY"); + grpc::string input_message_module_and_class = method->get_fb_builder(); + grpc::string output_message_module_and_class = method->get_fb_builder(); + method_cardinalities.insert( + make_pair(method->name(), method_cardinality)); + input_message_modules_and_classes.insert( + make_pair(method->name(), input_message_module_and_class)); + output_message_modules_and_classes.insert( + make_pair(method->name(), output_message_module_and_class)); + } + StringMap method_dict; + method_dict["PackageQualifiedServiceName"] = package_qualified_service_name; +// out->Print("request_serializers = {\n"); +// for (StringMap::iterator name_and_input_module_class_pair = +// input_message_modules_and_classes.begin(); +// name_and_input_module_class_pair != +// input_message_modules_and_classes.end(); +// name_and_input_module_class_pair++) { +// method_dict["MethodName"] = name_and_input_module_class_pair->first; +// method_dict["InputTypeModuleAndClass"] = +// name_and_input_module_class_pair->second; +// IndentScope raii_indent(out); +// out->Print(method_dict, +// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " +// "$InputTypeModuleAndClass$.SerializeToString,\n"); +// } +// out->Print("}\n"); +// out->Print("response_deserializers = {\n"); +// for (StringMap::iterator name_and_output_module_class_pair = +// output_message_modules_and_classes.begin(); +// name_and_output_module_class_pair != +// output_message_modules_and_classes.end(); +// name_and_output_module_class_pair++) { +// method_dict["MethodName"] = name_and_output_module_class_pair->first; +// method_dict["OutputTypeModuleAndClass"] = +// name_and_output_module_class_pair->second; +// IndentScope raii_indent(out); +// out->Print(method_dict, +// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): " +// "$OutputTypeModuleAndClass$.FromString,\n"); +// } +// out->Print("}\n"); + out->Print("cardinalities = {\n"); + for (StringMap::iterator name_and_cardinality = + method_cardinalities.begin(); + name_and_cardinality != method_cardinalities.end(); + name_and_cardinality++) { + method_dict["Method"] = name_and_cardinality->first; + method_dict["Cardinality"] = name_and_cardinality->second; + IndentScope raii_descriptions_indent(out); + out->Print(method_dict, + "\'$Method$\': cardinality.Cardinality.$Cardinality$,\n"); + } + out->Print("}\n"); + out->Print( + "stub_options = beta_implementations.stub_options(" + "host=host, metadata_transformer=metadata_transformer, " + "thread_pool=pool, thread_pool_size=pool_size)\n"); + out->Print(method_dict, + "return beta_implementations.dynamic_stub(channel, " + "\'$PackageQualifiedServiceName$\', " + "cardinalities, options=stub_options)\n"); + // "request_serializers=request_serializers, " + //"response_deserializers=response_deserializers, " + } +} + +void PrivateGenerator::PrintStub( + const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, grpc_generator::Printer* out) { + StringMap dict; + dict["Service"] = service->name(); + out->Print("\n\n"); + out->Print(dict, "class $Service$Stub(object):\n"); + { + IndentScope raii_class_indent(out); + out->Print("\n"); + out->Print("def __init__(self, channel):\n"); + { + IndentScope raii_init_indent(out); + out->Print("\"\"\"Constructor.\n"); + out->Print("\n"); + out->Print("Args:\n"); + { + IndentScope raii_args_indent(out); + out->Print("channel: A grpc.Channel.\n"); + } + out->Print("\"\"\"\n"); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + grpc::string multi_callable_constructor = + grpc::string(method->ClientStreaming() ? "stream" : "unary") + + "_" + + grpc::string(method->ServerStreaming() ? "stream" : "unary"); + grpc::string request_module_and_class = method->get_fb_builder(); + grpc::string response_module_and_class = method->get_fb_builder(); + StringMap method_dict; + method_dict["Method"] = method->name(); + method_dict["MultiCallableConstructor"] = multi_callable_constructor; + out->Print(method_dict, + "self.$Method$ = channel.$MultiCallableConstructor$(\n"); + { + method_dict["PackageQualifiedService"] = + package_qualified_service_name; + method_dict["RequestModuleAndClass"] = request_module_and_class; + method_dict["ResponseModuleAndClass"] = response_module_and_class; + IndentScope raii_first_attribute_indent(out); + IndentScope raii_second_attribute_indent(out); + out->Print(method_dict, "'/$PackageQualifiedService$/$Method$',\n"); + out->Print(method_dict,"\n"); + out->Print( + method_dict,"\n"); + out->Print(")\n"); + } + } + } + } +} + +void PrivateGenerator::PrintServicer(const grpc_generator::Service* service, + grpc_generator::Printer* out) { + StringMap service_dict; + service_dict["Service"] = service->name(); + out->Print("\n\n"); + out->Print(service_dict, "class $Service$Servicer(object):\n"); + { + IndentScope raii_class_indent(out); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + grpc::string arg_name = + method->ClientStreaming() ? "request_iterator" : "request"; + StringMap method_dict; + method_dict["Method"] = method->name(); + method_dict["ArgName"] = arg_name; + out->Print("\n"); + out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n"); + { + IndentScope raii_method_indent(out); + out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n"); + out->Print("context.set_details('Method not implemented!')\n"); + out->Print("raise NotImplementedError('Method not implemented!')\n"); + } + } + } +} + +void PrivateGenerator::PrintAddServicerToServer( + const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, grpc_generator::Printer* out) { + StringMap service_dict; + service_dict["Service"] = service->name(); + out->Print("\n\n"); + out->Print(service_dict, + "def add_$Service$Servicer_to_server(servicer, server):\n"); + { + IndentScope raii_class_indent(out); + out->Print("rpc_method_handlers = {\n"); + { + IndentScope raii_dict_first_indent(out); + IndentScope raii_dict_second_indent(out); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + grpc::string method_handler_constructor = + grpc::string(method->ClientStreaming() ? "stream" : "unary") + + "_" + + grpc::string(method->ServerStreaming() ? "stream" : "unary") + + "_rpc_method_handler"; + grpc::string request_module_and_class = method->get_fb_builder(); + grpc::string response_module_and_class = method->get_fb_builder(); + StringMap method_dict; + method_dict["Method"] = method->name(); + method_dict["MethodHandlerConstructor"] = method_handler_constructor; + method_dict["RequestModuleAndClass"] = request_module_and_class; + method_dict["ResponseModuleAndClass"] = response_module_and_class; + out->Print(method_dict, + "'$Method$': grpc.$MethodHandlerConstructor$(\n"); + { + IndentScope raii_call_first_indent(out); + IndentScope raii_call_second_indent(out); + out->Print(method_dict, "servicer.$Method$,\n"); + out->Print( + method_dict,"\n"); + out->Print( + method_dict, + "\n"); + } + out->Print("),\n"); + } + } + StringMap method_dict; + method_dict["PackageQualifiedServiceName"] = package_qualified_service_name; + out->Print("}\n"); + out->Print("generic_handler = grpc.method_handlers_generic_handler(\n"); + { + IndentScope raii_call_first_indent(out); + IndentScope raii_call_second_indent(out); + out->Print(method_dict, + "'$PackageQualifiedServiceName$', rpc_method_handlers)\n"); + } + out->Print("server.add_generic_rpc_handlers((generic_handler,))\n"); + } +} + +void PrivateGenerator::PrintBetaPreamble(grpc_generator::Printer* out) { + StringMap var; + var["Package"] = config.beta_package_root; + out->Print(var, + "from $Package$ import implementations as beta_implementations\n"); + out->Print(var, "from $Package$ import interfaces as beta_interfaces\n"); + out->Print("from grpc.framework.common import cardinality\n"); + out->Print( + "from grpc.framework.interfaces.face import utilities as " + "face_utilities\n"); +} + +void PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) { + StringMap var; + var["Package"] = config.grpc_package_root; + out->Print(var, "import $Package$\n"); + out->Print("\n"); + StringPairSet imports_set; + for (int i = 0; i < file->service_count(); ++i) { + auto service = file->service(i); + for (int j = 0; j < service->method_count(); ++j) { + auto method = service.get()->method(j); + + grpc::string input_type_file_name = method->get_fb_builder(); + grpc::string input_module_name = + ModuleName(input_type_file_name, config.import_prefix); + grpc::string input_module_alias = + ModuleAlias(input_type_file_name, config.import_prefix); + imports_set.insert( + std::make_tuple(input_module_name, input_module_alias)); + + grpc::string output_type_file_name = method->get_fb_builder(); + grpc::string output_module_name = + ModuleName(output_type_file_name, config.import_prefix); + grpc::string output_module_alias = + ModuleAlias(output_type_file_name, config.import_prefix); + imports_set.insert( + std::make_tuple(output_module_name, output_module_alias)); + } + } + + for (StringPairSet::iterator it = imports_set.begin(); + it != imports_set.end(); ++it) { + var["ModuleName"] = std::get<0>(*it); + var["ModuleAlias"] = std::get<1>(*it); + out->Print(var, "import $ModuleName$ as $ModuleAlias$\n"); + } +} + +void PrivateGenerator::PrintGAServices(grpc_generator::Printer* out) { + grpc::string package = file->package(); + if (!package.empty()) { + package = package.append("."); + } + + out->Print(file->additional_headers().c_str()); + + for (int i = 0; i < file->service_count(); ++i) { + auto service = file->service(i); + + grpc::string package_qualified_service_name = package + service->name(); + PrintStub(package_qualified_service_name, service.get(), out); + PrintServicer(service.get(), out); + PrintAddServicerToServer(package_qualified_service_name, service.get(), + out); + } +} + +void PrivateGenerator::PrintBetaServices(grpc_generator::Printer* out) { + grpc::string package = file->package(); + if (!package.empty()) { + package = package.append("."); + } + for (int i = 0; i < file->service_count(); ++i) { + auto service = file->service(i); + + grpc::string package_qualified_service_name = package + service->name(); + PrintBetaServicer(service.get(), out); + PrintBetaStub(service.get(), out); + PrintBetaServerFactory(package_qualified_service_name, service.get(), out); + PrintBetaStubFactory(package_qualified_service_name, service.get(), out); + } +} + +grpc::string PrivateGenerator::GetGrpcServices() { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto out = file->CreatePrinter(&output); + out->Print( + "# Generated by the gRPC Python protocol compiler plugin. " + "DO NOT EDIT!\n"); + StringMap var; + var["Package"] = config.grpc_package_root; + out->Print(var, "import $Package$\n"); + PrintGAServices(out.get()); + out->Print("try:\n"); + { + IndentScope raii_dict_try_indent(out.get()); + out->Print( + "# THESE ELEMENTS WILL BE DEPRECATED.\n" + "# Please use the generated *_pb2_grpc.py files instead.\n"); + out->Print(var, "import $Package$\n"); + PrintBetaPreamble(out.get()); + PrintGAServices(out.get()); + PrintBetaServices(out.get()); + } + out->Print("except ImportError:\n"); + { + IndentScope raii_dict_except_indent(out.get()); + out->Print("pass"); + } + } + return output; +} + +} // namespace grpc_python_generator diff --git a/grpc/src/compiler/python_generator.h b/grpc/src/compiler/python_generator.h new file mode 100644 index 000000000..8e3af8a23 --- /dev/null +++ b/grpc/src/compiler/python_generator.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H + +#include + +#include "src/compiler/schema_interface.h" + +namespace grpc_python_generator { + +// Data pertaining to configuration of the generator with respect to anything +// that may be used internally at Google. +struct GeneratorConfiguration { + grpc::string grpc_package_root; + // TODO(https://github.com/grpc/grpc/issues/8622): Drop this. + grpc::string beta_package_root; + // TODO(https://github.com/google/protobuf/issues/888): Drop this. + grpc::string import_prefix; +}; + +} // namespace grpc_python_generator + +#endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H diff --git a/grpc/src/compiler/python_private_generator.h b/grpc/src/compiler/python_private_generator.h new file mode 100644 index 000000000..f070145c6 --- /dev/null +++ b/grpc/src/compiler/python_private_generator.h @@ -0,0 +1,87 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H + +#include +#include + +#include "src/compiler/python_generator.h" +#include "src/compiler/schema_interface.h" + +namespace grpc_python_generator { + +// Tucks all generator state in an anonymous namespace away from +// PythonGrpcGenerator and the header file, mostly to encourage future changes +// to not require updates to the grpcio-tools C++ code part. Assumes that it is +// only ever used from a single thread. +struct PrivateGenerator { + const GeneratorConfiguration& config; + const grpc_generator::File* file; + + PrivateGenerator(const GeneratorConfiguration& config, + const grpc_generator::File* file); + + grpc::string GetGrpcServices(); + + private: + void PrintPreamble(grpc_generator::Printer* out); + void PrintBetaPreamble(grpc_generator::Printer* out); + void PrintGAServices(grpc_generator::Printer* out); + void PrintBetaServices(grpc_generator::Printer* out); + + void PrintAddServicerToServer( + const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, grpc_generator::Printer* out); + void PrintServicer(const grpc_generator::Service* service, + grpc_generator::Printer* out); + void PrintStub(const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, + grpc_generator::Printer* out); + + void PrintBetaServicer(const grpc_generator::Service* service, + grpc_generator::Printer* out); + void PrintBetaServerFactory( + const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, grpc_generator::Printer* out); + void PrintBetaStub(const grpc_generator::Service* service, + grpc_generator::Printer* out); + void PrintBetaStubFactory(const grpc::string& package_qualified_service_name, + const grpc_generator::Service* service, + grpc_generator::Printer* out); +}; + +} // namespace grpc_python_generator + +#endif // GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H diff --git a/grpc/src/compiler/schema_interface.h b/grpc/src/compiler/schema_interface.h index 638448d3a..52060bc51 100644 --- a/grpc/src/compiler/schema_interface.h +++ b/grpc/src/compiler/schema_interface.h @@ -79,6 +79,9 @@ struct Method : public CommentHolder { virtual grpc::string get_input_type_name() const = 0; virtual grpc::string get_output_type_name() const = 0; + + virtual grpc::string get_fb_builder() const = 0; + virtual bool NoStreaming() const = 0; virtual bool ClientStreaming() const = 0; virtual bool ServerStreaming() const = 0; diff --git a/grpc/tests/grpctest.py b/grpc/tests/grpctest.py new file mode 100644 index 000000000..1c5e92f06 --- /dev/null +++ b/grpc/tests/grpctest.py @@ -0,0 +1,174 @@ +from __future__ import print_function + +import os +import sys +import grpc +import flatbuffers + +from concurrent import futures + +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'tests')) +import MyGame.Example.Monster as Monster +import MyGame.Example.Stat as Stat +import MyGame.Example.Vec3 as Vec3 +import MyGame.Example.Test as Test +import MyGame.Example.monster_test_grpc_fb as monster_grpc_fb + + +test_stat_id = "test_stat_id" +test_stat_val = 8 +test_stat_count = 1 + +test_monster_name1 = "test_monster_name1" +test_monster_name2 = "test_monster_name2" +test_string = "test_string" +test_color = 2 +test_X = 3.0 +test_Y = 2.0 +test_Z = 6.0 +test_test1 = 4.0 +test_a = 8 +test_b = 5 +test_hp = 67 +test_inventory = [1, 1, 2, 3, 5, 8] +test_testtype = 4 + +test_monsters_name_retrieve = ["big_monster", "small_monster"] +test_no_of_monsters = 2 + + +class MonsterStorage(monster_grpc_fb.MonsterStorageServicer): + + def Store(self, request, context): + + m = Monster.Monster().GetRootAsMonster(request, 0) + + assert m.Name().decode("utf-8") == test_monster_name1 + + assert m.Pos().X() == test_X + assert m.Pos().Y() == test_Y + assert m.Pos().Z() == test_Z + assert m.Pos().Test1() == test_test1 + assert m.Pos().Test2() == test_color + test3 = Test.Test() + assert m.Pos().Test3(test3).A() == test_a + assert m.Pos().Test3(test3).B() == test_b + + assert m.Hp() == test_hp + + assert m.Color() == test_color + + assert m.InventoryLength() == len(test_inventory) + for i in range(0, len(test_inventory)): + assert m.Inventory(i) == test_inventory[len(test_inventory)-i -1] + + assert m.TestType() == test_testtype + + assert m.Test() is not None + table = m.Test() + + m2 = Monster.Monster() + m2.Init(table.Bytes, table.Pos) + assert m2.Name().decode("utf-8") == test_monster_name2 + + m3 = m.Enemy() + assert m3.Name().decode("utf-8") == test_monster_name2 + + assert m.Testarrayofstring(0).decode("utf-8") == test_string + + b = flatbuffers.Builder(0) + i = b.CreateString(test_stat_id) + Stat.StatStart(b) + Stat.StatAddId(b, i) + Stat.StatAddVal(b, test_stat_val) + Stat.StatAddCount(b, test_stat_count) + b.Finish(Stat.StatEnd(b)) + return bytes(b.Output()) + + def Retrieve(self, request, context): + + s = Stat.Stat().GetRootAsStat(request, 0) + + no_of_monsters = test_no_of_monsters + for i in range(0, no_of_monsters): + b = flatbuffers.Builder(0) + i = b.CreateString(test_monsters_name_retrieve[i]) + Monster.MonsterStart(b) + Monster.MonsterAddName(b, i) + b.Finish(Monster.MonsterEnd(b)) + yield bytes(b.Output()) + + +def serve(): + + server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server) + server.add_insecure_port('[::]:50051') + + server.start() + + run() + + +def run(): + + channel = grpc.insecure_channel('127.0.0.1:50051') + stub = monster_grpc_fb.MonsterStorageStub(channel) + + b = flatbuffers.Builder(0) + name2 = b.CreateString(test_monster_name2) + name1 = b.CreateString(test_monster_name1) + Monster.MonsterStart(b) + Monster.MonsterAddName(b, name2) + monster2 = Monster.MonsterEnd(b) + test1 = b.CreateString(test_string) + + Monster.MonsterStartInventoryVector(b, len(test_inventory)) + for i in range(0, len(test_inventory)): + b.PrependByte(test_inventory[i]) + inv = b.EndVector(len(test_inventory)) + + Monster.MonsterStartTest4Vector(b, 2) + Test.CreateTest(b, 10, 20) + Test.CreateTest(b, 30, 40) + test4 = b.EndVector(2) + + Monster.MonsterStartTestarrayofstringVector(b, 1) + b.PrependUOffsetTRelative(test1) + test_array_of_string = b.EndVector(1) + + Monster.MonsterStart(b) + + Monster.MonsterAddHp(b, test_hp) + Monster.MonsterAddName(b, name1) + Monster.MonsterAddColor(b, test_color) + pos = Vec3.CreateVec3(b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b) + Monster.MonsterAddPos(b, pos) + Monster.MonsterAddInventory(b, inv) + Monster.MonsterAddTestType(b, test_testtype) + Monster.MonsterAddTest(b, monster2) + Monster.MonsterAddTest4(b, test4) + Monster.MonsterAddEnemy(b, monster2) + Monster.MonsterAddTestarrayofstring(b, test_array_of_string) + monster = Monster.MonsterEnd(b) + + b.Finish(monster) + + stat_response = stub.Store(bytes(b.Output())) + + s = Stat.Stat().GetRootAsStat(stat_response, 0) + + assert s.Id().decode("utf-8") == test_stat_id + assert s.Val() == test_stat_val + assert s.Count() == test_stat_count + + monster_reponses = stub.Retrieve(stat_response) + count = 0 + for monster_reponse in monster_reponses: + m = Monster.Monster().GetRootAsMonster(monster_reponse, 0) + assert m.Name().decode("utf-8") == test_monsters_name_retrieve[count] + count = count + 1 + + +if __name__ == '__main__': + serve() diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 4d567dc99..5c7fc11d7 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -1090,6 +1090,12 @@ bool GenerateGoGRPC(const Parser &parser, const std::string &path, bool GenerateJavaGRPC(const Parser &parser, const std::string &path, const std::string &file_name); +// Generate GRPC Python interfaces. +// See idl_gen_grpc.cpp. +bool GeneratePythonGRPC(const Parser &parser, + const std::string &path, + const std::string &file_name); + } // namespace flatbuffers #endif // FLATBUFFERS_IDL_H_ diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index 1b02d2949..f54b94e8e 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -74,8 +74,8 @@ int main(int argc, const char *argv[]) { flatbuffers::IDLOptions::kCSharp, "Generate C# classes for tables/structs", flatbuffers::JavaCSharpMakeRule }, - { flatbuffers::GeneratePython, "-p", "--python", "Python", true, nullptr, - flatbuffers::IDLOptions::kPython, + { flatbuffers::GeneratePython, "-p", "--python", "Python", true, + flatbuffers::GeneratePythonGRPC, flatbuffers::IDLOptions::kPython, "Generate Python files for tables/structs", nullptr }, { flatbuffers::GenerateLobster, nullptr, "--lobster", "Lobster", true, nullptr, flatbuffers::IDLOptions::kLobster, diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp index ec129902c..84d6dba61 100644 --- a/src/idl_gen_grpc.cpp +++ b/src/idl_gen_grpc.cpp @@ -23,6 +23,8 @@ #include "src/compiler/cpp_generator.h" #include "src/compiler/go_generator.h" #include "src/compiler/java_generator.h" +#include "src/compiler/python_generator.h" +#include "src/compiler/python_private_generator.h" #if defined(_MSC_VER) # pragma warning(push) @@ -77,6 +79,10 @@ class FlatBufMethod : public grpc_generator::Method { return true; } + std::string get_fb_builder() const { + return "builder"; + } + std::string input_type_name() const { return GRPCType(*method_->request); } std::string output_type_name() const { return GRPCType(*method_->response); } @@ -179,7 +185,9 @@ class FlatBufPrinter : public grpc_generator::Printer { class FlatBufFile : public grpc_generator::File { public: - enum Language { kLanguageGo, kLanguageCpp, kLanguageJava }; + enum Language { + kLanguageGo, kLanguageCpp, kLanguageJava, kLanguagePython + }; FlatBufFile(const Parser &parser, const std::string &file_name, Language language) @@ -224,6 +232,9 @@ class FlatBufFile : public grpc_generator::File { case kLanguageJava: { return "import com.google.flatbuffers.grpc.FlatbuffersUtils;"; } + case kLanguagePython: { + return ""; + } } return ""; } @@ -360,6 +371,38 @@ bool GenerateJavaGRPC(const Parser &parser, const std::string &path, return JavaGRPCGenerator(parser, path, file_name).generate(); } +bool GeneratePythonGRPC(const Parser &parser, const std::string & /*path*/, + const std::string &file_name) { + + int nservices = 0; + for (auto it = parser.services_.vec.begin(); it != parser.services_.vec.end(); + ++it) { + if (!(*it)->generated) nservices++; + } + if (!nservices) return true; + + grpc_python_generator::GeneratorConfiguration config; + config.grpc_package_root = "grpc"; + config.beta_package_root = "grpc.beta"; + config.import_prefix = ""; + + FlatBufFile fbfile(parser, file_name, FlatBufFile::kLanguagePython); + + grpc_python_generator::PrivateGenerator generator(config, &fbfile); + + std::string code = generator.GetGrpcServices(); + std::string namespace_dir; + auto &namespaces = parser.namespaces_.back()->components; + for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { + if (it != namespaces.begin()) namespace_dir += kPathSeparator; + namespace_dir += *it; + } + + std::string grpc_py_filename = + namespace_dir + kPathSeparator + file_name + "_grpc_fb.py"; + return flatbuffers::SaveFile(grpc_py_filename.c_str(), code, false); +} + } // namespace flatbuffers #if defined(_MSC_VER) diff --git a/tests/MyGame/Example/monster_test_grpc_fb.py b/tests/MyGame/Example/monster_test_grpc_fb.py new file mode 100644 index 000000000..8375c9824 --- /dev/null +++ b/tests/MyGame/Example/monster_test_grpc_fb.py @@ -0,0 +1,241 @@ +# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! +import grpc + + +class MonsterStorageStub(object): + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Store = channel.unary_unary( + '/MyGame.Example.MonsterStorage/Store', + + + ) + self.Retrieve = channel.unary_stream( + '/MyGame.Example.MonsterStorage/Retrieve', + + + ) + self.GetMaxHitPoint = channel.stream_unary( + '/MyGame.Example.MonsterStorage/GetMaxHitPoint', + + + ) + self.GetMinMaxHitPoints = channel.unary_unary( + '/MyGame.Example.MonsterStorage/GetMinMaxHitPoints', + + + ) + + +class MonsterStorageServicer(object): + + def Store(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Retrieve(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMaxHitPoint(self, request_iterator, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMinMaxHitPoints(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + +def add_MonsterStorageServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Store': grpc.unary_unary_rpc_method_handler( + servicer.Store, + + + ), + 'Retrieve': grpc.unary_stream_rpc_method_handler( + servicer.Retrieve, + + + ), + 'GetMaxHitPoint': grpc.stream_unary_rpc_method_handler( + servicer.GetMaxHitPoint, + + + ), + 'GetMinMaxHitPoints': grpc.unary_unary_rpc_method_handler( + servicer.GetMinMaxHitPoints, + + + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'MyGame.Example.MonsterStorage', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) +try: + # THESE ELEMENTS WILL BE DEPRECATED. + # Please use the generated *_pb2_grpc.py files instead. + import grpc + from grpc.beta import implementations as beta_implementations + from grpc.beta import interfaces as beta_interfaces + from grpc.framework.common import cardinality + from grpc.framework.interfaces.face import utilities as face_utilities + + + class MonsterStorageStub(object): + + def __init__(self, channel): + """Constructor. + + Args: + channel: A grpc.Channel. + """ + self.Store = channel.unary_unary( + '/MyGame.Example.MonsterStorage/Store', + + + ) + self.Retrieve = channel.unary_stream( + '/MyGame.Example.MonsterStorage/Retrieve', + + + ) + self.GetMaxHitPoint = channel.stream_unary( + '/MyGame.Example.MonsterStorage/GetMaxHitPoint', + + + ) + self.GetMinMaxHitPoints = channel.unary_unary( + '/MyGame.Example.MonsterStorage/GetMinMaxHitPoints', + + + ) + + + class MonsterStorageServicer(object): + + def Store(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def Retrieve(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMaxHitPoint(self, request_iterator, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def GetMinMaxHitPoints(self, request, context): + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + + def add_MonsterStorageServicer_to_server(servicer, server): + rpc_method_handlers = { + 'Store': grpc.unary_unary_rpc_method_handler( + servicer.Store, + + + ), + 'Retrieve': grpc.unary_stream_rpc_method_handler( + servicer.Retrieve, + + + ), + 'GetMaxHitPoint': grpc.stream_unary_rpc_method_handler( + servicer.GetMaxHitPoint, + + + ), + 'GetMinMaxHitPoints': grpc.unary_unary_rpc_method_handler( + servicer.GetMinMaxHitPoints, + + + ), + } + generic_handler = grpc.method_handlers_generic_handler( + 'MyGame.Example.MonsterStorage', rpc_method_handlers) + server.add_generic_rpc_handlers((generic_handler,)) + + + class BetaMonsterStorageServicer(object): + """The Beta API is deprecated for 0.15.0 and later. + + It is recommended to use the GA API (classes and functions in this + file not marked beta) for all further purposes. This class was generated + only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" + def Store(self, request, context): + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) + def Retrieve(self, request, context): + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) + def GetMaxHitPoint(self, request_iterator, context): + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) + def GetMinMaxHitPoints(self, request, context): + context.code(beta_interfaces.StatusCode.UNIMPLEMENTED) + + + class BetaMonsterStorageStub(object): + """The Beta API is deprecated for 0.15.0 and later. + + It is recommended to use the GA API (classes and functions in this + file not marked beta) for all further purposes. This class was generated + only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0.""" + def Store(self, request, timeout, metadata=None, with_call=False, protocol_options=None): + raise NotImplementedError() + Store.future = None + def Retrieve(self, request, timeout, metadata=None, with_call=False, protocol_options=None): + raise NotImplementedError() + def GetMaxHitPoint(self, request_iterator, timeout, metadata=None, with_call=False, protocol_options=None): + raise NotImplementedError() + GetMaxHitPoint.future = None + def GetMinMaxHitPoints(self, request, timeout, metadata=None, with_call=False, protocol_options=None): + raise NotImplementedError() + GetMinMaxHitPoints.future = None + + + def beta_create_MonsterStorage_server(servicer, pool=None, pool_size=None, default_timeout=None, maximum_timeout=None): + """The Beta API is deprecated for 0.15.0 and later. + + It is recommended to use the GA API (classes and functions in this + file not marked beta) for all further purposes. This function was + generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" + method_implementations = { + ('MyGame.Example.MonsterStorage', 'GetMaxHitPoint'): face_utilities.stream_unary_inline(servicer.GetMaxHitPoint), + ('MyGame.Example.MonsterStorage', 'GetMinMaxHitPoints'): face_utilities.unary_unary_inline(servicer.GetMinMaxHitPoints), + ('MyGame.Example.MonsterStorage', 'Retrieve'): face_utilities.unary_stream_inline(servicer.Retrieve), + ('MyGame.Example.MonsterStorage', 'Store'): face_utilities.unary_unary_inline(servicer.Store), + } + server_options = beta_implementations.server_options(thread_pool=pool, thread_pool_size=pool_size, default_timeout=default_timeout, maximum_timeout=maximum_timeout) + return beta_implementations.server(method_implementations, options=server_options) + + + def beta_create_MonsterStorage_stub(channel, host=None, metadata_transformer=None, pool=None, pool_size=None): + """The Beta API is deprecated for 0.15.0 and later. + + It is recommended to use the GA API (classes and functions in this + file not marked beta) for all further purposes. This function was + generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0""" + cardinalities = { + 'GetMaxHitPoint': cardinality.Cardinality.STREAM_UNARY, + 'GetMinMaxHitPoints': cardinality.Cardinality.UNARY_UNARY, + 'Retrieve': cardinality.Cardinality.UNARY_STREAM, + 'Store': cardinality.Cardinality.UNARY_UNARY, + } + stub_options = beta_implementations.stub_options(host=host, metadata_transformer=metadata_transformer, thread_pool=pool, thread_pool_size=pool_size) + return beta_implementations.dynamic_stub(channel, 'MyGame.Example.MonsterStorage', cardinalities, options=stub_options) +except ImportError: + pass \ No newline at end of file From ff3781dc2d541c68122ec33c96ddf7032fcca27e Mon Sep 17 00:00:00 2001 From: FujiZ Date: Tue, 19 Nov 2019 04:02:14 +0800 Subject: [PATCH 22/28] add namespace prefix in FLATBUFFERS_MAX_BUFFER_SIZE (#5629) --- include/flatbuffers/base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/flatbuffers/base.h b/include/flatbuffers/base.h index 92c47a327..86ecf2386 100644 --- a/include/flatbuffers/base.h +++ b/include/flatbuffers/base.h @@ -296,7 +296,7 @@ typedef uint16_t voffset_t; typedef uintmax_t largest_scalar_t; // In 32bits, this evaluates to 2GB - 1 -#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1) +#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1) // We support aligning the contents of buffers up to this size. #define FLATBUFFERS_MAX_ALIGNMENT 16 From 091fa1fd1b9ae8eabb99075b3ddfd9023f95468d Mon Sep 17 00:00:00 2001 From: Vladimir Glavnyy <31897320+vglavnyy@users.noreply.github.com> Date: Tue, 19 Nov 2019 03:16:41 +0700 Subject: [PATCH 23/28] Add testing of C++ with sanitizers (CI-Docker) (#5631) * Add C++ build testing with clang and gcc This adds Dockerfiles which test building flatc and the C++ library against clang and gcc. See discussion at #5119. It is derived from the Travis CI tooling. The GRPC tests are failing due to #5099 so those are commented out. These are run from the .travis.yml file rather than the tests/docker/languages folder because the builds may each take longer than 30 minutes and were hitting Travis timeouts. Parallel builds and build caching attempt to keep the build times low. * Add GCC 8.3 and Clang 7.0 with sanitizers into CI (based on #5130) - Add a docker based on Debian Buster. - Add C++ building scripts for the docker. - Leak-sanitizer requires SYS_PTRACE. --- .../build-and-run-docker-test-containers.sh | 13 ++++++++---- CMakeLists.txt | 5 +++++ .../Dockerfile.testing.cpp.debian_buster | 10 ++++++++++ tests/docker/build_flatc.run.sh | 15 ++++++++++++++ tests/docker/cpp_test.run.sh | 20 +++++++++++++++++++ 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 tests/docker/Dockerfile.testing.cpp.debian_buster create mode 100755 tests/docker/build_flatc.run.sh create mode 100755 tests/docker/cpp_test.run.sh diff --git a/.travis/build-and-run-docker-test-containers.sh b/.travis/build-and-run-docker-test-containers.sh index e6039bf62..d377ba8dd 100755 --- a/.travis/build-and-run-docker-test-containers.sh +++ b/.travis/build-and-run-docker-test-containers.sh @@ -15,10 +15,15 @@ # limitations under the License. set -e -# build flatc on debian once to speed up the test loop below -docker build -t build_flatc_debian_stretch -f tests/docker/Dockerfile.testing.build_flatc_debian_stretch . -BUILD_CONTAINER_ID=$(docker create --read-only build_flatc_debian_stretch) -docker cp ${BUILD_CONTAINER_ID}:/code/flatc flatc_debian_stretch +docker build -t build_cpp_image -f tests/docker/Dockerfile.testing.cpp.debian_buster . +# Run tests with sanitizers (--cap-add SYS_PTRACE), both GCC and Clang. +cpp_test_args="--cap-add SYS_PTRACE build_cpp_image sh ./tests/docker/cpp_test.run.sh Debug" +docker run --rm $cpp_test_args +docker run --rm --env CC=/usr/bin/clang --env CXX=/usr/bin/clang++ $cpp_test_args +# Build flatc on debian once to speed up the test loop below. +docker run --name flatc_container build_cpp_image sh ./tests/docker/build_flatc.run.sh Debug +# All dependent dockers refer to 'flatc_debian_stretch'. +docker cp flatc_container:/flatbuffers/flatc flatc_debian_stretch for f in $(ls tests/docker/languages | sort) do diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b02d45cb..e7e998095 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ option(FLATBUFFERS_BUILD_FLATLIB "Enable the build of the flatbuffers library" ON) option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler" ON) +option(FLATBUFFERS_STATIC_FLATC "Build flatbuffers compiler with -static flag" + OFF) option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON) option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF) option(FLATBUFFERS_BUILD_SHAREDLIB @@ -295,6 +297,9 @@ if(FLATBUFFERS_BUILD_FLATC) # Make flatc.exe not depend on runtime dlls for easy distribution. target_compile_options(flatc PUBLIC $<$:/MT>) endif() + if(FLATBUFFERS_STATIC_FLATC AND NOT MSVC) + target_link_libraries(flatc PRIVATE -static) + endif() endif() if(FLATBUFFERS_BUILD_FLATHASH) diff --git a/tests/docker/Dockerfile.testing.cpp.debian_buster b/tests/docker/Dockerfile.testing.cpp.debian_buster new file mode 100644 index 000000000..7b0cce2de --- /dev/null +++ b/tests/docker/Dockerfile.testing.cpp.debian_buster @@ -0,0 +1,10 @@ +FROM debian:10.1-slim as base +RUN apt -qq update >/dev/null +RUN apt -qq install -y cmake make build-essential >/dev/null +RUN apt -qq install -y autoconf git libtool >/dev/null +RUN apt -qq install -y clang >/dev/null +FROM base +# Travis machines have 2 cores. Can be redefined with 'run --env PAR_JOBS=N'. +ENV JOBS=2 +WORKDIR /flatbuffers +ADD . . diff --git a/tests/docker/build_flatc.run.sh b/tests/docker/build_flatc.run.sh new file mode 100755 index 000000000..c8885b19b --- /dev/null +++ b/tests/docker/build_flatc.run.sh @@ -0,0 +1,15 @@ +set -e + +JOBS=${JOBS:-1} +config=$1 +echo "" +echo "Build 'flatc' compiler for '$config'" + +cmake . -DCMAKE_BUILD_TYPE=$config \ + -DFLATBUFFERS_BUILD_FLATC=1 -DFLATBUFFERS_STATIC_FLATC=1 \ + -DFLATBUFFERS_BUILD_TESTS=0 -DFLATBUFFERS_INSTALL=0 +cmake --build . --target flatc --clean-first -- -j$JOBS + +echo "Check generated code" +.travis/check-generate-code.sh +echo "Done" diff --git a/tests/docker/cpp_test.run.sh b/tests/docker/cpp_test.run.sh new file mode 100755 index 000000000..fa3b0fb10 --- /dev/null +++ b/tests/docker/cpp_test.run.sh @@ -0,0 +1,20 @@ +set -e + +JOBS=${JOBS:-1} +export UBSAN_OPTIONS=halt_on_error=1 +export ASAN_OPTIONS=halt_on_error=1 +export MAKEFLAGS="-j$JOBS" + +config=$1 +echo "" +echo "Build Flatbuffers project for '$config' with jobs=$JOBS" + +cmake . -DCMAKE_BUILD_TYPE=$config \ + -DFLATBUFFERS_BUILD_TESTS=ON -DFLATBUFFERS_CODE_SANITIZE=ON +cmake --build . --target all --clean-first -- -j$JOBS +ctest --extra-verbose --output-on-failure -j$JOBS + +echo "Check generated code" +.travis/check-generate-code.sh + +echo "C++ tests done" From 136d75fa6580ef87d1b7cbc243e617f21149852e Mon Sep 17 00:00:00 2001 From: Derek Bailey Date: Thu, 21 Nov 2019 10:25:31 -0800 Subject: [PATCH 24/28] Changed null checks in test. Removed verifier pointer usage (#5634) --- tests/test.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/test.cpp b/tests/test.cpp index 68716c67b..515e2c438 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -2319,7 +2319,6 @@ void EvolutionTest() { std::string schemas[NUM_VERSIONS]; std::string jsonfiles[NUM_VERSIONS]; std::vector binaries[NUM_VERSIONS]; - flatbuffers::Verifier *verifiers[NUM_VERSIONS]; flatbuffers::IDLOptions idl_opts; idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kBinary; @@ -2341,26 +2340,25 @@ void EvolutionTest() { auto buf = parser.builder_.GetBufferPointer(); binaries[i].reserve(bufLen); std::copy(buf, buf + bufLen, std::back_inserter(binaries[i])); - - verifiers[i] = new flatbuffers::Verifier(&binaries[i].front(), bufLen); } // Assert that all the verifiers for the different schema versions properly verify any version data. for (int i = 0; i < NUM_VERSIONS; ++i) { - TEST_ASSERT(Evolution::V1::VerifyRootBuffer(*verifiers[i])); - TEST_ASSERT(Evolution::V2::VerifyRootBuffer(*verifiers[i])); + flatbuffers::Verifier verifier(&binaries[i].front(), binaries[i].size()); + TEST_ASSERT(Evolution::V1::VerifyRootBuffer(verifier)); + TEST_ASSERT(Evolution::V2::VerifyRootBuffer(verifier)); } // Test backwards compatibility by reading old data with an evolved schema. auto root_v1_viewed_from_v2 = Evolution::V2::GetRoot(&binaries[0].front()); // field 'j' is new in version 2, so it should be null. - TEST_EQ(root_v1_viewed_from_v2->j(), NULL); + TEST_ASSERT(nullptr == root_v1_viewed_from_v2->j()); // field 'k' is new in version 2 with a default of 56. TEST_EQ(root_v1_viewed_from_v2->k(), 56); // field 'c' of 'TableA' is new in version 2, so it should be null. - TEST_EQ(root_v1_viewed_from_v2->e()->c(), NULL); + TEST_ASSERT(nullptr == root_v1_viewed_from_v2->e()->c()); // 'TableC' was added to field 'c' union in version 2, so it should be null. - TEST_EQ(root_v1_viewed_from_v2->c_as_TableC(), NULL); + TEST_ASSERT(nullptr == root_v1_viewed_from_v2->c_as_TableC()); // The field 'c' union should be of type 'TableB' regardless of schema version TEST_ASSERT(root_v1_viewed_from_v2->c_type() == Evolution::V2::Union::TableB); // The field 'f' was renamed to 'ff' in version 2, it should still be readable. From bcf1bd5c9e87df127f1647867574737e6e1674b0 Mon Sep 17 00:00:00 2001 From: FujiZ Date: Tue, 26 Nov 2019 04:52:42 +0800 Subject: [PATCH 25/28] read vtable size through ReadScalar() (#5636) --- include/flatbuffers/flatbuffers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 5c846a6d9..94f78d9b4 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1364,7 +1364,7 @@ class FlatBufferBuilder { it += sizeof(uoffset_t)) { auto vt_offset_ptr = reinterpret_cast(it); auto vt2 = reinterpret_cast(buf_.data_at(*vt_offset_ptr)); - auto vt2_size = *vt2; + auto vt2_size = ReadScalar(vt2); if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue; vt_use = *vt_offset_ptr; buf_.pop(GetSize() - vtableoffsetloc); From 075e8d676bbea12ca678409f413edbbe90276798 Mon Sep 17 00:00:00 2001 From: Vladimir Glavnyy <31897320+vglavnyy@users.noreply.github.com> Date: Tue, 26 Nov 2019 03:54:59 +0700 Subject: [PATCH 26/28] Simplify declarations of x-macro FLATBUFFERS_TD (#5638) --- include/flatbuffers/idl.h | 26 +++++++++++++----- src/idl_gen_cpp.cpp | 7 +++-- src/idl_gen_csharp.cpp | 7 +++-- src/idl_gen_go.cpp | 7 +++-- src/idl_gen_java.cpp | 12 ++++----- src/idl_gen_kotlin.cpp | 12 ++++----- src/idl_gen_lobster.cpp | 8 +++--- src/idl_gen_lua.cpp | 14 +++++----- src/idl_gen_php.cpp | 14 +++++----- src/idl_gen_python.cpp | 6 ++--- src/idl_gen_rust.cpp | 18 ++++++------- src/idl_gen_text.cpp | 25 ++++++++--------- src/idl_parser.cpp | 56 +++++++++++++++------------------------ 13 files changed, 102 insertions(+), 110 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 5c7fc11d7..4e8f71d37 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -91,6 +91,20 @@ switch (type) { } */ +// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation +// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed). +// In the above example, only CTYPE is used to generate the code, it can be rewritten: + +/* +switch (type) { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + case BASE_TYPE_ ## ENUM: \ + // do something specific to CTYPE here + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD +} +*/ + #define FLATBUFFERS_GEN_TYPES(TD) \ FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ FLATBUFFERS_GEN_TYPES_POINTER(TD) \ @@ -101,17 +115,15 @@ switch (type) { __extension__ // Stop GCC complaining about trailing comma with -Wpendantic. #endif enum BaseType { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ - RTYPE, KTYPE) \ - BASE_TYPE_ ## ENUM, + #define FLATBUFFERS_TD(ENUM, ...) \ + BASE_TYPE_ ## ENUM, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD }; -#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ - RTYPE, KTYPE) \ - static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \ - "define largest_scalar_t as " #CTYPE); +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \ + "define largest_scalar_t as " #CTYPE); FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 706732b0f..214b8c5d9 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -545,11 +545,10 @@ class CppGenerator : public BaseGenerator { std::string GenTypeBasic(const Type &type, bool user_facing_type) const { // clang-format off static const char *const ctypename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ - RTYPE, KTYPE) \ - #CTYPE, + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + #CTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD + #undef FLATBUFFERS_TD }; // clang-format on if (user_facing_type) { diff --git a/src/idl_gen_csharp.cpp b/src/idl_gen_csharp.cpp index 5045bd95d..ca7614847 100644 --- a/src/idl_gen_csharp.cpp +++ b/src/idl_gen_csharp.cpp @@ -119,11 +119,10 @@ class CSharpGenerator : public BaseGenerator { std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const { // clang-format off static const char * const csharp_typename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, ...) \ #NTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD }; // clang-format on diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 4ed1a80b2..7dc56df0d 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -1162,15 +1162,14 @@ class GoGenerator : public BaseGenerator { } std::string GenTypeBasic(const Type &type) { - static const char *ctypename[] = { // clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + static const char *ctypename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, ...) \ #GTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on }; + // clang-format on return ctypename[type.base_type]; } diff --git a/src/idl_gen_java.cpp b/src/idl_gen_java.cpp index b257111f8..b67438db0 100644 --- a/src/idl_gen_java.cpp +++ b/src/idl_gen_java.cpp @@ -142,15 +142,13 @@ class JavaGenerator : public BaseGenerator { std::string GenTypeBasic(const Type &type) const { // clang-format off - static const char * const java_typename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + static const char * const java_typename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, ...) \ #JTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - }; + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + }; // clang-format on - return java_typename[type.base_type]; } diff --git a/src/idl_gen_kotlin.cpp b/src/idl_gen_kotlin.cpp index b12e554d3..9827ebbac 100644 --- a/src/idl_gen_kotlin.cpp +++ b/src/idl_gen_kotlin.cpp @@ -139,14 +139,14 @@ class KotlinGenerator : public BaseGenerator { static std::string GenTypeBasic(const BaseType &type) { // clang-format off - static const char * const kotlin_typename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - #KTYPE, + static const char * const kotlin_typename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ + CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #KTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - // clang-format on + #undef FLATBUFFERS_TD }; + // clang-format on return kotlin_typename[type]; } diff --git a/src/idl_gen_lobster.cpp b/src/idl_gen_lobster.cpp index d5c99f7ee..3a0e321a0 100644 --- a/src/idl_gen_lobster.cpp +++ b/src/idl_gen_lobster.cpp @@ -83,15 +83,15 @@ class LobsterGenerator : public BaseGenerator { // This uses Python names for now.. std::string GenTypeBasic(const Type &type) { - static const char *ctypename[] = { // clang-format off + static const char *ctypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \ #PTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on }; + // clang-format on return ctypename[type.base_type]; } diff --git a/src/idl_gen_lua.cpp b/src/idl_gen_lua.cpp index 6ae7dd4cd..6be806b9d 100644 --- a/src/idl_gen_lua.cpp +++ b/src/idl_gen_lua.cpp @@ -595,15 +595,15 @@ class LuaGenerator : public BaseGenerator { } std::string GenTypeBasic(const Type &type) { - static const char *ctypename[] = { // clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - #PTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - // clang-format on + static const char *ctypename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ + CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \ + #PTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD }; + // clang-format on return ctypename[type.base_type]; } diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index 16e47816c..d1e3550cb 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -860,15 +860,15 @@ class PhpGenerator : public BaseGenerator { } static std::string GenTypeBasic(const Type &type) { - static const char *ctypename[] = { // clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - #NTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) - #undef FLATBUFFERS_TD - // clang-format on + static const char *ctypename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ + CTYPE, JTYPE, GTYPE, NTYPE, ...) \ + #NTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD }; + // clang-format on return ctypename[type.base_type]; } diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index bff0d8492..58d0e0fbe 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -667,15 +667,15 @@ class PythonGenerator : public BaseGenerator { } std::string GenTypeBasic(const Type &type) { - static const char *ctypename[] = { // clang-format off + static const char *ctypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, ...) \ #PTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on }; + // clang-format on return ctypename[IsArray(type) ? type.VectorType().base_type : type.base_type]; } diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 3c23f2f9d..fdf58e345 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -457,12 +457,12 @@ class RustGenerator : public BaseGenerator { // clang-format off static const char * const ctypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ - RTYPE, KTYPE) \ - #RTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + RTYPE, ...) \ + #RTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on }; + // clang-format on if (type.enum_def) { return WrapInNameSpace(*type.enum_def); } return ctypename[type.base_type]; @@ -476,15 +476,15 @@ class RustGenerator : public BaseGenerator { FLATBUFFERS_ASSERT(false && "precondition failed in GetEnumTypeForDecl"); } - static const char *ctypename[] = { // clang-format off + static const char *ctypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ - RTYPE, KTYPE) \ - #RTYPE, - FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + RTYPE, ...) \ + #RTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on }; + // clang-format on // Enums can be bools, but their Rust representation must be a u8, as used // in the repr attribute (#[repr(bool)] is an invalid attribute). diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp index 1d0a3caaf..4c00472df 100644 --- a/src/idl_gen_text.cpp +++ b/src/idl_gen_text.cpp @@ -167,8 +167,7 @@ bool Print(const void *val, Type type, int indent, // Call PrintVector above specifically for each element type: // clang-format off switch (vec_type.base_type) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_ ## ENUM: \ if (!PrintVector( \ *reinterpret_cast *>(val), \ @@ -187,8 +186,7 @@ bool Print(const void *val, Type type, int indent, // Call PrintArray above specifically for each element type: // clang-format off switch (vec_type.base_type) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_ ## ENUM: \ if (!PrintArray( \ *reinterpret_cast *>(val), \ @@ -198,6 +196,7 @@ bool Print(const void *val, Type type, int indent, } \ break; FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) + // Arrays of scalars or structs are only possible. FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) #undef FLATBUFFERS_TD case BASE_TYPE_ARRAY: FLATBUFFERS_ASSERT(0); @@ -286,19 +285,17 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, text += " "; switch (fd.value.type.base_type) { // clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - case BASE_TYPE_ ## ENUM: \ - if (!GenField(fd, table, struct_def.fixed, \ - opts, indent + Indent(opts), _text)) { \ - return false; \ - } \ - break; + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + case BASE_TYPE_ ## ENUM: \ + if (!GenField(fd, table, struct_def.fixed, \ + opts, indent + Indent(opts), _text)) { \ + return false; \ + } \ + break; FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) #undef FLATBUFFERS_TD // Generate drop-thru case statements for all pointer types: - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, ...) \ case BASE_TYPE_ ## ENUM: FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPE_ARRAY(FLATBUFFERS_TD) diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 56b1547ca..163d111b3 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -37,26 +37,22 @@ const char *FLATBUFFERS_VERSION() { const double kPi = 3.14159265358979323846; -const char *const kTypeNames[] = { // clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ +const char *const kTypeNames[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \ IDLTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on nullptr }; const char kTypeSizes[] = { -// clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - sizeof(CTYPE), + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + sizeof(CTYPE), FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - // clang-format on }; +// clang-format on // The enums in the reflection schema should match the ones we use internally. // Compare the last element to check if these go out of sync. @@ -222,8 +218,7 @@ static std::string TokenToString(int t) { #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) #undef FLATBUFFERS_TOKEN - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \ IDLTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD @@ -1179,8 +1174,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, size == SizeOf(field_value.type.base_type)) { switch (field_value.type.base_type) { // clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_ ## ENUM: \ builder_.Pad(field->padding); \ if (struct_def.fixed) { \ @@ -1194,10 +1188,9 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, builder_.AddElement(field_value.offset, val, valdef); \ } \ break; - FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); + FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) #undef FLATBUFFERS_TD - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_ ## ENUM: \ builder_.Pad(field->padding); \ if (IsStruct(field->value.type)) { \ @@ -1208,7 +1201,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, builder_.AddOffset(field_value.offset, val); \ } \ break; - FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD); + FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) #undef FLATBUFFERS_TD case BASE_TYPE_ARRAY: builder_.Pad(field->padding); @@ -1258,8 +1251,7 @@ CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) { static bool CompareType(const uint8_t *a, const uint8_t *b, BaseType ftype) { switch (ftype) { -#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ - RTYPE, KTYPE) \ +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_##ENUM: return ReadScalar(a) < ReadScalar(b); FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) #undef FLATBUFFERS_TD @@ -1314,8 +1306,7 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue, auto &val = field_stack_.back().first; switch (val.type.base_type) { // clang-format off - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE,...) \ case BASE_TYPE_ ## ENUM: \ if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ else { \ @@ -1429,8 +1420,7 @@ CheckedError Parser::ParseArray(Value &array) { auto &val = *it; // clang-format off switch (val.type.base_type) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_ ## ENUM: \ if (IsStruct(val.type)) { \ SerializeStruct(builder, *val.type.struct_def, val); \ @@ -1782,14 +1772,13 @@ CheckedError Parser::ParseSingleValue(const std::string *name, Value &e, if (check_now && IsScalar(match_type)) { // clang-format off switch (match_type) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, \ - CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \ - case BASE_TYPE_ ## ENUM: {\ - CTYPE val; \ - ECHECK(atot(e.constant.c_str(), *this, &val)); \ - SingleValueRepack(e, val); \ - break; } - FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ + case BASE_TYPE_ ## ENUM: {\ + CTYPE val; \ + ECHECK(atot(e.constant.c_str(), *this, &val)); \ + SingleValueRepack(e, val); \ + break; } + FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) #undef FLATBUFFERS_TD default: break; } @@ -2018,13 +2007,12 @@ struct EnumValBuilder { FLATBUFFERS_CHECKED_ERROR ValidateValue(int64_t *ev, bool next) { // clang-format off switch (enum_def.underlying_type.base_type) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE, RTYPE, KTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \ case BASE_TYPE_##ENUM: { \ if (!IsInteger(BASE_TYPE_##ENUM)) break; \ return ValidateImpl(ev, next ? 1 : 0); \ } - FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); + FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD) #undef FLATBUFFERS_TD default: break; } From c3c32ec9420bce55ef191ab47790ab742dd69b54 Mon Sep 17 00:00:00 2001 From: Vladimir Glavnyy <31897320+vglavnyy@users.noreply.github.com> Date: Tue, 26 Nov 2019 03:56:47 +0700 Subject: [PATCH 27/28] Fix ambiguity of a type deduction in TEST_EQ macro if arguments have `enum class` type. (#5630) --- include/flatbuffers/stl_emulation.h | 28 ++++++++++-- tests/test.cpp | 40 ++++++++--------- tests/test_assert.cpp | 8 ++-- tests/test_assert.h | 67 +++++++++++++++++++++++------ 4 files changed, 100 insertions(+), 43 deletions(-) diff --git a/include/flatbuffers/stl_emulation.h b/include/flatbuffers/stl_emulation.h index e68089ff9..8bae61bfd 100644 --- a/include/flatbuffers/stl_emulation.h +++ b/include/flatbuffers/stl_emulation.h @@ -96,13 +96,13 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { } }; - template <> class numeric_limits : + template <> class numeric_limits : public std::numeric_limits { public: static float lowest() { return -FLT_MAX; } }; - template <> class numeric_limits : + template <> class numeric_limits : public std::numeric_limits { public: static double lowest() { return -DBL_MAX; } @@ -138,18 +138,20 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { template using is_same = std::is_same; template using is_floating_point = std::is_floating_point; template using is_unsigned = std::is_unsigned; + template using is_enum = std::is_enum; template using make_unsigned = std::make_unsigned; template using conditional = std::conditional; template using integral_constant = std::integral_constant; -#else + #else // Map C++ TR1 templates defined by stlport. template using is_scalar = std::tr1::is_scalar; template using is_same = std::tr1::is_same; template using is_floating_point = std::tr1::is_floating_point; template using is_unsigned = std::tr1::is_unsigned; + template using is_enum = std::tr1::is_enum; // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned. template struct make_unsigned { static_assert(is_unsigned::value, "Specialization not implemented!"); @@ -165,7 +167,7 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { using conditional = std::tr1::conditional; template using integral_constant = std::tr1::integral_constant; -#endif // !FLATBUFFERS_CPP98_STL + #endif // !FLATBUFFERS_CPP98_STL #else // MSVC 2010 doesn't support C++11 aliases. template struct is_scalar : public std::is_scalar {}; @@ -173,6 +175,7 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { template struct is_floating_point : public std::is_floating_point {}; template struct is_unsigned : public std::is_unsigned {}; + template struct is_enum : public std::is_enum {}; template struct make_unsigned : public std::make_unsigned {}; template struct conditional : public std::conditional {}; @@ -280,6 +283,23 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { template bool operator==(const unique_ptr& x, intptr_t y) { return reinterpret_cast(x.get()) == y; } + + template bool operator!=(const unique_ptr& x, decltype(nullptr)) { + return !!x; + } + + template bool operator!=(decltype(nullptr), const unique_ptr& x) { + return !!x; + } + + template bool operator==(const unique_ptr& x, decltype(nullptr)) { + return !x; + } + + template bool operator==(decltype(nullptr), const unique_ptr& x) { + return !x; + } + #endif // !FLATBUFFERS_CPP98_STL } // namespace flatbuffers diff --git a/tests/test.cpp b/tests/test.cpp index 515e2c438..149831da5 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -1394,7 +1394,7 @@ void FuzzTest2() { break; } } - TEST_NOTNULL(NULL); + TEST_NOTNULL(nullptr); } // clang-format off @@ -2985,32 +2985,28 @@ void FixedLengthArrayTest() { TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)); TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()); mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()->Mutate(1, 5); - TEST_EQ(mArStruct->d()->Get(1)->a()->Get(1), 5); - TEST_EQ(mArStruct->d()->Get(0)->b() == MyGame::Example::TestEnum::B, true); + TEST_EQ(5, mArStruct->d()->Get(1)->a()->Get(1)); + TEST_EQ(MyGame::Example::TestEnum::B, mArStruct->d()->Get(0)->b()); TEST_NOTNULL(mArStruct->d()->Get(0)->c()); - TEST_EQ(mArStruct->d()->Get(0)->c()->Get(0) == MyGame::Example::TestEnum::C, - true); - TEST_EQ(mArStruct->d()->Get(0)->c()->Get(1) == MyGame::Example::TestEnum::A, - true); - TEST_EQ(mArStruct->d()->Get(0)->d()->Get(0), - flatbuffers::numeric_limits::max()); - TEST_EQ(mArStruct->d()->Get(0)->d()->Get(1), - flatbuffers::numeric_limits::min()); - TEST_EQ(mArStruct->d()->Get(1)->b() == MyGame::Example::TestEnum::C, true); + TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(0)->c()->Get(0)); + TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(0)->c()->Get(1)); + TEST_EQ(flatbuffers::numeric_limits::max(), + mArStruct->d()->Get(0)->d()->Get(0)); + TEST_EQ(flatbuffers::numeric_limits::min(), + mArStruct->d()->Get(0)->d()->Get(1)); + TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->b()); TEST_NOTNULL(mArStruct->d()->Get(1)->c()); - TEST_EQ(mArStruct->d()->Get(1)->c()->Get(0) == MyGame::Example::TestEnum::C, - true); - TEST_EQ(mArStruct->d()->Get(1)->c()->Get(1) == MyGame::Example::TestEnum::A, - true); - TEST_EQ(mArStruct->d()->Get(1)->d()->Get(0), - flatbuffers::numeric_limits::min()); - TEST_EQ(mArStruct->d()->Get(1)->d()->Get(1), - flatbuffers::numeric_limits::max()); + TEST_EQ(MyGame::Example::TestEnum::C, mArStruct->d()->Get(1)->c()->Get(0)); + TEST_EQ(MyGame::Example::TestEnum::A, mArStruct->d()->Get(1)->c()->Get(1)); + TEST_EQ(flatbuffers::numeric_limits::min(), + mArStruct->d()->Get(1)->d()->Get(0)); + TEST_EQ(flatbuffers::numeric_limits::max(), + mArStruct->d()->Get(1)->d()->Get(1)); for (int i = 0; i < mArStruct->b()->size() - 1; i++) TEST_EQ(mArStruct->b()->Get(i), i + 1); // Check alignment - TEST_EQ(reinterpret_cast(mArStruct->d()) % 8, 0); - TEST_EQ(reinterpret_cast(mArStruct->f()) % 8, 0); + TEST_EQ(0, reinterpret_cast(mArStruct->d()) % 8); + TEST_EQ(0, reinterpret_cast(mArStruct->f()) % 8); #endif } diff --git a/tests/test_assert.cpp b/tests/test_assert.cpp index eec777972..eb69a5493 100644 --- a/tests/test_assert.cpp +++ b/tests/test_assert.cpp @@ -12,8 +12,8 @@ static TestFailEventListener fail_listener_ = nullptr; void TestFail(const char *expval, const char *val, const char *exp, const char *file, int line, const char *func) { - TEST_OUTPUT_LINE("VALUE: \"%s\"", expval); - TEST_OUTPUT_LINE("EXPECTED: \"%s\"", val); + TEST_OUTPUT_LINE("EXPECTED: \"%s\"", expval); + TEST_OUTPUT_LINE("VALUE: \"%s\"", val); TEST_OUTPUT_LINE("TEST FAILED: %s:%d, %s in %s", file, line, exp, func ? func : ""); testing_fails++; @@ -25,8 +25,8 @@ void TestFail(const char *expval, const char *val, const char *exp, } void TestEqStr(const char *expval, const char *val, const char *exp, - const char *file, int line) { - if (strcmp(expval, val) != 0) { TestFail(expval, val, exp, file, line); } + const char *file, int line, const char *func) { + if (strcmp(expval, val) != 0) { TestFail(expval, val, exp, file, line, func); } } #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && defined(_MSC_VER) && \ diff --git a/tests/test_assert.h b/tests/test_assert.h index 883586b0e..b2d0562f8 100644 --- a/tests/test_assert.h +++ b/tests/test_assert.h @@ -16,17 +16,17 @@ { printf(__VA_ARGS__); printf("\n"); } #endif -#define TEST_EQ(exp, val) TestEq(exp, val, #exp, __FILE__, __LINE__) -#define TEST_ASSERT(exp) TestEq(exp, true, #exp, __FILE__, __LINE__) -#define TEST_NOTNULL(exp) TestEq(exp == NULL, false, #exp, __FILE__, __LINE__) -#define TEST_EQ_STR(exp, val) TestEqStr(exp, val, #exp, __FILE__, __LINE__) +#define TEST_EQ(exp, val) TestEq(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, "") +#define TEST_ASSERT(val) TestEq(true, !!(val), "'" "true" "' != '" #val "'", __FILE__, __LINE__, "") +#define TEST_NOTNULL(val) TestEq(true, (val) != nullptr, "'" "nullptr" "' == '" #val "'", __FILE__, __LINE__, "") +#define TEST_EQ_STR(exp, val) TestEqStr(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, "") #ifdef _WIN32 - #define TEST_ASSERT_FUNC(exp) TestEq(exp, true, #exp, __FILE__, __LINE__, __FUNCTION__) - #define TEST_EQ_FUNC(exp, val) TestEq(exp, val, #exp, __FILE__, __LINE__, __FUNCTION__) + #define TEST_ASSERT_FUNC(val) TestEq(true, !!(val), "'" "true" "' != '" #val "'", __FILE__, __LINE__, __FUNCTION__) + #define TEST_EQ_FUNC(exp, val) TestEq(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, __FUNCTION__) #else - #define TEST_ASSERT_FUNC(exp) TestEq(exp, true, #exp, __FILE__, __LINE__, __PRETTY_FUNCTION__) - #define TEST_EQ_FUNC(exp, val) TestEq(exp, val, #exp, __FILE__, __LINE__, __PRETTY_FUNCTION__) + #define TEST_ASSERT_FUNC(val) TestEq(true, !!(val), "'" "true" "' != '" #val "'", __FILE__, __LINE__, __PRETTY_FUNCTION__) + #define TEST_EQ_FUNC(exp, val) TestEq(exp, val, "'" #exp "' != '" #val "'", __FILE__, __LINE__, __PRETTY_FUNCTION__) #endif // clang-format on @@ -54,14 +54,55 @@ void TestFail(const char *expval, const char *val, const char *exp, const char *file, int line, const char *func = 0); void TestEqStr(const char *expval, const char *val, const char *exp, - const char *file, int line); + const char *file, int line, const char *func = 0); + +// Workaround for `enum class` printing. +// There is an issue with the printing of enums with a fixed underlying type. +// These enums are generated by `flatc` if `--scoped-enums` is active. +// All modern compilers have problems with `std::stringstream&<<(T v)` if T is +// an enum with fixed type. For details see DR1601: +// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1601 +// https://stackoverflow.com/questions/34336024/ambiguous-overload-when-writing-an-enum-with-an-enum-base-but-only-with-clang + +template::value> +struct underlying_of_scalar { + static_assert(flatbuffers::is_scalar::value, "invalid type T"); + typedef T type; +}; + +template struct underlying_of_scalar { +// clang-format off + // There are old compilers without full C++11 support (see stl_emulation.h). + #if defined(FLATBUFFERS_TEMPLATES_ALIASES) && !defined(FLATBUFFERS_CPP98_STL) + using type = typename std::underlying_type::type; + #else + typedef int64_t type; + #endif + // clang-format on +}; + +template +typename underlying_of_scalar::type scalar_as_underlying(T v) { + return static_cast::type>(v); +} template void TestEq(T expval, U val, const char *exp, const char *file, int line, - const char *func = 0) { - if (U(expval) != val) { - TestFail(flatbuffers::NumToString(expval).c_str(), - flatbuffers::NumToString(val).c_str(), exp, file, line, func); + const char *func) { + if (static_cast(expval) != val) { + TestFail(flatbuffers::NumToString(scalar_as_underlying(expval)).c_str(), + flatbuffers::NumToString(scalar_as_underlying(val)).c_str(), exp, + file, line, func); + } +} + +template<> +inline void TestEq(std::string expval, + std::string val, const char *exp, + const char *file, int line, + const char *func) { + if (expval != val) { + TestFail(expval.c_str(), val.c_str(), exp, file, line, func); } } From 3c964e10ab4f97e2a3602a8d0a8f4c402806ef89 Mon Sep 17 00:00:00 2001 From: Tiago Silva <3629062+tigrato@users.noreply.github.com> Date: Tue, 26 Nov 2019 20:25:36 +0000 Subject: [PATCH 28/28] [GO] Fix support for enums with underscores and Unions with imported members (#5600) * Fix Enum Stringer method when Enum has underscores Fixes #5481 * Fix go package importing itself when Union has imported members. --- src/idl_gen_go.cpp | 2 +- tests/MyGame/Example/Any.go | 60 ++++++++++----------- tests/MyGame/Example/AnyAmbiguousAliases.go | 60 ++++++++++----------- tests/MyGame/Example/AnyUniqueAliases.go | 60 ++++++++++----------- 4 files changed, 91 insertions(+), 91 deletions(-) diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 7dc56df0d..fce7b1258 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -81,13 +81,13 @@ class GoGenerator : public BaseGenerator { tracked_imported_namespaces_.clear(); needs_imports = false; std::string enumcode; + GenEnum(**it, &enumcode); if ((*it)->is_union && parser_.opts.generate_object_based_api) { GenNativeUnion(**it, &enumcode); GenNativeUnionPack(**it, &enumcode); GenNativeUnionUnPack(**it, &enumcode); needs_imports = true; } - GenEnum(**it, &enumcode); if (parser_.opts.one_file) { one_file_code += enumcode; } else { diff --git a/tests/MyGame/Example/Any.go b/tests/MyGame/Example/Any.go index 7b9ffb918..c9a0a166d 100644 --- a/tests/MyGame/Example/Any.go +++ b/tests/MyGame/Example/Any.go @@ -10,6 +10,36 @@ import ( MyGame__Example2 "MyGame/Example2" ) +type Any byte + +const ( + AnyNONE Any = 0 + AnyMonster Any = 1 + AnyTestSimpleTableWithEnum Any = 2 + AnyMyGame_Example2_Monster Any = 3 +) + +var EnumNamesAny = map[Any]string{ + AnyNONE: "NONE", + AnyMonster: "Monster", + AnyTestSimpleTableWithEnum: "TestSimpleTableWithEnum", + AnyMyGame_Example2_Monster: "MyGame_Example2_Monster", +} + +var EnumValuesAny = map[string]Any{ + "NONE": AnyNONE, + "Monster": AnyMonster, + "TestSimpleTableWithEnum": AnyTestSimpleTableWithEnum, + "MyGame_Example2_Monster": AnyMyGame_Example2_Monster, +} + +func (v Any) String() string { + if s, ok := EnumNamesAny[v]; ok { + return s + } + return "Any(" + strconv.FormatInt(int64(v), 10) + ")" +} + type AnyT struct { Type Any Value interface{} @@ -44,33 +74,3 @@ func AnyUnPack(t Any, table flatbuffers.Table) *AnyT { } return nil } - -type Any byte - -const ( - AnyNONE Any = 0 - AnyMonster Any = 1 - AnyTestSimpleTableWithEnum Any = 2 - AnyMyGame_Example2_Monster Any = 3 -) - -var EnumNamesAny = map[Any]string{ - AnyNONE: "NONE", - AnyMonster: "Monster", - AnyTestSimpleTableWithEnum: "TestSimpleTableWithEnum", - AnyMyGame_Example2_Monster: "MyGame_Example2_Monster", -} - -var EnumValuesAny = map[string]Any{ - "NONE": AnyNONE, - "Monster": AnyMonster, - "TestSimpleTableWithEnum": AnyTestSimpleTableWithEnum, - "MyGame_Example2_Monster": AnyMyGame_Example2_Monster, -} - -func (v Any) String() string { - if s, ok := EnumNamesAny[v]; ok { - return s - } - return "Any(" + strconv.FormatInt(int64(v), 10) + ")" -} diff --git a/tests/MyGame/Example/AnyAmbiguousAliases.go b/tests/MyGame/Example/AnyAmbiguousAliases.go index cc4adb8a0..08cc59625 100644 --- a/tests/MyGame/Example/AnyAmbiguousAliases.go +++ b/tests/MyGame/Example/AnyAmbiguousAliases.go @@ -8,6 +8,36 @@ import ( flatbuffers "github.com/google/flatbuffers/go" ) +type AnyAmbiguousAliases byte + +const ( + AnyAmbiguousAliasesNONE AnyAmbiguousAliases = 0 + AnyAmbiguousAliasesM1 AnyAmbiguousAliases = 1 + AnyAmbiguousAliasesM2 AnyAmbiguousAliases = 2 + AnyAmbiguousAliasesM3 AnyAmbiguousAliases = 3 +) + +var EnumNamesAnyAmbiguousAliases = map[AnyAmbiguousAliases]string{ + AnyAmbiguousAliasesNONE: "NONE", + AnyAmbiguousAliasesM1: "M1", + AnyAmbiguousAliasesM2: "M2", + AnyAmbiguousAliasesM3: "M3", +} + +var EnumValuesAnyAmbiguousAliases = map[string]AnyAmbiguousAliases{ + "NONE": AnyAmbiguousAliasesNONE, + "M1": AnyAmbiguousAliasesM1, + "M2": AnyAmbiguousAliasesM2, + "M3": AnyAmbiguousAliasesM3, +} + +func (v AnyAmbiguousAliases) String() string { + if s, ok := EnumNamesAnyAmbiguousAliases[v]; ok { + return s + } + return "AnyAmbiguousAliases(" + strconv.FormatInt(int64(v), 10) + ")" +} + type AnyAmbiguousAliasesT struct { Type AnyAmbiguousAliases Value interface{} @@ -42,33 +72,3 @@ func AnyAmbiguousAliasesUnPack(t AnyAmbiguousAliases, table flatbuffers.Table) * } return nil } - -type AnyAmbiguousAliases byte - -const ( - AnyAmbiguousAliasesNONE AnyAmbiguousAliases = 0 - AnyAmbiguousAliasesM1 AnyAmbiguousAliases = 1 - AnyAmbiguousAliasesM2 AnyAmbiguousAliases = 2 - AnyAmbiguousAliasesM3 AnyAmbiguousAliases = 3 -) - -var EnumNamesAnyAmbiguousAliases = map[AnyAmbiguousAliases]string{ - AnyAmbiguousAliasesNONE: "NONE", - AnyAmbiguousAliasesM1: "M1", - AnyAmbiguousAliasesM2: "M2", - AnyAmbiguousAliasesM3: "M3", -} - -var EnumValuesAnyAmbiguousAliases = map[string]AnyAmbiguousAliases{ - "NONE": AnyAmbiguousAliasesNONE, - "M1": AnyAmbiguousAliasesM1, - "M2": AnyAmbiguousAliasesM2, - "M3": AnyAmbiguousAliasesM3, -} - -func (v AnyAmbiguousAliases) String() string { - if s, ok := EnumNamesAnyAmbiguousAliases[v]; ok { - return s - } - return "AnyAmbiguousAliases(" + strconv.FormatInt(int64(v), 10) + ")" -} diff --git a/tests/MyGame/Example/AnyUniqueAliases.go b/tests/MyGame/Example/AnyUniqueAliases.go index 56b516380..008cada48 100644 --- a/tests/MyGame/Example/AnyUniqueAliases.go +++ b/tests/MyGame/Example/AnyUniqueAliases.go @@ -10,6 +10,36 @@ import ( MyGame__Example2 "MyGame/Example2" ) +type AnyUniqueAliases byte + +const ( + AnyUniqueAliasesNONE AnyUniqueAliases = 0 + AnyUniqueAliasesM AnyUniqueAliases = 1 + AnyUniqueAliasesTS AnyUniqueAliases = 2 + AnyUniqueAliasesM2 AnyUniqueAliases = 3 +) + +var EnumNamesAnyUniqueAliases = map[AnyUniqueAliases]string{ + AnyUniqueAliasesNONE: "NONE", + AnyUniqueAliasesM: "M", + AnyUniqueAliasesTS: "TS", + AnyUniqueAliasesM2: "M2", +} + +var EnumValuesAnyUniqueAliases = map[string]AnyUniqueAliases{ + "NONE": AnyUniqueAliasesNONE, + "M": AnyUniqueAliasesM, + "TS": AnyUniqueAliasesTS, + "M2": AnyUniqueAliasesM2, +} + +func (v AnyUniqueAliases) String() string { + if s, ok := EnumNamesAnyUniqueAliases[v]; ok { + return s + } + return "AnyUniqueAliases(" + strconv.FormatInt(int64(v), 10) + ")" +} + type AnyUniqueAliasesT struct { Type AnyUniqueAliases Value interface{} @@ -44,33 +74,3 @@ func AnyUniqueAliasesUnPack(t AnyUniqueAliases, table flatbuffers.Table) *AnyUni } return nil } - -type AnyUniqueAliases byte - -const ( - AnyUniqueAliasesNONE AnyUniqueAliases = 0 - AnyUniqueAliasesM AnyUniqueAliases = 1 - AnyUniqueAliasesTS AnyUniqueAliases = 2 - AnyUniqueAliasesM2 AnyUniqueAliases = 3 -) - -var EnumNamesAnyUniqueAliases = map[AnyUniqueAliases]string{ - AnyUniqueAliasesNONE: "NONE", - AnyUniqueAliasesM: "M", - AnyUniqueAliasesTS: "TS", - AnyUniqueAliasesM2: "M2", -} - -var EnumValuesAnyUniqueAliases = map[string]AnyUniqueAliases{ - "NONE": AnyUniqueAliasesNONE, - "M": AnyUniqueAliasesM, - "TS": AnyUniqueAliasesTS, - "M2": AnyUniqueAliasesM2, -} - -func (v AnyUniqueAliases) String() string { - if s, ok := EnumNamesAnyUniqueAliases[v]; ok { - return s - } - return "AnyUniqueAliases(" + strconv.FormatInt(int64(v), 10) + ")" -}