From: 吴凡 Date: Fri, 1 Jul 2016 03:03:25 +0000 (+0800) Subject: Sync from upstream X-Git-Tag: v1.4.0~40^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=70deb70b762816bd4fe6b0e3d36c43a7f81e6887;p=platform%2Fupstream%2Fflatbuffers.git Sync from upstream --- 70deb70b762816bd4fe6b0e3d36c43a7f81e6887 diff --cc CMakeLists.txt index 6dc73e7,c2dd950..32a5e21 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@@ -80,13 -97,38 +97,47 @@@ if(APPLE set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -Wall -pedantic -Werror -Wextra") elseif(CMAKE_COMPILER_IS_GNUCXX) + if(CYGWIN) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -std=gnu++11") + else(CYGWIN) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -std=c++0x") + endif(CYGWIN) set(CMAKE_CXX_FLAGS ++<<<<<<< HEAD + "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Werror=shadow") +elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++ -Wall -pedantic -Werror -Wextra") + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -lc++abi") ++======= + "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Werror=shadow") + if (GCC_VERSION VERSION_GREATER 4.4) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result") + endif() + + # Certain platforms such as ARM do not use signed chars by default + # which causes issues with certain bounds checks. + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsigned-char") + + elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++ -Wall -pedantic -Werror -Wextra") + if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -lc++abi") + endif() + + # Certain platforms such as ARM do not use signed chars by default + # which causes issues with certain bounds checks. + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsigned-char") + ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 endif() if(FLATBUFFERS_CODE_COVERAGE) diff --cc docs/source/Compiler.md index 9d89cb1,ad584c7..5f1427d --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@@ -32,6 -33,8 +33,11 @@@ For any schema input files, one or mor - `--php`: Generate PHP code. ++<<<<<<< HEAD ++======= + - `--grpc`: Generate RPC stub code for GRPC. + ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 For any data input files: - `--binary`, `-b` : If data is contained in this file, generate a diff --cc include/flatbuffers/idl.h index f1276f0,b22bc08..1b45425 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@@ -415,19 -545,16 +545,27 @@@ private std::map included_files_; std::map> files_included_per_file_; + std::map known_attributes_; + + IDLOptions opts; + private: ++<<<<<<< HEAD + const char *source_, *cursor_; + int line_; // the current line being parsed + int token_; + std::string files_being_parsed_; + bool proto_mode_; + bool strict_json_; + std::string attribute_; + std::vector doc_comment_; ++======= + const char *source_; ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 - std::vector> field_stack_; + std::string file_being_parsed_; - std::set known_attributes_; + std::vector> field_stack_; int anonymous_counter; }; diff --cc java/com/google/flatbuffers/FlatBufferBuilder.java index a6234ca,c2186fa..3bbd5d3 --- a/java/com/google/flatbuffers/FlatBufferBuilder.java +++ b/java/com/google/flatbuffers/FlatBufferBuilder.java @@@ -22,30 -27,37 +27,53 @@@ import java.nio.ByteBuffer import java.nio.ByteOrder; import java.nio.charset.Charset; + /// @file + /// @addtogroup flatbuffers_java_api + /// @{ + /** * Class that helps you build a FlatBuffer. See the section - * "Use in Java" in the - * main FlatBuffers documentation. + * "Use in Java/C#" in the main FlatBuffers documentation. */ public class FlatBufferBuilder { ++<<<<<<< HEAD + ByteBuffer bb; // Where we construct the FlatBuffer. + int space; // Remaining space in the ByteBuffer. + static final Charset utf8charset = Charset.forName("UTF-8"); + int minalign = 1; // Minimum alignment encountered so far. + int[] vtable = null; // The vtable for the current table. + int vtable_in_use = 0; // The amount of fields we're actually using. + boolean nested = false; // Whether we are currently serializing a table. + boolean finished = false; // Whether the buffer is finished. + int object_start; // Starting offset of the current struct/table. + int[] vtables = new int[16]; // List of offsets of all vtables. + int num_vtables = 0; // Number of entries in `vtables` in use. + int vector_num_elems = 0; // For the current vector being built. + boolean force_defaults = false; // False omits default values from the serialized data ++======= + /// @cond FLATBUFFERS_INTERNAL + ByteBuffer bb; // Where we construct the FlatBuffer. + int space; // Remaining space in the ByteBuffer. + static final Charset utf8charset = Charset.forName("UTF-8"); // The UTF-8 character set used by FlatBuffers. + int minalign = 1; // Minimum alignment encountered so far. + int[] vtable = null; // The vtable for the current table. + int vtable_in_use = 0; // The amount of fields we're actually using. + boolean nested = false; // Whether we are currently serializing a table. + boolean finished = false; // Whether the buffer is finished. + int object_start; // Starting offset of the current struct/table. + int[] vtables = new int[16]; // List of offsets of all vtables. + int num_vtables = 0; // Number of entries in `vtables` in use. + int vector_num_elems = 0; // For the current vector being built. + boolean force_defaults = false; // False omits default values from the serialized data. + CharsetEncoder encoder = utf8charset.newEncoder(); + ByteBuffer dst; + /// @endcond ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 /** - * Start with a buffer of size {@code initial_size}, then grow as required. + * Start with a buffer of size `initial_size`, then grow as required. * - * @param initial_size The initial size of the internal buffer to use + * @param initial_size The initial size of the internal buffer to use. */ public FlatBufferBuilder(int initial_size) { if (initial_size <= 0) initial_size = 1; @@@ -290,19 -413,20 +429,30 @@@ return endVector(); } + /// @cond FLATBUFFERS_INTERNAL + /** + * Should not be accessing the final buffer before it is finished. + */ + public void finished() { + if (!finished) + throw new AssertionError( + "FlatBuffers: you can only access the serialized buffer after it has been" + + " finished by FlatBufferBuilder.finish()."); + } + /** + * Should not be accessing the final buffer before it is finished. + */ + public void finished() { + if (!finished) + throw new AssertionError( + "FlatBuffers: you can only access the serialized buffer after it has been" + + " finished by FlatBufferBuilder.finish()."); + } + + /** * Should not be creating any other object, string or vector - * while an object is being constructed + * while an object is being constructed. */ public void notNested() { if (nested) @@@ -495,9 -725,13 +751,19 @@@ return this; } ++<<<<<<< HEAD + // Get the ByteBuffer representing the FlatBuffer. Only call this after you've + // called finish(). The actual data starts at the ByteBuffer's current position, + // not necessarily at 0. ++======= + /** + * Get the ByteBuffer representing the FlatBuffer. Only call this after you've + * called `finish()`. The actual data starts at the ByteBuffer's current position, + * not necessarily at `0`. + * + * @return The {@link ByteBuffer} representing the FlatBuffer + */ ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 public ByteBuffer dataBuffer() { finished(); return bb; diff --cc samples/monster_generated.h index 53935ee,1a16126..93bf73f --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@@ -66,6 -72,9 +72,12 @@@ struct Monster FLATBUFFERS_FINAL_CLASS VT_NAME = 10, VT_INVENTORY = 14, VT_COLOR = 16, ++<<<<<<< HEAD ++======= + VT_WEAPONS = 18, + VT_EQUIPPED_TYPE = 20, + VT_EQUIPPED = 22 ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 }; const Vec3 *pos() const { return GetStruct(VT_POS); } Vec3 *mutable_pos() { return GetStruct(VT_POS); } @@@ -79,6 -88,12 +91,15 @@@ flatbuffers::Vector *mutable_inventory() { return GetPointer *>(VT_INVENTORY); } Color color() const { return static_cast(GetField(VT_COLOR, 2)); } bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast(_color)); } ++<<<<<<< HEAD ++======= + const flatbuffers::Vector> *weapons() const { return GetPointer> *>(VT_WEAPONS); } + flatbuffers::Vector> *mutable_weapons() { return GetPointer> *>(VT_WEAPONS); } + Equipment equipped_type() const { return static_cast(GetField(VT_EQUIPPED_TYPE, 0)); } + bool mutate_equipped_type(Equipment _equipped_type) { return SetField(VT_EQUIPPED_TYPE, static_cast(_equipped_type)); } + const void *equipped() const { return GetPointer(VT_EQUIPPED); } + void *mutable_equipped() { return GetPointer(VT_EQUIPPED); } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_POS) && @@@ -89,6 -104,12 +110,15 @@@ VerifyField(verifier, VT_INVENTORY) && verifier.Verify(inventory()) && VerifyField(verifier, VT_COLOR) && ++<<<<<<< HEAD ++======= + VerifyField(verifier, VT_WEAPONS) && + verifier.Verify(weapons()) && + verifier.VerifyVectorOfTables(weapons()) && + VerifyField(verifier, VT_EQUIPPED_TYPE) && + VerifyField(verifier, VT_EQUIPPED) && + VerifyEquipment(verifier, equipped(), equipped_type()) && ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 verifier.EndTable(); } }; @@@ -102,6 -123,9 +132,12 @@@ struct MonsterBuilder void add_name(flatbuffers::Offset name) { fbb_.AddOffset(Monster::VT_NAME, name); } void add_inventory(flatbuffers::Offset> inventory) { fbb_.AddOffset(Monster::VT_INVENTORY, inventory); } void add_color(Color color) { fbb_.AddElement(Monster::VT_COLOR, static_cast(color), 2); } ++<<<<<<< HEAD ++======= + void add_weapons(flatbuffers::Offset>> weapons) { fbb_.AddOffset(Monster::VT_WEAPONS, weapons); } + void add_equipped_type(Equipment equipped_type) { fbb_.AddElement(Monster::VT_EQUIPPED_TYPE, static_cast(equipped_type), 0); } + void add_equipped(flatbuffers::Offset equipped) { fbb_.AddOffset(Monster::VT_EQUIPPED, equipped); } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } MonsterBuilder &operator=(const MonsterBuilder &); flatbuffers::Offset Finish() { diff --cc src/flatc.cpp index a27af79,c7ba29e..6a8d891 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@@ -26,8 -29,7 +29,12 @@@ static void Error(const std::string &er struct Generator { bool (*generate)(const flatbuffers::Parser &parser, const std::string &path, ++<<<<<<< HEAD + const std::string &file_name, + const flatbuffers::GeneratorOptions &opts); ++======= + const std::string &file_name); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 const char *generator_opt_short; const char *generator_opt_long; const char *lang_name; @@@ -42,41 -43,45 +48,81 @@@ const Generator generators[] = { { flatbuffers::GenerateBinary, "-b", "--binary", "binary", ++<<<<<<< HEAD + flatbuffers::GeneratorOptions::kMAX, + "Generate wire format binaries for any data definitions", + flatbuffers::BinaryMakeRule }, + { flatbuffers::GenerateTextFile, "-t", "--json", "text", + flatbuffers::GeneratorOptions::kMAX, + "Generate text output for any data definitions", + flatbuffers::TextMakeRule }, + { flatbuffers::GenerateCPP, "-c", "--cpp", "C++", + flatbuffers::GeneratorOptions::kMAX, + "Generate C++ headers for tables/structs", + flatbuffers::CPPMakeRule }, + { flatbuffers::GenerateGo, "-g", "--go", "Go", + flatbuffers::GeneratorOptions::kGo, + "Generate Go files for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GenerateGeneral, "-j", "--java", "Java", + flatbuffers::GeneratorOptions::kJava, + "Generate Java classes for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GenerateJS, "-s", "--js", "JavaScript", + flatbuffers::GeneratorOptions::kMAX, + "Generate JavaScript code for tables/structs", + flatbuffers::JSMakeRule }, + { flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", + flatbuffers::GeneratorOptions::kCSharp, + "Generate C# classes for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GeneratePython, "-p", "--python", "Python", + flatbuffers::GeneratorOptions::kMAX, + "Generate Python files for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", + flatbuffers::GeneratorOptions::kMAX, ++======= + flatbuffers::IDLOptions::kMAX, + "Generate wire format binaries for any data definitions", + flatbuffers::BinaryMakeRule }, + { flatbuffers::GenerateTextFile, "-t", "--json", "text", + flatbuffers::IDLOptions::kMAX, + "Generate text output for any data definitions", + flatbuffers::TextMakeRule }, + { flatbuffers::GenerateCPP, "-c", "--cpp", "C++", + flatbuffers::IDLOptions::kMAX, + "Generate C++ headers for tables/structs", + flatbuffers::CPPMakeRule }, + { flatbuffers::GenerateGo, "-g", "--go", "Go", + flatbuffers::IDLOptions::kGo, + "Generate Go files for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GenerateGeneral, "-j", "--java", "Java", + flatbuffers::IDLOptions::kJava, + "Generate Java classes for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GenerateJS, "-s", "--js", "JavaScript", + flatbuffers::IDLOptions::kMAX, + "Generate JavaScript code for tables/structs", + flatbuffers::JSMakeRule }, + { flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", + flatbuffers::IDLOptions::kCSharp, + "Generate C# classes for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GeneratePython, "-p", "--python", "Python", + flatbuffers::IDLOptions::kMAX, + "Generate Python files for tables/structs", + flatbuffers::GeneralMakeRule }, + { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", + flatbuffers::IDLOptions::kMAX, ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 "Generate PHP files for tables/structs", flatbuffers::GeneralMakeRule }, + { flatbuffers::GenerateGRPC, nullptr, "--grpc", "GRPC", + flatbuffers::IDLOptions::kMAX, + "Generate GRPC interfaces", + flatbuffers::CPPMakeRule }, }; const char *program_name = nullptr; @@@ -203,11 -221,15 +262,19 @@@ int main(int argc, const char *argv[]) if (!filenames.size()) Error("missing input files", false, true); - if (!any_generator) - Error("no options: specify one of -c -g -j -t -b etc.", true); + if (opts.proto_mode) { + if (any_generator) + Error("cannot generate code directly from .proto files", true); + } else if (!any_generator) { + Error("no options: specify at least one generator.", true); + } // Now process the files: ++<<<<<<< HEAD + parser = new flatbuffers::Parser(opts.strict_json, proto_mode); ++======= + parser = new flatbuffers::Parser(opts); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 for (auto file_it = filenames.begin(); file_it != filenames.end(); ++file_it) { @@@ -243,12 -265,16 +310,23 @@@ } } } else { ++<<<<<<< HEAD ++======= + // Check if file contains 0 bytes. + if (contents.length() != strlen(contents.c_str())) { + Error("input file appears to be binary: " + *file_it, true); + } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 if (flatbuffers::GetExtension(*file_it) == "fbs") { // If we're processing multiple schemas, make sure to start each // one from scratch. If it depends on previous schemas it must do // so explicitly using an include. delete parser; ++<<<<<<< HEAD + parser = new flatbuffers::Parser(opts.strict_json, proto_mode); ++======= + parser = new flatbuffers::Parser(opts); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } auto local_include_directory = flatbuffers::StripFileName(*file_it); include_directories.push_back(local_include_directory.c_str()); @@@ -272,7 -298,7 +350,11 @@@ if (generator_enabled[i]) { if (!print_make_rules) { flatbuffers::EnsureDirExists(output_path); ++<<<<<<< HEAD + if (!generators[i].generate(*parser, output_path, filebase, opts)) { ++======= + if (!generators[i].generate(*parser, output_path, filebase)) { ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 Error(std::string("Unable to generate ") + generators[i].lang_name + " for " + @@@ -280,7 -306,7 +362,11 @@@ } } else { std::string make_rule = generators[i].make_rule( ++<<<<<<< HEAD + *parser, output_path, *file_it, opts); ++======= + *parser, output_path, *file_it); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 if (!make_rule.empty()) printf("%s\n", flatbuffers::WordWrap( make_rule, 80, " ", " \\").c_str()); @@@ -288,7 -314,11 +374,15 @@@ } } ++<<<<<<< HEAD + if (proto_mode) GenerateFBS(*parser, output_path, filebase, opts); ++======= + if (opts.proto_mode) GenerateFBS(*parser, output_path, filebase); + + // We do not want to generate code for the definitions in this file + // in any files coming up next. + parser->MarkGenerated(); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } delete parser; diff --cc src/idl_gen_cpp.cpp index ca523dc,c690240..c8337af --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@@ -19,189 -19,380 +19,455 @@@ #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/util.h" + #include "flatbuffers/code_generators.h" namespace flatbuffers { - namespace cpp { - // Ensure that a type is prefixed with its namespace whenever it is used - // outside of its namespace. - static std::string WrapInNameSpace(const Parser &parser, const Namespace *ns, - const std::string &name) { - if (parser.namespaces_.back() != ns) { - std::string qualified_name; - for (auto it = ns->components.begin(); - it != ns->components.end(); ++it) { - qualified_name += *it + "::"; - } - return qualified_name + name; - } else { - return name; + struct IsAlnum { + bool operator()(char c) { + return !isalnum(c); } - } + }; - static std::string WrapInNameSpace(const Parser &parser, - const Definition &def) { - return WrapInNameSpace(parser, def.defined_namespace, def.name); + static std::string GeneratedFileName(const std::string &path, + const std::string &file_name) { + return path + file_name + "_generated.h"; } - // Translates a qualified name in flatbuffer text format to the same name in - // the equivalent C++ namepsace. - static std::string TranslateNameSpace(const std::string &qualified_name) { - std::string cpp_qualified_name = qualified_name; - size_t start_pos = 0; - while((start_pos = cpp_qualified_name.find(".", start_pos)) != - std::string::npos) { - cpp_qualified_name.replace(start_pos, 1, "::"); + namespace cpp { + class CppGenerator : public BaseGenerator { + public: + CppGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) + : BaseGenerator(parser, path, file_name, "", "::"){}; + // Iterate through all definitions we haven't generate code for (enums, + // structs, + // and tables) and output them to a single file. + bool generate() { + if (IsEverythingGenerated()) return true; + + std::string code; + code = code + "// " + FlatBuffersGeneratedWarning(); + + // Generate include guard. + std::string include_guard_ident = file_name_; + // Remove any non-alpha-numeric characters that may appear in a filename. + include_guard_ident.erase( + std::remove_if(include_guard_ident.begin(), include_guard_ident.end(), + IsAlnum()), + include_guard_ident.end()); + std::string include_guard = "FLATBUFFERS_GENERATED_" + include_guard_ident; + include_guard += "_"; + // For further uniqueness, also add the namespace. + auto name_space = parser_.namespaces_.back(); + for (auto it = name_space->components.begin(); + it != name_space->components.end(); ++it) { + include_guard += *it + "_"; + } + include_guard += "H_"; + std::transform(include_guard.begin(), include_guard.end(), + include_guard.begin(), ::toupper); + code += "#ifndef " + include_guard + "\n"; + code += "#define " + include_guard + "\n\n"; + + code += "#include \"flatbuffers/flatbuffers.h\"\n\n"; + + if (parser_.opts.include_dependence_headers) { + int num_includes = 0; + for (auto it = parser_.included_files_.begin(); + it != parser_.included_files_.end(); ++it) { + auto basename = + flatbuffers::StripPath(flatbuffers::StripExtension(it->first)); + if (basename != file_name_) { + code += "#include \"" + basename + "_generated.h\"\n"; + num_includes++; + } + } + if (num_includes) code += "\n"; + } + + assert(!cur_name_space_); + + // Generate forward declarations for all structs/tables, since they may + // have circular references. + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + if (!struct_def.generated) { + SetNameSpace(struct_def.defined_namespace, &code); + code += "struct " + struct_def.name + ";\n\n"; + } + } + + // Generate code for all the enum declarations. + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + auto &enum_def = **it; + if (!enum_def.generated) { + SetNameSpace((**it).defined_namespace, &code); + GenEnum(**it, &code); + } + } + + // Generate code for all structs, then all tables. + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + if (struct_def.fixed && !struct_def.generated) { + SetNameSpace(struct_def.defined_namespace, &code); + GenStruct(struct_def, &code); + } + } + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + if (!struct_def.fixed && !struct_def.generated) { + SetNameSpace(struct_def.defined_namespace, &code); + GenTable(struct_def, &code); + } + } + + // Generate code for union verifiers. + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + auto &enum_def = **it; + if (enum_def.is_union && !enum_def.generated) { + SetNameSpace(enum_def.defined_namespace, &code); + GenEnumPost(enum_def, &code); + } + } + + // Generate convenient global helper functions: + if (parser_.root_struct_def_) { + SetNameSpace((*parser_.root_struct_def_).defined_namespace, &code); + auto &name = parser_.root_struct_def_->name; + std::string qualified_name = + parser_.namespaces_.back()->GetFullyQualifiedName(name); + std::string cpp_qualified_name = TranslateNameSpace(qualified_name); + + // The root datatype accessor: + code += "inline const " + cpp_qualified_name + " *Get"; + code += name; + code += "(const void *buf) { return flatbuffers::GetRoot<"; + code += cpp_qualified_name + ">(buf); }\n\n"; + if (parser_.opts.mutable_buffer) { + code += "inline " + name + " *GetMutable"; + code += name; + code += "(void *buf) { return flatbuffers::GetMutableRoot<"; + code += name + ">(buf); }\n\n"; + } + + // The root verifier: + code += "inline bool Verify"; + code += name; + code += + "Buffer(flatbuffers::Verifier &verifier) { " + "return verifier.VerifyBuffer<"; + code += cpp_qualified_name + ">(); }\n\n"; + + if (parser_.file_identifier_.length()) { + // Return the identifier + code += "inline const char *" + name; + code += "Identifier() { return \"" + parser_.file_identifier_; + code += "\"; }\n\n"; + + // Check if a buffer has the identifier. + code += "inline bool " + name; + code += "BufferHasIdentifier(const void *buf) { return flatbuffers::"; + code += "BufferHasIdentifier(buf, "; + code += name + "Identifier()); }\n\n"; + } + + if (parser_.file_extension_.length()) { + // Return the extension + code += "inline const char *" + name; + code += "Extension() { return \"" + parser_.file_extension_; + code += "\"; }\n\n"; + } + + // Finish a buffer with a given root object: + code += "inline void Finish" + name; + code += + "Buffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<"; + code += cpp_qualified_name + "> root) { fbb.Finish(root"; + if (parser_.file_identifier_.length()) + code += ", " + name + "Identifier()"; + code += "); }\n\n"; + } + + assert(cur_name_space_); + SetNameSpace(nullptr, &code); + + // Close the include guard. + code += "#endif // " + include_guard + "\n"; + + return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false); } - return cpp_qualified_name; - } + private: + // This tracks the current namespace so we can insert namespace declarations. + const Namespace *cur_name_space_ = nullptr; ++<<<<<<< HEAD +// Return a C++ type from the table in idl.h +static std::string GenTypeBasic(const Parser &parser, const Type &type, + bool user_facing_type) { + static const char *ctypename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #CTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + }; + if (user_facing_type) { + if (type.enum_def) return WrapInNameSpace(parser, *type.enum_def); + if (type.base_type == BASE_TYPE_BOOL) return "bool"; + } + return ctypename[type.base_type]; +} + +static std::string GenTypeWire(const Parser &parser, const Type &type, + const char *postfix, bool user_facing_type); + +// Return a C++ pointer type, specialized to the actual struct/table types, +// and vector element types. +static std::string GenTypePointer(const Parser &parser, const Type &type) { + switch (type.base_type) { + case BASE_TYPE_STRING: + return "flatbuffers::String"; + case BASE_TYPE_VECTOR: + return "flatbuffers::Vector<" + + GenTypeWire(parser, type.VectorType(), "", false) + ">"; + case BASE_TYPE_STRUCT: { + return WrapInNameSpace(parser, *type.struct_def); + } + case BASE_TYPE_UNION: ++======= + const Namespace *CurrentNameSpace() { return cur_name_space_; } + + // Translates a qualified name in flatbuffer text format to the same name in + // the equivalent C++ namespace. + static std::string TranslateNameSpace(const std::string &qualified_name) { + std::string cpp_qualified_name = qualified_name; + size_t start_pos = 0; + while ((start_pos = cpp_qualified_name.find(".", start_pos)) != + std::string::npos) { + cpp_qualified_name.replace(start_pos, 1, "::"); + } + return cpp_qualified_name; + } + + // Return a C++ type from the table in idl.h + std::string GenTypeBasic(const Type &type, bool user_facing_type) { + static const char *ctypename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) #CTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + }; + if (user_facing_type) { + if (type.enum_def) return WrapInNameSpace(*type.enum_def); + if (type.base_type == BASE_TYPE_BOOL) return "bool"; + } + return ctypename[type.base_type]; + } + + // Return a C++ pointer type, specialized to the actual struct/table types, + // and vector element types. + std::string GenTypePointer(const Type &type) { + switch (type.base_type) { + case BASE_TYPE_STRING: + return "flatbuffers::String"; + case BASE_TYPE_VECTOR: + return "flatbuffers::Vector<" + + GenTypeWire(type.VectorType(), "", false) + ">"; + case BASE_TYPE_STRUCT: { + return WrapInNameSpace(*type.struct_def); + } + case BASE_TYPE_UNION: ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 // fall through - default: - return "void"; + default: + return "void"; + } } - } ++<<<<<<< HEAD +// Return a C++ type for any type (scalar/pointer) specifically for +// building a flatbuffer. +static std::string GenTypeWire(const Parser &parser, const Type &type, + const char *postfix, bool user_facing_type) { + return IsScalar(type.base_type) + ? GenTypeBasic(parser, type, user_facing_type) + postfix + : IsStruct(type) + ? "const " + GenTypePointer(parser, type) + " *" + : "flatbuffers::Offset<" + GenTypePointer(parser, type) + ">" + postfix; +} ++======= + // Return a C++ type for any type (scalar/pointer) specifically for + // building a flatbuffer. + std::string GenTypeWire(const Type &type, + const char *postfix, bool user_facing_type) { + return IsScalar(type.base_type) + ? GenTypeBasic(type, user_facing_type) + postfix + : IsStruct(type) + ? "const " + GenTypePointer(type) + " *" + : "flatbuffers::Offset<" + GenTypePointer(type) + + ">" + postfix; + } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 - // Return a C++ type for any type (scalar/pointer) that reflects its - // serialized size. - static std::string GenTypeSize(const Parser &parser, const Type &type) { - return IsScalar(type.base_type) - ? GenTypeBasic(parser, type, false) - : IsStruct(type) - ? GenTypePointer(parser, type) - : "flatbuffers::uoffset_t"; - } + // Return a C++ type for any type (scalar/pointer) that reflects its + // serialized size. + std::string GenTypeSize(const Type &type) { + return IsScalar(type.base_type) + ? GenTypeBasic(type, false) + : IsStruct(type) ? GenTypePointer(type) + : "flatbuffers::uoffset_t"; + } ++<<<<<<< HEAD +// Return a C++ type for any type (scalar/pointer) specifically for +// using a flatbuffer. +static std::string GenTypeGet(const Parser &parser, const Type &type, + const char *afterbasic, const char *beforeptr, + const char *afterptr, bool user_facing_type) { + return IsScalar(type.base_type) + ? GenTypeBasic(parser, type, user_facing_type) + afterbasic + : beforeptr + GenTypePointer(parser, type) + afterptr; +} ++======= + // Return a C++ type for any type (scalar/pointer) specifically for + // using a flatbuffer. + std::string GenTypeGet(const Type &type, + const char *afterbasic, const char *beforeptr, + const char *afterptr, bool user_facing_type) { + return IsScalar(type.base_type) + ? GenTypeBasic(type, user_facing_type) + afterbasic + : beforeptr + GenTypePointer(type) + afterptr; + } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 - static std::string GenEnumDecl(const EnumDef &enum_def, - const GeneratorOptions &opts) { - return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name; - } + static std::string GenEnumDecl(const EnumDef &enum_def, + const IDLOptions &opts) { + return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name; + } - static std::string GenEnumVal(const EnumDef &enum_def, const EnumVal &enum_val, - const GeneratorOptions &opts) { - return opts.prefixed_enums ? enum_def.name + "_" + enum_val.name - : enum_val.name; - } + static std::string GenEnumVal(const EnumDef &enum_def, + const std::string &enum_val, + const IDLOptions &opts) { + return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val; + } - static std::string GetEnumVal(const EnumDef &enum_def, const EnumVal &enum_val, - const GeneratorOptions &opts) { - if (opts.scoped_enums) { + static std::string GetEnumVal(const EnumDef &enum_def, + const EnumVal &enum_val, + const IDLOptions &opts) { + if (opts.scoped_enums) { return enum_def.name + "::" + enum_val.name; - } else if (opts.prefixed_enums) { + } else if (opts.prefixed_enums) { return enum_def.name + "_" + enum_val.name; - } else { + } else { return enum_val.name; + } } - } - // Generate an enum declaration and an enum string lookup table. - static void GenEnum(const Parser &parser, EnumDef &enum_def, - std::string *code_ptr, std::string *code_ptr_post, - const GeneratorOptions &opts) { - if (enum_def.generated) return; - std::string &code = *code_ptr; - std::string &code_post = *code_ptr_post; - GenComment(enum_def.doc_comment, code_ptr, nullptr); - code += GenEnumDecl(enum_def, opts); - if (opts.scoped_enums) - code += " : " + GenTypeBasic(parser, enum_def.underlying_type, false); - code += " {\n"; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - GenComment(ev.doc_comment, code_ptr, nullptr, " "); - code += " " + GenEnumVal(enum_def, ev, opts) + " = "; - code += NumToString(ev.value); - code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n"; - } - code += "};\n\n"; - - // 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.vals.vec.back()->value - - enum_def.vals.vec.front()->value + 1; - // Average distance between values above which we consider a table - // "too sparse". Change at will. - static const int kMaxSparseness = 5; - if (range / static_cast(enum_def.vals.vec.size()) < kMaxSparseness) { - code += "inline const char **EnumNames" + enum_def.name + "() {\n"; - code += " static const char *names[] = { "; - auto val = enum_def.vals.vec.front()->value; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); + std::string EnumSignature(EnumDef &enum_def) { + return "inline bool Verify" + enum_def.name + + "(flatbuffers::Verifier &verifier, " + "const void *union_obj, " + + enum_def.name + " type)"; + } + + // Generate an enum declaration and an enum string lookup table. + void GenEnum(EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + GenComment(enum_def.doc_comment, code_ptr, nullptr); + code += GenEnumDecl(enum_def, parser_.opts); + if (parser_.opts.scoped_enums) + code += " : " + GenTypeBasic(enum_def.underlying_type, false); + code += " {\n"; + int64_t anyv = 0; + EnumVal *minv = nullptr, *maxv = nullptr; + for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); ++it) { ++<<<<<<< HEAD + while (val++ != (*it)->value) code += "\"\", "; + code += "\"" + (*it)->name + "\", "; + } + code += "nullptr };\n return names;\n}\n\n"; + code += "inline const char *EnumName" + enum_def.name; + code += "(" + enum_def.name + " e) { return EnumNames" + enum_def.name; + code += "()[static_cast(e)"; + if (enum_def.vals.vec.front()->value) { + code += " - static_cast("; + code += GetEnumVal(enum_def, *enum_def.vals.vec.front(), opts) +")"; + } + code += "]; }\n\n"; ++======= + auto &ev = **it; + GenComment(ev.doc_comment, code_ptr, nullptr, " "); + code += " " + GenEnumVal(enum_def, ev.name, parser_.opts) + " = "; + code += NumToString(ev.value) + ",\n"; + minv = !minv || minv->value > ev.value ? &ev : minv; + maxv = !maxv || maxv->value < ev.value ? &ev : maxv; + anyv |= ev.value; + } + if (parser_.opts.scoped_enums || parser_.opts.prefixed_enums) { + assert(minv && maxv); + if (enum_def.attributes.Lookup("bit_flags")) { + if (minv->value != 0) // If the user didn't defined NONE value + code += " " + GenEnumVal(enum_def, "NONE", parser_.opts) + " = 0,\n"; + if (maxv->value != anyv) // If the user didn't defined ANY value + code += " " + GenEnumVal(enum_def, "ANY", parser_.opts) + " = " + + NumToString(anyv) + "\n"; + } else { // MIN & MAX are useless for bit_flags + code += " " + GenEnumVal(enum_def, "MIN", parser_.opts) + " = "; + code += GenEnumVal(enum_def, minv->name, parser_.opts) + ",\n"; + code += " " + GenEnumVal(enum_def, "MAX", parser_.opts) + " = "; + code += GenEnumVal(enum_def, maxv->name, parser_.opts) + "\n"; + } + } + code += "};\n"; + if (parser_.opts.scoped_enums && enum_def.attributes.Lookup("bit_flags")) + code += "DEFINE_BITMASK_OPERATORS(" + enum_def.name + ", " + + GenTypeBasic(enum_def.underlying_type, false) + ")\n"; + code += "\n"; + + // 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.vals.vec.back()->value - enum_def.vals.vec.front()->value + 1; + // Average distance between values above which we consider a table + // "too sparse". Change at will. + static const int kMaxSparseness = 5; + if (range / static_cast(enum_def.vals.vec.size()) < + kMaxSparseness) { + code += "inline const char **EnumNames" + enum_def.name + "() {\n"; + code += " static const char *names[] = { "; + auto val = enum_def.vals.vec.front()->value; + for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); + ++it) { + while (val++ != (*it)->value) code += "\"\", "; + code += "\"" + (*it)->name + "\", "; + } + code += "nullptr };\n return names;\n}\n\n"; + code += "inline const char *EnumName" + enum_def.name; + code += "(" + enum_def.name + " e) { return EnumNames" + enum_def.name; + code += "()[static_cast(e)"; + if (enum_def.vals.vec.front()->value) { + code += " - static_cast("; + code += + GetEnumVal(enum_def, *enum_def.vals.vec.front(), parser_.opts) + ")"; + } + code += "]; }\n\n"; + } + + if (enum_def.is_union) { + code += EnumSignature(enum_def) + ";\n\n"; + } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } - if (enum_def.is_union) { + void GenEnumPost(EnumDef &enum_def, std::string *code_ptr_post) { // Generate a verifier function for this union that can be called by the // table verifier functions. It uses a switch case to select a specific // verifier function to call, this should be safe even if the union type @@@ -227,611 -414,476 +489,745 @@@ } code_post += " default: return false;\n }\n}\n\n"; } - } ++<<<<<<< HEAD +// Generates a value with optionally a cast applied if the field has a +// different underlying type from its interface type (currently only the +// case for enums. "from" specify the direction, true meaning from the +// underlying type to the interface type. +std::string GenUnderlyingCast(const Parser &parser, const FieldDef &field, + bool from, const std::string &val) { + return (field.value.type.enum_def && IsScalar(field.value.type.base_type)) || + field.value.type.base_type == BASE_TYPE_BOOL + ? "static_cast<" + GenTypeBasic(parser, field.value.type, from) + ">(" + + val + ")" + : val; +} + +std::string GenFieldOffsetName(const FieldDef &field) { + std::string uname = field.name; + std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper); + return "VT_" + uname; +} + +// Generate an accessor struct, builder structs & function for a table. +static void GenTable(const Parser &parser, StructDef &struct_def, + const GeneratorOptions &opts, std::string *code_ptr) { + if (struct_def.generated) return; + std::string &code = *code_ptr; + + // Generate an accessor struct, with methods of the form: + // type name() const { return GetField(offset, defaultval); } + GenComment(struct_def.doc_comment, code_ptr, nullptr); + code += "struct " + struct_def.name; + code += " FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table"; + code += " {\n"; + // Generate field id constants. + code += " enum {\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (!field.deprecated) { // Deprecated fields won't be accessible. + code += " " + GenFieldOffsetName(field) + " = "; + code += NumToString(field.value.offset) + ",\n"; + } + } + code += " };\n"; + // Generate the accessors. + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (!field.deprecated) { // Deprecated fields won't be accessible. + auto is_scalar = IsScalar(field.value.type.base_type); + GenComment(field.doc_comment, code_ptr, nullptr, " "); + code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " *", + true); + code += field.name + "() const { return "; + // Call a different accessor for pointers, that indirects. + auto accessor = is_scalar + ? "GetField<" + : (IsStruct(field.value.type) ? "GetStruct<" : "GetPointer<"); + auto offsetstr = GenFieldOffsetName(field); + auto call = + accessor + + GenTypeGet(parser, field.value.type, "", "const ", " *", false) + + ">(" + offsetstr; + // Default value as second arg for non-pointer types. + if (IsScalar(field.value.type.base_type)) + call += ", " + field.value.constant; + call += ")"; + code += GenUnderlyingCast(parser, field, true, call); + code += "; }\n"; + if (opts.mutable_buffer) { + if (is_scalar) { + code += " bool mutate_" + field.name + "("; + code += GenTypeBasic(parser, field.value.type, true); + code += " _" + field.name + ") { return SetField(" + offsetstr + ", "; + code += GenUnderlyingCast(parser, field, false, "_" + field.name); + code += "); }\n"; + } else { + auto type = GenTypeGet(parser, field.value.type, " ", "", " *", true); + code += " " + type + "mutable_" + field.name + "() { return "; + code += GenUnderlyingCast(parser, field, true, + accessor + type + ">(" + offsetstr + ")"); + code += "; }\n"; ++======= + // Generates a value with optionally a cast applied if the field has a + // different underlying type from its interface type (currently only the + // case for enums. "from" specify the direction, true meaning from the + // underlying type to the interface type. + std::string GenUnderlyingCast(const FieldDef &field, bool from, + const std::string &val) { + if (from && field.value.type.base_type == BASE_TYPE_BOOL) { + return val + " != 0"; + } else if ((field.value.type.enum_def && + IsScalar(field.value.type.base_type)) || + field.value.type.base_type == BASE_TYPE_BOOL) { + return "static_cast<" + GenTypeBasic(field.value.type, from) + ">(" + + val + ")"; + } else { + return val; + } + } + + std::string GenFieldOffsetName(const FieldDef &field) { + std::string uname = field.name; + std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper); + return "VT_" + uname; + } + + void GenFullyQualifiedNameGetter(const std::string &name, + std::string &code) { + if (parser_.opts.generate_name_strings) { + code += + " static FLATBUFFERS_CONSTEXPR const char *GetFullyQualifiedName() " + "{\n"; + code += " return \"" + + parser_.namespaces_.back()->GetFullyQualifiedName(name) + "\";\n"; + code += " }\n"; + } + } + + std::string GenDefaultConstant(const FieldDef &field) { + return field.value.type.base_type == BASE_TYPE_FLOAT + ? field.value.constant + "f" + : field.value.constant; + } + + // Generate an accessor struct, builder structs & function for a table. + void GenTable(StructDef &struct_def, std::string *code_ptr) { + std::string &code = *code_ptr; + // Generate an accessor struct, with methods of the form: + // type name() const { return GetField(offset, defaultval); } + GenComment(struct_def.doc_comment, code_ptr, nullptr); + code += "struct " + struct_def.name; + code += " FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table"; + code += " {\n"; + // Generate GetFullyQualifiedName + GenFullyQualifiedNameGetter(struct_def.name, code); + // Generate field id constants. + if (struct_def.fields.vec.size() > 0) { + code += " enum {\n"; + bool is_first_field = + true; // track the first field that's not deprecated + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated) { // Deprecated fields won't be accessible. + if (!is_first_field) { + // Add trailing comma and newline to previous element. Don't add + // trailing comma to + // last element since older versions of gcc complain about this. + code += ",\n"; + } else { + is_first_field = false; + } + code += " " + GenFieldOffsetName(field) + " = "; + code += NumToString(field.value.offset); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } } - auto nested = field.attributes.Lookup("nested_flatbuffer"); - if (nested) { - std::string qualified_name = - parser.namespaces_.back()->GetFullyQualifiedName(nested->constant); - auto nested_root = parser.structs_.Lookup(qualified_name); - assert(nested_root); // Guaranteed to exist by parser. - (void)nested_root; - std::string cpp_qualified_name = TranslateNameSpace(qualified_name); - - code += " const " + cpp_qualified_name + " *" + field.name; - code += "_nested_root() const { return flatbuffers::GetRoot<"; - code += cpp_qualified_name + ">(" + field.name + "()->Data()); }\n"; - } - // Generate a comparison function for this field if it is a key. - if (field.key) { - code += " bool KeyCompareLessThan(const " + struct_def.name; - code += " *o) const { return "; - if (field.value.type.base_type == BASE_TYPE_STRING) code += "*"; - code += field.name + "() < "; - if (field.value.type.base_type == BASE_TYPE_STRING) code += "*"; - code += "o->" + field.name + "(); }\n"; - code += " int KeyCompareWithValue("; - if (field.value.type.base_type == BASE_TYPE_STRING) { - code += "const char *val) const { return strcmp(" + field.name; - code += "()->c_str(), val); }\n"; - } else { - if (opts.scoped_enums && - field.value.type.enum_def && - IsScalar(field.value.type.base_type)) { - code += GenTypeGet(parser, field.value.type, " ", "const ", " *", - true); + code += "\n };\n"; + } + // Generate the accessors. + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated) { // Deprecated fields won't be accessible. + auto is_scalar = IsScalar(field.value.type.base_type); + GenComment(field.doc_comment, code_ptr, nullptr, " "); + code += " " + + GenTypeGet(field.value.type, " ", "const ", " *", true); + code += field.name + "() const { return "; + // Call a different accessor for pointers, that indirects. + auto accessor = + is_scalar + ? "GetField<" + : (IsStruct(field.value.type) ? "GetStruct<" : "GetPointer<"); + auto offsetstr = GenFieldOffsetName(field); + auto call = accessor + GenTypeGet(field.value.type, "", + "const ", " *", false) + + ">(" + offsetstr; + // Default value as second arg for non-pointer types. + if (IsScalar(field.value.type.base_type)) + call += ", " + GenDefaultConstant(field); + call += ")"; + code += GenUnderlyingCast(field, true, call); + code += "; }\n"; + if (parser_.opts.mutable_buffer) { + if (is_scalar) { + code += " bool mutate_" + field.name + "("; + code += GenTypeBasic(field.value.type, true); + code += + " _" + field.name + ") { return SetField(" + offsetstr + ", "; + code += GenUnderlyingCast(field, false, "_" + field.name); + code += "); }\n"; + } else { + auto type = + GenTypeGet(field.value.type, " ", "", " *", true); + code += " " + type + "mutable_" + field.name + "() { return "; + code += GenUnderlyingCast(field, true, + accessor + type + ">(" + offsetstr + ")"); + code += "; }\n"; + } + } + auto nested = field.attributes.Lookup("nested_flatbuffer"); + if (nested) { + std::string qualified_name = + parser_.namespaces_.back()->GetFullyQualifiedName( + nested->constant); + auto nested_root = parser_.structs_.Lookup(qualified_name); + assert(nested_root); // Guaranteed to exist by parser. + (void)nested_root; + std::string cpp_qualified_name = TranslateNameSpace(qualified_name); + + code += " const " + cpp_qualified_name + " *" + field.name; + code += "_nested_root() const { return flatbuffers::GetRoot<"; + code += cpp_qualified_name + ">(" + field.name + "()->Data()); }\n"; + } + // Generate a comparison function for this field if it is a key. + if (field.key) { + code += " bool KeyCompareLessThan(const " + struct_def.name; + code += " *o) const { return "; + if (field.value.type.base_type == BASE_TYPE_STRING) code += "*"; + code += field.name + "() < "; + if (field.value.type.base_type == BASE_TYPE_STRING) code += "*"; + code += "o->" + field.name + "(); }\n"; + code += " int KeyCompareWithValue("; + if (field.value.type.base_type == BASE_TYPE_STRING) { + code += "const char *val) const { return strcmp(" + field.name; + code += "()->c_str(), val); }\n"; } else { - code += GenTypeBasic(parser, field.value.type, false); + if (parser_.opts.scoped_enums && field.value.type.enum_def && + IsScalar(field.value.type.base_type)) { + code += GenTypeGet(field.value.type, " ", "const ", " *", true); + } else { + code += GenTypeBasic(field.value.type, false); + } + code += " val) const { return " + field.name + "() < val ? -1 : "; + code += field.name + "() > val; }\n"; } - code += " val) const { return " + field.name + "() < val ? -1 : "; - code += field.name + "() > val; }\n"; } } } ++<<<<<<< HEAD + } + // Generate a verifier function that can check a buffer from an untrusted + // source will never cause reads outside the buffer. + code += " bool Verify(flatbuffers::Verifier &verifier) const {\n"; + code += " return VerifyTableStart(verifier)"; + std::string prefix = " &&\n "; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (!field.deprecated) { + code += prefix + "VerifyField"; + if (field.required) code += "Required"; + code += "<" + GenTypeSize(parser, field.value.type); + code += ">(verifier, " + GenFieldOffsetName(field) + ")"; + switch (field.value.type.base_type) { + case BASE_TYPE_UNION: + code += prefix + "Verify" + field.value.type.enum_def->name; + code += "(verifier, " + field.name + "(), " + field.name + "_type())"; + break; + case BASE_TYPE_STRUCT: + if (!field.value.type.struct_def->fixed) { + code += prefix + "verifier.VerifyTable(" + field.name; + code += "())"; + } + break; + case BASE_TYPE_STRING: + code += prefix + "verifier.Verify(" + field.name + "())"; + break; + case BASE_TYPE_VECTOR: + code += prefix + "verifier.Verify(" + field.name + "())"; + switch (field.value.type.element) { + case BASE_TYPE_STRING: { + code += prefix + "verifier.VerifyVectorOfStrings(" + field.name; ++======= + // Generate a verifier function that can check a buffer from an untrusted + // source will never cause reads outside the buffer. + code += " bool Verify(flatbuffers::Verifier &verifier) const {\n"; + code += " return VerifyTableStart(verifier)"; + std::string prefix = " &&\n "; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated) { + code += prefix + "VerifyField"; + if (field.required) code += "Required"; + code += "<" + GenTypeSize(field.value.type); + code += ">(verifier, " + GenFieldOffsetName(field) + ")"; + switch (field.value.type.base_type) { + case BASE_TYPE_UNION: + code += prefix + "Verify" + field.value.type.enum_def->name; + code += "(verifier, " + field.name + "(), " + field.name + + UnionTypeFieldSuffix() + "())"; + break; + case BASE_TYPE_STRUCT: + if (!field.value.type.struct_def->fixed) { + code += prefix + "verifier.VerifyTable(" + field.name; ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 code += "())"; - break; } - case BASE_TYPE_STRUCT: { - if (!field.value.type.struct_def->fixed) { - code += prefix + "verifier.VerifyVectorOfTables(" + field.name; + break; + case BASE_TYPE_STRING: + code += prefix + "verifier.Verify(" + field.name + "())"; + break; + case BASE_TYPE_VECTOR: + code += prefix + "verifier.Verify(" + field.name + "())"; + switch (field.value.type.element) { + case BASE_TYPE_STRING: { + code += prefix + "verifier.VerifyVectorOfStrings(" + field.name; code += "())"; + break; + } + case BASE_TYPE_STRUCT: { + if (!field.value.type.struct_def->fixed) { + code += + prefix + "verifier.VerifyVectorOfTables(" + field.name; + code += "())"; + } + break; } - break; + default: + break; } - default: - break; - } - break; - default: - break; + break; + default: + break; + } } } - } - code += prefix + "verifier.EndTable()"; - code += ";\n }\n"; - code += "};\n\n"; + code += prefix + "verifier.EndTable()"; + code += ";\n }\n"; + code += "};\n\n"; - // Generate a builder struct, with methods of the form: - // void add_name(type name) { fbb_.AddElement(offset, name, default); } - code += "struct " + struct_def.name; - code += "Builder {\n flatbuffers::FlatBufferBuilder &fbb_;\n"; - code += " flatbuffers::uoffset_t start_;\n"; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); - ++it) { - auto &field = **it; - if (!field.deprecated) { - code += " void add_" + field.name + "("; - code += GenTypeWire(parser, field.value.type, " ", true) + field.name; - code += ") { fbb_.Add"; - if (IsScalar(field.value.type.base_type)) { - code += "Element<" + GenTypeWire(parser, field.value.type, "", false); - code += ">"; - } else if (IsStruct(field.value.type)) { - code += "Struct"; - } else { - code += "Offset"; + // Generate a builder struct, with methods of the form: + // void add_name(type name) { fbb_.AddElement(offset, name, default); + // } + code += "struct " + struct_def.name; + code += "Builder {\n flatbuffers::FlatBufferBuilder &fbb_;\n"; + code += " flatbuffers::uoffset_t start_;\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated) { + code += " void add_" + field.name + "("; + code += GenTypeWire(field.value.type, " ", true) + field.name; + code += ") { fbb_.Add"; + if (IsScalar(field.value.type.base_type)) { + code += "Element<" + GenTypeWire(field.value.type, "", false); + code += ">"; + } else if (IsStruct(field.value.type)) { + code += "Struct"; + } else { + code += "Offset"; + } + code += "(" + struct_def.name + "::" + GenFieldOffsetName(field) + ", "; + code += GenUnderlyingCast(field, false, field.name); + if (IsScalar(field.value.type.base_type)) + code += ", " + GenDefaultConstant(field); + code += "); }\n"; } ++<<<<<<< HEAD + code += "(" + struct_def.name + "::" + GenFieldOffsetName(field) + ", "; + code += GenUnderlyingCast(parser, field, false, field.name); + if (IsScalar(field.value.type.base_type)) + code += ", " + field.value.constant; + code += "); }\n"; + } + } + code += " " + struct_def.name; + code += "Builder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) "; + code += "{ start_ = fbb_.StartTable(); }\n"; + code += " " + struct_def.name + "Builder &operator=(const "; + code += struct_def.name + "Builder &);\n"; + code += " flatbuffers::Offset<" + struct_def.name; + code += "> Finish() {\n auto o = flatbuffers::Offset<" + struct_def.name; + code += ">(fbb_.EndTable(start_, "; + 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 && field.required) { + code += " fbb_.Required(o, "; + code += struct_def.name + "::" + GenFieldOffsetName(field); + code += "); // " + field.name + "\n"; ++======= } - } - code += " return o;\n }\n};\n\n"; + code += " " + struct_def.name; + code += "Builder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) "; + code += "{ start_ = fbb_.StartTable(); }\n"; + code += " " + struct_def.name + "Builder &operator=(const "; + code += struct_def.name + "Builder &);\n"; + code += " flatbuffers::Offset<" + struct_def.name; + code += "> Finish() {\n auto o = flatbuffers::Offset<" + struct_def.name; + code += ">(fbb_.EndTable(start_, "; + 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 && field.required) { + code += " fbb_.Required(o, "; + code += struct_def.name + "::" + GenFieldOffsetName(field); + code += "); // " + field.name + "\n"; + } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 + } + code += " return o;\n }\n};\n\n"; - // Generate a convenient CreateX function that uses the above builder - // to create a table in one go. - code += "inline flatbuffers::Offset<" + struct_def.name + "> Create"; - code += struct_def.name; - code += "(flatbuffers::FlatBufferBuilder &_fbb"; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); - ++it) { - auto &field = **it; - if (!field.deprecated) { - code += ",\n " + GenTypeWire(parser, field.value.type, " ", true); - code += field.name + " = "; - if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) { - auto ev = field.value.type.enum_def->ReverseLookup( - static_cast(StringToInt(field.value.constant.c_str())), false); - if (ev) { - code += WrapInNameSpace(parser, - field.value.type.enum_def->defined_namespace, - GetEnumVal(*field.value.type.enum_def, *ev, - opts)); + // Generate a convenient CreateX function that uses the above builder + // to create a table in one go. + code += "inline flatbuffers::Offset<" + struct_def.name + "> Create"; + code += struct_def.name; + code += "(flatbuffers::FlatBufferBuilder &_fbb"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (!field.deprecated) { + code += ",\n " + GenTypeWire(field.value.type, " ", true); + code += field.name + " = "; + if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) { + auto ev = field.value.type.enum_def->ReverseLookup( + static_cast(StringToInt(field.value.constant.c_str())), + false); + if (ev) { + code += WrapInNameSpace( + field.value.type.enum_def->defined_namespace, + GetEnumVal(*field.value.type.enum_def, *ev, parser_.opts)); + } else { + code += GenUnderlyingCast(field, true, field.value.constant); + } + } else if (field.value.type.base_type == BASE_TYPE_BOOL) { + code += field.value.constant == "0" ? "false" : "true"; } else { - code += GenUnderlyingCast(parser, field, true, field.value.constant); + code += GenDefaultConstant(field); } ++<<<<<<< HEAD + } else if (field.value.type.base_type == BASE_TYPE_BOOL) { + code += field.value.constant == "0" ? "false" : "true"; + } else { + code += field.value.constant; ++======= ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } } - } - code += ") {\n " + struct_def.name + "Builder builder_(_fbb);\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 += " builder_.add_" + field.name + "(" + field.name + ");\n"; + code += ") {\n " + struct_def.name + "Builder builder_(_fbb);\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 += " builder_.add_" + field.name + "(" + field.name + ");\n"; + } } } + code += " return builder_.Finish();\n}\n\n"; } - code += " return builder_.Finish();\n}\n\n"; - } ++<<<<<<< HEAD +static void GenPadding(const FieldDef &field, + const std::function &f) { + if (field.padding) { + for (int i = 0; i < 4; i++) + if (static_cast(field.padding) & (1 << i)) + f((1 << i) * 8); + assert(!(field.padding & ~0xF)); + } +} + +// Generate an accessor struct with constructor for a flatbuffers struct. +static void GenStruct(const Parser &parser, StructDef &struct_def, + const GeneratorOptions &opts, std::string *code_ptr) { + if (struct_def.generated) return; + std::string &code = *code_ptr; + + // Generate an accessor struct, with private variables of the form: + // type name_; + // Generates manual padding and alignment. + // Variables are private because they contain little endian data on all + // platforms. + GenComment(struct_def.doc_comment, code_ptr, nullptr); + code += "MANUALLY_ALIGNED_STRUCT(" + NumToString(struct_def.minalign) + ") "; + code += struct_def.name + " FLATBUFFERS_FINAL_CLASS {\n private:\n"; + int padding_id = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + code += " " + GenTypeGet(parser, field.value.type, " ", "", " ", false); + code += field.name + "_;\n"; + GenPadding(field, [&code, &padding_id](int bits) { + code += " int" + NumToString(bits) + + "_t __padding" + NumToString(padding_id++) + ";\n"; + }); + } + + // Generate a constructor that takes all fields as arguments. + code += "\n public:\n " + struct_def.name + "("; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (it != struct_def.fields.vec.begin()) code += ", "; + code += GenTypeGet(parser, field.value.type, " ", "const ", " &", true); + code += "_" + field.name; + } + code += ")\n : "; + padding_id = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (it != struct_def.fields.vec.begin()) code += ", "; + code += field.name + "_("; + if (IsScalar(field.value.type.base_type)) { + code += "flatbuffers::EndianScalar("; + code += GenUnderlyingCast(parser, field, false, "_" + field.name); + code += "))"; + } else { + code += "_" + field.name + ")"; + } + GenPadding(field, [&code, &padding_id](int bits) { + (void)bits; + code += ", __padding" + NumToString(padding_id++) + "(0)"; + }); + } + code += " {"; + padding_id = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + GenPadding(field, [&code, &padding_id](int bits) { + (void)bits; + code += " (void)__padding" + NumToString(padding_id++) + ";"; + }); + } + code += " }\n\n"; + + // Generate accessor methods of the form: + // type name() const { return flatbuffers::EndianScalar(name_); } + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + GenComment(field.doc_comment, code_ptr, nullptr, " "); + auto is_scalar = IsScalar(field.value.type.base_type); + code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " &", + true); + code += field.name + "() const { return "; + code += GenUnderlyingCast(parser, field, true, + is_scalar + ? "flatbuffers::EndianScalar(" + field.name + "_)" + : field.name + "_"); + code += "; }\n"; + if (opts.mutable_buffer) { + if (is_scalar) { + code += " void mutate_" + field.name + "("; + code += GenTypeBasic(parser, field.value.type, true); + code += " _" + field.name + ") { flatbuffers::WriteScalar(&"; + code += field.name + "_, "; + code += GenUnderlyingCast(parser, field, false, "_" + field.name); + code += "); }\n"; + } else { + code += " "; + code += GenTypeGet(parser, field.value.type, "", "", " &", true); + code += "mutable_" + field.name + "() { return " + field.name; + code += "_; }\n"; + } ++======= + static void GenPadding(const FieldDef &field, std::string &code, + int &padding_id, + const std::function &f) { + if (field.padding) { + for (int i = 0; i < 4; i++) + if (static_cast(field.padding) & (1 << i)) + f((1 << i) * 8, code, padding_id); + assert(!(field.padding & ~0xF)); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } } - code += "};\nSTRUCT_END(" + struct_def.name + ", "; - code += NumToString(struct_def.bytesize) + ");\n\n"; - } - void GenerateNestedNameSpaces(Namespace *ns, std::string *code_ptr) { - for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { - *code_ptr += "namespace " + *it + " {\n"; + static void PaddingDefinition(int bits, std::string &code, int &padding_id) { + code += " int" + NumToString(bits) + "_t __padding" + + NumToString(padding_id++) + ";\n"; } - } - void CloseNestedNameSpaces(Namespace *ns, std::string *code_ptr) { - for (auto it = ns->components.rbegin(); it != ns->components.rend(); ++it) { - *code_ptr += "} // namespace " + *it + "\n"; + static void PaddingDeclaration(int bits, std::string &code, int &padding_id) { + (void)bits; + code += " (void)__padding" + NumToString(padding_id++) + ";"; } - } - - } // namespace cpp - // Iterate through all definitions we haven't generate code for (enums, structs, - // and tables) and output them to a single file. - std::string GenerateCPP(const Parser &parser, - const std::string &file_name, - const GeneratorOptions &opts) { - using namespace cpp; - - // Generate code for all the enum declarations. - std::string enum_code, enum_code_post; - for (auto it = parser.enums_.vec.begin(); - it != parser.enums_.vec.end(); ++it) { - GenEnum(parser, **it, &enum_code, &enum_code_post, opts); - } - - // Generate forward declarations for all structs/tables, since they may - // have circular references. - std::string forward_decl_code_same_namespace; - std::string forward_decl_code_other_namespace; - Namespace *cur_name_space = nullptr; - for (auto it = parser.structs_.vec.begin(); - it != parser.structs_.vec.end(); ++it) { - auto &struct_def = **it; - auto decl = "struct " + struct_def.name + ";\n"; - if (struct_def.defined_namespace == parser.namespaces_.back()) { - forward_decl_code_same_namespace += decl; - } else { - // Wrap this decl in the correct namespace. Only open a namespace if - // the adjacent one is different. - // TODO: this could be done more intelligently, by sorting to - // namespace path and only opening/closing what is necessary, but that's - // quite a bit more complexity. - if (cur_name_space != struct_def.defined_namespace) { - if (cur_name_space) { - CloseNestedNameSpaces(cur_name_space, - &forward_decl_code_other_namespace); - } - GenerateNestedNameSpaces(struct_def.defined_namespace, - &forward_decl_code_other_namespace); - cur_name_space = struct_def.defined_namespace; - } - forward_decl_code_other_namespace += decl; - } - } - if (cur_name_space) { - CloseNestedNameSpaces(cur_name_space, - &forward_decl_code_other_namespace); + static void PaddingInitializer(int bits, std::string &code, int &padding_id) { + (void)bits; + code += ", __padding" + NumToString(padding_id++) + "(0)"; } - // Generate code for all structs, then all tables. - std::string decl_code; - for (auto it = parser.structs_.vec.begin(); - it != parser.structs_.vec.end(); ++it) { - if ((**it).fixed) GenStruct(parser, **it, opts, &decl_code); - } - for (auto it = parser.structs_.vec.begin(); - it != parser.structs_.vec.end(); ++it) { - if (!(**it).fixed) GenTable(parser, **it, opts, &decl_code); - } - - // Only output file-level code if there were any declarations. - if (enum_code.length() || decl_code.length()) { - std::string code; - code = "// automatically generated by the FlatBuffers compiler," - " do not modify\n\n"; + // Generate an accessor struct with constructor for a flatbuffers struct. + void GenStruct(StructDef &struct_def, std::string *code_ptr) { + if (struct_def.generated) return; + std::string &code = *code_ptr; - // Generate include guard. - std::string include_guard_ident = file_name; - // Remove any non-alpha-numeric characters that may appear in a filename. - include_guard_ident.erase( - std::remove_if(include_guard_ident.begin(), - include_guard_ident.end(), - [](char c) { return !isalnum(c); }), - include_guard_ident.end()); - std::string include_guard = "FLATBUFFERS_GENERATED_" + include_guard_ident; - include_guard += "_"; - // For further uniqueness, also add the namespace. - auto name_space = parser.namespaces_.back(); - for (auto it = name_space->components.begin(); - it != name_space->components.end(); ++it) { - include_guard += *it + "_"; + // Generate an accessor struct, with private variables of the form: + // type name_; + // Generates manual padding and alignment. + // Variables are private because they contain little endian data on all + // platforms. + GenComment(struct_def.doc_comment, code_ptr, nullptr); + code += + "MANUALLY_ALIGNED_STRUCT(" + NumToString(struct_def.minalign) + ") "; + code += struct_def.name + " FLATBUFFERS_FINAL_CLASS {\n private:\n"; + int padding_id = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + code += " " + GenTypeGet(field.value.type, " ", "", " ", false); + code += field.name + "_;\n"; + GenPadding(field, code, padding_id, PaddingDefinition); } - include_guard += "H_"; - std::transform(include_guard.begin(), include_guard.end(), - include_guard.begin(), ::toupper); - code += "#ifndef " + include_guard + "\n"; - code += "#define " + include_guard + "\n\n"; - code += "#include \"flatbuffers/flatbuffers.h\"\n\n"; + // Generate GetFullyQualifiedName + code += "\n public:\n"; + GenFullyQualifiedNameGetter(struct_def.name, code); - if (opts.include_dependence_headers) { - int num_includes = 0; - for (auto it = parser.included_files_.begin(); - it != parser.included_files_.end(); ++it) { - auto basename = flatbuffers::StripPath( - flatbuffers::StripExtension(it->first)); - if (basename != file_name) { - code += "#include \"" + basename + "_generated.h\"\n"; - num_includes++; - } - } - if (num_includes) code += "\n"; + // Generate a constructor that takes all fields as arguments. + code += " " + struct_def.name + "("; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (it != struct_def.fields.vec.begin()) code += ", "; + code += GenTypeGet(field.value.type, " ", "const ", " &", true); + code += "_" + field.name; } - - code += forward_decl_code_other_namespace; - code += "\n"; - - GenerateNestedNameSpaces(name_space, &code); - code += "\n"; - - code += forward_decl_code_same_namespace; - code += "\n"; - - // Output the main declaration code from above. - code += enum_code; - code += decl_code; - code += enum_code_post; - - // Generate convenient global helper functions: - if (parser.root_struct_def_) { - auto &name = parser.root_struct_def_->name; - std::string qualified_name = - parser.namespaces_.back()->GetFullyQualifiedName(name); - std::string cpp_qualified_name = TranslateNameSpace(qualified_name); - - // The root datatype accessor: - code += "inline const " + cpp_qualified_name + " *Get"; - code += name; - code += "(const void *buf) { return flatbuffers::GetRoot<"; - code += cpp_qualified_name + ">(buf); }\n\n"; - if (opts.mutable_buffer) { - code += "inline " + name + " *GetMutable"; - code += name; - code += "(void *buf) { return flatbuffers::GetMutableRoot<"; - code += name + ">(buf); }\n\n"; + code += ")\n : "; + padding_id = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + if (it != struct_def.fields.vec.begin()) code += ", "; + code += field.name + "_("; + if (IsScalar(field.value.type.base_type)) { + code += "flatbuffers::EndianScalar("; + code += GenUnderlyingCast(field, false, "_" + field.name); + code += "))"; + } else { + code += "_" + field.name + ")"; } + GenPadding(field, code, padding_id, PaddingInitializer); + } - // The root verifier: - code += "inline bool Verify"; - code += name; - code += "Buffer(flatbuffers::Verifier &verifier) { " - "return verifier.VerifyBuffer<"; - code += cpp_qualified_name + ">(); }\n\n"; - - if (parser.file_identifier_.length()) { - // Return the identifier - code += "inline const char *" + name; - code += "Identifier() { return \"" + parser.file_identifier_; - code += "\"; }\n\n"; - - // Check if a buffer has the identifier. - code += "inline bool " + name; - code += "BufferHasIdentifier(const void *buf) { return flatbuffers::"; - code += "BufferHasIdentifier(buf, "; - code += name + "Identifier()); }\n\n"; - } + code += " {"; + padding_id = 0; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + GenPadding(field, code, padding_id, PaddingDeclaration); + } + code += " }\n\n"; - if (parser.file_extension_.length()) { - // Return the extension - code += "inline const char *" + name; - code += "Extension() { return \"" + parser.file_extension_; - code += "\"; }\n\n"; + // Generate accessor methods of the form: + // type name() const { return flatbuffers::EndianScalar(name_); } + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); ++it) { + auto &field = **it; + GenComment(field.doc_comment, code_ptr, nullptr, " "); + auto is_scalar = IsScalar(field.value.type.base_type); + code += " " + + GenTypeGet(field.value.type, " ", "const ", " &", true); + code += field.name + "() const { return "; + code += GenUnderlyingCast( + field, true, is_scalar + ? "flatbuffers::EndianScalar(" + field.name + "_)" + : field.name + "_"); + code += "; }\n"; + if (parser_.opts.mutable_buffer) { + if (is_scalar) { + code += " void mutate_" + field.name + "("; + code += GenTypeBasic(field.value.type, true); + code += " _" + field.name + ") { flatbuffers::WriteScalar(&"; + code += field.name + "_, "; + code += GenUnderlyingCast(field, false, "_" + field.name); + code += "); }\n"; + } else { + code += " "; + code += GenTypeGet(field.value.type, "", "", " &", true); + code += "mutable_" + field.name + "() { return " + field.name; + code += "_; }\n"; + } } - - // Finish a buffer with a given root object: - code += "inline void Finish" + name; - code += "Buffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<"; - code += cpp_qualified_name + "> root) { fbb.Finish(root"; - if (parser.file_identifier_.length()) - code += ", " + name + "Identifier()"; - code += "); }\n\n"; - } - - CloseNestedNameSpaces(name_space, &code); - - // Close the include guard. - code += "\n#endif // " + include_guard + "\n"; - - return code; + code += "};\nSTRUCT_END(" + struct_def.name + ", "; + code += NumToString(struct_def.bytesize) + ");\n\n"; } - return std::string(); - } - - static std::string GeneratedFileName(const std::string &path, - const std::string &file_name) { - return path + file_name + "_generated.h"; - } + // Set up the correct namespace. Only open a namespace if + // the existing one is different (closing/opening only what is necessary) : + // + // the file must start and end with an empty (or null) namespace + // so that namespaces are properly opened and closed + void SetNameSpace(const Namespace *ns, std::string *code_ptr) { + if (cur_name_space_ == ns) return; + // compute the size of the longest common namespace prefix. + // if cur_name_space is A::B::C::D and ns is A::B::E::F::G, + // the common prefix is A::B:: and we have old_size = 4, new_size = 5 + // and common_prefix_size = 2 + auto old_size = + cur_name_space_ == nullptr ? 0 : cur_name_space_->components.size(); + auto new_size = ns == nullptr ? 0 : ns->components.size(); + std::vector::size_type common_prefix_size = 0; + while (common_prefix_size < old_size && common_prefix_size < new_size && + ns->components[common_prefix_size] == + cur_name_space_->components[common_prefix_size]) + common_prefix_size++; + // close cur_name_space in reverse order to reach the common prefix + // in the previous example, D then C are closed + for (auto j = old_size; j > common_prefix_size; --j) + *code_ptr += + "} // namespace " + cur_name_space_->components[j - 1] + "\n"; + if (old_size != common_prefix_size) *code_ptr += "\n"; + // open namespace parts to reach the ns namespace + // in the previous example, E, then F, then G are opened + for (auto j = common_prefix_size; j != new_size; ++j) + *code_ptr += "namespace " + ns->components[j] + " {\n"; + if (new_size != common_prefix_size) *code_ptr += "\n"; + cur_name_space_ = ns; + } + }; + } // namespace cpp - bool GenerateCPP(const Parser &parser, - const std::string &path, - const std::string &file_name, - const GeneratorOptions &opts) { - auto code = GenerateCPP(parser, file_name, opts); - return !code.length() || - SaveFile(GeneratedFileName(path, file_name).c_str(), code, false); + bool GenerateCPP(const Parser &parser, const std::string &path, + const std::string &file_name) { + cpp::CppGenerator generator(parser, path, file_name); + return generator.generate(); } std::string CPPMakeRule(const Parser &parser, diff --cc src/idl_parser.cpp index f2b7fc9,b758e95..36a63c6 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@@ -885,14 -1160,14 +1160,18 @@@ StructDef *Parser::LookupCreateStruct(c return struct_def; } - EnumDef &Parser::ParseEnum(bool is_union) { + CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { std::vector enum_comment = doc_comment_; - Next(); + NEXT(); std::string enum_name = attribute_; - Expect(kTokenIdentifier); + EXPECT(kTokenIdentifier); auto &enum_def = *new EnumDef(); enum_def.name = enum_name; ++<<<<<<< HEAD + enum_def.file = files_being_parsed_; ++======= + enum_def.file = file_being_parsed_; ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 enum_def.doc_comment = enum_comment; enum_def.is_union = is_union; enum_def.defined_namespace = namespaces_.back(); @@@ -965,15 -1255,16 +1259,20 @@@ (*it)->value = 1LL << (*it)->value; } } - return enum_def; + if (dest) *dest = &enum_def; + return NoError(); } - StructDef &Parser::StartStruct(const std::string &name) { + CheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { auto &struct_def = *LookupCreateStruct(name, true, true); - if (!struct_def.predecl) Error("datatype already exists: " + name); + if (!struct_def.predecl) return Error("datatype already exists: " + name); struct_def.predecl = false; struct_def.name = name; ++<<<<<<< HEAD + struct_def.file = files_being_parsed_; ++======= + struct_def.file = file_being_parsed_; ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 // Move this struct to the back of the vector just in case it was predeclared, // to preserve declaration order. *remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def; @@@ -1351,7 -1779,12 +1787,16 @@@ CheckedError Parser::SkipJsonString() bool Parser::Parse(const char *source, const char **include_paths, const char *source_filename) { ++<<<<<<< HEAD + files_being_parsed_ = source_filename ? source_filename : ""; ++======= + return !DoParse(source, include_paths, source_filename).Check(); + } + + CheckedError Parser::DoParse(const char *source, const char **include_paths, + const char *source_filename) { + file_being_parsed_ = source_filename ? source_filename : ""; ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 if (source_filename && included_files_.find(source_filename) == included_files_.end()) { included_files_[source_filename] = true; @@@ -1367,140 -1800,133 +1812,148 @@@ builder_.Clear(); // Start with a blank namespace just in case this file doesn't have one. namespaces_.push_back(new Namespace()); - try { - Next(); - // Includes must come before type declarations: - for (;;) { - // Parse pre-include proto statements if any: - if (proto_mode_ && - (attribute_ == "option" || attribute_ == "syntax" || - attribute_ == "package")) { - ParseProtoDecl(); - } else if (IsNext(kTokenInclude) || - (proto_mode_ && - attribute_ == "import" && - IsNext(kTokenIdentifier))) { - if (proto_mode_ && attribute_ == "public") Next(); - auto name = attribute_; - Expect(kTokenStringConstant); - // Look for the file in include_paths. - std::string filepath; - for (auto paths = include_paths; paths && *paths; paths++) { - filepath = flatbuffers::ConCatPathFileName(*paths, name); - if(FileExists(filepath.c_str())) break; - } - if (filepath.empty()) - Error("unable to locate include file: " + name); - if (source_filename) - files_included_per_file_[source_filename].insert(filepath); - if (included_files_.find(filepath) == included_files_.end()) { - // We found an include file that we have not parsed yet. - // Load it and parse it. - std::string contents; - if (!LoadFile(filepath.c_str(), true, &contents)) - Error("unable to load include file: " + name); - if (!Parse(contents.c_str(), include_paths, filepath.c_str())) { - // Any errors, we're done. - return false; - } - // We do not want to output code for any included files: - MarkGenerated(); - // This is the easiest way to continue this file after an include: - // instead of saving and restoring all the state, we simply start the - // file anew. This will cause it to encounter the same include statement - // again, but this time it will skip it, because it was entered into - // included_files_. - // This is recursive, but only go as deep as the number of include - // statements. - return Parse(source, include_paths, source_filename); - } - Expect(';'); - } else { - break; + ECHECK(SkipByteOrderMark()); + NEXT(); + // Includes must come before type declarations: + for (;;) { + // Parse pre-include proto statements if any: + if (opts.proto_mode && + (attribute_ == "option" || attribute_ == "syntax" || + attribute_ == "package")) { + ECHECK(ParseProtoDecl()); + } else if (Is(kTokenInclude) || + (opts.proto_mode && + attribute_ == "import" && + Is(kTokenIdentifier))) { + NEXT(); + if (opts.proto_mode && attribute_ == "public") NEXT(); + auto name = attribute_; + EXPECT(kTokenStringConstant); + // Look for the file in include_paths. + std::string filepath; + for (auto paths = include_paths; paths && *paths; paths++) { + filepath = flatbuffers::ConCatPathFileName(*paths, name); + if(FileExists(filepath.c_str())) break; } - } - // Now parse all other kinds of declarations: - while (token_ != kTokenEof) { - if (proto_mode_) { - ParseProtoDecl(); - } else if (token_ == kTokenNameSpace) { - ParseNamespace(); - } else if (token_ == '{') { - if (!root_struct_def_) Error("no root type set to parse json with"); - if (builder_.GetSize()) { - Error("cannot have more than one json object in a file"); - } - builder_.Finish(Offset(ParseTable(*root_struct_def_, nullptr)), - file_identifier_.length() ? file_identifier_.c_str() : nullptr); - } else if (token_ == kTokenEnum) { - ParseEnum(false); - } else if (token_ == kTokenUnion) { - ParseEnum(true); - } else if (token_ == kTokenRootType) { - Next(); - auto root_type = attribute_; - Expect(kTokenIdentifier); - if (!SetRootType(root_type.c_str())) - Error("unknown root type: " + root_type); - if (root_struct_def_->fixed) - Error("root type must be a table"); - Expect(';'); - } else if (token_ == kTokenFileIdentifier) { - Next(); - file_identifier_ = attribute_; - Expect(kTokenStringConstant); - if (file_identifier_.length() != - FlatBufferBuilder::kFileIdentifierLength) - Error("file_identifier must be exactly " + - NumToString(FlatBufferBuilder::kFileIdentifierLength) + - " characters"); - Expect(';'); - } else if (token_ == kTokenFileExtension) { - Next(); - file_extension_ = attribute_; - Expect(kTokenStringConstant); - Expect(';'); - } else if(token_ == kTokenInclude) { - Error("includes must come before declarations"); - } else if(token_ == kTokenAttribute) { - Next(); - auto name = attribute_; - Expect(kTokenStringConstant); - Expect(';'); - known_attributes_.insert(name); - } else { - ParseDecl(); + if (filepath.empty()) + return Error("unable to locate include file: " + name); + if (source_filename) + files_included_per_file_[source_filename].insert(filepath); + if (included_files_.find(filepath) == included_files_.end()) { + // We found an include file that we have not parsed yet. + // Load it and parse it. + std::string contents; + if (!LoadFile(filepath.c_str(), true, &contents)) + return Error("unable to load include file: " + name); + ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str())); + // We generally do not want to output code for any included files: + if (!opts.generate_all) MarkGenerated(); + // This is the easiest way to continue this file after an include: + // instead of saving and restoring all the state, we simply start the + // file anew. This will cause it to encounter the same include + // statement again, but this time it will skip it, because it was + // entered into included_files_. + // This is recursive, but only go as deep as the number of include + // statements. + return DoParse(source, include_paths, source_filename); } + EXPECT(';'); + } else { + break; } - for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { - if ((*it)->predecl) { - Error("type referenced but not defined: " + (*it)->name); + } + // Now parse all other kinds of declarations: + while (token_ != kTokenEof) { + if (opts.proto_mode) { + ECHECK(ParseProtoDecl()); + } else if (token_ == kTokenNameSpace) { + ECHECK(ParseNamespace()); + } else if (token_ == '{') { + if (!root_struct_def_) + return Error("no root type set to parse json with"); + if (builder_.GetSize()) { + return Error("cannot have more than one json object in a file"); } + uoffset_t toff; + ECHECK(ParseTable(*root_struct_def_, nullptr, &toff)); + builder_.Finish(Offset
(toff), + file_identifier_.length() ? file_identifier_.c_str() : nullptr); + } else if (token_ == kTokenEnum) { + ECHECK(ParseEnum(false, nullptr)); + } else if (token_ == kTokenUnion) { + ECHECK(ParseEnum(true, nullptr)); + } else if (token_ == kTokenRootType) { + NEXT(); + auto root_type = attribute_; + EXPECT(kTokenIdentifier); + ECHECK(ParseNamespacing(&root_type, nullptr)); + 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"); + EXPECT(';'); + } else if (token_ == kTokenFileIdentifier) { + NEXT(); + file_identifier_ = attribute_; + EXPECT(kTokenStringConstant); + if (file_identifier_.length() != + FlatBufferBuilder::kFileIdentifierLength) + return Error("file_identifier must be exactly " + + NumToString(FlatBufferBuilder::kFileIdentifierLength) + + " characters"); + EXPECT(';'); + } else if (token_ == kTokenFileExtension) { + NEXT(); + file_extension_ = attribute_; + EXPECT(kTokenStringConstant); + EXPECT(';'); + } else if(token_ == kTokenInclude) { + return Error("includes must come before declarations"); + } else if(token_ == kTokenAttribute) { + NEXT(); + auto name = attribute_; + EXPECT(kTokenStringConstant); + EXPECT(';'); + known_attributes_[name] = false; + } else if (token_ == kTokenService) { + ECHECK(ParseService()); + } else { + ECHECK(ParseDecl()); } - for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { - auto &enum_def = **it; - if (enum_def.is_union) { - for (auto val_it = enum_def.vals.vec.begin(); - val_it != enum_def.vals.vec.end(); - ++val_it) { - auto &val = **val_it; - if (val.struct_def && val.struct_def->fixed) - Error("only tables can be union elements: " + val.name); - } + } + for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { + if ((*it)->predecl) { + return Error("type referenced but not defined: " + (*it)->name); + } + } + for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { + auto &enum_def = **it; + if (enum_def.is_union) { + for (auto val_it = enum_def.vals.vec.begin(); + val_it != enum_def.vals.vec.end(); + ++val_it) { + auto &val = **val_it; + if (val.struct_def && val.struct_def->fixed) + return Error("only tables can be union elements: " + val.name); } } ++<<<<<<< HEAD + } catch (const std::string &msg) { + error_ = source_filename ? AbsolutePath(source_filename) : ""; + #ifdef _WIN32 + error_ += "(" + NumToString(line_) + ")"; // MSVC alike + #else + if (source_filename) error_ += ":"; + error_ += NumToString(line_) + ":0"; // gcc alike + #endif + error_ += ": error: " + msg; + return false; + } + return true; ++======= + } + return NoError(); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } std::set Parser::GetIncludedFilesRecursive( diff --cc tests/generate_code.sh index 91661f3,3436d85..eca73aa --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@@ -1,2 -1,20 +1,25 @@@ ++<<<<<<< HEAD +../flatc --cpp --java --csharp --go --binary --python --js --php --gen-mutable --no-includes monster_test.fbs monsterdata_test.json +../flatc --binary --schema monster_test.fbs ++======= + #!/bin/bash + # + # Copyright 2015 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. + + ../flatc --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --no-includes monster_test.fbs monsterdata_test.json + ../flatc --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs + ../flatc --binary --schema monster_test.fbs + ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 diff --cc tests/monster_test_generated.h index 90814a9,50fbc28..5038edd --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@@ -96,9 -105,40 +105,44 @@@ MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBU }; STRUCT_END(Vec3, 32); + } // namespace Example + + namespace Example2 { + + struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + verifier.EndTable(); + } + }; + + struct MonsterBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + MonsterBuilder &operator=(const MonsterBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 0)); + return o; + } + }; + + inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder &_fbb) { + MonsterBuilder builder_(_fbb); + return builder_.Finish(); + } + + } // namespace Example2 + + namespace Example { + struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { enum { ++<<<<<<< HEAD + VT_COLOR = 4, ++======= + VT_COLOR = 4 ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 }; Color color() const { return static_cast(GetField(VT_COLOR, 2)); } bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast(_color)); } @@@ -132,7 -172,7 +176,11 @@@ struct Stat FLATBUFFERS_FINAL_CLASS : p enum { VT_ID = 4, VT_VAL = 6, ++<<<<<<< HEAD + VT_COUNT = 8, ++======= + VT_COUNT = 8 ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 }; const flatbuffers::String *id() const { return GetPointer(VT_ID); } flatbuffers::String *mutable_id() { return GetPointer(VT_ID); } @@@ -202,6 -242,10 +250,13 @@@ struct Monster FLATBUFFERS_FINAL_CLASS VT_TESTHASHS64_FNV1A = 48, VT_TESTHASHU64_FNV1A = 50, VT_TESTARRAYOFBOOLS = 52, ++<<<<<<< HEAD ++======= + VT_TESTF = 54, + VT_TESTF2 = 56, + VT_TESTF3 = 58, + VT_TESTARRAYOFSTRING2 = 60 ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 }; const Vec3 *pos() const { return GetStruct(VT_POS); } Vec3 *mutable_pos() { return GetStruct(VT_POS); } @@@ -236,7 -280,7 +291,11 @@@ const MyGame::Example::Monster *testnestedflatbuffer_nested_root() const { return flatbuffers::GetRoot(testnestedflatbuffer()->Data()); } const Stat *testempty() const { return GetPointer(VT_TESTEMPTY); } Stat *mutable_testempty() { return GetPointer(VT_TESTEMPTY); } ++<<<<<<< HEAD + bool testbool() const { return static_cast(GetField(VT_TESTBOOL, 0)); } ++======= + bool testbool() const { return GetField(VT_TESTBOOL, 0) != 0; } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 bool mutate_testbool(bool _testbool) { return SetField(VT_TESTBOOL, static_cast(_testbool)); } int32_t testhashs32_fnv1() const { return GetField(VT_TESTHASHS32_FNV1, 0); } bool mutate_testhashs32_fnv1(int32_t _testhashs32_fnv1) { return SetField(VT_TESTHASHS32_FNV1, _testhashs32_fnv1); } @@@ -256,6 -300,14 +315,17 @@@ bool mutate_testhashu64_fnv1a(uint64_t _testhashu64_fnv1a) { return SetField(VT_TESTHASHU64_FNV1A, _testhashu64_fnv1a); } const flatbuffers::Vector *testarrayofbools() const { return GetPointer *>(VT_TESTARRAYOFBOOLS); } flatbuffers::Vector *mutable_testarrayofbools() { return GetPointer *>(VT_TESTARRAYOFBOOLS); } ++<<<<<<< HEAD ++======= + float testf() const { return GetField(VT_TESTF, 3.14159f); } + bool mutate_testf(float _testf) { return SetField(VT_TESTF, _testf); } + float testf2() const { return GetField(VT_TESTF2, 3.0f); } + bool mutate_testf2(float _testf2) { return SetField(VT_TESTF2, _testf2); } + float testf3() const { return GetField(VT_TESTF3, 0.0f); } + bool mutate_testf3(float _testf3) { return SetField(VT_TESTF3, _testf3); } + const flatbuffers::Vector> *testarrayofstring2() const { return GetPointer> *>(VT_TESTARRAYOFSTRING2); } + flatbuffers::Vector> *mutable_testarrayofstring2() { return GetPointer> *>(VT_TESTARRAYOFSTRING2); } ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_POS) && @@@ -325,10 -383,14 +401,21 @@@ struct MonsterBuilder void add_testhashs64_fnv1a(int64_t testhashs64_fnv1a) { fbb_.AddElement(Monster::VT_TESTHASHS64_FNV1A, testhashs64_fnv1a, 0); } void add_testhashu64_fnv1a(uint64_t testhashu64_fnv1a) { fbb_.AddElement(Monster::VT_TESTHASHU64_FNV1A, testhashu64_fnv1a, 0); } void add_testarrayofbools(flatbuffers::Offset> testarrayofbools) { fbb_.AddOffset(Monster::VT_TESTARRAYOFBOOLS, testarrayofbools); } ++<<<<<<< HEAD + MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + MonsterBuilder &operator=(const MonsterBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 25)); ++======= + void add_testf(float testf) { fbb_.AddElement(Monster::VT_TESTF, testf, 3.14159f); } + void add_testf2(float testf2) { fbb_.AddElement(Monster::VT_TESTF2, testf2, 3.0f); } + void add_testf3(float testf3) { fbb_.AddElement(Monster::VT_TESTF3, testf3, 0.0f); } + void add_testarrayofstring2(flatbuffers::Offset>> testarrayofstring2) { fbb_.AddOffset(Monster::VT_TESTARRAYOFSTRING2, testarrayofstring2); } + MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + MonsterBuilder &operator=(const MonsterBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 29)); ++>>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 fbb_.Required(o, Monster::VT_NAME); // name return o; }