From 6267f8c6c002cb62d168fa7b7c6137e65f47b8a1 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 25 Nov 2015 15:50:30 -0800 Subject: [PATCH 01/42] Fixed crash related to flatc parsing duplicate input files. Thanks @Chaosvex for reporting. Change-Id: I73f60ab0bf875a3e0849eaec5f42f6d036881094 Tested: on Linux. --- include/flatbuffers/idl.h | 2 +- src/idl_parser.cpp | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index ad755f8c9..f1276f01b 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -419,7 +419,7 @@ class Parser { const char *source_, *cursor_; int line_; // the current line being parsed int token_; - std::stack files_being_parsed_; + std::string files_being_parsed_; bool proto_mode_; bool strict_json_; std::string attribute_; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 13290e74b..233eeceef 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -892,7 +892,7 @@ EnumDef &Parser::ParseEnum(bool is_union) { Expect(kTokenIdentifier); auto &enum_def = *new EnumDef(); enum_def.name = enum_name; - if (!files_being_parsed_.empty()) enum_def.file = files_being_parsed_.top(); + enum_def.file = files_being_parsed_; enum_def.doc_comment = enum_comment; enum_def.is_union = is_union; enum_def.defined_namespace = namespaces_.back(); @@ -973,7 +973,7 @@ StructDef &Parser::StartStruct(const std::string &name) { if (!struct_def.predecl) Error("datatype already exists: " + name); struct_def.predecl = false; struct_def.name = name; - if (!files_being_parsed_.empty()) struct_def.file = files_being_parsed_.top(); + struct_def.file = files_being_parsed_; // 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; @@ -1352,11 +1352,11 @@ Type Parser::ParseTypeFromProtoType() { bool Parser::Parse(const char *source, const char **include_paths, const char *source_filename) { + files_being_parsed_ = source_filename ? source_filename : ""; if (source_filename && included_files_.find(source_filename) == included_files_.end()) { included_files_[source_filename] = true; files_included_per_file_[source_filename] = std::set(); - files_being_parsed_.push(source_filename); } if (!include_paths) { static const char *current_directory[] = { "", nullptr }; @@ -1499,10 +1499,8 @@ bool Parser::Parse(const char *source, const char **include_paths, error_ += NumToString(line_) + ":0"; // gcc alike #endif error_ += ": error: " + msg; - if (source_filename) files_being_parsed_.pop(); return false; } - if (source_filename) files_being_parsed_.pop(); return true; } From ec0c0b14cad95f8e0e5ee21763d0b064254e974d Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 25 Nov 2015 16:48:28 -0800 Subject: [PATCH 02/42] Made generated C++ code respect gcc -Werror=shadow. Change-Id: I17de0bcc462770124227a9967e2aab620467f6eb Tested: on Linux. --- CMakeLists.txt | 2 +- include/flatbuffers/flatbuffers.h | 4 +-- samples/monster_generated.h | 16 ++++----- src/idl_gen_cpp.cpp | 14 ++++---- tests/monster_test_generated.h | 54 +++++++++++++++---------------- 5 files changed, 45 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eef851b0..47a428230 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ if(APPLE) "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -Wall -pedantic -Werror -Wextra") elseif(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra") + "${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") diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 41b3b266c..a728a79cf 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -329,9 +329,9 @@ public: return nullptr; // Key not found. } - const uint8_t *data = reinterpret_cast(search_result); + const uint8_t *element = reinterpret_cast(search_result); - return IndirectHelper::Read(data, 0); + return IndirectHelper::Read(element, 0); } protected: diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 878a7688b..854e712ee 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -46,15 +46,15 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS { float z_; public: - Vec3(float x, float y, float z) - : x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)), z_(flatbuffers::EndianScalar(z)) { } + Vec3(float _x, float _y, float _z) + : x_(flatbuffers::EndianScalar(_x)), y_(flatbuffers::EndianScalar(_y)), z_(flatbuffers::EndianScalar(_z)) { } float x() const { return flatbuffers::EndianScalar(x_); } - void mutate_x(float x) { flatbuffers::WriteScalar(&x_, x); } + void mutate_x(float _x) { flatbuffers::WriteScalar(&x_, _x); } float y() const { return flatbuffers::EndianScalar(y_); } - void mutate_y(float y) { flatbuffers::WriteScalar(&y_, y); } + void mutate_y(float _y) { flatbuffers::WriteScalar(&y_, _y); } float z() const { return flatbuffers::EndianScalar(z_); } - void mutate_z(float z) { flatbuffers::WriteScalar(&z_, z); } + void mutate_z(float _z) { flatbuffers::WriteScalar(&z_, _z); } }; STRUCT_END(Vec3, 12); @@ -62,15 +62,15 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const Vec3 *pos() const { return GetStruct(4); } Vec3 *mutable_pos() { return GetStruct(4); } int16_t mana() const { return GetField(6, 150); } - bool mutate_mana(int16_t mana) { return SetField(6, mana); } + bool mutate_mana(int16_t _mana) { return SetField(6, _mana); } int16_t hp() const { return GetField(8, 100); } - bool mutate_hp(int16_t hp) { return SetField(8, hp); } + bool mutate_hp(int16_t _hp) { return SetField(8, _hp); } const flatbuffers::String *name() const { return GetPointer(10); } flatbuffers::String *mutable_name() { return GetPointer(10); } const flatbuffers::Vector *inventory() const { return GetPointer *>(14); } flatbuffers::Vector *mutable_inventory() { return GetPointer *>(14); } Color color() const { return static_cast(GetField(16, 2)); } - bool mutate_color(Color color) { return SetField(16, static_cast(color)); } + bool mutate_color(Color _color) { return SetField(16, static_cast(_color)); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, 4 /* pos */) && diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 904f4706b..641103810 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -277,8 +277,8 @@ static void GenTable(const Parser &parser, StructDef &struct_def, 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 += " _" + field.name + ") { return SetField(" + offsetstr + ", "; + code += GenUnderlyingCast(parser, field, false, "_" + field.name); code += "); }\n"; } else { auto type = GenTypeGet(parser, field.value.type, " ", "", " *", true); @@ -524,7 +524,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, auto &field = **it; if (it != struct_def.fields.vec.begin()) code += ", "; code += GenTypeGet(parser, field.value.type, " ", "const ", " &", true); - code += field.name; + code += "_" + field.name; } code += ")\n : "; padding_id = 0; @@ -536,10 +536,10 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, code += field.name + "_("; if (IsScalar(field.value.type.base_type)) { code += "flatbuffers::EndianScalar("; - code += GenUnderlyingCast(parser, field, false, field.name); + code += GenUnderlyingCast(parser, field, false, "_" + field.name); code += "))"; } else { - code += field.name + ")"; + code += "_" + field.name + ")"; } GenPadding(field, [&code, &padding_id](int bits) { (void)bits; @@ -579,9 +579,9 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, if (is_scalar) { code += " void mutate_" + field.name + "("; code += GenTypeBasic(parser, field.value.type, true); - code += " " + field.name + ") { flatbuffers::WriteScalar(&"; + code += " _" + field.name + ") { flatbuffers::WriteScalar(&"; code += field.name + "_, "; - code += GenUnderlyingCast(parser, field, false, field.name); + code += GenUnderlyingCast(parser, field, false, "_" + field.name); code += "); }\n"; } else { code += " "; diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index ece639808..9ef76597b 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -55,13 +55,13 @@ MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS { int8_t __padding0; public: - Test(int16_t a, int8_t b) - : a_(flatbuffers::EndianScalar(a)), b_(flatbuffers::EndianScalar(b)), __padding0(0) { (void)__padding0; } + Test(int16_t _a, int8_t _b) + : a_(flatbuffers::EndianScalar(_a)), b_(flatbuffers::EndianScalar(_b)), __padding0(0) { (void)__padding0; } int16_t a() const { return flatbuffers::EndianScalar(a_); } - void mutate_a(int16_t a) { flatbuffers::WriteScalar(&a_, a); } + void mutate_a(int16_t _a) { flatbuffers::WriteScalar(&a_, _a); } int8_t b() const { return flatbuffers::EndianScalar(b_); } - void mutate_b(int8_t b) { flatbuffers::WriteScalar(&b_, b); } + void mutate_b(int8_t _b) { flatbuffers::WriteScalar(&b_, _b); } }; STRUCT_END(Test, 4); @@ -78,19 +78,19 @@ MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS { int16_t __padding2; public: - Vec3(float x, float y, float z, double test1, Color test2, const Test &test3) - : x_(flatbuffers::EndianScalar(x)), y_(flatbuffers::EndianScalar(y)), z_(flatbuffers::EndianScalar(z)), __padding0(0), test1_(flatbuffers::EndianScalar(test1)), test2_(flatbuffers::EndianScalar(static_cast(test2))), __padding1(0), test3_(test3), __padding2(0) { (void)__padding0; (void)__padding1; (void)__padding2; } + Vec3(float _x, float _y, float _z, double _test1, Color _test2, const Test &_test3) + : x_(flatbuffers::EndianScalar(_x)), y_(flatbuffers::EndianScalar(_y)), z_(flatbuffers::EndianScalar(_z)), __padding0(0), test1_(flatbuffers::EndianScalar(_test1)), test2_(flatbuffers::EndianScalar(static_cast(_test2))), __padding1(0), test3_(_test3), __padding2(0) { (void)__padding0; (void)__padding1; (void)__padding2; } float x() const { return flatbuffers::EndianScalar(x_); } - void mutate_x(float x) { flatbuffers::WriteScalar(&x_, x); } + void mutate_x(float _x) { flatbuffers::WriteScalar(&x_, _x); } float y() const { return flatbuffers::EndianScalar(y_); } - void mutate_y(float y) { flatbuffers::WriteScalar(&y_, y); } + void mutate_y(float _y) { flatbuffers::WriteScalar(&y_, _y); } float z() const { return flatbuffers::EndianScalar(z_); } - void mutate_z(float z) { flatbuffers::WriteScalar(&z_, z); } + void mutate_z(float _z) { flatbuffers::WriteScalar(&z_, _z); } double test1() const { return flatbuffers::EndianScalar(test1_); } - void mutate_test1(double test1) { flatbuffers::WriteScalar(&test1_, test1); } + void mutate_test1(double _test1) { flatbuffers::WriteScalar(&test1_, _test1); } Color test2() const { return static_cast(flatbuffers::EndianScalar(test2_)); } - void mutate_test2(Color test2) { flatbuffers::WriteScalar(&test2_, static_cast(test2)); } + void mutate_test2(Color _test2) { flatbuffers::WriteScalar(&test2_, static_cast(_test2)); } const Test &test3() const { return test3_; } Test &mutable_test3() { return test3_; } }; @@ -98,7 +98,7 @@ STRUCT_END(Vec3, 32); struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { Color color() const { return static_cast(GetField(4, 2)); } - bool mutate_color(Color color) { return SetField(4, static_cast(color)); } + bool mutate_color(Color _color) { return SetField(4, static_cast(_color)); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, 4 /* color */) && @@ -129,9 +129,9 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::String *id() const { return GetPointer(4); } flatbuffers::String *mutable_id() { return GetPointer(4); } int64_t val() const { return GetField(6, 0); } - bool mutate_val(int64_t val) { return SetField(6, val); } + bool mutate_val(int64_t _val) { return SetField(6, _val); } uint16_t count() const { return GetField(8, 0); } - bool mutate_count(uint16_t count) { return SetField(8, count); } + bool mutate_count(uint16_t _count) { return SetField(8, _count); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, 4 /* id */) && @@ -172,9 +172,9 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const Vec3 *pos() const { return GetStruct(4); } Vec3 *mutable_pos() { return GetStruct(4); } int16_t mana() const { return GetField(6, 150); } - bool mutate_mana(int16_t mana) { return SetField(6, mana); } + bool mutate_mana(int16_t _mana) { return SetField(6, _mana); } int16_t hp() const { return GetField(8, 100); } - bool mutate_hp(int16_t hp) { return SetField(8, hp); } + bool mutate_hp(int16_t _hp) { return SetField(8, _hp); } const flatbuffers::String *name() const { return GetPointer(10); } flatbuffers::String *mutable_name() { return GetPointer(10); } bool KeyCompareLessThan(const Monster *o) const { return *name() < *o->name(); } @@ -182,9 +182,9 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector *inventory() const { return GetPointer *>(14); } flatbuffers::Vector *mutable_inventory() { return GetPointer *>(14); } Color color() const { return static_cast(GetField(16, 8)); } - bool mutate_color(Color color) { return SetField(16, static_cast(color)); } + bool mutate_color(Color _color) { return SetField(16, static_cast(_color)); } Any test_type() const { return static_cast(GetField(18, 0)); } - bool mutate_test_type(Any test_type) { return SetField(18, static_cast(test_type)); } + bool mutate_test_type(Any _test_type) { return SetField(18, static_cast(_test_type)); } const void *test() const { return GetPointer(20); } void *mutable_test() { return GetPointer(20); } const flatbuffers::Vector *test4() const { return GetPointer *>(22); } @@ -203,23 +203,23 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const Stat *testempty() const { return GetPointer(32); } Stat *mutable_testempty() { return GetPointer(32); } uint8_t testbool() const { return GetField(34, 0); } - bool mutate_testbool(uint8_t testbool) { return SetField(34, testbool); } + bool mutate_testbool(uint8_t _testbool) { return SetField(34, _testbool); } int32_t testhashs32_fnv1() const { return GetField(36, 0); } - bool mutate_testhashs32_fnv1(int32_t testhashs32_fnv1) { return SetField(36, testhashs32_fnv1); } + bool mutate_testhashs32_fnv1(int32_t _testhashs32_fnv1) { return SetField(36, _testhashs32_fnv1); } uint32_t testhashu32_fnv1() const { return GetField(38, 0); } - bool mutate_testhashu32_fnv1(uint32_t testhashu32_fnv1) { return SetField(38, testhashu32_fnv1); } + bool mutate_testhashu32_fnv1(uint32_t _testhashu32_fnv1) { return SetField(38, _testhashu32_fnv1); } int64_t testhashs64_fnv1() const { return GetField(40, 0); } - bool mutate_testhashs64_fnv1(int64_t testhashs64_fnv1) { return SetField(40, testhashs64_fnv1); } + bool mutate_testhashs64_fnv1(int64_t _testhashs64_fnv1) { return SetField(40, _testhashs64_fnv1); } uint64_t testhashu64_fnv1() const { return GetField(42, 0); } - bool mutate_testhashu64_fnv1(uint64_t testhashu64_fnv1) { return SetField(42, testhashu64_fnv1); } + bool mutate_testhashu64_fnv1(uint64_t _testhashu64_fnv1) { return SetField(42, _testhashu64_fnv1); } int32_t testhashs32_fnv1a() const { return GetField(44, 0); } - bool mutate_testhashs32_fnv1a(int32_t testhashs32_fnv1a) { return SetField(44, testhashs32_fnv1a); } + bool mutate_testhashs32_fnv1a(int32_t _testhashs32_fnv1a) { return SetField(44, _testhashs32_fnv1a); } uint32_t testhashu32_fnv1a() const { return GetField(46, 0); } - bool mutate_testhashu32_fnv1a(uint32_t testhashu32_fnv1a) { return SetField(46, testhashu32_fnv1a); } + bool mutate_testhashu32_fnv1a(uint32_t _testhashu32_fnv1a) { return SetField(46, _testhashu32_fnv1a); } int64_t testhashs64_fnv1a() const { return GetField(48, 0); } - bool mutate_testhashs64_fnv1a(int64_t testhashs64_fnv1a) { return SetField(48, testhashs64_fnv1a); } + bool mutate_testhashs64_fnv1a(int64_t _testhashs64_fnv1a) { return SetField(48, _testhashs64_fnv1a); } uint64_t testhashu64_fnv1a() const { return GetField(50, 0); } - bool mutate_testhashu64_fnv1a(uint64_t testhashu64_fnv1a) { return SetField(50, testhashu64_fnv1a); } + bool mutate_testhashu64_fnv1a(uint64_t _testhashu64_fnv1a) { return SetField(50, _testhashu64_fnv1a); } const flatbuffers::Vector *testarrayofbools() const { return GetPointer *>(52); } flatbuffers::Vector *mutable_testarrayofbools() { return GetPointer *>(52); } bool Verify(flatbuffers::Verifier &verifier) const { From d10f9a6abcf85d1ce13c4705b311292446b67ec1 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 25 Nov 2015 17:26:34 -0800 Subject: [PATCH 03/42] Added long form options for all generators (--cpp etc.) Short-form versions are still supported, but are deprecated. Change-Id: I15f70ca8d69ba5790368205caa9603b65e1b7fff Tested: on Linux. --- docs/html/md__compiler.html | 27 +++++++++++++++++-------- docs/source/Compiler.md | 34 +++++++++++++++++++++++--------- src/flatc.cpp | 34 +++++++++++++++++++------------- tests/generate_code.sh | 4 ++-- tests/monster_test.bfbs | Bin 2784 -> 2744 bytes tests/monster_test_generated.js | 2 ++ 6 files changed, 68 insertions(+), 33 deletions(-) diff --git a/docs/html/md__compiler.html b/docs/html/md__compiler.html index 2fe560da6..ff3f7fe22 100644 --- a/docs/html/md__compiler.html +++ b/docs/html/md__compiler.html @@ -61,18 +61,28 @@ $(document).ready(function(){initNavTree('md__compiler.html','');});
Using the schema compiler
-

Usage:

flatc [ -c ] [ -j ] [ -b ] [ -t ] [ -o PATH ] [ -I PATH ] [ -S ] FILES...
+

Usage:

flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] [ -S ] FILES...
       [ -- FILES...]
 

The files are read and parsed in order, and can contain either schemas or data (see below). Later files can make use of definitions in earlier files.

-- indicates that the following files are binary files in FlatBuffer format conforming to the schema(s) indicated before it. Incompatible binary files currently will give unpredictable results (!)

Depending on the flags passed, additional files may be generated for each file processed:

+

For any schema input files, one or more generators can be specified:

+
    +
  • --cpp, -c : Generate a C++ header for all definitions in this file (as filename_generated.h).
  • +
  • --java, -j : Generate Java code.
  • +
  • --csharp, -n : Generate C# code.
  • +
  • --go, -g : Generate Go code.
  • +
  • --python, -p: Generate Python code.
  • +
  • --javascript, -s: Generate JavaScript code.
  • +
  • --php: Generate PHP code.
  • +
+

For any data input files:

+
    +
  • --binary, -b : If data is contained in this file, generate a filename.bin containing the binary flatbuffer (or a different extension if one is specified in the schema).
  • +
  • --json, -t : If data is contained in this file, generate a filename.json representing the data in the flatbuffer.
  • +
+

Additional options:

    -
  • -c : Generate a C++ header for all definitions in this file (as filename_generated.h). Skipped for data.
  • -
  • -j : Generate Java classes. Skipped for data.
  • -
  • -n : Generate C# classes. Skipped for data.
  • -
  • -g : Generate Go classes. Skipped for data.
  • -
  • -b : If data is contained in this file, generate a filename.bin containing the binary flatbuffer.
  • -
  • -t : If data is contained in this file, generate a filename.json representing the data in the flatbuffer.
  • -o PATH : Output all generated files to PATH (either absolute, or relative to the current directory). If omitted, PATH will be the current directory. PATH should end in your systems path separator, e.g. / or \.
  • -I PATH : when encountering include statements, attempt to load the files from this path. Paths will be tried in the order given, and if all fail (or none are specified) it will try to load relative to the path of the schema file being parsed.
  • -M : Print make rules for generated files.
  • @@ -86,8 +96,9 @@ $(document).ready(function(){initNavTree('md__compiler.html','');});
  • --gen-onefile : Generate single output file (useful for C#)
  • --raw-binary : Allow binaries without a file_indentifier to be read. This may crash flatc given a mismatched schema.
  • --proto: Expect input files to be .proto files (protocol buffers). Output the corresponding .fbs file. Currently supports: package, message, enum, nested declarations, import (use -I for paths), extend, oneof, group. Does not support, but will skip without error: option, service, extensions, and most everything else.
  • -
  • --schema: Serialize schemas instead of JSON (use with -b). This will output a binary version of the specified schema that itself corresponds to the reflection/reflection.fbs schema. Loading this binary file is the basis for reflection functionality.
  • +
  • --schema: Serialize schemas instead of JSON (use with -b). This will output a binary version of the specified schema that itself corresponds to the reflection/reflection.fbs schema. Loading this binary file is the basis for reflection functionality.
+

NOTE: short-form options for generators are deprecated, use the long form whenever possible.

diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md index 4e6b7994b..27ddf52e4 100755 --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@ -2,7 +2,7 @@ Usage: - flatc [ -c ] [ -j ] [ -b ] [ -t ] [ -o PATH ] [ -I PATH ] [ -S ] FILES... + flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] [ -S ] FILES... [ -- FILES...] The files are read and parsed in order, and can contain either schemas @@ -16,21 +16,34 @@ Incompatible binary files currently will give unpredictable results (!) Depending on the flags passed, additional files may be generated for each file processed: -- `-c` : Generate a C++ header for all definitions in this file (as - `filename_generated.h`). Skipped for data. +For any schema input files, one or more generators can be specified: -- `-j` : Generate Java classes. Skipped for data. +- `--cpp`, `-c` : Generate a C++ header for all definitions in this file (as + `filename_generated.h`). -- `-n` : Generate C# classes. Skipped for data. +- `--java`, `-j` : Generate Java code. -- `-g` : Generate Go classes. Skipped for data. +- `--csharp`, `-n` : Generate C# code. -- `-b` : If data is contained in this file, generate a - `filename.bin` containing the binary flatbuffer. +- `--go`, `-g` : Generate Go code. -- `-t` : If data is contained in this file, generate a +- `--python`, `-p`: Generate Python code. + +- `--javascript`, `-s`: Generate JavaScript code. + +- `--php`: Generate PHP code. + +For any data input files: + +- `--binary`, `-b` : If data is contained in this file, generate a + `filename.bin` containing the binary flatbuffer (or a different extension + if one is specified in the schema). + +- `--json`, `-t` : If data is contained in this file, generate a `filename.json` representing the data in the flatbuffer. +Additional options: + - `-o PATH` : Output all generated files to PATH (either absolute, or relative to the current directory). If omitted, PATH will be the current directory. PATH should end in your systems path separator, @@ -82,3 +95,6 @@ be generated for each file processed: output a binary version of the specified schema that itself corresponds to the reflection/reflection.fbs schema. Loading this binary file is the basis for reflection functionality. + +NOTE: short-form options for generators are deprecated, use the long form +whenever possible. diff --git a/src/flatc.cpp b/src/flatc.cpp index 337ce5d8e..2479da12b 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -28,7 +28,8 @@ struct Generator { const std::string &path, const std::string &file_name, const flatbuffers::GeneratorOptions &opts); - const char *generator_opt; + const char *generator_opt_short; + const char *generator_opt_long; const char *lang_name; flatbuffers::GeneratorOptions::Language lang; const char *generator_help; @@ -40,41 +41,41 @@ struct Generator { }; const Generator generators[] = { - { flatbuffers::GenerateBinary, "-b", "binary", + { flatbuffers::GenerateBinary, "-b", "--binary", "binary", flatbuffers::GeneratorOptions::kMAX, "Generate wire format binaries for any data definitions", flatbuffers::BinaryMakeRule }, - { flatbuffers::GenerateTextFile, "-t", "text", + { flatbuffers::GenerateTextFile, "-t", "--json", "text", flatbuffers::GeneratorOptions::kMAX, "Generate text output for any data definitions", flatbuffers::TextMakeRule }, - { flatbuffers::GenerateCPP, "-c", "C++", + { flatbuffers::GenerateCPP, "-c", "--cpp", "C++", flatbuffers::GeneratorOptions::kMAX, "Generate C++ headers for tables/structs", flatbuffers::CPPMakeRule }, - { flatbuffers::GenerateGo, "-g", "Go", + { flatbuffers::GenerateGo, "-g", "--go", "Go", flatbuffers::GeneratorOptions::kGo, "Generate Go files for tables/structs", flatbuffers::GeneralMakeRule }, - { flatbuffers::GenerateGeneral, "-j", "Java", + { flatbuffers::GenerateGeneral, "-j", "--java", "Java", flatbuffers::GeneratorOptions::kJava, "Generate Java classes for tables/structs", flatbuffers::GeneralMakeRule }, - { flatbuffers::GenerateJS, "-s", "JavaScript", + { flatbuffers::GenerateJS, "-s", "--js", "JavaScript", flatbuffers::GeneratorOptions::kMAX, "Generate JavaScript code for tables/structs", flatbuffers::JSMakeRule }, - { flatbuffers::GenerateGeneral, "-n", "C#", + { flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", flatbuffers::GeneratorOptions::kCSharp, "Generate C# classes for tables/structs", flatbuffers::GeneralMakeRule }, - { flatbuffers::GeneratePython, "-p", "Python", + { flatbuffers::GeneratePython, "-p", "--python", "Python", flatbuffers::GeneratorOptions::kMAX, "Generate Python files for tables/structs", flatbuffers::GeneralMakeRule }, - { flatbuffers::GeneratePhp, "--php", "PHP", + { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", flatbuffers::GeneratorOptions::kMAX, - "Generate Php files for tables/structs", + "Generate PHP files for tables/structs", flatbuffers::GeneralMakeRule }, }; @@ -86,8 +87,11 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) { if (usage) { printf("usage: %s [OPTION]... FILE... [-- FILE...]\n", program_name); for (size_t i = 0; i < sizeof(generators) / sizeof(generators[0]); ++i) - printf(" %s %s.\n", - generators[i].generator_opt, + printf(" %-12s %s %s.\n", + generators[i].generator_opt_long, + generators[i].generator_opt_short + ? generators[i].generator_opt_short + : " ", generators[i].generator_help); printf( " -o PATH Prefix PATH to all generated files.\n" @@ -179,7 +183,9 @@ int main(int argc, const char *argv[]) { print_make_rules = true; } else { for (size_t i = 0; i < num_generators; ++i) { - if (arg == generators[i].generator_opt) { + if (arg == generators[i].generator_opt_long || + (generators[i].generator_opt_short && + arg == generators[i].generator_opt_short)) { generator_enabled[i] = true; any_generator = true; goto found; diff --git a/tests/generate_code.sh b/tests/generate_code.sh index 91158bff4..91661f30d 100644 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -1,2 +1,2 @@ -../flatc -c -j -n -g -b -p -s --php --gen-mutable --no-includes monster_test.fbs monsterdata_test.json -../flatc -b --schema monster_test.fbs +../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 diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index 8d54ead7e9a3a5047063843fdf0f38af5266385b..e5f51face696a1ee9b3aa64b70bba83df1c4645a 100644 GIT binary patch literal 2744 zcmaJ@O^91n6h4{!|4fqBF&(9pAVVodhITp(B1P&*>kl>sCr-hIoi~#g6G`3+$xCQl zhzl39Dy{}sBBc~@DXzK@aUs%05f??Il;TRda5-qLjo)|fyP1auFPxm0d%tt;ch0%z zzIRka)-SAYKw%VRQ4*4of|O+e{{+7x&qH2-oP!kRL{iWR=-1LBUt~qfkT-K8_wYZC zHR2yYc4NRnU%XUP|6J?(9=tE;9%<}Sz#K-5x(qoAA?{^wtoma-Z$UW!aDOs^f>(~5 zaxK6UwpO0I84=K$jw5)gyMth(-R*VUy0hJJFSmo%d2iUoN)9#&>~HM3_bGS|oeM&d zi@rAq+`i-{lL_OX)GpP|L&+BA$eH=6LXwbI{Epv;CjS=XEQEe<{h_?$^!+RBI0vfJ zLBH#rp=&vDjWH1yjfZ=@+IL+Kt7WZ|!I6jM&As1p8(KkD5*5=N6SD|m9`le3eZTv< zx6>ImT(#x=8-{1r?3sf#nVCKKL{6d2rqdDG2j1p@`$u#34E}!&GM~cP5{!2tKjZ(m z&~?afkaPH7fNVi{zJ37q6UaR}gT4X%0FP&(uR=GVKZkw{AwC1lO>kJ0RgIJ}FlPa3 z?)3Z4*l%w8erJFw@&0BFigR~?KO!qr{Gkxvat5v8+Uk|2H#+TL?#Z88vs?nHTX;u_yu$fD@FcMK7$DUn!%^{fPYF(PVqM0D1W$- zZwx;7J@AL+#7w;9PyFv8|9#*O$?=(Z%b)mTe`&m#VJflpqZRa~?_;rR-9sqlbZH-1aB zc@Z|eo#=ZBVrv@O41#{!dk@`|!A;7ZVPApMd>?jMsi+-$m7EyIDi8(5n!5_v5{|xH z2R?&nZ478B#Y4%mo_7sRZUdK=!-`{WY%Z?^?*lN8K|W4!cj2l?!T zcic5&qj%a#6WAgEqrWO^D zeUcSD9R+Y_KI|aR7-npK_Ur;Q^WSwmULW!j@(7jm^jz4R*t{Eh{y^@S^%C_L0?wo;Ae@Nf-z4s%YZ$LhR&^{UV5pBtvXPbt< zm_77NkAO>ry%X($73~3@6?<+(&)!Yo;~LRHAJgw?Aipzy3%7x>Ib+;B=pR7%E{4iK z#Ci;oFkh@I*LiL;+MTvPC4V0{n^R)0Lg-uaMKCzX9lx8n&k}^V|N9Q%I(vp4z#GHV zg&8u#)`c@w2dxUDHnh literal 2784 zcmaKuOK6-`6vxjblTI?3Owt&qQG$e0N{~=&T8gWpv8^%CRQiaULY*Yvn8?gG!#slN zLPUxyS6y^bBr6dYr4$!I#8nn9y68$=Ns%n13m0A0cgNrV-nm~t>*K?678Wi=J^)uJ%F-Wts=a!tTc*mg!(8n3G zeazo8pURot8bTg=GY^k_0d2C8!%6`hBQwK~Y)I!9kGfs)AZP0X=F8AzZ~tn%#VYT7 zEuaatPWBEC;$AWiu(}wv+7~uzjcRnUyi$$c+Gwwzjyp9@^2lVd@8!qf%wo|QWsRG5 zwjQ_IQPYauZdZPZmd-7mX0kPSX`d@UJD>X{uUNbdDIU^00KHbP)|MiMzkAbv;50gY$alnMdf9P(- zKJDA&z1(b;x9XLZdcE3$Ww*f}u(7tRtjJIwcCBxjwJYRJbo~Z?;M*;^q&MjVY3PTk;muK_*M!ZgMY?eOz?-<<7PhG zH|;-s+va@SW)l3e#}B3P!GGcJalYRUC-{#%elU#>{tN$@^D(-E&K3V1kI$v?!GGb8 z{MPM`+Q9_>qsRBDhLkTQO1NckMVn4)c9%WuQOdw*BMuwY8f|rf4>=pL7ZRP#$F2sl zs(0y(p=hmAEw@)Xl?soUv4c#(rV{-JfA{)zrneTwQBAt8Q0eo zn^o7xN@!IF&$>SEfc%u80sb|l!#U&ni0>w z>dqmKY5YO~uKggf=@*}QKlxtkMM3%xGytl!2AAJ4S zC=P34GOm010p()7Ax?>V{=0kzFG37%2-+Lp^>oOGS~*sWv3Fg4WRo1-{?pf@VojU0 zM!jVxsA=g7y;gkrCpT0N(s!X@E3SJr~uXI^eZG1(wci|*}NW|qBVg`0+?Lv|M+-Qx%7bLbi*-6Rah_=W$7ms{ZHTZ^Q4$i{S6F#}yO{VU9BI!b`{Ns>ckg z*Ib39JCnNe&D6Q-S8pJ^72s|tPQm8g6#hNl#*=?$UIRGYA>>sy^}Y4~-z_B~6mlag zeuUi2uvKj+Cw{1(=v{?=Vo99*Th=$9^yzENfAay(C{N0v^eD!fFGGiV`-`r}ggW_W zAIKmPVsOvZxVO7P%!>aJGuiYv()Wk&1-=K`fMQcd^2wK@k00!eWI_yCx_Y}5cUpW3 F*)yDt; diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js index d46a9c684..9d0f48b09 100644 --- a/tests/monster_test_generated.js +++ b/tests/monster_test_generated.js @@ -352,6 +352,8 @@ MyGame.Example.Stat.endStat = function(builder) { }; /** + * an example documentation comment: monster object + * * @constructor */ MyGame.Example.Monster = function() { From 9202f0cf09b80e356a6b468e280b2fb0f10d2871 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 27 Nov 2015 20:05:48 +0000 Subject: [PATCH 04/42] Return the full string when requested from a flatbuffers::String, even if it contains a NULL byte. --- include/flatbuffers/flatbuffers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index a728a79cf..c2b938d36 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -379,7 +379,7 @@ template static inline size_t VectorLength(const Vector *v) { struct String : public Vector { const char *c_str() const { return reinterpret_cast(Data()); } - std::string str() const { return c_str(); } + std::string str() const { return std::string(c_str(), Length()); } bool operator <(const String &o) const { return strcmp(c_str(), o.c_str()) < 0; From 345e8ca804265640f12e4edd93fb9d752aed9cf8 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 27 Nov 2015 20:06:41 +0000 Subject: [PATCH 05/42] Fix use of std::max when Windows.h is imported. --- include/flatbuffers/flatbuffers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index c2b938d36..2af4486c7 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -445,7 +445,7 @@ class vector_downward { if (len > static_cast(cur_ - buf_)) { auto old_size = size(); auto largest_align = AlignOf(); - reserved_ += std::max(len, growth_policy(reserved_)); + reserved_ += (std::max)(len, growth_policy(reserved_)); // Round up to avoid undefined behavior from unaligned loads and stores. reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1); auto new_buf = allocator_.allocate(reserved_); From c5835b896cfc6202b327a88d2bd8517c5ae94f51 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 30 Nov 2015 11:25:21 -0800 Subject: [PATCH 06/42] Java builder now checks if buffer was finished upon access. Also checks for nesting of objects in vector construction. This avoids common errors in FlatBuffer construction. Change-Id: I5507c5d767684e20e94883a92448f05acefba4d6 Tested: on Linux. --- .../google/flatbuffers/FlatBufferBuilder.java | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java index 368be2f30..a6234ca63 100644 --- a/java/com/google/flatbuffers/FlatBufferBuilder.java +++ b/java/com/google/flatbuffers/FlatBufferBuilder.java @@ -28,18 +28,19 @@ import java.nio.charset.Charset; * main FlatBuffers documentation. */ public class FlatBufferBuilder { - ByteBuffer bb; // Where we construct the FlatBuffer. - int space; // Remaining space in the ByteBuffer. + 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. - 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 + 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 /** * Start with a buffer of size {@code initial_size}, then grow as required. @@ -86,6 +87,7 @@ public class FlatBufferBuilder { space = bb.capacity(); vtable_in_use = 0; nested = false; + finished = false; object_start = 0; num_vtables = 0; vector_num_elems = 0; @@ -240,6 +242,7 @@ public class FlatBufferBuilder { vector_num_elems = num_elems; prep(SIZEOF_INT, elem_size * num_elems); prep(alignment, elem_size * num_elems); // Just in case alignment > int. + nested = true; } /** @@ -250,6 +253,9 @@ public class FlatBufferBuilder { * @see #startVector(int, int, int) */ public int endVector() { + if (!nested) + throw new AssertionError("FlatBuffers: endVector called without startVector"); + nested = false; putInt(vector_num_elems); return offset(); } @@ -284,6 +290,16 @@ public class FlatBufferBuilder { return endVector(); } + /** + * 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 @@ -452,6 +468,7 @@ public class FlatBufferBuilder { prep(minalign, SIZEOF_INT); addOffset(root_table); bb.position(space); + finished = true; } public void finish(int root_table, String file_identifier) { @@ -481,7 +498,10 @@ public class FlatBufferBuilder { // 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. - public ByteBuffer dataBuffer() { return bb; } + public ByteBuffer dataBuffer() { + finished(); + return bb; + } /** * The FlatBuffer data doesn't start at offset 0 in the {@link ByteBuffer}, but @@ -493,6 +513,7 @@ public class FlatBufferBuilder { */ @Deprecated private int dataStart() { + finished(); return space; } @@ -506,6 +527,7 @@ public class FlatBufferBuilder { * @throws IndexOutOfBoundsException If the range of bytes is ouf of bound */ public byte[] sizedByteArray(int start, int length){ + finished(); byte[] array = new byte[length]; bb.position(start); bb.get(array); From 07da3fc216c62b18eb13a8bcb9afa95d7c325418 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 30 Nov 2015 11:50:09 -0800 Subject: [PATCH 07/42] Allow vectors to be aligned beyond their natural type. Change-Id: I09ade6b688a6b97d65fd832558917225d86c9118 --- include/flatbuffers/flatbuffers.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index a728a79cf..62c3d1f8f 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -799,6 +799,15 @@ class FlatBufferBuilder FLATBUFFERS_FINAL_CLASS { PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t. } + // Call this right before StartVector/CreateVector if you want to force the + // alignment to be something different than what the element size would + // normally dictate. + // This is useful when storing a nested_flatbuffer in a vector of bytes, + // or when storing SIMD floats, etc. + void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) { + PreAlign(len * elemsize, alignment); + } + uint8_t *ReserveElements(size_t len, size_t elemsize) { return buf_.make_space(len * elemsize); } From 59dc29a19a4ade02440c5cd336aa92aaa0824c5b Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 30 Nov 2015 13:54:24 -0800 Subject: [PATCH 08/42] Made C++ generated code use "bool" instead of uint8_t wire type. Change-Id: I5756d15a758429ca67456264842017063d1f755e Tested: on Linux. --- src/idl_gen_cpp.cpp | 34 +++++++++++++++++++++------------- tests/monster_test_generated.h | 8 ++++---- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 641103810..7c39c325a 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -59,20 +59,22 @@ static std::string TranslateNameSpace(const std::string &qualified_name) { // Return a C++ type from the table in idl.h static std::string GenTypeBasic(const Parser &parser, const Type &type, - bool real_enum) { + 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 }; - return real_enum && type.enum_def - ? WrapInNameSpace(parser, *type.enum_def) - : ctypename[type.base_type]; + 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 real_enum); + const char *postfix, bool user_facing_type); // Return a C++ pointer type, specialized to the actual struct/table types, // and vector element types. @@ -96,9 +98,9 @@ static std::string GenTypePointer(const Parser &parser, const Type &type) { // 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 real_enum) { + const char *postfix, bool user_facing_type) { return IsScalar(type.base_type) - ? GenTypeBasic(parser, type, real_enum) + postfix + ? GenTypeBasic(parser, type, user_facing_type) + postfix : IsStruct(type) ? "const " + GenTypePointer(parser, type) + " *" : "flatbuffers::Offset<" + GenTypePointer(parser, type) + ">" + postfix; @@ -118,9 +120,9 @@ static std::string GenTypeSize(const Parser &parser, const Type &type) { // using a flatbuffer. static std::string GenTypeGet(const Parser &parser, const Type &type, const char *afterbasic, const char *beforeptr, - const char *afterptr, bool real_enum) { + const char *afterptr, bool user_facing_type) { return IsScalar(type.base_type) - ? GenTypeBasic(parser, type, real_enum) + afterbasic + ? GenTypeBasic(parser, type, user_facing_type) + afterbasic : beforeptr + GenTypePointer(parser, type) + afterptr; } @@ -190,9 +192,12 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def, } 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 + "()[static_cast(e)"; - if (enum_def.vals.vec.front()->value) - code += " - static_cast(" + GetEnumVal(enum_def, *enum_def.vals.vec.front(), opts) +")"; + 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"; } @@ -230,7 +235,8 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def, // 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) + 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; @@ -456,6 +462,8 @@ static void GenTable(const Parser &parser, StructDef &struct_def, } else { code += GenUnderlyingCast(parser, field, true, field.value.constant); } + } else if (field.value.type.base_type == BASE_TYPE_BOOL) { + code += field.value.constant == "0" ? "false" : "true"; } else { code += field.value.constant; } diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 9ef76597b..8a78de530 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -202,8 +202,8 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const MyGame::Example::Monster *testnestedflatbuffer_nested_root() const { return flatbuffers::GetRoot(testnestedflatbuffer()->Data()); } const Stat *testempty() const { return GetPointer(32); } Stat *mutable_testempty() { return GetPointer(32); } - uint8_t testbool() const { return GetField(34, 0); } - bool mutate_testbool(uint8_t _testbool) { return SetField(34, _testbool); } + bool testbool() const { return static_cast(GetField(34, 0)); } + bool mutate_testbool(bool _testbool) { return SetField(34, static_cast(_testbool)); } int32_t testhashs32_fnv1() const { return GetField(36, 0); } bool mutate_testhashs32_fnv1(int32_t _testhashs32_fnv1) { return SetField(36, _testhashs32_fnv1); } uint32_t testhashu32_fnv1() const { return GetField(38, 0); } @@ -281,7 +281,7 @@ struct MonsterBuilder { void add_enemy(flatbuffers::Offset enemy) { fbb_.AddOffset(28, enemy); } void add_testnestedflatbuffer(flatbuffers::Offset> testnestedflatbuffer) { fbb_.AddOffset(30, testnestedflatbuffer); } void add_testempty(flatbuffers::Offset testempty) { fbb_.AddOffset(32, testempty); } - void add_testbool(uint8_t testbool) { fbb_.AddElement(34, testbool, 0); } + void add_testbool(bool testbool) { fbb_.AddElement(34, static_cast(testbool), 0); } void add_testhashs32_fnv1(int32_t testhashs32_fnv1) { fbb_.AddElement(36, testhashs32_fnv1, 0); } void add_testhashu32_fnv1(uint32_t testhashu32_fnv1) { fbb_.AddElement(38, testhashu32_fnv1, 0); } void add_testhashs64_fnv1(int64_t testhashs64_fnv1) { fbb_.AddElement(40, testhashs64_fnv1, 0); } @@ -315,7 +315,7 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder flatbuffers::Offset enemy = 0, flatbuffers::Offset> testnestedflatbuffer = 0, flatbuffers::Offset testempty = 0, - uint8_t testbool = 0, + bool testbool = false, int32_t testhashs32_fnv1 = 0, uint32_t testhashu32_fnv1 = 0, int64_t testhashs64_fnv1 = 0, From 1fa803d187c244e8de0bb40f0d3c91f22408bde0 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 30 Nov 2015 14:27:47 -0800 Subject: [PATCH 09/42] C++ generated code now has constants for vtable offsets. Besides making the generated code looking a lot more readable, it also allows you to use these offsets in calls to Table::CheckField, to see if a field is present in a table. Change-Id: I1b4cc350c4f27c4e474c31add40c701ef4ae63b2 Tested: On Linux. --- samples/monster_generated.h | 56 ++++--- src/idl_gen_cpp.cpp | 29 +++- tests/monster_test_generated.h | 260 +++++++++++++++++++-------------- 3 files changed, 203 insertions(+), 142 deletions(-) diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 854e712ee..53935ee93 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -59,28 +59,36 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS { STRUCT_END(Vec3, 12); struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const Vec3 *pos() const { return GetStruct(4); } - Vec3 *mutable_pos() { return GetStruct(4); } - int16_t mana() const { return GetField(6, 150); } - bool mutate_mana(int16_t _mana) { return SetField(6, _mana); } - int16_t hp() const { return GetField(8, 100); } - bool mutate_hp(int16_t _hp) { return SetField(8, _hp); } - const flatbuffers::String *name() const { return GetPointer(10); } - flatbuffers::String *mutable_name() { return GetPointer(10); } - const flatbuffers::Vector *inventory() const { return GetPointer *>(14); } - flatbuffers::Vector *mutable_inventory() { return GetPointer *>(14); } - Color color() const { return static_cast(GetField(16, 2)); } - bool mutate_color(Color _color) { return SetField(16, static_cast(_color)); } + enum { + VT_POS = 4, + VT_MANA = 6, + VT_HP = 8, + VT_NAME = 10, + VT_INVENTORY = 14, + VT_COLOR = 16, + }; + const Vec3 *pos() const { return GetStruct(VT_POS); } + Vec3 *mutable_pos() { return GetStruct(VT_POS); } + int16_t mana() const { return GetField(VT_MANA, 150); } + bool mutate_mana(int16_t _mana) { return SetField(VT_MANA, _mana); } + int16_t hp() const { return GetField(VT_HP, 100); } + bool mutate_hp(int16_t _hp) { return SetField(VT_HP, _hp); } + const flatbuffers::String *name() const { return GetPointer(VT_NAME); } + flatbuffers::String *mutable_name() { return GetPointer(VT_NAME); } + const flatbuffers::Vector *inventory() const { return GetPointer *>(VT_INVENTORY); } + 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)); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyField(verifier, 4 /* pos */) && - VerifyField(verifier, 6 /* mana */) && - VerifyField(verifier, 8 /* hp */) && - VerifyField(verifier, 10 /* name */) && + VerifyField(verifier, VT_POS) && + VerifyField(verifier, VT_MANA) && + VerifyField(verifier, VT_HP) && + VerifyField(verifier, VT_NAME) && verifier.Verify(name()) && - VerifyField(verifier, 14 /* inventory */) && + VerifyField(verifier, VT_INVENTORY) && verifier.Verify(inventory()) && - VerifyField(verifier, 16 /* color */) && + VerifyField(verifier, VT_COLOR) && verifier.EndTable(); } }; @@ -88,12 +96,12 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct MonsterBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_pos(const Vec3 *pos) { fbb_.AddStruct(4, pos); } - void add_mana(int16_t mana) { fbb_.AddElement(6, mana, 150); } - void add_hp(int16_t hp) { fbb_.AddElement(8, hp, 100); } - void add_name(flatbuffers::Offset name) { fbb_.AddOffset(10, name); } - void add_inventory(flatbuffers::Offset> inventory) { fbb_.AddOffset(14, inventory); } - void add_color(Color color) { fbb_.AddElement(16, static_cast(color), 2); } + void add_pos(const Vec3 *pos) { fbb_.AddStruct(Monster::VT_POS, pos); } + void add_mana(int16_t mana) { fbb_.AddElement(Monster::VT_MANA, mana, 150); } + void add_hp(int16_t hp) { fbb_.AddElement(Monster::VT_HP, hp, 100); } + 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); } MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } MonsterBuilder &operator=(const MonsterBuilder &); flatbuffers::Offset Finish() { diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 7c39c325a..ca523dcda 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -242,6 +242,12 @@ std::string GenUnderlyingCast(const Parser &parser, const FieldDef &field, : 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) { @@ -254,6 +260,19 @@ static void GenTable(const Parser &parser, StructDef &struct_def, 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) { @@ -268,7 +287,7 @@ static void GenTable(const Parser &parser, StructDef &struct_def, auto accessor = is_scalar ? "GetField<" : (IsStruct(field.value.type) ? "GetStruct<" : "GetPointer<"); - auto offsetstr = NumToString(field.value.offset); + auto offsetstr = GenFieldOffsetName(field); auto call = accessor + GenTypeGet(parser, field.value.type, "", "const ", " *", false) + @@ -347,8 +366,7 @@ static void GenTable(const Parser &parser, StructDef &struct_def, code += prefix + "VerifyField"; if (field.required) code += "Required"; code += "<" + GenTypeSize(parser, field.value.type); - code += ">(verifier, " + NumToString(field.value.offset); - code += " /* " + field.name + " */)"; + code += ">(verifier, " + GenFieldOffsetName(field) + ")"; switch (field.value.type.base_type) { case BASE_TYPE_UNION: code += prefix + "Verify" + field.value.type.enum_def->name; @@ -412,7 +430,7 @@ static void GenTable(const Parser &parser, StructDef &struct_def, } else { code += "Offset"; } - code += "(" + NumToString(field.value.offset) + ", "; + code += "(" + struct_def.name + "::" + GenFieldOffsetName(field) + ", "; code += GenUnderlyingCast(parser, field, false, field.name); if (IsScalar(field.value.type.base_type)) code += ", " + field.value.constant; @@ -433,7 +451,8 @@ static void GenTable(const Parser &parser, StructDef &struct_def, ++it) { auto &field = **it; if (!field.deprecated && field.required) { - code += " fbb_.Required(o, " + NumToString(field.value.offset); + code += " fbb_.Required(o, "; + code += struct_def.name + "::" + GenFieldOffsetName(field); code += "); // " + field.name + "\n"; } } diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 8a78de530..90814a94f 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -97,11 +97,14 @@ MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS { STRUCT_END(Vec3, 32); struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - Color color() const { return static_cast(GetField(4, 2)); } - bool mutate_color(Color _color) { return SetField(4, static_cast(_color)); } + enum { + VT_COLOR = 4, + }; + Color color() const { return static_cast(GetField(VT_COLOR, 2)); } + bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast(_color)); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyField(verifier, 4 /* color */) && + VerifyField(verifier, VT_COLOR) && verifier.EndTable(); } }; @@ -109,7 +112,7 @@ struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta struct TestSimpleTableWithEnumBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_color(Color color) { fbb_.AddElement(4, static_cast(color), 2); } + void add_color(Color color) { fbb_.AddElement(TestSimpleTableWithEnum::VT_COLOR, static_cast(color), 2); } TestSimpleTableWithEnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } TestSimpleTableWithEnumBuilder &operator=(const TestSimpleTableWithEnumBuilder &); flatbuffers::Offset Finish() { @@ -126,18 +129,23 @@ inline flatbuffers::Offset CreateTestSimpleTableWithEnu } struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const flatbuffers::String *id() const { return GetPointer(4); } - flatbuffers::String *mutable_id() { return GetPointer(4); } - int64_t val() const { return GetField(6, 0); } - bool mutate_val(int64_t _val) { return SetField(6, _val); } - uint16_t count() const { return GetField(8, 0); } - bool mutate_count(uint16_t _count) { return SetField(8, _count); } + enum { + VT_ID = 4, + VT_VAL = 6, + VT_COUNT = 8, + }; + const flatbuffers::String *id() const { return GetPointer(VT_ID); } + flatbuffers::String *mutable_id() { return GetPointer(VT_ID); } + int64_t val() const { return GetField(VT_VAL, 0); } + bool mutate_val(int64_t _val) { return SetField(VT_VAL, _val); } + uint16_t count() const { return GetField(VT_COUNT, 0); } + bool mutate_count(uint16_t _count) { return SetField(VT_COUNT, _count); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyField(verifier, 4 /* id */) && + VerifyField(verifier, VT_ID) && verifier.Verify(id()) && - VerifyField(verifier, 6 /* val */) && - VerifyField(verifier, 8 /* count */) && + VerifyField(verifier, VT_VAL) && + VerifyField(verifier, VT_COUNT) && verifier.EndTable(); } }; @@ -145,9 +153,9 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct StatBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_id(flatbuffers::Offset id) { fbb_.AddOffset(4, id); } - void add_val(int64_t val) { fbb_.AddElement(6, val, 0); } - void add_count(uint16_t count) { fbb_.AddElement(8, count, 0); } + void add_id(flatbuffers::Offset id) { fbb_.AddOffset(Stat::VT_ID, id); } + void add_val(int64_t val) { fbb_.AddElement(Stat::VT_VAL, val, 0); } + void add_count(uint16_t count) { fbb_.AddElement(Stat::VT_COUNT, count, 0); } StatBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } StatBuilder &operator=(const StatBuilder &); flatbuffers::Offset Finish() { @@ -169,96 +177,122 @@ inline flatbuffers::Offset CreateStat(flatbuffers::FlatBufferBuilder &_fbb /// an example documentation comment: monster object struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const Vec3 *pos() const { return GetStruct(4); } - Vec3 *mutable_pos() { return GetStruct(4); } - int16_t mana() const { return GetField(6, 150); } - bool mutate_mana(int16_t _mana) { return SetField(6, _mana); } - int16_t hp() const { return GetField(8, 100); } - bool mutate_hp(int16_t _hp) { return SetField(8, _hp); } - const flatbuffers::String *name() const { return GetPointer(10); } - flatbuffers::String *mutable_name() { return GetPointer(10); } + enum { + VT_POS = 4, + VT_MANA = 6, + VT_HP = 8, + VT_NAME = 10, + VT_INVENTORY = 14, + VT_COLOR = 16, + VT_TEST_TYPE = 18, + VT_TEST = 20, + VT_TEST4 = 22, + VT_TESTARRAYOFSTRING = 24, + VT_TESTARRAYOFTABLES = 26, + VT_ENEMY = 28, + VT_TESTNESTEDFLATBUFFER = 30, + VT_TESTEMPTY = 32, + VT_TESTBOOL = 34, + VT_TESTHASHS32_FNV1 = 36, + VT_TESTHASHU32_FNV1 = 38, + VT_TESTHASHS64_FNV1 = 40, + VT_TESTHASHU64_FNV1 = 42, + VT_TESTHASHS32_FNV1A = 44, + VT_TESTHASHU32_FNV1A = 46, + VT_TESTHASHS64_FNV1A = 48, + VT_TESTHASHU64_FNV1A = 50, + VT_TESTARRAYOFBOOLS = 52, + }; + const Vec3 *pos() const { return GetStruct(VT_POS); } + Vec3 *mutable_pos() { return GetStruct(VT_POS); } + int16_t mana() const { return GetField(VT_MANA, 150); } + bool mutate_mana(int16_t _mana) { return SetField(VT_MANA, _mana); } + int16_t hp() const { return GetField(VT_HP, 100); } + bool mutate_hp(int16_t _hp) { return SetField(VT_HP, _hp); } + const flatbuffers::String *name() const { return GetPointer(VT_NAME); } + flatbuffers::String *mutable_name() { return GetPointer(VT_NAME); } bool KeyCompareLessThan(const Monster *o) const { return *name() < *o->name(); } int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); } - const flatbuffers::Vector *inventory() const { return GetPointer *>(14); } - flatbuffers::Vector *mutable_inventory() { return GetPointer *>(14); } - Color color() const { return static_cast(GetField(16, 8)); } - bool mutate_color(Color _color) { return SetField(16, static_cast(_color)); } - Any test_type() const { return static_cast(GetField(18, 0)); } - bool mutate_test_type(Any _test_type) { return SetField(18, static_cast(_test_type)); } - const void *test() const { return GetPointer(20); } - void *mutable_test() { return GetPointer(20); } - const flatbuffers::Vector *test4() const { return GetPointer *>(22); } - flatbuffers::Vector *mutable_test4() { return GetPointer *>(22); } - const flatbuffers::Vector> *testarrayofstring() const { return GetPointer> *>(24); } - flatbuffers::Vector> *mutable_testarrayofstring() { return GetPointer> *>(24); } + const flatbuffers::Vector *inventory() const { return GetPointer *>(VT_INVENTORY); } + flatbuffers::Vector *mutable_inventory() { return GetPointer *>(VT_INVENTORY); } + Color color() const { return static_cast(GetField(VT_COLOR, 8)); } + bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast(_color)); } + Any test_type() const { return static_cast(GetField(VT_TEST_TYPE, 0)); } + bool mutate_test_type(Any _test_type) { return SetField(VT_TEST_TYPE, static_cast(_test_type)); } + const void *test() const { return GetPointer(VT_TEST); } + void *mutable_test() { return GetPointer(VT_TEST); } + const flatbuffers::Vector *test4() const { return GetPointer *>(VT_TEST4); } + flatbuffers::Vector *mutable_test4() { return GetPointer *>(VT_TEST4); } + const flatbuffers::Vector> *testarrayofstring() const { return GetPointer> *>(VT_TESTARRAYOFSTRING); } + flatbuffers::Vector> *mutable_testarrayofstring() { return GetPointer> *>(VT_TESTARRAYOFSTRING); } /// an example documentation comment: this will end up in the generated code /// multiline too - const flatbuffers::Vector> *testarrayoftables() const { return GetPointer> *>(26); } - flatbuffers::Vector> *mutable_testarrayoftables() { return GetPointer> *>(26); } - const Monster *enemy() const { return GetPointer(28); } - Monster *mutable_enemy() { return GetPointer(28); } - const flatbuffers::Vector *testnestedflatbuffer() const { return GetPointer *>(30); } - flatbuffers::Vector *mutable_testnestedflatbuffer() { return GetPointer *>(30); } + const flatbuffers::Vector> *testarrayoftables() const { return GetPointer> *>(VT_TESTARRAYOFTABLES); } + flatbuffers::Vector> *mutable_testarrayoftables() { return GetPointer> *>(VT_TESTARRAYOFTABLES); } + const Monster *enemy() const { return GetPointer(VT_ENEMY); } + Monster *mutable_enemy() { return GetPointer(VT_ENEMY); } + const flatbuffers::Vector *testnestedflatbuffer() const { return GetPointer *>(VT_TESTNESTEDFLATBUFFER); } + flatbuffers::Vector *mutable_testnestedflatbuffer() { return GetPointer *>(VT_TESTNESTEDFLATBUFFER); } const MyGame::Example::Monster *testnestedflatbuffer_nested_root() const { return flatbuffers::GetRoot(testnestedflatbuffer()->Data()); } - const Stat *testempty() const { return GetPointer(32); } - Stat *mutable_testempty() { return GetPointer(32); } - bool testbool() const { return static_cast(GetField(34, 0)); } - bool mutate_testbool(bool _testbool) { return SetField(34, static_cast(_testbool)); } - int32_t testhashs32_fnv1() const { return GetField(36, 0); } - bool mutate_testhashs32_fnv1(int32_t _testhashs32_fnv1) { return SetField(36, _testhashs32_fnv1); } - uint32_t testhashu32_fnv1() const { return GetField(38, 0); } - bool mutate_testhashu32_fnv1(uint32_t _testhashu32_fnv1) { return SetField(38, _testhashu32_fnv1); } - int64_t testhashs64_fnv1() const { return GetField(40, 0); } - bool mutate_testhashs64_fnv1(int64_t _testhashs64_fnv1) { return SetField(40, _testhashs64_fnv1); } - uint64_t testhashu64_fnv1() const { return GetField(42, 0); } - bool mutate_testhashu64_fnv1(uint64_t _testhashu64_fnv1) { return SetField(42, _testhashu64_fnv1); } - int32_t testhashs32_fnv1a() const { return GetField(44, 0); } - bool mutate_testhashs32_fnv1a(int32_t _testhashs32_fnv1a) { return SetField(44, _testhashs32_fnv1a); } - uint32_t testhashu32_fnv1a() const { return GetField(46, 0); } - bool mutate_testhashu32_fnv1a(uint32_t _testhashu32_fnv1a) { return SetField(46, _testhashu32_fnv1a); } - int64_t testhashs64_fnv1a() const { return GetField(48, 0); } - bool mutate_testhashs64_fnv1a(int64_t _testhashs64_fnv1a) { return SetField(48, _testhashs64_fnv1a); } - uint64_t testhashu64_fnv1a() const { return GetField(50, 0); } - bool mutate_testhashu64_fnv1a(uint64_t _testhashu64_fnv1a) { return SetField(50, _testhashu64_fnv1a); } - const flatbuffers::Vector *testarrayofbools() const { return GetPointer *>(52); } - flatbuffers::Vector *mutable_testarrayofbools() { return GetPointer *>(52); } + const Stat *testempty() const { return GetPointer(VT_TESTEMPTY); } + Stat *mutable_testempty() { return GetPointer(VT_TESTEMPTY); } + bool testbool() const { return static_cast(GetField(VT_TESTBOOL, 0)); } + 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); } + uint32_t testhashu32_fnv1() const { return GetField(VT_TESTHASHU32_FNV1, 0); } + bool mutate_testhashu32_fnv1(uint32_t _testhashu32_fnv1) { return SetField(VT_TESTHASHU32_FNV1, _testhashu32_fnv1); } + int64_t testhashs64_fnv1() const { return GetField(VT_TESTHASHS64_FNV1, 0); } + bool mutate_testhashs64_fnv1(int64_t _testhashs64_fnv1) { return SetField(VT_TESTHASHS64_FNV1, _testhashs64_fnv1); } + uint64_t testhashu64_fnv1() const { return GetField(VT_TESTHASHU64_FNV1, 0); } + bool mutate_testhashu64_fnv1(uint64_t _testhashu64_fnv1) { return SetField(VT_TESTHASHU64_FNV1, _testhashu64_fnv1); } + int32_t testhashs32_fnv1a() const { return GetField(VT_TESTHASHS32_FNV1A, 0); } + bool mutate_testhashs32_fnv1a(int32_t _testhashs32_fnv1a) { return SetField(VT_TESTHASHS32_FNV1A, _testhashs32_fnv1a); } + uint32_t testhashu32_fnv1a() const { return GetField(VT_TESTHASHU32_FNV1A, 0); } + bool mutate_testhashu32_fnv1a(uint32_t _testhashu32_fnv1a) { return SetField(VT_TESTHASHU32_FNV1A, _testhashu32_fnv1a); } + int64_t testhashs64_fnv1a() const { return GetField(VT_TESTHASHS64_FNV1A, 0); } + bool mutate_testhashs64_fnv1a(int64_t _testhashs64_fnv1a) { return SetField(VT_TESTHASHS64_FNV1A, _testhashs64_fnv1a); } + uint64_t testhashu64_fnv1a() const { return GetField(VT_TESTHASHU64_FNV1A, 0); } + 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); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyField(verifier, 4 /* pos */) && - VerifyField(verifier, 6 /* mana */) && - VerifyField(verifier, 8 /* hp */) && - VerifyFieldRequired(verifier, 10 /* name */) && + VerifyField(verifier, VT_POS) && + VerifyField(verifier, VT_MANA) && + VerifyField(verifier, VT_HP) && + VerifyFieldRequired(verifier, VT_NAME) && verifier.Verify(name()) && - VerifyField(verifier, 14 /* inventory */) && + VerifyField(verifier, VT_INVENTORY) && verifier.Verify(inventory()) && - VerifyField(verifier, 16 /* color */) && - VerifyField(verifier, 18 /* test_type */) && - VerifyField(verifier, 20 /* test */) && + VerifyField(verifier, VT_COLOR) && + VerifyField(verifier, VT_TEST_TYPE) && + VerifyField(verifier, VT_TEST) && VerifyAny(verifier, test(), test_type()) && - VerifyField(verifier, 22 /* test4 */) && + VerifyField(verifier, VT_TEST4) && verifier.Verify(test4()) && - VerifyField(verifier, 24 /* testarrayofstring */) && + VerifyField(verifier, VT_TESTARRAYOFSTRING) && verifier.Verify(testarrayofstring()) && verifier.VerifyVectorOfStrings(testarrayofstring()) && - VerifyField(verifier, 26 /* testarrayoftables */) && + VerifyField(verifier, VT_TESTARRAYOFTABLES) && verifier.Verify(testarrayoftables()) && verifier.VerifyVectorOfTables(testarrayoftables()) && - VerifyField(verifier, 28 /* enemy */) && + VerifyField(verifier, VT_ENEMY) && verifier.VerifyTable(enemy()) && - VerifyField(verifier, 30 /* testnestedflatbuffer */) && + VerifyField(verifier, VT_TESTNESTEDFLATBUFFER) && verifier.Verify(testnestedflatbuffer()) && - VerifyField(verifier, 32 /* testempty */) && + VerifyField(verifier, VT_TESTEMPTY) && verifier.VerifyTable(testempty()) && - VerifyField(verifier, 34 /* testbool */) && - VerifyField(verifier, 36 /* testhashs32_fnv1 */) && - VerifyField(verifier, 38 /* testhashu32_fnv1 */) && - VerifyField(verifier, 40 /* testhashs64_fnv1 */) && - VerifyField(verifier, 42 /* testhashu64_fnv1 */) && - VerifyField(verifier, 44 /* testhashs32_fnv1a */) && - VerifyField(verifier, 46 /* testhashu32_fnv1a */) && - VerifyField(verifier, 48 /* testhashs64_fnv1a */) && - VerifyField(verifier, 50 /* testhashu64_fnv1a */) && - VerifyField(verifier, 52 /* testarrayofbools */) && + VerifyField(verifier, VT_TESTBOOL) && + VerifyField(verifier, VT_TESTHASHS32_FNV1) && + VerifyField(verifier, VT_TESTHASHU32_FNV1) && + VerifyField(verifier, VT_TESTHASHS64_FNV1) && + VerifyField(verifier, VT_TESTHASHU64_FNV1) && + VerifyField(verifier, VT_TESTHASHS32_FNV1A) && + VerifyField(verifier, VT_TESTHASHU32_FNV1A) && + VerifyField(verifier, VT_TESTHASHS64_FNV1A) && + VerifyField(verifier, VT_TESTHASHU64_FNV1A) && + VerifyField(verifier, VT_TESTARRAYOFBOOLS) && verifier.Verify(testarrayofbools()) && verifier.EndTable(); } @@ -267,35 +301,35 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct MonsterBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_pos(const Vec3 *pos) { fbb_.AddStruct(4, pos); } - void add_mana(int16_t mana) { fbb_.AddElement(6, mana, 150); } - void add_hp(int16_t hp) { fbb_.AddElement(8, hp, 100); } - void add_name(flatbuffers::Offset name) { fbb_.AddOffset(10, name); } - void add_inventory(flatbuffers::Offset> inventory) { fbb_.AddOffset(14, inventory); } - void add_color(Color color) { fbb_.AddElement(16, static_cast(color), 8); } - void add_test_type(Any test_type) { fbb_.AddElement(18, static_cast(test_type), 0); } - void add_test(flatbuffers::Offset test) { fbb_.AddOffset(20, test); } - void add_test4(flatbuffers::Offset> test4) { fbb_.AddOffset(22, test4); } - void add_testarrayofstring(flatbuffers::Offset>> testarrayofstring) { fbb_.AddOffset(24, testarrayofstring); } - void add_testarrayoftables(flatbuffers::Offset>> testarrayoftables) { fbb_.AddOffset(26, testarrayoftables); } - void add_enemy(flatbuffers::Offset enemy) { fbb_.AddOffset(28, enemy); } - void add_testnestedflatbuffer(flatbuffers::Offset> testnestedflatbuffer) { fbb_.AddOffset(30, testnestedflatbuffer); } - void add_testempty(flatbuffers::Offset testempty) { fbb_.AddOffset(32, testempty); } - void add_testbool(bool testbool) { fbb_.AddElement(34, static_cast(testbool), 0); } - void add_testhashs32_fnv1(int32_t testhashs32_fnv1) { fbb_.AddElement(36, testhashs32_fnv1, 0); } - void add_testhashu32_fnv1(uint32_t testhashu32_fnv1) { fbb_.AddElement(38, testhashu32_fnv1, 0); } - void add_testhashs64_fnv1(int64_t testhashs64_fnv1) { fbb_.AddElement(40, testhashs64_fnv1, 0); } - void add_testhashu64_fnv1(uint64_t testhashu64_fnv1) { fbb_.AddElement(42, testhashu64_fnv1, 0); } - void add_testhashs32_fnv1a(int32_t testhashs32_fnv1a) { fbb_.AddElement(44, testhashs32_fnv1a, 0); } - void add_testhashu32_fnv1a(uint32_t testhashu32_fnv1a) { fbb_.AddElement(46, testhashu32_fnv1a, 0); } - void add_testhashs64_fnv1a(int64_t testhashs64_fnv1a) { fbb_.AddElement(48, testhashs64_fnv1a, 0); } - void add_testhashu64_fnv1a(uint64_t testhashu64_fnv1a) { fbb_.AddElement(50, testhashu64_fnv1a, 0); } - void add_testarrayofbools(flatbuffers::Offset> testarrayofbools) { fbb_.AddOffset(52, testarrayofbools); } + void add_pos(const Vec3 *pos) { fbb_.AddStruct(Monster::VT_POS, pos); } + void add_mana(int16_t mana) { fbb_.AddElement(Monster::VT_MANA, mana, 150); } + void add_hp(int16_t hp) { fbb_.AddElement(Monster::VT_HP, hp, 100); } + 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), 8); } + void add_test_type(Any test_type) { fbb_.AddElement(Monster::VT_TEST_TYPE, static_cast(test_type), 0); } + void add_test(flatbuffers::Offset test) { fbb_.AddOffset(Monster::VT_TEST, test); } + void add_test4(flatbuffers::Offset> test4) { fbb_.AddOffset(Monster::VT_TEST4, test4); } + void add_testarrayofstring(flatbuffers::Offset>> testarrayofstring) { fbb_.AddOffset(Monster::VT_TESTARRAYOFSTRING, testarrayofstring); } + void add_testarrayoftables(flatbuffers::Offset>> testarrayoftables) { fbb_.AddOffset(Monster::VT_TESTARRAYOFTABLES, testarrayoftables); } + void add_enemy(flatbuffers::Offset enemy) { fbb_.AddOffset(Monster::VT_ENEMY, enemy); } + void add_testnestedflatbuffer(flatbuffers::Offset> testnestedflatbuffer) { fbb_.AddOffset(Monster::VT_TESTNESTEDFLATBUFFER, testnestedflatbuffer); } + void add_testempty(flatbuffers::Offset testempty) { fbb_.AddOffset(Monster::VT_TESTEMPTY, testempty); } + void add_testbool(bool testbool) { fbb_.AddElement(Monster::VT_TESTBOOL, static_cast(testbool), 0); } + void add_testhashs32_fnv1(int32_t testhashs32_fnv1) { fbb_.AddElement(Monster::VT_TESTHASHS32_FNV1, testhashs32_fnv1, 0); } + void add_testhashu32_fnv1(uint32_t testhashu32_fnv1) { fbb_.AddElement(Monster::VT_TESTHASHU32_FNV1, testhashu32_fnv1, 0); } + void add_testhashs64_fnv1(int64_t testhashs64_fnv1) { fbb_.AddElement(Monster::VT_TESTHASHS64_FNV1, testhashs64_fnv1, 0); } + void add_testhashu64_fnv1(uint64_t testhashu64_fnv1) { fbb_.AddElement(Monster::VT_TESTHASHU64_FNV1, testhashu64_fnv1, 0); } + void add_testhashs32_fnv1a(int32_t testhashs32_fnv1a) { fbb_.AddElement(Monster::VT_TESTHASHS32_FNV1A, testhashs32_fnv1a, 0); } + void add_testhashu32_fnv1a(uint32_t testhashu32_fnv1a) { fbb_.AddElement(Monster::VT_TESTHASHU32_FNV1A, testhashu32_fnv1a, 0); } + 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); } MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } MonsterBuilder &operator=(const MonsterBuilder &); flatbuffers::Offset Finish() { auto o = flatbuffers::Offset(fbb_.EndTable(start_, 25)); - fbb_.Required(o, 10); // name + fbb_.Required(o, Monster::VT_NAME); // name return o; } }; From ac49eda0531b8679bc1eeb55e486dc4390c3f08c Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 30 Nov 2015 16:42:48 -0800 Subject: [PATCH 10/42] Multiple schemas parsed by flatc are now parsed independently. It used to be such that later schemas could depend on earlier schemas. This was a convenience from days before include files were implemented. Nowadays they cause subtle bugs rather than being useful, so this functionality has been removed. You now need to explicitly include files you depend upon. Change-Id: Id8292c3c621fc38fbd796da2d2cbdd63efc230d1 Tested: on Linux. --- docs/html/md__compiler.html | 4 ++-- docs/source/Compiler.md | 7 +++---- include/flatbuffers/util.h | 6 ++++++ src/flatc.cpp | 36 +++++++++++++++++++++--------------- src/idl_parser.cpp | 7 +++---- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/docs/html/md__compiler.html b/docs/html/md__compiler.html index ff3f7fe22..1b3cd1db4 100644 --- a/docs/html/md__compiler.html +++ b/docs/html/md__compiler.html @@ -63,8 +63,8 @@ $(document).ready(function(){initNavTree('md__compiler.html','');});

Usage:

flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] [ -S ] FILES...
       [ -- FILES...]
-

The files are read and parsed in order, and can contain either schemas or data (see below). Later files can make use of definitions in earlier files.

-

-- indicates that the following files are binary files in FlatBuffer format conforming to the schema(s) indicated before it. Incompatible binary files currently will give unpredictable results (!)

+

The files are read and parsed in order, and can contain either schemas or data (see below). Data files are processed according to the definitions of the most recent schema specified.

+

-- indicates that the following files are binary files in FlatBuffer format conforming to the schema indicated before it.

Depending on the flags passed, additional files may be generated for each file processed:

For any schema input files, one or more generators can be specified:

    diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md index 27ddf52e4..9d89cb104 100755 --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@ -6,12 +6,11 @@ Usage: [ -- FILES...] The files are read and parsed in order, and can contain either schemas -or data (see below). Later files can make use of definitions in earlier -files. +or data (see below). Data files are processed according to the definitions of +the most recent schema specified. `--` indicates that the following files are binary files in -FlatBuffer format conforming to the schema(s) indicated before it. -Incompatible binary files currently will give unpredictable results (!) +FlatBuffer format conforming to the schema indicated before it. Depending on the flags passed, additional files may be generated for each file processed: diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h index 8e5d09908..ba73d67bd 100644 --- a/include/flatbuffers/util.h +++ b/include/flatbuffers/util.h @@ -174,6 +174,12 @@ inline std::string StripExtension(const std::string &filepath) { return i != std::string::npos ? filepath.substr(0, i) : filepath; } +// Returns the extension, if any. +inline std::string GetExtension(const std::string &filepath) { + size_t i = filepath.find_last_of("."); + return i != std::string::npos ? filepath.substr(i + 1) : ""; +} + // Return the last component of the path, after the last separator. inline std::string StripPath(const std::string &filepath) { size_t i = filepath.find_last_of(PathSeparatorSet); diff --git a/src/flatc.cpp b/src/flatc.cpp index 2479da12b..86de77416 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -79,7 +79,8 @@ const Generator generators[] = { flatbuffers::GeneralMakeRule }, }; -const char *program_name = NULL; +const char *program_name = nullptr; +flatbuffers::Parser *parser = nullptr; static void Error(const std::string &err, bool usage, bool show_exe_name) { if (show_exe_name) printf("%s: ", program_name); @@ -122,6 +123,7 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) { "example: %s -c -b schema1.fbs schema2.fbs data.json\n", program_name); } + if (parser) delete parser; exit(1); } @@ -205,7 +207,7 @@ int main(int argc, const char *argv[]) { Error("no options: specify one of -c -g -j -t -b etc.", true); // Now process the files: - flatbuffers::Parser parser(opts.strict_json, proto_mode); + parser = new flatbuffers::Parser(opts.strict_json, proto_mode); for (auto file_it = filenames.begin(); file_it != filenames.end(); ++file_it) { @@ -216,8 +218,8 @@ int main(int argc, const char *argv[]) { bool is_binary = static_cast(file_it - filenames.begin()) >= binary_files_from; if (is_binary) { - parser.builder_.Clear(); - parser.builder_.PushFlatBuffer( + parser->builder_.Clear(); + parser->builder_.PushFlatBuffer( reinterpret_cast(contents.c_str()), contents.length()); if (!raw_binary) { @@ -226,30 +228,37 @@ int main(int argc, const char *argv[]) { // does not contain a file identifier. // We'd expect that typically any binary used as a file would have // such an identifier, so by default we require them to match. - if (!parser.file_identifier_.length()) { + if (!parser->file_identifier_.length()) { Error("current schema has no file_identifier: cannot test if \"" + *file_it + "\" matches the schema, use --raw-binary to read this file" " anyway."); } else if (!flatbuffers::BufferHasIdentifier(contents.c_str(), - parser.file_identifier_.c_str())) { + parser->file_identifier_.c_str())) { Error("binary \"" + *file_it + "\" does not have expected file_identifier \"" + - parser.file_identifier_ + + parser->file_identifier_ + "\", use --raw-binary to read this file anyway."); } } } else { + 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; + parser = new flatbuffers::Parser(opts.strict_json, proto_mode); + } auto local_include_directory = flatbuffers::StripFileName(*file_it); include_directories.push_back(local_include_directory.c_str()); include_directories.push_back(nullptr); - if (!parser.Parse(contents.c_str(), &include_directories[0], + if (!parser->Parse(contents.c_str(), &include_directories[0], file_it->c_str())) - Error(parser.error_, false, false); + Error(parser->error_, false, false); if (schema_binary) { - parser.Serialize(); - parser.file_extension_ = reflection::SchemaExtension(); + parser->Serialize(); + parser->file_extension_ = reflection::SchemaExtension(); } include_directories.pop_back(); include_directories.pop_back(); @@ -280,11 +289,8 @@ int main(int argc, const char *argv[]) { } if (proto_mode) GenerateFBS(parser, output_path, filebase, opts); - - // We do not want to generate code for the definitions in this file - // in any files coming up next. - parser.MarkGenerated(); } + delete parser; return 0; } diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 233eeceef..f2b7fc9c4 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1072,10 +1072,9 @@ bool Parser::SetRootType(const char *name) { } void Parser::MarkGenerated() { - // Since the Parser object retains definitions across files, we must - // ensure we only output code for definitions once, in the file they are first - // declared. This function marks all existing definitions as having already - // been generated. + // This function marks all existing definitions as having already + // been generated, which signals no code for included files should be + // generated. for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { (*it)->generated = true; From e4abeef65c81f079909b66af82be450601d54d52 Mon Sep 17 00:00:00 2001 From: Perry Hung Date: Mon, 30 Nov 2015 19:41:54 -0500 Subject: [PATCH 11/42] Link clang builds against libc++abi on Linux Simply running clang with -stdlib=libc++ requires a manual link against libc++abi on Linux. This is documented in the libc++ documentation: http://libcxx.llvm.org/ Tested on Arch Linux, using clang 3.7.0 RELEASE. Signed-off-by: Perry Hung --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 47a428230..6dc73e7a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,7 +84,9 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) "${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") + "${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++ -Wall -pedantic -Werror -Wextra") + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -lc++abi") endif() if(FLATBUFFERS_CODE_COVERAGE) From b611dc4b993a48af61f84c2807d7d65879aaf769 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 30 Nov 2015 17:49:51 -0800 Subject: [PATCH 12/42] Fixed implicit dereference in flatc. Change-Id: If2e62a325b47399561b4c20d2def55ede4831d19 Tested: on Linux. --- src/flatc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/flatc.cpp b/src/flatc.cpp index 86de77416..a27af7950 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -272,7 +272,7 @@ int main(int argc, const char *argv[]) { if (generator_enabled[i]) { if (!print_make_rules) { flatbuffers::EnsureDirExists(output_path); - if (!generators[i].generate(parser, output_path, filebase, opts)) { + if (!generators[i].generate(*parser, output_path, filebase, opts)) { Error(std::string("Unable to generate ") + generators[i].lang_name + " for " + @@ -280,7 +280,7 @@ int main(int argc, const char *argv[]) { } } else { std::string make_rule = generators[i].make_rule( - parser, output_path, *file_it, opts); + *parser, output_path, *file_it, opts); if (!make_rule.empty()) printf("%s\n", flatbuffers::WordWrap( make_rule, 80, " ", " \\").c_str()); @@ -288,7 +288,7 @@ int main(int argc, const char *argv[]) { } } - if (proto_mode) GenerateFBS(parser, output_path, filebase, opts); + if (proto_mode) GenerateFBS(*parser, output_path, filebase, opts); } delete parser; From d06e571b31179c0dd7986456a558fafb9b92f265 Mon Sep 17 00:00:00 2001 From: Stewart Miles Date: Mon, 23 May 2016 16:27:35 -0700 Subject: [PATCH 13/42] Removed reference to deprecated NDK toolchain version. Change-Id: I8d39a66ca5642427619c60f349fa78917aec2455 --- android/jni/Application.mk | 2 +- samples/android/jni/Application.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/android/jni/Application.mk b/android/jni/Application.mk index 56952fc96..2fc9c7379 100755 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -18,5 +18,5 @@ APP_PROJECT_PATH := $(call my-dir)/.. APP_STL := gnustl_static APP_ABI := armeabi-v7a -NDK_TOOLCHAIN_VERSION := 4.8 + APP_CPPFLAGS += -std=c++11 diff --git a/samples/android/jni/Application.mk b/samples/android/jni/Application.mk index 56952fc96..2fc9c7379 100755 --- a/samples/android/jni/Application.mk +++ b/samples/android/jni/Application.mk @@ -18,5 +18,5 @@ APP_PROJECT_PATH := $(call my-dir)/.. APP_STL := gnustl_static APP_ABI := armeabi-v7a -NDK_TOOLCHAIN_VERSION := 4.8 + APP_CPPFLAGS += -std=c++11 From fe9787e58db79ff108f2d41d8b2030ea2b9925da Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 23 May 2016 16:35:20 -0700 Subject: [PATCH 14/42] Add a fuzzer for flatbuffers, derived from the one used in Chromium: https://code.google.com/p/chromium/codesearch#chromium/src/testing/libfuzzer/fuzzers/flatbuffers_verifier_fuzzer.cc (mirrored from cl 122676317) Change-Id: I0074af435cf37f5e6368b040563c3733d9e02345 --- .../fuzz-0-flatbuffers_verifier_fuzzer | Bin 0 -> 411 bytes tests/fuzzer/flatbuffers_verifier_fuzzer.cc | 14 ++++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fuzz-0-flatbuffers_verifier_fuzzer create mode 100644 tests/fuzzer/flatbuffers_verifier_fuzzer.cc diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/fuzz-0-flatbuffers_verifier_fuzzer b/tests/fuzzer/flatbuffers_verifier_corpus/fuzz-0-flatbuffers_verifier_fuzzer new file mode 100644 index 0000000000000000000000000000000000000000..ada82f163f5670ff70daa87141aec4c2d0d421b3 GIT binary patch literal 411 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9ze{%;KL9ABoi1i7(y5# z7z%*w7$B|y>I4Et2B2(%J&@%9L_iD!91cuClh|NfDE$RUKLO%1K->Vt5kTw!#EvH` z?}BjQlEyv|Rso6~oLK$oYy*E@<3$Ml@oxI@J03rsAvDNsxO@Tf2gnyLU|-k(Rb~J& z$R7w_RDgZ)8QB;5Kt&D^KO_6Z*Ix=6Sjc|*>C6mN&d9)Mwd?=?|13Z@2)h-frT{4h fCLk68Vvras5SOGDmly(RNSGqrt-$~ZeW)q`2B|>A literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_fuzzer.cc b/tests/fuzzer/flatbuffers_verifier_fuzzer.cc new file mode 100644 index 000000000..d2fa73ad7 --- /dev/null +++ b/tests/fuzzer/flatbuffers_verifier_fuzzer.cc @@ -0,0 +1,14 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include +#include + +#include "third_party/flatbuffers/tests/monster_test_generated.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + flatbuffers::Verifier verifier(data, size); + MyGame::Example::VerifyMonsterBuffer(verifier); + return 0; +} From 64b91da9cf139f639135aa199354833b7f302af9 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 23 May 2016 16:37:57 -0700 Subject: [PATCH 15/42] Uncomment the corpus attribute since b/28762769 is fixed, add more items to the corpus (taken from the ClusterFuzz-generated corpus). (mirrored from cl 122690857) Change-Id: I98c7672169a9a27fe18bedae8501e6fb85a0681d --- .../01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 | Bin 0 -> 383 bytes .../075a40dd6e6eec9cc96f0399c182f62361cdc553 | Bin 0 -> 154 bytes .../0c319e8089228db0958f35c54614d4e2d917f9d5 | Bin 0 -> 383 bytes .../0d654589709444777a4a854ec16b7160b0b8f06f | Bin 0 -> 154 bytes .../10ace4829162a0d37730ad898ee6ef2b76849ce4 | Bin 0 -> 383 bytes .../12986603181adee83afedc8206f86ead9fd20653 | Bin 0 -> 383 bytes .../14c816a2f528da8004315f8e71aec9e7e9f4df89 | Bin 0 -> 383 bytes .../14d90e4ac5f58f07be524633e96fb8f6521116e2 | Bin 0 -> 771 bytes .../2290776813d50bf54386dc6670aea41c8eb4f73f | Bin 0 -> 383 bytes .../2357f92773faefb0049312fcf7421f2c4ef08dc5 | Bin 0 -> 383 bytes .../235a53ee083b428f4eb80eb5af6a8b41a4036d55 | Bin 0 -> 384 bytes .../243d7b9356afab5800b0fd424a0f90cefeb8f411 | Bin 0 -> 79 bytes .../2e2249e476941c7390d924d8f6c88b5d59d0e300 | Bin 0 -> 384 bytes .../3068bc815c5e573acf89236689705409b253e3c1 | Bin 0 -> 384 bytes .../3470f740d4b2e405c2922ebf68838a03fd690a64 | Bin 0 -> 153 bytes .../489b729a42a6ff5bcc30d341f29fd1660700c0b8 | Bin 0 -> 384 bytes .../50866a2404c2cfbbcaae258011c012d819a842a5 | Bin 0 -> 656 bytes .../50c219f74b02582ea4eaa683f0605b5cd16d6ed6 | Bin 0 -> 154 bytes .../525f958d1709f5e926cba564e23180b60d80fb9a | Bin 0 -> 384 bytes .../543e528d3150cd0d2a45973cf98e992d67f7c406 | Bin 0 -> 384 bytes .../5a2f21b370496184851baffbbbb450fe49aed324 | Bin 0 -> 383 bytes .../5bbf4a7b9da7aee4db6b21ea62128df74aa23b59 | Bin 0 -> 384 bytes .../61005237d5ba26c372b347249143b793c324186a | Bin 0 -> 383 bytes .../6207082d567e33f6569e5ffac1e882b6988f5e86 | Bin 0 -> 383 bytes .../699e2869e8bb9dad4ed0ca23245976e08d6abf96 | Bin 0 -> 384 bytes .../6a9bcfb376f95d3d235f6e3479ae37b906be2a17 | Bin 0 -> 384 bytes .../6b1e41ca991828476b077ebda3f7e9936b549c32 | Bin 0 -> 383 bytes .../6e146549ff6aefcd1314a8b04cd7ee0955796002 | Bin 0 -> 383 bytes .../7c1217cf933de200b58fd2bf494044ebb6d90cde | Bin 0 -> 384 bytes .../7e0fac79b1dfbbdcaeee925535b66c2834d13814 | Bin 0 -> 384 bytes .../8718d7c1e9a536adb95fb0c749db4554311895e0 | Bin 0 -> 383 bytes .../8ae96e1702303027346b59d0a6acbd1ef0b1955f | Bin 0 -> 384 bytes .../8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae | Bin 0 -> 384 bytes .../903747bd5d4239da836d24087e7e279715cc0980 | Bin 0 -> 384 bytes .../93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 | Bin 0 -> 128 bytes .../9f6095cae432e38efe7464bfac3cacd6df3bbc48 | Bin 0 -> 578 bytes .../ae3e1a31be33cc502b6586253274e6b620c78829 | Bin 0 -> 383 bytes .../b75487b8176eda7fb18e4f408208caa82d7c121a | Bin 0 -> 174 bytes .../bf3d7a99df32ac45e9081eb3519524930c85de89 | Bin 0 -> 383 bytes .../bf60f275ed989532747e7bbcc93ab2bbd834becc | Bin 0 -> 122 bytes .../c5170081fc1f8a36ab30541f087cf530ab0845b6 | Bin 0 -> 384 bytes .../c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 | Bin 0 -> 384 bytes .../cd6ac24fd00acc3e9887fdf2ae300481e745f53a | Bin 0 -> 384 bytes .../cd8e4aef993fcdebd9583069cd0a5468d254c5c7 | 1 + .../decff8b2d7524b5fad71129ecf0f4edd9082af2a | Bin 0 -> 384 bytes .../df0b39717d20371162754b37747a0c989623cb48 | Bin 0 -> 384 bytes .../e423e0b67927e2c303dbb7ead3fd68706b92d657 | Bin 0 -> 153 bytes .../e72266e5ad67af5c27bcd69961460770e82bd24c | Bin 0 -> 383 bytes .../ee80034f2e35e3f07a708b211be4f1967c83b6e9 | Bin 0 -> 383 bytes .../f5fd02697cac00a81809909a971f80f28aa4c020 | Bin 0 -> 383 bytes .../fbe211a4df09673e54945bb8f5afc4c5cfa67778 | Bin 0 -> 383 bytes .../fc5d4b9117ba9e87388174aee4f4970bdfe8d066 | 1 + .../fd11c36a6b2cbceeac9664690b5d35f0f9bb6f01 | Bin 0 -> 383 bytes .../ff085b6090cadabfabb6f5e785681353fb89eb87 | Bin 0 -> 384 bytes 54 files changed, 2 insertions(+) create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/075a40dd6e6eec9cc96f0399c182f62361cdc553 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/0c319e8089228db0958f35c54614d4e2d917f9d5 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/0d654589709444777a4a854ec16b7160b0b8f06f create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/10ace4829162a0d37730ad898ee6ef2b76849ce4 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/12986603181adee83afedc8206f86ead9fd20653 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/14c816a2f528da8004315f8e71aec9e7e9f4df89 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/14d90e4ac5f58f07be524633e96fb8f6521116e2 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/2290776813d50bf54386dc6670aea41c8eb4f73f create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/2357f92773faefb0049312fcf7421f2c4ef08dc5 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/235a53ee083b428f4eb80eb5af6a8b41a4036d55 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/243d7b9356afab5800b0fd424a0f90cefeb8f411 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/2e2249e476941c7390d924d8f6c88b5d59d0e300 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/3068bc815c5e573acf89236689705409b253e3c1 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/3470f740d4b2e405c2922ebf68838a03fd690a64 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/489b729a42a6ff5bcc30d341f29fd1660700c0b8 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/50866a2404c2cfbbcaae258011c012d819a842a5 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/50c219f74b02582ea4eaa683f0605b5cd16d6ed6 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/525f958d1709f5e926cba564e23180b60d80fb9a create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/543e528d3150cd0d2a45973cf98e992d67f7c406 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/5a2f21b370496184851baffbbbb450fe49aed324 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/5bbf4a7b9da7aee4db6b21ea62128df74aa23b59 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/61005237d5ba26c372b347249143b793c324186a create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6207082d567e33f6569e5ffac1e882b6988f5e86 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/699e2869e8bb9dad4ed0ca23245976e08d6abf96 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6a9bcfb376f95d3d235f6e3479ae37b906be2a17 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6b1e41ca991828476b077ebda3f7e9936b549c32 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6e146549ff6aefcd1314a8b04cd7ee0955796002 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/7c1217cf933de200b58fd2bf494044ebb6d90cde create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/7e0fac79b1dfbbdcaeee925535b66c2834d13814 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/8718d7c1e9a536adb95fb0c749db4554311895e0 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/8ae96e1702303027346b59d0a6acbd1ef0b1955f create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/903747bd5d4239da836d24087e7e279715cc0980 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/9f6095cae432e38efe7464bfac3cacd6df3bbc48 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/ae3e1a31be33cc502b6586253274e6b620c78829 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/b75487b8176eda7fb18e4f408208caa82d7c121a create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/bf3d7a99df32ac45e9081eb3519524930c85de89 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/bf60f275ed989532747e7bbcc93ab2bbd834becc create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/c5170081fc1f8a36ab30541f087cf530ab0845b6 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/cd6ac24fd00acc3e9887fdf2ae300481e745f53a create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/decff8b2d7524b5fad71129ecf0f4edd9082af2a create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/df0b39717d20371162754b37747a0c989623cb48 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/e423e0b67927e2c303dbb7ead3fd68706b92d657 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/e72266e5ad67af5c27bcd69961460770e82bd24c create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/ee80034f2e35e3f07a708b211be4f1967c83b6e9 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/f5fd02697cac00a81809909a971f80f28aa4c020 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fbe211a4df09673e54945bb8f5afc4c5cfa67778 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fd11c36a6b2cbceeac9664690b5d35f0f9bb6f01 create mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/ff085b6090cadabfabb6f5e785681353fb89eb87 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 b/tests/fuzzer/flatbuffers_verifier_corpus/01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 new file mode 100644 index 0000000000000000000000000000000000000000..e36b1ce5c29d0393b164383915462bc0a15075ac GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Z~d;Pk{Ig5H|pE1Q0s_vE#|g zyC7V+q_Gc#RTvr>7$#PKI@`dX*LV>^f4rN1{Eo*@XBf>4)W-;fyZ-;RG@(ee?5*OHzw~OaSp4Ik^A; literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/075a40dd6e6eec9cc96f0399c182f62361cdc553 b/tests/fuzzer/flatbuffers_verifier_corpus/075a40dd6e6eec9cc96f0399c182f62361cdc553 new file mode 100644 index 0000000000000000000000000000000000000000..063942bfe400275e933b2ce096f248bbcf41eebb GIT binary patch literal 154 zcmeZZU|{g|_X`G6Kw!ntz`()4u!F$_$gu!oRt6ge2L=})%L9l(z=t7#A%P)7ogsuF vf}wz+f*}ShYy~121As(>J&t18V8b=A8xE9aV8{Rf@81tj literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/0c319e8089228db0958f35c54614d4e2d917f9d5 b/tests/fuzzer/flatbuffers_verifier_corpus/0c319e8089228db0958f35c54614d4e2d917f9d5 new file mode 100644 index 0000000000000000000000000000000000000000..a505619059d3c4d522c0f976bda36bab5b9e4ae7 GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoFYxFof>#1M@QQey>FCC8uvW^vR3DIfspfdEY)TL8v^(g;}wpqw;N j6ci31Q4ogN53-Yik%^fF=n_sKv(h&|uec<&2*?BgA>le= literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/0d654589709444777a4a854ec16b7160b0b8f06f b/tests/fuzzer/flatbuffers_verifier_corpus/0d654589709444777a4a854ec16b7160b0b8f06f new file mode 100644 index 0000000000000000000000000000000000000000..437134b35b22650767965a2d7ec0d55177e09265 GIT binary patch literal 154 zcmeZZU|{g|_X`G6Kw!ntz`y}wm;kW_5VJDaFgP%{09hVD3<5q30SpNY8R`rn3=s?k o3>6G9U|}l|$ru168tj3D0}wfYv|yUe#$W^#$7eWDnt>q$0E@p4ZU6uP literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/10ace4829162a0d37730ad898ee6ef2b76849ce4 b/tests/fuzzer/flatbuffers_verifier_corpus/10ace4829162a0d37730ad898ee6ef2b76849ce4 new file mode 100644 index 0000000000000000000000000000000000000000..7c9321c577166660235baa100beaa3097ad403be GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAwYIS z0Ye1?Lky5*1(IT90LnGk16dA01jI1F;lKnmi4Deu(qDk|6CgeV#0@|k0mKeK?0B;B zE(jMcY3u`G6`)UWCve@1`HWDVqowAVupYOh75)f zh6siNh6*4z28gXd;*3Bkh6Z~e%K?ah7zQ{Tn1Cj+!MITR3y^*S#AkrG0f-}j*a3(g zPgdRq;ld@2eITp?6gxPv`qSA4{=CME5c=cY^y7CtemcWwW}q5IAl&u;|9=)B8-(48 zQd58w0}~L705M366^Khxi%SgA*dR4rKvi-K8bFp6I23>kupSUCfW!uw0|5vYgs%V& h2aqTT!|Vsy$-v0O%mQ=?Cy-g`o1a%)l3E000svxiIs*Uz literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/14c816a2f528da8004315f8e71aec9e7e9f4df89 b/tests/fuzzer/flatbuffers_verifier_corpus/14c816a2f528da8004315f8e71aec9e7e9f4df89 new file mode 100644 index 0000000000000000000000000000000000000000..321ff5675d1e4fc7e778edbe7aee76c8a2904043 GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Y1;Pk{Ig5H|pE1Q0s_vE#|g zyC7V+q_Gc#Re)lR6RSU+ZQ##?(I4-oAHU=A(-}-NJA3>Ds$m4eUH||8X92Q7*sUlv z1xPV40kH@WgTz>YxFof>#2ATf2xNoQZ~;}xF=zl;R^U*uW>5#~0f}G(kU;Z=N(q2z eP&lC553-Yik%<{3&I!c6mA?6T#U-gl3=9BApgPU~ literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/14d90e4ac5f58f07be524633e96fb8f6521116e2 b/tests/fuzzer/flatbuffers_verifier_corpus/14d90e4ac5f58f07be524633e96fb8f6521116e2 new file mode 100644 index 0000000000000000000000000000000000000000..807a5b29079e5c6addcf62855be149edb7681cb3 GIT binary patch literal 771 zcmZ`%Jxc>Y5Pf%=aM);(P7npbkH!xKqX=#=$Q6kRXpzDqg+Z|pV^SDwE`_a-pCI@v z`~woue_%Ql1sgvatMkq5T{MKu@^)rtc6T0c*9VXFwX``o>zop>c^CBrGxZgd)%YP)mOys8q@%r#pVpAW(4 zN$fv5hj)+u&sOY*xX0nR4Z~3Gz9hEKDhDt0E|DT6pCIbbwfeHebBrss`jXv(5hsNS z%(AkoDo|us59w>`^o#4xB-YGfYwRajeQ`j!qCXTFtPg6*#`c+#)}a8jS|IY$sgRoms zY6_5IU;<(hAO?xC0`Z*G;u0e$y9CHK1hPSDxPYqU7&L$^9dIZB8DKpi8U#T4AppTr pU{Hh!f@x4VfMh|~1!_OYP6kFMW)`3=oIqx!Z+>2JNoo<02>{z}I@bUI literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/2357f92773faefb0049312fcf7421f2c4ef08dc5 b/tests/fuzzer/flatbuffers_verifier_corpus/2357f92773faefb0049312fcf7421f2c4ef08dc5 new file mode 100644 index 0000000000000000000000000000000000000000..762bb8c5aab88c57d5fb6cdd4582c7fd719acbe3 GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Z~d z-UZ>pC5?R`tO68koLK$oYy*E@<3$Ml@oxI@J03rsVKg&P4I>a9`2YVu3y=-MZbhjn zK#GA0h(&-HB*qHFb5e^-jG*iiAlneg2C3l!s*+>S0D46L911`oupR~mEf5pR1~ZZP jiU~2NDiI1jI1F;lRYe3N#fJd;xNw0Pz_hZUADCi4H*Qc(U>?2p2AC z>;qvHpjhL?>Q84I`14@&$Ghpr?|A%lhSAJGHH<*G>;M1%EI>90yA`FT04WA0AQk~) zkQgfvm!uY#7$LC@fozZ(E}$wo1`Qy~3K$9?5r`fz0}G*mMGO=U==Ou`WME`s28nY5 Qv2UeseqM1&Y7vkP03Dz?rT_o{ literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/243d7b9356afab5800b0fd424a0f90cefeb8f411 b/tests/fuzzer/flatbuffers_verifier_corpus/243d7b9356afab5800b0fd424a0f90cefeb8f411 new file mode 100644 index 0000000000000000000000000000000000000000..6c6d7cc4e3b4070f11901efce9120d2e6838d13f GIT binary patch literal 79 zcmeZZU|{g|_X`G6Kw!ntz`y~d**t&*iZD==4Jc*;#1=rT$Y28`wHO>2Kq`Tvjto9P G1_J;!>;~5W literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/2e2249e476941c7390d924d8f6c88b5d59d0e300 b/tests/fuzzer/flatbuffers_verifier_corpus/2e2249e476941c7390d924d8f6c88b5d59d0e300 new file mode 100644 index 0000000000000000000000000000000000000000..ffc21832c8814390e59fbaf6f5c45f1d94cf07f7 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT10MFt`9&9zYBNJ`4d22|yUa5W!Hu zP{9xb7PSJAi~&HR!5&CB01*(w0EYt;&?Gh(7fOEt(ocZ+3=lT}aRd-M0I}oA%DW(3 zxTLWUgjIlIjT5Usoo(RHgV7)FrXRoK@zWVbGXvEy0^zRz|NpZ9*&yszl$!DkNHYPk z2vm#}NSCA*mly$QR!s=o5Xc6p;R33XW6%JytQaJKBnW`aAq9ZK0oi_#UXYy(j7-cR SaZVuit@O>$D=tYb0AoF%l0p8Rpw z@nq%Q!X=G;AglruYn)j9>1+dk9*q8YH~sh>kDtykni;5u(VBsgVb}lv|5<<>5Oym{ zO#xC&Kr8|kVg=GAsl`CT22JNoo<04FIR>I}QK< literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/3470f740d4b2e405c2922ebf68838a03fd690a64 b/tests/fuzzer/flatbuffers_verifier_corpus/3470f740d4b2e405c2922ebf68838a03fd690a64 new file mode 100644 index 0000000000000000000000000000000000000000..a0f773fda45ae984b0116fcd9133a9158aba3a78 GIT binary patch literal 153 zcmeZZU|{g|_X`G6Kw!ntz`y}wm;kW_5VJDaFgP%{09hVD3<5q30SpNY84Mu|5ex+k q6$~+8Q7aJ17yu+1?16*>5IKN!U>eQFU<4G$Wwry*Y#?x8$N&I$%no+| literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/489b729a42a6ff5bcc30d341f29fd1660700c0b8 b/tests/fuzzer/flatbuffers_verifier_corpus/489b729a42a6ff5bcc30d341f29fd1660700c0b8 new file mode 100644 index 0000000000000000000000000000000000000000..62afb03c11744761a8c0e6afdd079fdc070f63a6 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt{)=Fn9oYAmGCgz>vU@!4Sd_ z!BD_Z0ThV=Vk?joV*rq7um=(jKm^1vz~R6IG>Hwyh0BsMQ{B(xV%s@4aK)CDw|NksNHVC^FrKUUs z(m=;Eh=9d38CV?{7)nx$OF;f(1!54}5J-d6Z~;}xF=zl;R^U(oGQj45XcQoT!b9PJ f!U5TSkR-?+21X`kkT@q0`&Rnq=M|Tv76I7+ZA?0l literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/50866a2404c2cfbbcaae258011c012d819a842a5 b/tests/fuzzer/flatbuffers_verifier_corpus/50866a2404c2cfbbcaae258011c012d819a842a5 new file mode 100644 index 0000000000000000000000000000000000000000..70f6819bca01e9d5ba202fdad4f68cf86cf51593 GIT binary patch literal 656 zcmZuvyGjF55IwuP5^S_cEeaO8ouK$Y@CJiyVN5`aEi6(P6btc@B4V>CY=wM+VBt6T z10v`jm`<#06dSAcoV$DTKxcDiCTHjF9PUg6pi47Ks&N2J7@83?jx7 zunp8u=d*_xr)Z%=UMFc@jV{@sGyDA597hB#$)JTv3k!l(dmFjVS@BNv_5Bei>XiC}6XrB_~OB4SBejiip literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/50c219f74b02582ea4eaa683f0605b5cd16d6ed6 b/tests/fuzzer/flatbuffers_verifier_corpus/50c219f74b02582ea4eaa683f0605b5cd16d6ed6 new file mode 100644 index 0000000000000000000000000000000000000000..d68d6bb88dd68467ca1c5b20fab8f46c47246bb6 GIT binary patch literal 154 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= i1q>AoF!Hc%S_Lk0kSSPoAB literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/525f958d1709f5e926cba564e23180b60d80fb9a b/tests/fuzzer/flatbuffers_verifier_corpus/525f958d1709f5e926cba564e23180b60d80fb9a new file mode 100644 index 0000000000000000000000000000000000000000..b4a324f4a184e723c03a87cf8bbcdb339001cd18 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22|yUa5W!Hu zP{9xb7PSJAi~&HR!5&CB01*(w0EYt;&?Gh(7fOEt(ocZ+3=lT}aRd-M0I}oA%DW(3 zxTLWUgjIlIjT5Usoo(RHgV7)FrXRoK@zWVbGXvEy0^zRz|NpZ9*&yszl$!DkNHYPk z2vm#}NSCA*mly$QR!s=o5Xc6p;R33XW6%JytiYiFWPr^9(L@3(P&gpl57Gy+lYx_7fCz|TfWv_aXc8NY3#GpR=_f#Z28bJgI0A?rfY|Y5 zx^PYHHwyh0i}ybGT1OUFt`9&9ze{%-~%E85*RWVLKq?# z3K%LF7*50hg{(m0j6f-d274gO0f>MY1~?p;fF`lQxKR2FkbVNhXMnf?h$Dd50f-$> zR^A2S!X=G;AglruJ2TsYpc+OX-1Yzee-{gVT z0;Cw2fLH{GL1L^xT#{N`VuZvt1hPSDxPYqU7&L$^D{v?<0NEftFo4X~U=RQbBa47k jDS*QPBnrYX`$2XxFfuW-0Bzv}GAn)a^NLGSi-1f3wm>AoFB zybHpGOB(w?SOqB7II;TE*#`bR82#~X`tds+Kb>JTGthb<-1Yzee-@x}5Oym{O#xC2 zOh7CG5n??8WS68Gl`s^8{03qdml#6TZ~;}xF=zmJR^U(oGQj45XktJEP!T8`(Cr7= Y!@$VI3=-!AV&6*N{Ji3l)FL1o09x!i-T(jq literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/6a9bcfb376f95d3d235f6e3479ae37b906be2a17 b/tests/fuzzer/flatbuffers_verifier_corpus/6a9bcfb376f95d3d235f6e3479ae37b906be2a17 new file mode 100644 index 0000000000000000000000000000000000000000..9c42a4db117a10f20cb91945dbd7cedbbb709463 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoFrQJD#k( z3&Mp<8v8(41t``yvHH{52L3!4{qb)4@jD(ronbUHPz@sx?)v}#KMRlz!fr*WDL{&W z35Z1?LaaxC?2^>t5+fkZ3S}DtX^o#){Due+%9zUI7G&4{iBg1EgUH||8X92Q7*sUlv z1xPV40kH@WgTz>Ycus0@i4l}t0%RKk*&sDsKvi-K8bFo~I23>kupST%0wDbmfM6*w oD8dB6G$vU@!4Sd_ z!BD_Z!4Lx$wE~fh0YIX`9!NL<5fB4GHi+PGU;>)N24W(CFF^JaAU*@c4L}?L#1260 zc=E?x$CH(JmlQ53Y;5f7Qvr%KPOScPwt+tnMt{7Ue*BKdPiGj-3{=Bt&A`a8>;M1% zEIKQj39v5sY182owXU;bIVBkYmsQvaEoi00B^KKn_R+ kVE_sTkRA|rGXh%=wuga{i5Vou3BAoF<==hFd4wWz}R39WI6y55W@h60~63BHW(L5e*w}@fcOj$Hvn-25IX>|;Ln56AMd6gzvJ=K8AdY$)i46#uK)l4vjEv3>{gVT0;Cw2 zfLH{GL1L^xT#{N`VvNK#1hPSDxPYqUfMLMEU~2NDiI1jI1F;lRYe3N#fJd;xNw0P!6lZUADCi4H*Qc(U>?2p2AC z>;qvHpjhL?>Q84I`14@&$Ghpr?|A%lhSAJGHH<*G>;M1%EI>90yA`FT04WA0AQk~) zkQgfvm!uY#7$LC@fozZ(E}$wo1`Qy~3LFYR23QY>#s(Cy2!g@^$$kcq13-2%FfuWN T#5sZ3x6(I1uec<&2*?HiEHF8= literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/8718d7c1e9a536adb95fb0c749db4554311895e0 b/tests/fuzzer/flatbuffers_verifier_corpus/8718d7c1e9a536adb95fb0c749db4554311895e0 new file mode 100644 index 0000000000000000000000000000000000000000..ea284ed7e257decd953485ec6a42f4f9527f0fdb GIT binary patch literal 383 zcmeZZU|{g|_frN^Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoF8-O?hh#i2~@nq#) z5H4KO*ayNYK(WS&)t}Bb@cT7h1k-sR@1`HWvU@!4Sd_ z!BD_Z!4Lx$wE~fh0YIX`{y76s3xfj?!vKc^6VN0!7#B)^0n$%^_zVy?0C5BmI{>lc z$;!JRT)3pM4}?{KVvQ54Kb>vh&x6q)@1`HW1#lQr_B0vlhV+G=p)Z!8(rXi3GQo;pPB*&luWLbej0muMr0nx+)D@KSOWa~jz YGB7eRgTy$2*tgO*Kd-nXwFu~20QJr~hyVZp literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae b/tests/fuzzer/flatbuffers_verifier_corpus/8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae new file mode 100644 index 0000000000000000000000000000000000000000..63453c1fc6e1cf2ae71e7f1ca50b2ff39114e59a GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`(&!!@$O10_0f$F)M=&g9C#LkmUiyAmGCgz>vU@!4Sd_ z!BD_Z!4Lx$wE~fh0YIX`9!NL<5fH-whXWJPBsLfqN`C>;Pk{Ig5H|pE1Q0s_vE#`f zcO6ew-d$3-q_DBEuTKRi);O{H)7b|8JQ)4)Zu;>%9zUI7G&4{QqcsB~!><4T|FZx& zAnaC@ngXPlfLH{?2Le_gE=es05=Jm~i6Kx7q=t(@gh7r$1IV%hh5`gYwLy9KC%g~K-kR)Y(3Z>21X`kkQgTr`&Rnq=M|Tv76I7+=KDHh literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/903747bd5d4239da836d24087e7e279715cc0980 b/tests/fuzzer/flatbuffers_verifier_corpus/903747bd5d4239da836d24087e7e279715cc0980 new file mode 100644 index 0000000000000000000000000000000000000000..d69ca9575972f008c84502d5702b4cf00fb393f4 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SO0AoFA5Wv`A4`ew25fH-whXWJPBsLfqN`C>;Pk{Ig5H|p^77#lCvE#|g zyC7V+q_Gc#Re)lR6RSU+ZQ##?(I4-oAHU=A(-}rH1Jy7B;jaJx|FZzuAnaC@ngXO4 zfX-qN0a^hP1No;UwYbCxiERjEgVb;VRmm}E09jU`P)Gzaz~+ExVgV=|(Cr7=$-v0O U3=-!AV&6*N{Ji3l)FL1o0N@lk;s5{u literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 b/tests/fuzzer/flatbuffers_verifier_corpus/93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 new file mode 100644 index 0000000000000000000000000000000000000000..47ffbb41bb23fefdda156e609a1d062fb1d90595 GIT binary patch literal 128 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= n1q>AoFr?{fJ#87GcW)EB{&QP literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/9f6095cae432e38efe7464bfac3cacd6df3bbc48 b/tests/fuzzer/flatbuffers_verifier_corpus/9f6095cae432e38efe7464bfac3cacd6df3bbc48 new file mode 100644 index 0000000000000000000000000000000000000000..39405a609898a431d2b85c9d13d8690bf5960089 GIT binary patch literal 578 zcma)2u}%U(6r4MO5E?D4tti9_5(Hb-Gg;y?Hm{D2|R zKY-5IOKhml8IBF1^4{LOnVr1d&5Z}3ad+Dyu}TP#CZ|wjza)|Oie#nVa{zD;LBmfrOBdHoq2 z_bvad9^RMUrfT_!GY;2048sKV3vn~*-G7r^;*^k|B*wkRab7wX=>oN8GMqZYIaP6+ zf?S=^&9+XgIB=CuRLVhT1idd;Zz{e2bFS?sNvOw*xob2WRlJye;Hm;FU=TlN?1Oe( Kh8<C%l0 zo~*nJ!i7s3`<67S^c4cd8YfnNI@`dX2ctjUO+S9e0Pz_d9KaNq@b#C1TEpSM1T>coE(KDHaDyD08z8a} GmjD3k4-g&z literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/bf3d7a99df32ac45e9081eb3519524930c85de89 b/tests/fuzzer/flatbuffers_verifier_corpus/bf3d7a99df32ac45e9081eb3519524930c85de89 new file mode 100644 index 0000000000000000000000000000000000000000..8657dcb0214a3645742750dc0910c4646cefa631 GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9ze{%puph65WtYYkP#9A z~2NDiI1jI1F;lKnmi4Deu(qDk|6CgeV#0@|UGSLBu9Zy!? z1>wRajeQ`j0u*bUSpDg21AiWj{&+Y2_#Ka*&M=x8sD=>;cm4nWp9RPUVYi~x6f+>r z1jHgxF;*a5l3HA12&9qOAT?Y-RdNg(K$aCa6o3q{IUpJa7-0+?G$_6aWAK literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/bf60f275ed989532747e7bbcc93ab2bbd834becc b/tests/fuzzer/flatbuffers_verifier_corpus/bf60f275ed989532747e7bbcc93ab2bbd834becc new file mode 100644 index 0000000000000000000000000000000000000000..e99b11a480cc2abb57fa2dbcd7df3ccd25ff1a84 GIT binary patch literal 122 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Z~d6X?86YikN{+bFhnpE vFjO$a0L4B7bpin+15mC(AINg>Py`8h05Q;X2M3@CkO>0T{!&2OG=dobRWS~S literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/c5170081fc1f8a36ab30541f087cf530ab0845b6 b/tests/fuzzer/flatbuffers_verifier_corpus/c5170081fc1f8a36ab30541f087cf530ab0845b6 new file mode 100644 index 0000000000000000000000000000000000000000..0b0dcaa82eaaa4e546307652bac98b05124f87c3 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoF%l0o~*nJ z!i7s3`#@L)DAqW!`qSA4{yZ4{@oxI@J03rs?|y{P%s@4aK)CDw|NksNHVC^FrKSKW z1|}dD0b-CCD-f5Y7MB>Ju|aCMfU4veG=MBCa3}y7U_BsO4MZRVbz}~L4GITz`$2Xx XFfuWN#5sZ3x6(I1uec<&2*?HivF15> literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 b/tests/fuzzer/flatbuffers_verifier_corpus/c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 new file mode 100644 index 0000000000000000000000000000000000000000..4d8cc5591e93bdbf7fbc563df9b9ae313a77e643 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt{)=Fn9oYAmGCgz>vU@!4Sd_ z!BD_Z0ThV=Vk?joV*rq7um=(jKm^1vz~R6IG>Hwyh0BsMQ{B(xV%s@4aK)CDw|NksNHVC^FrKUUs z(m=;Eh=9d38CV?{7)nx$OF;f(1!54}5J-d6Z~;}xF=zl;R^U(oGQj45Xcz#Qiw}Up e0oi_#T97>qj7-cRaZVuit@O>$D=tYb0AoF%l0o~*nJ z!i7s3`#@L)DAqW!`qSA4{yZ4{@oxI@J03rs?|y{P%s@4aK)CDw|NksNHVC^FrKSKW z1|}dD0b-CCD-f5Y7MBN2kQy$aDmexXAj=9I3P1)}4~S-9P=in~QXR%Xr9t6< bZa>IQ21X`kkT@q0`&Rnq=M|Tv76I7+u@X6W literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 b/tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 new file mode 100644 index 000000000..8e458cce5 --- /dev/null +++ b/tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 @@ -0,0 +1 @@ +š(!!@*YÌø! 'í*!!µ;Fû:'iÊ<:';‚b!ó)*);::!*È''(9à'')(¼ÿ(ô‘('!)!!ê* \ No newline at end of file diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/decff8b2d7524b5fad71129ecf0f4edd9082af2a b/tests/fuzzer/flatbuffers_verifier_corpus/decff8b2d7524b5fad71129ecf0f4edd9082af2a new file mode 100644 index 0000000000000000000000000000000000000000..b2d43130e566d5c15e4cf6896042f398b5df2517 GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYC~X7FJMU`Sxd2#El4 z3m7UGVnE_Roj|}C03;ghfrJAP0Wl14I4}WCVuNv^^cNug1c=W7aRU&8OmqNZ$CH(J zLAY>9V;=~s0L2<7R)0F%z@OJRQ4>smyqkXfj>k`D7|je+!w7`C{{R2a0%U`*TTyBX zkYZp0Vi6z)iLnB4NosM45fa-F$Oft50;-Z@&;YWmz@Y$Sfc1cAOaKZeOaKZ8bo)Ve YGB7eRgTy(3*tgO*Kd-nXwFt-t00d|`V*mgE literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/df0b39717d20371162754b37747a0c989623cb48 b/tests/fuzzer/flatbuffers_verifier_corpus/df0b39717d20371162754b37747a0c989623cb48 new file mode 100644 index 0000000000000000000000000000000000000000..abd11f664558e405bce4a22c3fd9b545fd7c445d GIT binary patch literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoF%l0p8Rpw z@nq%Q!X=G;AglruYn)j9>1+dk9*q8YH~sh>kDtykni;5u(VBsgVb}lv|5<<>5Oym{ zO#xC&Kr8|kVg=GAsl`CT2UQ literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/e72266e5ad67af5c27bcd69961460770e82bd24c b/tests/fuzzer/flatbuffers_verifier_corpus/e72266e5ad67af5c27bcd69961460770e82bd24c new file mode 100644 index 0000000000000000000000000000000000000000..752f2835e72491919f0d1c43f0a0b41855062fb5 GIT binary patch literal 383 zcmeZZU|{go@Cyb~Kw!ntz`y~d*%(Y1;Pk{Ig5H|pE1Q0s_vE#|g zyC7V+q_Gc#Re)lR6RSU+ZQ##?(I4-oAHU=A(-}-NJA3>Ds$m4eUH||8X92QPfY_}l z6+|&G0kH@WgTz^ZxFof>#2ATf2xNoQZ~;}xF=zl;R=`l;V6XXz-AUz<=kW%E93Zy`GGB7eRgTy$2*tgO*Kd-nXwTOWM06)b#=l}o! literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/ee80034f2e35e3f07a708b211be4f1967c83b6e9 b/tests/fuzzer/flatbuffers_verifier_corpus/ee80034f2e35e3f07a708b211be4f1967c83b6e9 new file mode 100644 index 0000000000000000000000000000000000000000..2d56c75decbe5477f6c9f2e509bd5c2a294b86fa GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!nd#=ybQ0A!f}u>}ybGT1OUFt`9&9ze{%-~%E85*RWVLKq?# z3K%LF7*50hg{(m0j6f-d274gO0f>MY1~?p;fF`lQxKR2FkbVNhXMnf?h$Dd50f-$> zR^A2S!X=G;AglruJ2TsYpc+OX-1Yzee-x^PYH^7XlwAX48v@x(K+FYHCC8uvWJv%+fq_92h(UT_0GSQ; oEQ%~hl>#^%K)N2IE5MFF^VU5T60!1|SBR=K#cxCoAuQ zaN&~1J`h#`iZxEG{&cp1Kd%y_;u0eywjq!WQo{vQCC8uvWLbej0muOB0ns1;(vJ#IMWlg}pl|?* ef-uZ}kev*SOw24mTR4HtO5gmv;*!)NAQJ$ZO*usX literal 0 HcmV?d00001 diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/fbe211a4df09673e54945bb8f5afc4c5cfa67778 b/tests/fuzzer/flatbuffers_verifier_corpus/fbe211a4df09673e54945bb8f5afc4c5cfa67778 new file mode 100644 index 0000000000000000000000000000000000000000..ddbd1cea2dc2c3bd64f9186db04f3295580b7afe GIT binary patch literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy+;56DyE(U~mEQJb)Mkd>8^45*RWVLKq?# z3K%LFV!)zSAd)cvNHo|32?rnoVi@3XU}9henu-d(0J%?q_zVy?0C5BmI{>lc$;!JR zT)3pM4}?{KVvQ54Kb>vh&x6q)@1`HW;DVGXvEy0^zRz|NpZ9*&ysz zl$!DkNHYPk2vm#}NSCA*mly$Q7~25I2C3l!s*+>S0J5yWp#Wrn%>mI23|bHhgItFq h0tyFY`$3W*dl(p*m_g#4Kla+Tt zxNu2h9|)@e#TqA8e>&U1pVxR1LVvuQe*BKdPiGj-3{=AiguDL#|IY$sgRomsY6_5I zU;<(hAO?xC0`Z*G;u0e$y9CHK1hPSDxPYqU7&L$^D{v?P8DKpi8U#T4VF08G!dHX| kfoV`UfW$!AoF Date: Fri, 22 Apr 2016 18:29:22 -0700 Subject: [PATCH 16/42] Add simple libfuzzer based test. This tests the verifier and the parser. Tested: on Linux. Bug: 27230459 Change-Id: I3417faba9385dc941199c57a08d8a50c2faec1aa --- tests/fuzzer/build_fuzzer.sh | 20 ++++++++++++++++++ tests/fuzzer/build_run_parser_test.sh | 20 ++++++++++++++++++ tests/fuzzer/build_run_verifier_test.sh | 20 ++++++++++++++++++ tests/fuzzer/flatbuffers_parser_fuzzer.cc | 16 ++++++++++++++ .../01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 | Bin 383 -> 0 bytes .../075a40dd6e6eec9cc96f0399c182f62361cdc553 | Bin 154 -> 0 bytes .../0c319e8089228db0958f35c54614d4e2d917f9d5 | Bin 383 -> 0 bytes .../0d654589709444777a4a854ec16b7160b0b8f06f | Bin 154 -> 0 bytes .../10ace4829162a0d37730ad898ee6ef2b76849ce4 | Bin 383 -> 0 bytes .../12986603181adee83afedc8206f86ead9fd20653 | Bin 383 -> 0 bytes .../14c816a2f528da8004315f8e71aec9e7e9f4df89 | Bin 383 -> 0 bytes .../14d90e4ac5f58f07be524633e96fb8f6521116e2 | Bin 771 -> 0 bytes .../2290776813d50bf54386dc6670aea41c8eb4f73f | Bin 383 -> 0 bytes .../2357f92773faefb0049312fcf7421f2c4ef08dc5 | Bin 383 -> 0 bytes .../235a53ee083b428f4eb80eb5af6a8b41a4036d55 | Bin 384 -> 0 bytes .../243d7b9356afab5800b0fd424a0f90cefeb8f411 | Bin 79 -> 0 bytes .../2e2249e476941c7390d924d8f6c88b5d59d0e300 | Bin 384 -> 0 bytes .../3068bc815c5e573acf89236689705409b253e3c1 | Bin 384 -> 0 bytes .../3470f740d4b2e405c2922ebf68838a03fd690a64 | Bin 153 -> 0 bytes .../489b729a42a6ff5bcc30d341f29fd1660700c0b8 | Bin 384 -> 0 bytes .../50866a2404c2cfbbcaae258011c012d819a842a5 | Bin 656 -> 0 bytes .../50c219f74b02582ea4eaa683f0605b5cd16d6ed6 | Bin 154 -> 0 bytes .../525f958d1709f5e926cba564e23180b60d80fb9a | Bin 384 -> 0 bytes .../543e528d3150cd0d2a45973cf98e992d67f7c406 | Bin 384 -> 0 bytes .../5a2f21b370496184851baffbbbb450fe49aed324 | Bin 383 -> 0 bytes .../5bbf4a7b9da7aee4db6b21ea62128df74aa23b59 | Bin 384 -> 0 bytes .../61005237d5ba26c372b347249143b793c324186a | Bin 383 -> 0 bytes .../6207082d567e33f6569e5ffac1e882b6988f5e86 | Bin 383 -> 0 bytes .../699e2869e8bb9dad4ed0ca23245976e08d6abf96 | Bin 384 -> 0 bytes .../6a9bcfb376f95d3d235f6e3479ae37b906be2a17 | Bin 384 -> 0 bytes .../6b1e41ca991828476b077ebda3f7e9936b549c32 | Bin 383 -> 0 bytes .../6e146549ff6aefcd1314a8b04cd7ee0955796002 | Bin 383 -> 0 bytes .../7c1217cf933de200b58fd2bf494044ebb6d90cde | Bin 384 -> 0 bytes .../7e0fac79b1dfbbdcaeee925535b66c2834d13814 | Bin 384 -> 0 bytes .../8718d7c1e9a536adb95fb0c749db4554311895e0 | Bin 383 -> 0 bytes .../8ae96e1702303027346b59d0a6acbd1ef0b1955f | Bin 384 -> 0 bytes .../8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae | Bin 384 -> 0 bytes .../903747bd5d4239da836d24087e7e279715cc0980 | Bin 384 -> 0 bytes .../93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 | Bin 128 -> 0 bytes .../9f6095cae432e38efe7464bfac3cacd6df3bbc48 | Bin 578 -> 0 bytes .../ae3e1a31be33cc502b6586253274e6b620c78829 | Bin 383 -> 0 bytes .../b75487b8176eda7fb18e4f408208caa82d7c121a | Bin 174 -> 0 bytes .../bf3d7a99df32ac45e9081eb3519524930c85de89 | Bin 383 -> 0 bytes .../bf60f275ed989532747e7bbcc93ab2bbd834becc | Bin 122 -> 0 bytes .../c5170081fc1f8a36ab30541f087cf530ab0845b6 | Bin 384 -> 0 bytes .../c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 | Bin 384 -> 0 bytes .../cd6ac24fd00acc3e9887fdf2ae300481e745f53a | Bin 384 -> 0 bytes .../cd8e4aef993fcdebd9583069cd0a5468d254c5c7 | 1 - .../decff8b2d7524b5fad71129ecf0f4edd9082af2a | Bin 384 -> 0 bytes .../df0b39717d20371162754b37747a0c989623cb48 | Bin 384 -> 0 bytes .../e423e0b67927e2c303dbb7ead3fd68706b92d657 | Bin 153 -> 0 bytes .../e72266e5ad67af5c27bcd69961460770e82bd24c | Bin 383 -> 0 bytes .../ee80034f2e35e3f07a708b211be4f1967c83b6e9 | Bin 383 -> 0 bytes .../f5fd02697cac00a81809909a971f80f28aa4c020 | Bin 383 -> 0 bytes .../fbe211a4df09673e54945bb8f5afc4c5cfa67778 | Bin 383 -> 0 bytes .../fc5d4b9117ba9e87388174aee4f4970bdfe8d066 | 1 - .../fd11c36a6b2cbceeac9664690b5d35f0f9bb6f01 | Bin 383 -> 0 bytes .../ff085b6090cadabfabb6f5e785681353fb89eb87 | Bin 384 -> 0 bytes .../fuzz-0-flatbuffers_verifier_fuzzer | Bin 411 -> 0 bytes tests/fuzzer/flatbuffers_verifier_fuzzer.cc | 2 +- 60 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 tests/fuzzer/build_fuzzer.sh create mode 100644 tests/fuzzer/build_run_parser_test.sh create mode 100644 tests/fuzzer/build_run_verifier_test.sh create mode 100644 tests/fuzzer/flatbuffers_parser_fuzzer.cc delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/075a40dd6e6eec9cc96f0399c182f62361cdc553 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/0c319e8089228db0958f35c54614d4e2d917f9d5 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/0d654589709444777a4a854ec16b7160b0b8f06f delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/10ace4829162a0d37730ad898ee6ef2b76849ce4 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/12986603181adee83afedc8206f86ead9fd20653 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/14c816a2f528da8004315f8e71aec9e7e9f4df89 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/14d90e4ac5f58f07be524633e96fb8f6521116e2 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/2290776813d50bf54386dc6670aea41c8eb4f73f delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/2357f92773faefb0049312fcf7421f2c4ef08dc5 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/235a53ee083b428f4eb80eb5af6a8b41a4036d55 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/243d7b9356afab5800b0fd424a0f90cefeb8f411 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/2e2249e476941c7390d924d8f6c88b5d59d0e300 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/3068bc815c5e573acf89236689705409b253e3c1 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/3470f740d4b2e405c2922ebf68838a03fd690a64 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/489b729a42a6ff5bcc30d341f29fd1660700c0b8 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/50866a2404c2cfbbcaae258011c012d819a842a5 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/50c219f74b02582ea4eaa683f0605b5cd16d6ed6 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/525f958d1709f5e926cba564e23180b60d80fb9a delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/543e528d3150cd0d2a45973cf98e992d67f7c406 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/5a2f21b370496184851baffbbbb450fe49aed324 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/5bbf4a7b9da7aee4db6b21ea62128df74aa23b59 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/61005237d5ba26c372b347249143b793c324186a delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6207082d567e33f6569e5ffac1e882b6988f5e86 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/699e2869e8bb9dad4ed0ca23245976e08d6abf96 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6a9bcfb376f95d3d235f6e3479ae37b906be2a17 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6b1e41ca991828476b077ebda3f7e9936b549c32 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/6e146549ff6aefcd1314a8b04cd7ee0955796002 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/7c1217cf933de200b58fd2bf494044ebb6d90cde delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/7e0fac79b1dfbbdcaeee925535b66c2834d13814 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/8718d7c1e9a536adb95fb0c749db4554311895e0 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/8ae96e1702303027346b59d0a6acbd1ef0b1955f delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/903747bd5d4239da836d24087e7e279715cc0980 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/9f6095cae432e38efe7464bfac3cacd6df3bbc48 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/ae3e1a31be33cc502b6586253274e6b620c78829 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/b75487b8176eda7fb18e4f408208caa82d7c121a delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/bf3d7a99df32ac45e9081eb3519524930c85de89 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/bf60f275ed989532747e7bbcc93ab2bbd834becc delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/c5170081fc1f8a36ab30541f087cf530ab0845b6 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/cd6ac24fd00acc3e9887fdf2ae300481e745f53a delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/decff8b2d7524b5fad71129ecf0f4edd9082af2a delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/df0b39717d20371162754b37747a0c989623cb48 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/e423e0b67927e2c303dbb7ead3fd68706b92d657 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/e72266e5ad67af5c27bcd69961460770e82bd24c delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/ee80034f2e35e3f07a708b211be4f1967c83b6e9 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/f5fd02697cac00a81809909a971f80f28aa4c020 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fbe211a4df09673e54945bb8f5afc4c5cfa67778 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fc5d4b9117ba9e87388174aee4f4970bdfe8d066 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fd11c36a6b2cbceeac9664690b5d35f0f9bb6f01 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/ff085b6090cadabfabb6f5e785681353fb89eb87 delete mode 100644 tests/fuzzer/flatbuffers_verifier_corpus/fuzz-0-flatbuffers_verifier_fuzzer diff --git a/tests/fuzzer/build_fuzzer.sh b/tests/fuzzer/build_fuzzer.sh new file mode 100644 index 000000000..48eb3b7c9 --- /dev/null +++ b/tests/fuzzer/build_fuzzer.sh @@ -0,0 +1,20 @@ +#!/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. + +git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer +clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer +ar ruv libFuzzer.a Fuzzer*.o +rm -rf Fuzzer *.o diff --git a/tests/fuzzer/build_run_parser_test.sh b/tests/fuzzer/build_run_parser_test.sh new file mode 100644 index 000000000..3a053e762 --- /dev/null +++ b/tests/fuzzer/build_run_parser_test.sh @@ -0,0 +1,20 @@ +#!/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. + +clang++ -fsanitize-coverage=edge -fsanitize=address -std=c++11 -stdlib=libstdc++ -I.. -I../../include flatbuffers_parser_fuzzer.cc ../../src/idl_parser.cpp ../../src/util.cpp libFuzzer.a -o fuzz_parser +mkdir -p parser_corpus +cp ../*.json ../*.fbs parser_corpus +./fuzz_parser parser_corpus diff --git a/tests/fuzzer/build_run_verifier_test.sh b/tests/fuzzer/build_run_verifier_test.sh new file mode 100644 index 000000000..67616496a --- /dev/null +++ b/tests/fuzzer/build_run_verifier_test.sh @@ -0,0 +1,20 @@ +#!/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. + +clang++ -fsanitize-coverage=edge -fsanitize=address -std=c++11 -stdlib=libstdc++ -I.. -I../../include flatbuffers_verifier_fuzzer.cc libFuzzer.a -o fuzz_verifier +mkdir -p verifier_corpus +cp ../*.mon verifier_corpus +./fuzz_verifier verifier_corpus diff --git a/tests/fuzzer/flatbuffers_parser_fuzzer.cc b/tests/fuzzer/flatbuffers_parser_fuzzer.cc new file mode 100644 index 000000000..632b3b18d --- /dev/null +++ b/tests/fuzzer/flatbuffers_parser_fuzzer.cc @@ -0,0 +1,16 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include +#include + +#include "flatbuffers/idl.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + flatbuffers::Parser parser; + // Guarantee 0-termination. + std::string s(reinterpret_cast(data), size); + parser.Parse(s.c_str()); + return 0; +} diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 b/tests/fuzzer/flatbuffers_verifier_corpus/01a40c02ea9c030b9fcf8aaf51fe1b6681e00490 deleted file mode 100644 index e36b1ce5c29d0393b164383915462bc0a15075ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Z~d;Pk{Ig5H|pE1Q0s_vE#|g zyC7V+q_Gc#RTvr>7$#PKI@`dX*LV>^f4rN1{Eo*@XBf>4)W-;fyZ-;RG@(ee?5*OHzw~OaSp4Ik^A; diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/075a40dd6e6eec9cc96f0399c182f62361cdc553 b/tests/fuzzer/flatbuffers_verifier_corpus/075a40dd6e6eec9cc96f0399c182f62361cdc553 deleted file mode 100644 index 063942bfe400275e933b2ce096f248bbcf41eebb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154 zcmeZZU|{g|_X`G6Kw!ntz`()4u!F$_$gu!oRt6ge2L=})%L9l(z=t7#A%P)7ogsuF vf}wz+f*}ShYy~121As(>J&t18V8b=A8xE9aV8{Rf@81tj diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/0c319e8089228db0958f35c54614d4e2d917f9d5 b/tests/fuzzer/flatbuffers_verifier_corpus/0c319e8089228db0958f35c54614d4e2d917f9d5 deleted file mode 100644 index a505619059d3c4d522c0f976bda36bab5b9e4ae7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoFYxFof>#1M@QQey>FCC8uvW^vR3DIfspfdEY)TL8v^(g;}wpqw;N j6ci31Q4ogN53-Yik%^fF=n_sKv(h&|uec<&2*?BgA>le= diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/0d654589709444777a4a854ec16b7160b0b8f06f b/tests/fuzzer/flatbuffers_verifier_corpus/0d654589709444777a4a854ec16b7160b0b8f06f deleted file mode 100644 index 437134b35b22650767965a2d7ec0d55177e09265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154 zcmeZZU|{g|_X`G6Kw!ntz`y}wm;kW_5VJDaFgP%{09hVD3<5q30SpNY8R`rn3=s?k o3>6G9U|}l|$ru168tj3D0}wfYv|yUe#$W^#$7eWDnt>q$0E@p4ZU6uP diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/10ace4829162a0d37730ad898ee6ef2b76849ce4 b/tests/fuzzer/flatbuffers_verifier_corpus/10ace4829162a0d37730ad898ee6ef2b76849ce4 deleted file mode 100644 index 7c9321c577166660235baa100beaa3097ad403be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAwYIS z0Ye1?Lky5*1(IT90LnGk16dA01jI1F;lKnmi4Deu(qDk|6CgeV#0@|k0mKeK?0B;B zE(jMcY3u`G6`)UWCve@1`HWDVqowAVupYOh75)f zh6siNh6*4z28gXd;*3Bkh6Z~e%K?ah7zQ{Tn1Cj+!MITR3y^*S#AkrG0f-}j*a3(g zPgdRq;ld@2eITp?6gxPv`qSA4{=CME5c=cY^y7CtemcWwW}q5IAl&u;|9=)B8-(48 zQd58w0}~L705M366^Khxi%SgA*dR4rKvi-K8bFp6I23>kupSUCfW!uw0|5vYgs%V& h2aqTT!|Vsy$-v0O%mQ=?Cy-g`o1a%)l3E000svxiIs*Uz diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/14c816a2f528da8004315f8e71aec9e7e9f4df89 b/tests/fuzzer/flatbuffers_verifier_corpus/14c816a2f528da8004315f8e71aec9e7e9f4df89 deleted file mode 100644 index 321ff5675d1e4fc7e778edbe7aee76c8a2904043..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Y1;Pk{Ig5H|pE1Q0s_vE#|g zyC7V+q_Gc#Re)lR6RSU+ZQ##?(I4-oAHU=A(-}-NJA3>Ds$m4eUH||8X92Q7*sUlv z1xPV40kH@WgTz>YxFof>#2ATf2xNoQZ~;}xF=zl;R^U*uW>5#~0f}G(kU;Z=N(q2z eP&lC553-Yik%<{3&I!c6mA?6T#U-gl3=9BApgPU~ diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/14d90e4ac5f58f07be524633e96fb8f6521116e2 b/tests/fuzzer/flatbuffers_verifier_corpus/14d90e4ac5f58f07be524633e96fb8f6521116e2 deleted file mode 100644 index 807a5b29079e5c6addcf62855be149edb7681cb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 771 zcmZ`%Jxc>Y5Pf%=aM);(P7npbkH!xKqX=#=$Q6kRXpzDqg+Z|pV^SDwE`_a-pCI@v z`~woue_%Ql1sgvatMkq5T{MKu@^)rtc6T0c*9VXFwX``o>zop>c^CBrGxZgd)%YP)mOys8q@%r#pVpAW(4 zN$fv5hj)+u&sOY*xX0nR4Z~3Gz9hEKDhDt0E|DT6pCIbbwfeHebBrss`jXv(5hsNS z%(AkoDo|us59w>`^o#4xB-YGfYwRajeQ`j!qCXTFtPg6*#`c+#)}a8jS|IY$sgRoms zY6_5IU;<(hAO?xC0`Z*G;u0e$y9CHK1hPSDxPYqU7&L$^9dIZB8DKpi8U#T4AppTr pU{Hh!f@x4VfMh|~1!_OYP6kFMW)`3=oIqx!Z+>2JNoo<02>{z}I@bUI diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/2357f92773faefb0049312fcf7421f2c4ef08dc5 b/tests/fuzzer/flatbuffers_verifier_corpus/2357f92773faefb0049312fcf7421f2c4ef08dc5 deleted file mode 100644 index 762bb8c5aab88c57d5fb6cdd4582c7fd719acbe3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Z~d z-UZ>pC5?R`tO68koLK$oYy*E@<3$Ml@oxI@J03rsVKg&P4I>a9`2YVu3y=-MZbhjn zK#GA0h(&-HB*qHFb5e^-jG*iiAlneg2C3l!s*+>S0D46L911`oupR~mEf5pR1~ZZP jiU~2NDiI1jI1F;lRYe3N#fJd;xNw0Pz_hZUADCi4H*Qc(U>?2p2AC z>;qvHpjhL?>Q84I`14@&$Ghpr?|A%lhSAJGHH<*G>;M1%EI>90yA`FT04WA0AQk~) zkQgfvm!uY#7$LC@fozZ(E}$wo1`Qy~3K$9?5r`fz0}G*mMGO=U==Ou`WME`s28nY5 Qv2UeseqM1&Y7vkP03Dz?rT_o{ diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/243d7b9356afab5800b0fd424a0f90cefeb8f411 b/tests/fuzzer/flatbuffers_verifier_corpus/243d7b9356afab5800b0fd424a0f90cefeb8f411 deleted file mode 100644 index 6c6d7cc4e3b4070f11901efce9120d2e6838d13f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 79 zcmeZZU|{g|_X`G6Kw!ntz`y~d**t&*iZD==4Jc*;#1=rT$Y28`wHO>2Kq`Tvjto9P G1_J;!>;~5W diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/2e2249e476941c7390d924d8f6c88b5d59d0e300 b/tests/fuzzer/flatbuffers_verifier_corpus/2e2249e476941c7390d924d8f6c88b5d59d0e300 deleted file mode 100644 index ffc21832c8814390e59fbaf6f5c45f1d94cf07f7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT10MFt`9&9zYBNJ`4d22|yUa5W!Hu zP{9xb7PSJAi~&HR!5&CB01*(w0EYt;&?Gh(7fOEt(ocZ+3=lT}aRd-M0I}oA%DW(3 zxTLWUgjIlIjT5Usoo(RHgV7)FrXRoK@zWVbGXvEy0^zRz|NpZ9*&yszl$!DkNHYPk z2vm#}NSCA*mly$QR!s=o5Xc6p;R33XW6%JytQaJKBnW`aAq9ZK0oi_#UXYy(j7-cR SaZVuit@O>$D=tYb0AoF%l0p8Rpw z@nq%Q!X=G;AglruYn)j9>1+dk9*q8YH~sh>kDtykni;5u(VBsgVb}lv|5<<>5Oym{ zO#xC&Kr8|kVg=GAsl`CT22JNoo<04FIR>I}QK< diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/3470f740d4b2e405c2922ebf68838a03fd690a64 b/tests/fuzzer/flatbuffers_verifier_corpus/3470f740d4b2e405c2922ebf68838a03fd690a64 deleted file mode 100644 index a0f773fda45ae984b0116fcd9133a9158aba3a78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 153 zcmeZZU|{g|_X`G6Kw!ntz`y}wm;kW_5VJDaFgP%{09hVD3<5q30SpNY84Mu|5ex+k q6$~+8Q7aJ17yu+1?16*>5IKN!U>eQFU<4G$Wwry*Y#?x8$N&I$%no+| diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/489b729a42a6ff5bcc30d341f29fd1660700c0b8 b/tests/fuzzer/flatbuffers_verifier_corpus/489b729a42a6ff5bcc30d341f29fd1660700c0b8 deleted file mode 100644 index 62afb03c11744761a8c0e6afdd079fdc070f63a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt{)=Fn9oYAmGCgz>vU@!4Sd_ z!BD_Z0ThV=Vk?joV*rq7um=(jKm^1vz~R6IG>Hwyh0BsMQ{B(xV%s@4aK)CDw|NksNHVC^FrKUUs z(m=;Eh=9d38CV?{7)nx$OF;f(1!54}5J-d6Z~;}xF=zl;R^U(oGQj45XcQoT!b9PJ f!U5TSkR-?+21X`kkT@q0`&Rnq=M|Tv76I7+ZA?0l diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/50866a2404c2cfbbcaae258011c012d819a842a5 b/tests/fuzzer/flatbuffers_verifier_corpus/50866a2404c2cfbbcaae258011c012d819a842a5 deleted file mode 100644 index 70f6819bca01e9d5ba202fdad4f68cf86cf51593..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 656 zcmZuvyGjF55IwuP5^S_cEeaO8ouK$Y@CJiyVN5`aEi6(P6btc@B4V>CY=wM+VBt6T z10v`jm`<#06dSAcoV$DTKxcDiCTHjF9PUg6pi47Ks&N2J7@83?jx7 zunp8u=d*_xr)Z%=UMFc@jV{@sGyDA597hB#$)JTv3k!l(dmFjVS@BNv_5Bei>XiC}6XrB_~OB4SBejiip diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/50c219f74b02582ea4eaa683f0605b5cd16d6ed6 b/tests/fuzzer/flatbuffers_verifier_corpus/50c219f74b02582ea4eaa683f0605b5cd16d6ed6 deleted file mode 100644 index d68d6bb88dd68467ca1c5b20fab8f46c47246bb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 154 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= i1q>AoF!Hc%S_Lk0kSSPoAB diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/525f958d1709f5e926cba564e23180b60d80fb9a b/tests/fuzzer/flatbuffers_verifier_corpus/525f958d1709f5e926cba564e23180b60d80fb9a deleted file mode 100644 index b4a324f4a184e723c03a87cf8bbcdb339001cd18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22|yUa5W!Hu zP{9xb7PSJAi~&HR!5&CB01*(w0EYt;&?Gh(7fOEt(ocZ+3=lT}aRd-M0I}oA%DW(3 zxTLWUgjIlIjT5Usoo(RHgV7)FrXRoK@zWVbGXvEy0^zRz|NpZ9*&yszl$!DkNHYPk z2vm#}NSCA*mly$QR!s=o5Xc6p;R33XW6%JytiYiFWPr^9(L@3(P&gpl57Gy+lYx_7fCz|TfWv_aXc8NY3#GpR=_f#Z28bJgI0A?rfY|Y5 zx^PYHHwyh0i}ybGT1OUFt`9&9ze{%-~%E85*RWVLKq?# z3K%LF7*50hg{(m0j6f-d274gO0f>MY1~?p;fF`lQxKR2FkbVNhXMnf?h$Dd50f-$> zR^A2S!X=G;AglruJ2TsYpc+OX-1Yzee-{gVT z0;Cw2fLH{GL1L^xT#{N`VuZvt1hPSDxPYqU7&L$^D{v?<0NEftFo4X~U=RQbBa47k jDS*QPBnrYX`$2XxFfuW-0Bzv}GAn)a^NLGSi-1f3wm>AoFB zybHpGOB(w?SOqB7II;TE*#`bR82#~X`tds+Kb>JTGthb<-1Yzee-@x}5Oym{O#xC2 zOh7CG5n??8WS68Gl`s^8{03qdml#6TZ~;}xF=zmJR^U(oGQj45XktJEP!T8`(Cr7= Y!@$VI3=-!AV&6*N{Ji3l)FL1o09x!i-T(jq diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/6a9bcfb376f95d3d235f6e3479ae37b906be2a17 b/tests/fuzzer/flatbuffers_verifier_corpus/6a9bcfb376f95d3d235f6e3479ae37b906be2a17 deleted file mode 100644 index 9c42a4db117a10f20cb91945dbd7cedbbb709463..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoFrQJD#k( z3&Mp<8v8(41t``yvHH{52L3!4{qb)4@jD(ronbUHPz@sx?)v}#KMRlz!fr*WDL{&W z35Z1?LaaxC?2^>t5+fkZ3S}DtX^o#){Due+%9zUI7G&4{iBg1EgUH||8X92Q7*sUlv z1xPV40kH@WgTz>Ycus0@i4l}t0%RKk*&sDsKvi-K8bFo~I23>kupST%0wDbmfM6*w oD8dB6G$vU@!4Sd_ z!BD_Z!4Lx$wE~fh0YIX`9!NL<5fB4GHi+PGU;>)N24W(CFF^JaAU*@c4L}?L#1260 zc=E?x$CH(JmlQ53Y;5f7Qvr%KPOScPwt+tnMt{7Ue*BKdPiGj-3{=Bt&A`a8>;M1% zEIKQj39v5sY182owXU;bIVBkYmsQvaEoi00B^KKn_R+ kVE_sTkRA|rGXh%=wuga{i5Vou3BAoF<==hFd4wWz}R39WI6y55W@h60~63BHW(L5e*w}@fcOj$Hvn-25IX>|;Ln56AMd6gzvJ=K8AdY$)i46#uK)l4vjEv3>{gVT0;Cw2 zfLH{GL1L^xT#{N`VvNK#1hPSDxPYqUfMLMEU~2NDiI1jI1F;lRYe3N#fJd;xNw0P!6lZUADCi4H*Qc(U>?2p2AC z>;qvHpjhL?>Q84I`14@&$Ghpr?|A%lhSAJGHH<*G>;M1%EI>90yA`FT04WA0AQk~) zkQgfvm!uY#7$LC@fozZ(E}$wo1`Qy~3LFYR23QY>#s(Cy2!g@^$$kcq13-2%FfuWN T#5sZ3x6(I1uec<&2*?HiEHF8= diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/8718d7c1e9a536adb95fb0c749db4554311895e0 b/tests/fuzzer/flatbuffers_verifier_corpus/8718d7c1e9a536adb95fb0c749db4554311895e0 deleted file mode 100644 index ea284ed7e257decd953485ec6a42f4f9527f0fdb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_frN^Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoF8-O?hh#i2~@nq#) z5H4KO*ayNYK(WS&)t}Bb@cT7h1k-sR@1`HWvU@!4Sd_ z!BD_Z!4Lx$wE~fh0YIX`{y76s3xfj?!vKc^6VN0!7#B)^0n$%^_zVy?0C5BmI{>lc z$;!JRT)3pM4}?{KVvQ54Kb>vh&x6q)@1`HW1#lQr_B0vlhV+G=p)Z!8(rXi3GQo;pPB*&luWLbej0muMr0nx+)D@KSOWa~jz YGB7eRgTy$2*tgO*Kd-nXwFu~20QJr~hyVZp diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae b/tests/fuzzer/flatbuffers_verifier_corpus/8ed7b897a2c4f2f262a5319910a5bd1db4b6dcae deleted file mode 100644 index 63453c1fc6e1cf2ae71e7f1ca50b2ff39114e59a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`(&!!@$O10_0f$F)M=&g9C#LkmUiyAmGCgz>vU@!4Sd_ z!BD_Z!4Lx$wE~fh0YIX`9!NL<5fH-whXWJPBsLfqN`C>;Pk{Ig5H|pE1Q0s_vE#`f zcO6ew-d$3-q_DBEuTKRi);O{H)7b|8JQ)4)Zu;>%9zUI7G&4{QqcsB~!><4T|FZx& zAnaC@ngXPlfLH{?2Le_gE=es05=Jm~i6Kx7q=t(@gh7r$1IV%hh5`gYwLy9KC%g~K-kR)Y(3Z>21X`kkQgTr`&Rnq=M|Tv76I7+=KDHh diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/903747bd5d4239da836d24087e7e279715cc0980 b/tests/fuzzer/flatbuffers_verifier_corpus/903747bd5d4239da836d24087e7e279715cc0980 deleted file mode 100644 index d69ca9575972f008c84502d5702b4cf00fb393f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SO0AoFA5Wv`A4`ew25fH-whXWJPBsLfqN`C>;Pk{Ig5H|p^77#lCvE#|g zyC7V+q_Gc#Re)lR6RSU+ZQ##?(I4-oAHU=A(-}rH1Jy7B;jaJx|FZzuAnaC@ngXO4 zfX-qN0a^hP1No;UwYbCxiERjEgVb;VRmm}E09jU`P)Gzaz~+ExVgV=|(Cr7=$-v0O U3=-!AV&6*N{Ji3l)FL1o0N@lk;s5{u diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 b/tests/fuzzer/flatbuffers_verifier_corpus/93a0adc29bf3cb1c7ed1b5a12778c1eba06972d7 deleted file mode 100644 index 47ffbb41bb23fefdda156e609a1d062fb1d90595..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= n1q>AoFr?{fJ#87GcW)EB{&QP diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/9f6095cae432e38efe7464bfac3cacd6df3bbc48 b/tests/fuzzer/flatbuffers_verifier_corpus/9f6095cae432e38efe7464bfac3cacd6df3bbc48 deleted file mode 100644 index 39405a609898a431d2b85c9d13d8690bf5960089..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 578 zcma)2u}%U(6r4MO5E?D4tti9_5(Hb-Gg;y?Hm{D2|R zKY-5IOKhml8IBF1^4{LOnVr1d&5Z}3ad+Dyu}TP#CZ|wjza)|Oie#nVa{zD;LBmfrOBdHoq2 z_bvad9^RMUrfT_!GY;2048sKV3vn~*-G7r^;*^k|B*wkRab7wX=>oN8GMqZYIaP6+ zf?S=^&9+XgIB=CuRLVhT1idd;Zz{e2bFS?sNvOw*xob2WRlJye;Hm;FU=TlN?1Oe( Kh8<C%l0 zo~*nJ!i7s3`<67S^c4cd8YfnNI@`dX2ctjUO+S9e0Pz_d9KaNq@b#C1TEpSM1T>coE(KDHaDyD08z8a} GmjD3k4-g&z diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/bf3d7a99df32ac45e9081eb3519524930c85de89 b/tests/fuzzer/flatbuffers_verifier_corpus/bf3d7a99df32ac45e9081eb3519524930c85de89 deleted file mode 100644 index 8657dcb0214a3645742750dc0910c4646cefa631..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9ze{%puph65WtYYkP#9A z~2NDiI1jI1F;lKnmi4Deu(qDk|6CgeV#0@|UGSLBu9Zy!? z1>wRajeQ`j0u*bUSpDg21AiWj{&+Y2_#Ka*&M=x8sD=>;cm4nWp9RPUVYi~x6f+>r z1jHgxF;*a5l3HA12&9qOAT?Y-RdNg(K$aCa6o3q{IUpJa7-0+?G$_6aWAK diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/bf60f275ed989532747e7bbcc93ab2bbd834becc b/tests/fuzzer/flatbuffers_verifier_corpus/bf60f275ed989532747e7bbcc93ab2bbd834becc deleted file mode 100644 index e99b11a480cc2abb57fa2dbcd7df3ccd25ff1a84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 122 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(Z~d6X?86YikN{+bFhnpE vFjO$a0L4B7bpin+15mC(AINg>Py`8h05Q;X2M3@CkO>0T{!&2OG=dobRWS~S diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/c5170081fc1f8a36ab30541f087cf530ab0845b6 b/tests/fuzzer/flatbuffers_verifier_corpus/c5170081fc1f8a36ab30541f087cf530ab0845b6 deleted file mode 100644 index 0b0dcaa82eaaa4e546307652bac98b05124f87c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoF%l0o~*nJ z!i7s3`#@L)DAqW!`qSA4{yZ4{@oxI@J03rs?|y{P%s@4aK)CDw|NksNHVC^FrKSKW z1|}dD0b-CCD-f5Y7MB>Ju|aCMfU4veG=MBCa3}y7U_BsO4MZRVbz}~L4GITz`$2Xx XFfuWN#5sZ3x6(I1uec<&2*?HivF15> diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 b/tests/fuzzer/flatbuffers_verifier_corpus/c51a7d5885bdaa3bae2b125fe13b12e2fba4f9b6 deleted file mode 100644 index 4d8cc5591e93bdbf7fbc563df9b9ae313a77e643..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt{)=Fn9oYAmGCgz>vU@!4Sd_ z!BD_Z0ThV=Vk?joV*rq7um=(jKm^1vz~R6IG>Hwyh0BsMQ{B(xV%s@4aK)CDw|NksNHVC^FrKUUs z(m=;Eh=9d38CV?{7)nx$OF;f(1!54}5J-d6Z~;}xF=zl;R^U(oGQj45Xcz#Qiw}Up e0oi_#T97>qj7-cRaZVuit@O>$D=tYb0AoF%l0o~*nJ z!i7s3`#@L)DAqW!`qSA4{yZ4{@oxI@J03rs?|y{P%s@4aK)CDw|NksNHVC^FrKSKW z1|}dD0b-CCD-f5Y7MBN2kQy$aDmexXAj=9I3P1)}4~S-9P=in~QXR%Xr9t6< bZa>IQ21X`kkT@q0`&Rnq=M|Tv76I7+u@X6W diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 b/tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 deleted file mode 100644 index 8e458cce5..000000000 --- a/tests/fuzzer/flatbuffers_verifier_corpus/cd8e4aef993fcdebd9583069cd0a5468d254c5c7 +++ /dev/null @@ -1 +0,0 @@ -š(!!@*YÌø! 'í*!!µ;Fû:'iÊ<:';‚b!ó)*);::!*È''(9à'')(¼ÿ(ô‘('!)!!ê* \ No newline at end of file diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/decff8b2d7524b5fad71129ecf0f4edd9082af2a b/tests/fuzzer/flatbuffers_verifier_corpus/decff8b2d7524b5fad71129ecf0f4edd9082af2a deleted file mode 100644 index b2d43130e566d5c15e4cf6896042f398b5df2517..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYC~X7FJMU`Sxd2#El4 z3m7UGVnE_Roj|}C03;ghfrJAP0Wl14I4}WCVuNv^^cNug1c=W7aRU&8OmqNZ$CH(J zLAY>9V;=~s0L2<7R)0F%z@OJRQ4>smyqkXfj>k`D7|je+!w7`C{{R2a0%U`*TTyBX zkYZp0Vi6z)iLnB4NosM45fa-F$Oft50;-Z@&;YWmz@Y$Sfc1cAOaKZeOaKZ8bo)Ve YGB7eRgTy(3*tgO*Kd-nXwFt-t00d|`V*mgE diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/df0b39717d20371162754b37747a0c989623cb48 b/tests/fuzzer/flatbuffers_verifier_corpus/df0b39717d20371162754b37747a0c989623cb48 deleted file mode 100644 index abd11f664558e405bce4a22c3fd9b545fd7c445d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy-SOGT1OUFt`9&9zYBNJ`4d22@DwwAq)`= z1q>AoF%l0p8Rpw z@nq%Q!X=G;AglruYn)j9>1+dk9*q8YH~sh>kDtykni;5u(VBsgVb}lv|5<<>5Oym{ zO#xC&Kr8|kVg=GAsl`CT2UQ diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/e72266e5ad67af5c27bcd69961460770e82bd24c b/tests/fuzzer/flatbuffers_verifier_corpus/e72266e5ad67af5c27bcd69961460770e82bd24c deleted file mode 100644 index 752f2835e72491919f0d1c43f0a0b41855062fb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{go@Cyb~Kw!ntz`y~d*%(Y1;Pk{Ig5H|pE1Q0s_vE#|g zyC7V+q_Gc#Re)lR6RSU+ZQ##?(I4-oAHU=A(-}-NJA3>Ds$m4eUH||8X92QPfY_}l z6+|&G0kH@WgTz^ZxFof>#2ATf2xNoQZ~;}xF=zl;R=`l;V6XXz-AUz<=kW%E93Zy`GGB7eRgTy$2*tgO*Kd-nXwTOWM06)b#=l}o! diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/ee80034f2e35e3f07a708b211be4f1967c83b6e9 b/tests/fuzzer/flatbuffers_verifier_corpus/ee80034f2e35e3f07a708b211be4f1967c83b6e9 deleted file mode 100644 index 2d56c75decbe5477f6c9f2e509bd5c2a294b86fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!nd#=ybQ0A!f}u>}ybGT1OUFt`9&9ze{%-~%E85*RWVLKq?# z3K%LF7*50hg{(m0j6f-d274gO0f>MY1~?p;fF`lQxKR2FkbVNhXMnf?h$Dd50f-$> zR^A2S!X=G;AglruJ2TsYpc+OX-1Yzee-x^PYH^7XlwAX48v@x(K+FYHCC8uvWJv%+fq_92h(UT_0GSQ; oEQ%~hl>#^%K)N2IE5MFF^VU5T60!1|SBR=K#cxCoAuQ zaN&~1J`h#`iZxEG{&cp1Kd%y_;u0eywjq!WQo{vQCC8uvWLbej0muOB0ns1;(vJ#IMWlg}pl|?* ef-uZ}kev*SOw24mTR4HtO5gmv;*!)NAQJ$ZO*usX diff --git a/tests/fuzzer/flatbuffers_verifier_corpus/fbe211a4df09673e54945bb8f5afc4c5cfa67778 b/tests/fuzzer/flatbuffers_verifier_corpus/fbe211a4df09673e54945bb8f5afc4c5cfa67778 deleted file mode 100644 index ddbd1cea2dc2c3bd64f9186db04f3295580b7afe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 383 zcmeZZU|{g|_X`G6Kw!ntz`y~d*%(ZKqy+;56DyE(U~mEQJb)Mkd>8^45*RWVLKq?# z3K%LFV!)zSAd)cvNHo|32?rnoVi@3XU}9henu-d(0J%?q_zVy?0C5BmI{>lc$;!JR zT)3pM4}?{KVvQ54Kb>vh&x6q)@1`HW;DVGXvEy0^zRz|NpZ9*&ysz zl$!DkNHYPk2vm#}NSCA*mly$Q7~25I2C3l!s*+>S0J5yWp#Wrn%>mI23|bHhgItFq h0tyFY`$3W*dl(p*m_g#4Kla+Tt zxNu2h9|)@e#TqA8e>&U1pVxR1LVvuQe*BKdPiGj-3{=AiguDL#|IY$sgRomsY6_5I zU;<(hAO?xC0`Z*G;u0e$y9CHK1hPSDxPYqU7&L$^D{v?P8DKpi8U#T4VF08G!dHX| kfoV`UfW$!AoFI4Et2B2(%J&@%9L_iD!91cuClh|NfDE$RUKLO%1K->Vt5kTw!#EvH` z?}BjQlEyv|Rso6~oLK$oYy*E@<3$Ml@oxI@J03rsAvDNsxO@Tf2gnyLU|-k(Rb~J& z$R7w_RDgZ)8QB;5Kt&D^KO_6Z*Ix=6Sjc|*>C6mN&d9)Mwd?=?|13Z@2)h-frT{4h fCLk68Vvras5SOGDmly(RNSGqrt-$~ZeW)q`2B|>A diff --git a/tests/fuzzer/flatbuffers_verifier_fuzzer.cc b/tests/fuzzer/flatbuffers_verifier_fuzzer.cc index d2fa73ad7..d7d453c82 100644 --- a/tests/fuzzer/flatbuffers_verifier_fuzzer.cc +++ b/tests/fuzzer/flatbuffers_verifier_fuzzer.cc @@ -5,7 +5,7 @@ #include #include -#include "third_party/flatbuffers/tests/monster_test_generated.h" +#include "monster_test_generated.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { flatbuffers::Verifier verifier(data, size); From a9194c4c686ace7455b1ae5b146544d788feaafd Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Thu, 2 Jun 2016 21:56:27 +0200 Subject: [PATCH 17/42] cpp generator : pulling all methods inside the class --- src/idl_gen_cpp.cpp | 1406 ++++++++++++++++---------------- tests/monster_test_generated.h | 4 +- 2 files changed, 698 insertions(+), 712 deletions(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 7efa1334e..875345933 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -22,706 +22,6 @@ #include "flatbuffers/code_generators.h" namespace flatbuffers { -namespace cpp { - -// This tracks the current namespace so we can insert namespace declarations. -// TODO(wvo): this needs to be moved into a code generator context object. -static const Namespace *code_generator_cur_name_space = nullptr; - -// Ensure that a type is prefixed with its namespace whenever it is used -// outside of its namespace. -static std::string WrapInNameSpace(const Namespace *ns, - const std::string &name) { - if (code_generator_cur_name_space != 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; - } -} - -static std::string WrapInNameSpace(const Definition &def) { - return WrapInNameSpace(def.defined_namespace, def.name); -} - -// 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 -static 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]; -} - -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(*type.struct_def); - } - case BASE_TYPE_UNION: - // fall through - default: - return "void"; - } -} - -// 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(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) that reflects its -// serialized size. -static std::string GenTypeSize(const Parser &parser, const Type &type) { - return IsScalar(type.base_type) - ? GenTypeBasic(type, false) - : IsStruct(type) - ? GenTypePointer(parser, type) - : "flatbuffers::uoffset_t"; -} - -// 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(type, user_facing_type) + afterbasic - : beforeptr + GenTypePointer(parser, type) + afterptr; -} - -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 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 IDLOptions &opts) { - if (opts.scoped_enums) { - return enum_def.name + "::" + enum_val.name; - } else if (opts.prefixed_enums) { - return enum_def.name + "_" + enum_val.name; - } else { - return enum_val.name; - } -} - -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. -static void GenEnum(const Parser &parser, 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) { - 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"; - } -} - -static void GenEnumPost(const Parser &parser, 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 - // has been corrupted, since the verifiers will simply fail when called - // on the wrong type. - std::string &code_post = *code_ptr_post; - code_post += EnumSignature(enum_def) + " {\n switch (type) {\n"; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - code_post += " case " + GetEnumVal(enum_def, ev, parser.opts); - if (!ev.value) { - code_post += ": return true;\n"; // "NONE" enum value. - } else { - code_post += ": return verifier.VerifyTable(reinterpret_cast(" + 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; -} - -static void GenFullyQualifiedNameGetter(const Parser &parser, 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. -static void GenTable(const Parser &parser, 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(parser, 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); - } - } - 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(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 += ", " + 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(parser, 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 { - if (parser.opts.scoped_enums && - field.value.type.enum_def && - IsScalar(field.value.type.base_type)) { - code += GenTypeGet(parser, 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"; - } - } - } - } - // 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; - code += "())"; - break; - } - case BASE_TYPE_STRUCT: { - if (!field.value.type.struct_def->fixed) { - code += prefix + "verifier.VerifyVectorOfTables(" + field.name; - code += "())"; - } - break; - } - default: - break; - } - break; - default: - break; - } - } - } - 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"; - } - code += "(" + struct_def.name + "::" + GenFieldOffsetName(field) + ", "; - code += GenUnderlyingCast(field, false, field.name); - if (IsScalar(field.value.type.base_type)) - code += ", " + GenDefaultConstant(field); - 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"; - - // 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(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 += GenDefaultConstant(field); - } - } - } - 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"; -} - -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)); - } -} - -static void PaddingDefinition(int bits, std::string &code, int &padding_id) { - code += " int" + NumToString(bits) + - "_t __padding" + NumToString(padding_id++) + ";\n"; -} - -static void PaddingDeclaration(int bits, std::string &code, int &padding_id) { - (void)bits; - code += " (void)__padding" + NumToString(padding_id++) + ";"; -} - -static void PaddingInitializer(int bits, std::string &code, int &padding_id) { - (void)bits; - code += ", __padding" + NumToString(padding_id++) + "(0)"; -} - -// Generate an accessor struct with constructor for a flatbuffers struct. -static void GenStruct(const Parser &parser, StructDef &struct_def, - 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, PaddingDefinition); - } - - // Generate GetFullyQualifiedName - code += "\n public:\n"; - GenFullyQualifiedNameGetter(parser, struct_def.name, code); - - // 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(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(field, false, "_" + field.name); - code += "))"; - } else { - code += "_" + field.name + ")"; - } - GenPadding(field, code, padding_id, PaddingInitializer); - } - - 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"; - - // 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(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(parser, field.value.type, "", "", " &", true); - code += "mutable_" + field.name + "() { return " + field.name; - code += "_; }\n"; - } - } - } - code += "};\nSTRUCT_END(" + struct_def.name + ", "; - code += NumToString(struct_def.bytesize) + ");\n\n"; -} - -void GenerateNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { - for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { - *code_ptr += "namespace " + *it + " {\n"; - } -} - -void CloseNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { - for (auto it = ns->components.rbegin(); it != ns->components.rend(); ++it) { - *code_ptr += "} // namespace " + *it + "\n"; - } -} - -void CheckNameSpace(const Definition &def, std::string *code_ptr) { - // Set up the correct namespace. Only open a namespace if - // the existing 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 (code_generator_cur_name_space != def.defined_namespace) { - if (code_generator_cur_name_space) { - CloseNestedNameSpaces(code_generator_cur_name_space, code_ptr); - if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; - } - GenerateNestedNameSpaces(def.defined_namespace, code_ptr); - code_generator_cur_name_space = def.defined_namespace; - if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; - } -} - -} // namespace cpp struct IsAlnum { bool operator()(char c) { @@ -790,8 +90,8 @@ class CppGenerator : public BaseGenerator { // 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) { + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (!struct_def.generated) { CheckNameSpace(struct_def, &code); @@ -805,25 +105,25 @@ class CppGenerator : public BaseGenerator { auto &enum_def = **it; if (!enum_def.generated) { CheckNameSpace(**it, &code); - GenEnum(parser_, **it, &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) { + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (struct_def.fixed && !struct_def.generated) { CheckNameSpace(struct_def, &code); - GenStruct(parser_, struct_def, &code); + GenStruct(struct_def, &code); } } - for (auto it = parser_.structs_.vec.begin(); it != parser_.structs_.vec.end(); - ++it) { + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (!struct_def.fixed && !struct_def.generated) { CheckNameSpace(struct_def, &code); - GenTable(parser_, struct_def, &code); + GenTable(struct_def, &code); } } @@ -833,7 +133,7 @@ class CppGenerator : public BaseGenerator { auto &enum_def = **it; if (enum_def.is_union && !enum_def.generated) { CheckNameSpace(enum_def, &code); - GenEnumPost(parser_, enum_def, &code); + GenEnumPost(enum_def, &code); } } @@ -905,6 +205,692 @@ class CppGenerator : public BaseGenerator { return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false); } + + private: + // This tracks the current namespace so we can insert namespace declarations. + const Namespace *code_generator_cur_name_space = nullptr; + + // Ensure that a type is prefixed with its namespace whenever it is used + // outside of its namespace. + std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { + if (code_generator_cur_name_space != 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; + } + } + + std::string WrapInNameSpace(const Definition &def) { + return WrapInNameSpace(def.defined_namespace, def.name); + } + + // 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: + // fall through + default: + return "void"; + } + } + + // 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; + } + + // 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"; + } + + // 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; + } + + 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 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 IDLOptions &opts) { + if (opts.scoped_enums) { + return enum_def.name + "::" + enum_val.name; + } else if (opts.prefixed_enums) { + return enum_def.name + "_" + enum_val.name; + } else { + return enum_val.name; + } + } + + 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) { + 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"; + } + } + + 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 + // has been corrupted, since the verifiers will simply fail when called + // on the wrong type. + std::string &code_post = *code_ptr_post; + code_post += EnumSignature(enum_def) + " {\n switch (type) {\n"; + for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + code_post += " case " + GetEnumVal(enum_def, ev, parser_.opts); + if (!ev.value) { + code_post += ": return true;\n"; // "NONE" enum value. + } else { + code_post += ": return verifier.VerifyTable(reinterpret_cast(" + + 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); + } + } + 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 { + 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"; + } + } + } + } + // 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 + "_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; + code += "())"; + break; + } + case BASE_TYPE_STRUCT: { + if (!field.value.type.struct_def->fixed) { + code += + prefix + "verifier.VerifyVectorOfTables(" + field.name; + code += "())"; + } + break; + } + default: + break; + } + break; + default: + break; + } + } + } + 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(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"; + } + } + 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"; + + // 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 += GenDefaultConstant(field); + } + } + } + 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"; + } + + 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)); + } + } + + static void PaddingDefinition(int bits, std::string &code, int &padding_id) { + code += " int" + NumToString(bits) + "_t __padding" + + NumToString(padding_id++) + ";\n"; + } + + static void PaddingDeclaration(int bits, std::string &code, int &padding_id) { + (void)bits; + code += " (void)__padding" + NumToString(padding_id++) + ";"; + } + + static void PaddingInitializer(int bits, std::string &code, int &padding_id) { + (void)bits; + code += ", __padding" + NumToString(padding_id++) + "(0)"; + } + + // 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 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); + } + + // Generate GetFullyQualifiedName + code += "\n public:\n"; + GenFullyQualifiedNameGetter(struct_def.name, code); + + // 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 += ")\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); + } + + 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"; + + // 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"; + } + } + } + code += "};\nSTRUCT_END(" + struct_def.name + ", "; + code += NumToString(struct_def.bytesize) + ");\n\n"; + } + + void GenerateNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { + for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { + *code_ptr += "namespace " + *it + " {\n"; + } + } + + void CloseNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { + for (auto it = ns->components.rbegin(); it != ns->components.rend(); ++it) { + *code_ptr += "} // namespace " + *it + "\n"; + } + } + + void CheckNameSpace(const Definition &def, std::string *code_ptr) { + // Set up the correct namespace. Only open a namespace if + // the existing 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 (code_generator_cur_name_space != def.defined_namespace) { + if (code_generator_cur_name_space) { + CloseNestedNameSpaces(code_generator_cur_name_space, code_ptr); + if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; + } + GenerateNestedNameSpaces(def.defined_namespace, code_ptr); + code_generator_cur_name_space = def.defined_namespace; + if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; + } + } }; } // namespace cpp diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 594c6f7c8..3da41faef 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -22,8 +22,8 @@ enum Color { Color_Red = 1, Color_Green = 2, Color_Blue = 8, - Color_MIN = Color_Red, - Color_MAX = Color_Blue + Color_NONE = 0, + Color_ANY = 11 }; inline const char **EnumNamesColor() { From a3a2bf890f9e02f3f0f5f28f2e07edb630419707 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Thu, 2 Jun 2016 23:01:40 +0200 Subject: [PATCH 18/42] Better C++ namespace management --- src/idl_gen_cpp.cpp | 72 ++++++++----------- .../namespace_test2_generated.h | 4 -- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 875345933..f3a9f1254 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -86,7 +86,7 @@ class CppGenerator : public BaseGenerator { if (num_includes) code += "\n"; } - assert(!code_generator_cur_name_space); + assert(!cur_name_space_); // Generate forward declarations for all structs/tables, since they may // have circular references. @@ -94,7 +94,7 @@ class CppGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (!struct_def.generated) { - CheckNameSpace(struct_def, &code); + CheckNameSpace(struct_def.defined_namespace, &code); code += "struct " + struct_def.name + ";\n\n"; } } @@ -104,7 +104,7 @@ class CppGenerator : public BaseGenerator { ++it) { auto &enum_def = **it; if (!enum_def.generated) { - CheckNameSpace(**it, &code); + CheckNameSpace((**it).defined_namespace, &code); GenEnum(**it, &code); } } @@ -114,7 +114,7 @@ class CppGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (struct_def.fixed && !struct_def.generated) { - CheckNameSpace(struct_def, &code); + CheckNameSpace(struct_def.defined_namespace, &code); GenStruct(struct_def, &code); } } @@ -122,7 +122,7 @@ class CppGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (!struct_def.fixed && !struct_def.generated) { - CheckNameSpace(struct_def, &code); + CheckNameSpace(struct_def.defined_namespace, &code); GenTable(struct_def, &code); } } @@ -132,14 +132,14 @@ class CppGenerator : public BaseGenerator { ++it) { auto &enum_def = **it; if (enum_def.is_union && !enum_def.generated) { - CheckNameSpace(enum_def, &code); + CheckNameSpace(enum_def.defined_namespace, &code); GenEnumPost(enum_def, &code); } } // Generate convenient global helper functions: if (parser_.root_struct_def_) { - CheckNameSpace(*parser_.root_struct_def_, &code); + CheckNameSpace((*parser_.root_struct_def_).defined_namespace, &code); auto &name = parser_.root_struct_def_->name; std::string qualified_name = parser_.namespaces_.back()->GetFullyQualifiedName(name); @@ -195,25 +195,23 @@ class CppGenerator : public BaseGenerator { code += "); }\n\n"; } - assert(code_generator_cur_name_space); - CloseNestedNameSpaces(code_generator_cur_name_space, &code); - - code_generator_cur_name_space = nullptr; + assert(cur_name_space_); + CheckNameSpace(nullptr, &code); // Close the include guard. - code += "\n#endif // " + include_guard + "\n"; + code += "#endif // " + include_guard + "\n"; return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false); } private: // This tracks the current namespace so we can insert namespace declarations. - const Namespace *code_generator_cur_name_space = nullptr; + const Namespace *cur_name_space_ = nullptr; // Ensure that a type is prefixed with its namespace whenever it is used // outside of its namespace. std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { - if (code_generator_cur_name_space != ns) { + if (cur_name_space_ != ns) { std::string qualified_name; for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { qualified_name += *it + "::"; @@ -863,33 +861,25 @@ class CppGenerator : public BaseGenerator { code += NumToString(struct_def.bytesize) + ");\n\n"; } - void GenerateNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { - for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { - *code_ptr += "namespace " + *it + " {\n"; - } - } - - void CloseNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { - for (auto it = ns->components.rbegin(); it != ns->components.rend(); ++it) { - *code_ptr += "} // namespace " + *it + "\n"; - } - } - - void CheckNameSpace(const Definition &def, std::string *code_ptr) { - // Set up the correct namespace. Only open a namespace if - // the existing 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 (code_generator_cur_name_space != def.defined_namespace) { - if (code_generator_cur_name_space) { - CloseNestedNameSpaces(code_generator_cur_name_space, code_ptr); - if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; - } - GenerateNestedNameSpaces(def.defined_namespace, code_ptr); - code_generator_cur_name_space = def.defined_namespace; - if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; - } + // Set up the correct namespace. Only open a namespace if + // the existing one is different (opening/closing only what is necessary) + // the file must start and end with an empty namespace + void CheckNameSpace(const Namespace *ns, std::string *code_ptr) { + if (cur_name_space_ == ns) return; + auto s1 = cur_name_space_ == nullptr ? 0 : cur_name_space_->components.size(); + auto s2 = ns == nullptr ? 0 : ns->components.size(); + std::vector::size_type limit = 0; + while (limit < s1 && limit < s2 && + ns->components[limit] == cur_name_space_->components[limit]) + limit++; + for (auto j = s1; j > limit; --j) + *code_ptr += + "} // namespace " + cur_name_space_->components[j - 1] + "\n"; + if (s1 != limit) *code_ptr += "\n"; + for (auto j = limit; j != s2; ++j) + *code_ptr += "namespace " + ns->components[j] + " {\n"; + if (s2 != limit) *code_ptr += "\n"; + cur_name_space_ = ns; } }; } // namespace cpp diff --git a/tests/namespace_test/namespace_test2_generated.h b/tests/namespace_test/namespace_test2_generated.h index d0cc5fab2..8e6b3ada8 100644 --- a/tests/namespace_test/namespace_test2_generated.h +++ b/tests/namespace_test/namespace_test2_generated.h @@ -23,10 +23,6 @@ namespace NamespaceA { struct SecondTableInA; -} // namespace NamespaceA - -namespace NamespaceA { - struct TableInFirstNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { enum { VT_FOO_TABLE = 4, From 4ffc881fb6002f37163ec7507c3dd2d1009abd08 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 25 May 2016 17:47:44 -0700 Subject: [PATCH 19/42] Fixed LoadFile crashing on directory arguments. Change-Id: I737f6fd0bb1302ab7cfa6ab8b06108e221ebb63c Tested: on Linux. --- include/flatbuffers/util.h | 6 +++++- samples/monster_generated.h | 19 ++++++++++++++++++- src/util.cpp | 17 ++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/include/flatbuffers/util.h b/include/flatbuffers/util.h index cfb211f09..7bd7513bb 100644 --- a/include/flatbuffers/util.h +++ b/include/flatbuffers/util.h @@ -35,9 +35,10 @@ #include #include #else -#include #include #endif +#include +#include #include "flatbuffers/flatbuffers.h" @@ -124,6 +125,9 @@ FileExistsFunction SetFileExistsFunction(FileExistsFunction // Check if file "name" exists. bool FileExists(const char *name); +// Check if "name" exists and it is also a directory. +bool DirExists(const char *name); + // Load file "name" into "buf" returning true if successful // false otherwise. If "binary" is false data is read // using ifstream's text mode, otherwise data is read with diff --git a/samples/monster_generated.h b/samples/monster_generated.h index cf45bbb91..1a16126a5 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -5,12 +5,13 @@ #include "flatbuffers/flatbuffers.h" - namespace MyGame { namespace Sample { struct Vec3; + struct Monster; + struct Weapon; enum Color { @@ -55,8 +56,11 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS { : x_(flatbuffers::EndianScalar(_x)), y_(flatbuffers::EndianScalar(_y)), z_(flatbuffers::EndianScalar(_z)) { } float x() const { return flatbuffers::EndianScalar(x_); } + void mutate_x(float _x) { flatbuffers::WriteScalar(&x_, _x); } float y() const { return flatbuffers::EndianScalar(y_); } + void mutate_y(float _y) { flatbuffers::WriteScalar(&y_, _y); } float z() const { return flatbuffers::EndianScalar(z_); } + void mutate_z(float _z) { flatbuffers::WriteScalar(&z_, _z); } }; STRUCT_END(Vec3, 12); @@ -73,14 +77,23 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_EQUIPPED = 22 }; const Vec3 *pos() const { return GetStruct(VT_POS); } + Vec3 *mutable_pos() { return GetStruct(VT_POS); } int16_t mana() const { return GetField(VT_MANA, 150); } + bool mutate_mana(int16_t _mana) { return SetField(VT_MANA, _mana); } int16_t hp() const { return GetField(VT_HP, 100); } + bool mutate_hp(int16_t _hp) { return SetField(VT_HP, _hp); } const flatbuffers::String *name() const { return GetPointer(VT_NAME); } + flatbuffers::String *mutable_name() { return GetPointer(VT_NAME); } const flatbuffers::Vector *inventory() const { return GetPointer *>(VT_INVENTORY); } + 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)); } 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); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_POS) && @@ -150,7 +163,9 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_DAMAGE = 6 }; const flatbuffers::String *name() const { return GetPointer(VT_NAME); } + flatbuffers::String *mutable_name() { return GetPointer(VT_NAME); } int16_t damage() const { return GetField(VT_DAMAGE, 0); } + bool mutate_damage(int16_t _damage) { return SetField(VT_DAMAGE, _damage); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_NAME) && @@ -192,6 +207,8 @@ inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_o inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot(buf); } +inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot(buf); } + inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(); } inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset root) { fbb.Finish(root); } diff --git a/src/util.cpp b/src/util.cpp index 452e9eae5..f4aecb5c3 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -24,12 +24,14 @@ bool FileExistsRaw(const char *name) { } bool LoadFileRaw(const char *name, bool binary, std::string *buf) { + if (DirExists(name)) return false; std::ifstream ifs(name, binary ? std::ifstream::binary : std::ifstream::in); if (!ifs.is_open()) return false; if (binary) { // The fastest way to read a file into a string. ifs.seekg(0, std::ios::end); - (*buf).resize(static_cast(ifs.tellg())); + auto size = ifs.tellg(); + (*buf).resize(static_cast(size)); ifs.seekg(0, std::ios::beg); ifs.read(&(*buf)[0], (*buf).size()); } else { @@ -54,6 +56,19 @@ bool FileExists(const char *name) { return g_file_exists_function(name); } +bool DirExists(const char *name) { + #ifdef _WIN32 + #define flatbuffers_stat _stat + #define FLATBUFFERS_S_IFDIR _S_IFDIR + #else + #define flatbuffers_stat stat + #define FLATBUFFERS_S_IFDIR S_IFDIR + #endif + struct flatbuffers_stat file_info; + if (flatbuffers_stat(name, &file_info) != 0) return false; + return (file_info.st_mode & FLATBUFFERS_S_IFDIR) != 0; +} + LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function) { LoadFileFunction previous_function = g_load_file_function; g_load_file_function = load_file_function ? load_file_function : LoadFileRaw; From 2bdf44a25d435f5428afb79e18657d0ba03cb7c2 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 6 Jun 2016 17:38:21 -0700 Subject: [PATCH 20/42] Added a way to get mutable tables out of a mutable vector of tables. Change-Id: I8f9ef1d14f86671ced929c7a159115b1d8510327 Tested: on Linux. --- include/flatbuffers/flatbuffers.h | 10 ++++++++++ tests/test.cpp | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 0fa31250f..b22aaaa6a 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -207,6 +207,7 @@ template size_t AlignOf() { // (avoiding the need for a trailing return decltype) template struct IndirectHelper { typedef T return_type; + typedef T mutable_return_type; static const size_t element_stride = sizeof(T); static return_type Read(const uint8_t *p, uoffset_t i) { return EndianScalar((reinterpret_cast(p))[i]); @@ -214,6 +215,7 @@ template struct IndirectHelper { }; template struct IndirectHelper> { typedef const T *return_type; + typedef T *mutable_return_type; static const size_t element_stride = sizeof(uoffset_t); static return_type Read(const uint8_t *p, uoffset_t i) { p += i * sizeof(uoffset_t); @@ -222,6 +224,7 @@ template struct IndirectHelper> { }; template struct IndirectHelper { typedef const T *return_type; + typedef T *mutable_return_type; static const size_t element_stride = sizeof(T); static return_type Read(const uint8_t *p, uoffset_t i) { return reinterpret_cast(p + i * sizeof(T)); @@ -306,6 +309,7 @@ public: uoffset_t Length() const { return size(); } typedef typename IndirectHelper::return_type return_type; + typedef typename IndirectHelper::mutable_return_type mutable_return_type; return_type Get(uoffset_t i) const { assert(i < size()); @@ -347,6 +351,12 @@ public: WriteScalar(data() + i, val - (Data() + i * sizeof(uoffset_t))); } + // Get a mutable pointer to tables/strings inside this vector. + mutable_return_type GetMutableObject(uoffset_t i) const { + assert(i < size()); + return const_cast(IndirectHelper::Read(Data(), i)); + } + // The raw data in little endian format. Use with care. const uint8_t *Data() const { return reinterpret_cast(&length_ + 1); diff --git a/tests/test.cpp b/tests/test.cpp index e636f1f3c..73af97133 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -108,6 +108,7 @@ flatbuffers::unique_ptr_t CreateFlatBufferTest(std::string &buffer) { mlocs[0] = mb1.Finish(); MonsterBuilder mb2(builder); mb2.add_name(barney); + mb2.add_hp(1000); mlocs[1] = mb2.Finish(); MonsterBuilder mb3(builder); mb3.add_name(wilma); @@ -203,6 +204,7 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length) { for (auto it = vecoftables->begin(); it != vecoftables->end(); ++it) TEST_EQ(strlen(it->name()->c_str()) >= 4, true); TEST_EQ_STR(vecoftables->Get(0)->name()->c_str(), "Barney"); + TEST_EQ(vecoftables->Get(0)->hp(), 1000); TEST_EQ_STR(vecoftables->Get(1)->name()->c_str(), "Fred"); TEST_EQ_STR(vecoftables->Get(2)->name()->c_str(), "Wilma"); TEST_NOTNULL(vecoftables->LookupByKey("Barney")); @@ -260,6 +262,13 @@ void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) { TEST_EQ(inventory->Get(9), 100); inventory->Mutate(9, 9); + auto tables = monster->mutable_testarrayoftables(); + auto first = tables->GetMutableObject(0); + TEST_EQ(first->hp(), 1000); + first->mutate_hp(0); + TEST_EQ(first->hp(), 0); + first->mutate_hp(1000); + // Run the verifier and the regular test to make sure we didn't trample on // anything. AccessFlatBufferTest(flatbuf, length); From 15863c34a0733929069da177aab2861ddb719e80 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 7 Jun 2016 14:46:25 +0200 Subject: [PATCH 21/42] SetNameSpace algorithm documentation and more meaningful variable names --- src/idl_gen_cpp.cpp | 52 ++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index f3a9f1254..b1402d8e6 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -94,7 +94,7 @@ class CppGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (!struct_def.generated) { - CheckNameSpace(struct_def.defined_namespace, &code); + SetNameSpace(struct_def.defined_namespace, &code); code += "struct " + struct_def.name + ";\n\n"; } } @@ -104,7 +104,7 @@ class CppGenerator : public BaseGenerator { ++it) { auto &enum_def = **it; if (!enum_def.generated) { - CheckNameSpace((**it).defined_namespace, &code); + SetNameSpace((**it).defined_namespace, &code); GenEnum(**it, &code); } } @@ -114,7 +114,7 @@ class CppGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (struct_def.fixed && !struct_def.generated) { - CheckNameSpace(struct_def.defined_namespace, &code); + SetNameSpace(struct_def.defined_namespace, &code); GenStruct(struct_def, &code); } } @@ -122,7 +122,7 @@ class CppGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; if (!struct_def.fixed && !struct_def.generated) { - CheckNameSpace(struct_def.defined_namespace, &code); + SetNameSpace(struct_def.defined_namespace, &code); GenTable(struct_def, &code); } } @@ -132,14 +132,14 @@ class CppGenerator : public BaseGenerator { ++it) { auto &enum_def = **it; if (enum_def.is_union && !enum_def.generated) { - CheckNameSpace(enum_def.defined_namespace, &code); + SetNameSpace(enum_def.defined_namespace, &code); GenEnumPost(enum_def, &code); } } // Generate convenient global helper functions: if (parser_.root_struct_def_) { - CheckNameSpace((*parser_.root_struct_def_).defined_namespace, &code); + SetNameSpace((*parser_.root_struct_def_).defined_namespace, &code); auto &name = parser_.root_struct_def_->name; std::string qualified_name = parser_.namespaces_.back()->GetFullyQualifiedName(name); @@ -196,7 +196,7 @@ class CppGenerator : public BaseGenerator { } assert(cur_name_space_); - CheckNameSpace(nullptr, &code); + SetNameSpace(nullptr, &code); // Close the include guard. code += "#endif // " + include_guard + "\n"; @@ -862,23 +862,35 @@ class CppGenerator : public BaseGenerator { } // Set up the correct namespace. Only open a namespace if - // the existing one is different (opening/closing only what is necessary) - // the file must start and end with an empty namespace - void CheckNameSpace(const Namespace *ns, std::string *code_ptr) { + // 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; - auto s1 = cur_name_space_ == nullptr ? 0 : cur_name_space_->components.size(); - auto s2 = ns == nullptr ? 0 : ns->components.size(); - std::vector::size_type limit = 0; - while (limit < s1 && limit < s2 && - ns->components[limit] == cur_name_space_->components[limit]) - limit++; - for (auto j = s1; j > limit; --j) + // 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 (s1 != limit) *code_ptr += "\n"; - for (auto j = limit; j != s2; ++j) + 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 (s2 != limit) *code_ptr += "\n"; + if (new_size != common_prefix_size) *code_ptr += "\n"; cur_name_space_ = ns; } }; From 3ae503a19194666eb56a78f5b5cbb106e2d201f3 Mon Sep 17 00:00:00 2001 From: Alexander Gallego Date: Tue, 7 Jun 2016 18:08:09 -0400 Subject: [PATCH 22/42] Add env var for flatc schema compiler cmake module --- CMake/BuildFlatBuffers.cmake | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMake/BuildFlatBuffers.cmake b/CMake/BuildFlatBuffers.cmake index 2c28899a7..42f78de77 100644 --- a/CMake/BuildFlatBuffers.cmake +++ b/CMake/BuildFlatBuffers.cmake @@ -63,6 +63,13 @@ function(build_flatbuffers flatbuffers_schemas set(FLATC_TARGET flatc) set(FLATC flatc) endif() + set(FLATC_SCHEMA_ARGS --gen-mutable) + if(FLATBUFFERS_FLATC_SCHEMA_EXTRA_ARGS) + set(FLATC_SCHEMA_ARGS + ${FLATBUFFERS_FLATC_SCHEMA_EXTRA_ARGS} + ${FLATC_SCHEMA_ARGS} + ) + endif() set(schema_glob "*.fbs") # Generate the include files parameters. @@ -86,7 +93,7 @@ function(build_flatbuffers flatbuffers_schemas set(generated_include ${generated_includes_dir}/${filename}_generated.h) add_custom_command( OUTPUT ${generated_include} - COMMAND ${FLATC} --gen-mutable + COMMAND ${FLATC} ${FLATC_SCHEMA_ARGS} -o ${generated_includes_dir} ${include_params} -c ${schema} From afa276288c8db9a983aa8ae134328b1b447bec70 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 15 Jun 2016 12:10:01 -0700 Subject: [PATCH 23/42] Added additional convenience overloads to CreateVector(). Bug: 29337887, 29336299 Change-Id: Iad8b3b2263f6cea7ee7e45994369194960df293b Tested: on Linux. --- docs/source/Tutorial.md | 10 ++++- include/flatbuffers/flatbuffers.h | 55 +++++++++++++++++++++------ tests/MyGame/Example/Monster.cs | 7 +++- tests/MyGame/Example/Monster.go | 22 ++++++++++- tests/MyGame/Example/Monster.java | 7 +++- tests/MyGame/Example/Monster.php | 60 ++++++++++++++++++++++++++++-- tests/MyGame/Example/Monster.py | 19 +++++++++- tests/monster_test.fbs | 1 + tests/monster_test_generated.h | 19 +++++++--- tests/monster_test_generated.js | 49 +++++++++++++++++++++++- tests/monsterdata_test.mon | Bin 384 -> 384 bytes tests/test.cpp | 29 +++++++++++---- 12 files changed, 244 insertions(+), 34 deletions(-) diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md index 1e48796d9..6f6ac9a51 100644 --- a/docs/source/Tutorial.md +++ b/docs/source/Tutorial.md @@ -790,6 +790,14 @@ offsets. ~~~
+
+
+Note there's additional convenience overloads of `CreateVector`, allowing you +to work with data that's not in a `std::vector`, or allowing you to generate +elements by calling a lambda. For the common case of `std::vector` +there's also `CreateVectorOfStrings`. +
+ To create a `struct`, use the `Vec3` class/struct that was generated by the schema compiler: @@ -1075,7 +1083,7 @@ Here is a repetition these lines, to help highlight them more clearly:
~~~{.c} // Add union type and data simultanously. - ns(Monster_equipped_Weapon_add(B, axe)); + ns(Monster_equipped_Weapon_add(B, axe)); ~~~
diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index ff83da6d2..ae50d57d6 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -36,16 +36,17 @@ (!defined(_MSC_VER) || _MSC_VER < 1600) && \ (!defined(__GNUC__) || \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400)) - #error A C++11 compatible compiler with support for the auto typing is required for FlatBuffers. + #error A C++11 compatible compiler with support for the auto typing is \ + required for FlatBuffers. #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ #endif #if !defined(__clang__) && \ defined(__GNUC__) && \ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600) - // Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr and constexpr - // keywords. Note the __clang__ check is needed, because clang presents itself as an older GNUC - // compiler. + // Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr + // and constexpr keywords. Note the __clang__ check is needed, because clang + // presents itself as an older GNUC compiler. #ifndef nullptr_t const class nullptr_t { public: @@ -983,6 +984,33 @@ FLATBUFFERS_FINAL_CLASS return CreateVector(v.data(), v.size()); } + /// @brief Serialize values returned by a function into a FlatBuffer `vector`. + /// This is a convenience function that takes care of iteration for you. + /// @tparam T The data type of the `std::vector` elements. + /// @param f A function that takes the current iteration 0..vector_size-1 and + /// returns any type that you can construct a FlatBuffers vector out of. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template Offset> CreateVector(size_t vector_size, + const std::function &f) { + std::vector elems(vector_size); + for (size_t i = 0; i < vector_size; i++) elems[i] = f(i); + return CreateVector(elems.data(), elems.size()); + } + + /// @brief Serialize a `std::vector` into a FlatBuffer `vector`. + /// This is a convenience function for a common case. + /// @param v A const reference to the `std::vector` to serialize into the + /// buffer as a `vector`. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + Offset>> CreateVectorOfStrings( + const std::vector &v) { + std::vector> offsets(v.size()); + for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]); + return CreateVector(offsets.data(), offsets.size()); + } + /// @brief Serialize an array of structs into a FlatBuffer `vector`. /// @tparam T The data type of the struct array elements. /// @param[in] v A pointer to the array of type `T` to serialize into the @@ -991,7 +1019,7 @@ FLATBUFFERS_FINAL_CLASS /// @return Returns a typed `Offset` into the serialized data indicating /// where the vector is stored. template Offset> CreateVectorOfStructs( - const T *v, size_t len) { + const T *v, size_t len) { StartVector(len * sizeof(T) / AlignOf(), AlignOf()); PushBytes(reinterpret_cast(v), sizeof(T) * len); return Offset>(EndVector(len)); @@ -1004,7 +1032,7 @@ FLATBUFFERS_FINAL_CLASS /// @return Returns a typed `Offset` into the serialized data indicating /// where the vector is stored. template Offset> CreateVectorOfStructs( - const std::vector &v) { + const std::vector &v) { return CreateVectorOfStructs(v.data(), v.size()); } @@ -1033,7 +1061,7 @@ FLATBUFFERS_FINAL_CLASS /// @return Returns a typed `Offset` into the serialized data indicating /// where the vector is stored. template Offset>> CreateVectorOfSortedTables( - Offset *v, size_t len) { + Offset *v, size_t len) { std::sort(v, v + len, TableKeyComparator(buf_)); return CreateVector(v, len); } @@ -1046,7 +1074,7 @@ FLATBUFFERS_FINAL_CLASS /// @return Returns a typed `Offset` into the serialized data indicating /// where the vector is stored. template Offset>> CreateVectorOfSortedTables( - std::vector> *v) { + std::vector> *v) { return CreateVectorOfSortedTables(v->data(), v->size()); } @@ -1077,7 +1105,7 @@ FLATBUFFERS_FINAL_CLASS /// written to at a later time to serialize the data into a `vector` /// in the buffer. template Offset> CreateUninitializedVector( - size_t len, T **buf) { + size_t len, T **buf) { return CreateUninitializedVector(len, sizeof(T), reinterpret_cast(buf)); } @@ -1162,13 +1190,16 @@ template const T *GetRoot(const void *buf) { } /// Helpers to get a typed pointer to objects that are currently beeing built. -/// @warning Creating new objects will lead to reallocations and invalidates the pointer! -template T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset offset) { +/// @warning Creating new objects will lead to reallocations and invalidates +/// the pointer! +template T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, + Offset offset) { return reinterpret_cast(fbb.GetCurrentBufferPointer() + fbb.GetSize() - offset.o); } -template const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset offset) { +template const T *GetTemporaryPointer(FlatBufferBuilder &fbb, + Offset offset) { return GetMutableTemporaryPointer(fbb, offset); } diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs index 6101f464c..fdfd2b0a3 100644 --- a/tests/MyGame/Example/Monster.cs +++ b/tests/MyGame/Example/Monster.cs @@ -78,8 +78,10 @@ public sealed class Monster : Table { public bool MutateTestf2(float testf2) { int o = __offset(56); if (o != 0) { bb.PutFloat(o + bb_pos, testf2); return true; } else { return false; } } public float Testf3 { get { int o = __offset(58); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)0.0f; } } public bool MutateTestf3(float testf3) { int o = __offset(58); if (o != 0) { bb.PutFloat(o + bb_pos, testf3); return true; } else { return false; } } + public string GetTestarrayofstring2(int j) { int o = __offset(60); return o != 0 ? __string(__vector(o) + j * 4) : null; } + public int Testarrayofstring2Length { get { int o = __offset(60); return o != 0 ? __vector_len(o) : 0; } } - public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(28); } + public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(29); } public static void AddPos(FlatBufferBuilder builder, Offset posOffset) { builder.AddStruct(0, posOffset.Value, 0); } public static void AddMana(FlatBufferBuilder builder, short mana) { builder.AddShort(1, mana, 150); } public static void AddHp(FlatBufferBuilder builder, short hp) { builder.AddShort(2, hp, 100); } @@ -118,6 +120,9 @@ public sealed class Monster : Table { public static void AddTestf(FlatBufferBuilder builder, float testf) { builder.AddFloat(25, testf, 3.14159f); } public static void AddTestf2(FlatBufferBuilder builder, float testf2) { builder.AddFloat(26, testf2, 3.0f); } public static void AddTestf3(FlatBufferBuilder builder, float testf3) { builder.AddFloat(27, testf3, 0.0f); } + public static void AddTestarrayofstring2(FlatBufferBuilder builder, VectorOffset testarrayofstring2Offset) { builder.AddOffset(28, testarrayofstring2Offset.Value, 0); } + public static VectorOffset CreateTestarrayofstring2Vector(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); } + public static void StartTestarrayofstring2Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } public static Offset EndMonster(FlatBufferBuilder builder) { int o = builder.EndObject(); builder.Required(o, 10); // name diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go index fbd849e81..0c42f45a5 100644 --- a/tests/MyGame/Example/Monster.go +++ b/tests/MyGame/Example/Monster.go @@ -337,7 +337,24 @@ func (rcv *Monster) Testf3() float32 { return 0.0 } -func MonsterStart(builder *flatbuffers.Builder) { builder.StartObject(28) } +func (rcv *Monster) Testarrayofstring2(j int) []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(60)) + if o != 0 { + a := rcv._tab.Vector(o) + return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j * 4)) + } + return nil +} + +func (rcv *Monster) Testarrayofstring2Length() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(60)) + if o != 0 { + return rcv._tab.VectorLen(o) + } + return 0 +} + +func MonsterStart(builder *flatbuffers.Builder) { builder.StartObject(29) } func MonsterAddPos(builder *flatbuffers.Builder, pos flatbuffers.UOffsetT) { builder.PrependStructSlot(0, flatbuffers.UOffsetT(pos), 0) } func MonsterAddMana(builder *flatbuffers.Builder, mana int16) { builder.PrependInt16Slot(1, mana, 150) } func MonsterAddHp(builder *flatbuffers.Builder, hp int16) { builder.PrependInt16Slot(2, hp, 100) } @@ -377,4 +394,7 @@ func MonsterStartTestarrayofboolsVector(builder *flatbuffers.Builder, numElems i func MonsterAddTestf(builder *flatbuffers.Builder, testf float32) { builder.PrependFloat32Slot(25, testf, 3.14159) } func MonsterAddTestf2(builder *flatbuffers.Builder, testf2 float32) { builder.PrependFloat32Slot(26, testf2, 3.0) } func MonsterAddTestf3(builder *flatbuffers.Builder, testf3 float32) { builder.PrependFloat32Slot(27, testf3, 0.0) } +func MonsterAddTestarrayofstring2(builder *flatbuffers.Builder, testarrayofstring2 flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(28, flatbuffers.UOffsetT(testarrayofstring2), 0) } +func MonsterStartTestarrayofstring2Vector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(4, numElems, 4) +} func MonsterEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java index d85e4baac..bfd4be1c9 100644 --- a/tests/MyGame/Example/Monster.java +++ b/tests/MyGame/Example/Monster.java @@ -84,8 +84,10 @@ public final class Monster extends Table { public boolean mutateTestf2(float testf2) { int o = __offset(56); if (o != 0) { bb.putFloat(o + bb_pos, testf2); return true; } else { return false; } } public float testf3() { int o = __offset(58); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } public boolean mutateTestf3(float testf3) { int o = __offset(58); if (o != 0) { bb.putFloat(o + bb_pos, testf3); return true; } else { return false; } } + public String testarrayofstring2(int j) { int o = __offset(60); return o != 0 ? __string(__vector(o) + j * 4) : null; } + public int testarrayofstring2Length() { int o = __offset(60); return o != 0 ? __vector_len(o) : 0; } - public static void startMonster(FlatBufferBuilder builder) { builder.startObject(28); } + public static void startMonster(FlatBufferBuilder builder) { builder.startObject(29); } public static void addPos(FlatBufferBuilder builder, int posOffset) { builder.addStruct(0, posOffset, 0); } public static void addMana(FlatBufferBuilder builder, short mana) { builder.addShort(1, mana, 150); } public static void addHp(FlatBufferBuilder builder, short hp) { builder.addShort(2, hp, 100); } @@ -124,6 +126,9 @@ public final class Monster extends Table { public static void addTestf(FlatBufferBuilder builder, float testf) { builder.addFloat(25, testf, 3.14159f); } public static void addTestf2(FlatBufferBuilder builder, float testf2) { builder.addFloat(26, testf2, 3.0f); } public static void addTestf3(FlatBufferBuilder builder, float testf3) { builder.addFloat(27, testf3, 0.0f); } + public static void addTestarrayofstring2(FlatBufferBuilder builder, int testarrayofstring2Offset) { builder.addOffset(28, testarrayofstring2Offset, 0); } + public static int createTestarrayofstring2Vector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startTestarrayofstring2Vector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endMonster(FlatBufferBuilder builder) { int o = builder.endObject(); builder.required(o, 10); // name diff --git a/tests/MyGame/Example/Monster.php b/tests/MyGame/Example/Monster.php index 9f82d5a9c..c06cffbc6 100644 --- a/tests/MyGame/Example/Monster.php +++ b/tests/MyGame/Example/Monster.php @@ -360,22 +360,41 @@ class Monster extends Table return $o != 0 ? $this->bb->getFloat($o + $this->bb_pos) : 0.0; } + /** + * @param int offset + * @return string + */ + public function getTestarrayofstring2($j) + { + $o = $this->__offset(60); + return $o != 0 ? $this->__string($this->__vector($o) + $j * 4) : 0; + } + + /** + * @return int + */ + public function getTestarrayofstring2Length() + { + $o = $this->__offset(60); + return $o != 0 ? $this->__vector_len($o) : 0; + } + /** * @param FlatBufferBuilder $builder * @return void */ public static function startMonster(FlatBufferBuilder $builder) { - $builder->StartObject(28); + $builder->StartObject(29); } /** * @param FlatBufferBuilder $builder * @return Monster */ - public static function createMonster(FlatBufferBuilder $builder, $pos, $mana, $hp, $name, $inventory, $color, $test_type, $test, $test4, $testarrayofstring, $testarrayoftables, $enemy, $testnestedflatbuffer, $testempty, $testbool, $testhashs32_fnv1, $testhashu32_fnv1, $testhashs64_fnv1, $testhashu64_fnv1, $testhashs32_fnv1a, $testhashu32_fnv1a, $testhashs64_fnv1a, $testhashu64_fnv1a, $testarrayofbools, $testf, $testf2, $testf3) + public static function createMonster(FlatBufferBuilder $builder, $pos, $mana, $hp, $name, $inventory, $color, $test_type, $test, $test4, $testarrayofstring, $testarrayoftables, $enemy, $testnestedflatbuffer, $testempty, $testbool, $testhashs32_fnv1, $testhashu32_fnv1, $testhashs64_fnv1, $testhashu64_fnv1, $testhashs32_fnv1a, $testhashu32_fnv1a, $testhashs64_fnv1a, $testhashu64_fnv1a, $testarrayofbools, $testf, $testf2, $testf3, $testarrayofstring2) { - $builder->startObject(28); + $builder->startObject(29); self::addPos($builder, $pos); self::addMana($builder, $mana); self::addHp($builder, $hp); @@ -403,6 +422,7 @@ class Monster extends Table self::addTestf($builder, $testf); self::addTestf2($builder, $testf2); self::addTestf3($builder, $testf3); + self::addTestarrayofstring2($builder, $testarrayofstring2); $o = $builder->endObject(); $builder->required($o, 10); // name return $o; @@ -817,6 +837,40 @@ class Monster extends Table $builder->addFloatX(27, $testf3, 0.0); } + /** + * @param FlatBufferBuilder $builder + * @param VectorOffset + * @return void + */ + public static function addTestarrayofstring2(FlatBufferBuilder $builder, $testarrayofstring2) + { + $builder->addOffsetX(28, $testarrayofstring2, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @param array offset array + * @return int vector offset + */ + public static function createTestarrayofstring2Vector(FlatBufferBuilder $builder, array $data) + { + $builder->startVector(4, count($data), 4); + for ($i = count($data) - 1; $i >= 0; $i--) { + $builder->addOffset($data[$i]); + } + return $builder->endVector(); + } + + /** + * @param FlatBufferBuilder $builder + * @param int $numElems + * @return void + */ + public static function startTestarrayofstring2Vector(FlatBufferBuilder $builder, $numElems) + { + $builder->startVector(4, $numElems, 4); + } + /** * @param FlatBufferBuilder $builder * @return int table offset diff --git a/tests/MyGame/Example/Monster.py b/tests/MyGame/Example/Monster.py index 4f1ca2dfa..9d2909e89 100644 --- a/tests/MyGame/Example/Monster.py +++ b/tests/MyGame/Example/Monster.py @@ -283,7 +283,22 @@ class Monster(object): return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) return 0.0 -def MonsterStart(builder): builder.StartObject(28) + # Monster + def Testarrayofstring2(self, j): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(60)) + if o != 0: + a = self._tab.Vector(o) + return self._tab.String(a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4)) + return "" + + # Monster + def Testarrayofstring2Length(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(60)) + if o != 0: + return self._tab.VectorLen(o) + return 0 + +def MonsterStart(builder): builder.StartObject(29) def MonsterAddPos(builder, pos): builder.PrependStructSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(pos), 0) def MonsterAddMana(builder, mana): builder.PrependInt16Slot(1, mana, 150) def MonsterAddHp(builder, hp): builder.PrependInt16Slot(2, hp, 100) @@ -317,4 +332,6 @@ def MonsterStartTestarrayofboolsVector(builder, numElems): return builder.StartV def MonsterAddTestf(builder, testf): builder.PrependFloat32Slot(25, testf, 3.14159) def MonsterAddTestf2(builder, testf2): builder.PrependFloat32Slot(26, testf2, 3.0) def MonsterAddTestf3(builder, testf3): builder.PrependFloat32Slot(27, testf3, 0.0) +def MonsterAddTestarrayofstring2(builder, testarrayofstring2): builder.PrependUOffsetTRelativeSlot(28, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayofstring2), 0) +def MonsterStartTestarrayofstring2Vector(builder, numElems): return builder.StartVector(4, numElems, 4) def MonsterEnd(builder): return builder.EndObject() diff --git a/tests/monster_test.fbs b/tests/monster_test.fbs index f302ce444..08e72d4a5 100755 --- a/tests/monster_test.fbs +++ b/tests/monster_test.fbs @@ -44,6 +44,7 @@ table Monster { /// multiline too testarrayoftables:[Monster] (id: 11); testarrayofstring:[string] (id: 10); + testarrayofstring2:[string] (id: 28); testarrayofbools:[bool] (id: 24); enemy:MyGame.Example.Monster (id:12); // Test referring by full namespace. test:Any (id: 8); diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 594c6f7c8..60abbdecd 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -22,8 +22,8 @@ enum Color { Color_Red = 1, Color_Green = 2, Color_Blue = 8, - Color_MIN = Color_Red, - Color_MAX = Color_Blue + Color_NONE = 0, + Color_ANY = 11 }; inline const char **EnumNamesColor() { @@ -206,7 +206,8 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_TESTARRAYOFBOOLS = 52, VT_TESTF = 54, VT_TESTF2 = 56, - VT_TESTF3 = 58 + VT_TESTF3 = 58, + VT_TESTARRAYOFSTRING2 = 60 }; const Vec3 *pos() const { return GetStruct(VT_POS); } Vec3 *mutable_pos() { return GetStruct(VT_POS); } @@ -267,6 +268,8 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_POS) && @@ -308,6 +311,9 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_TESTF) && VerifyField(verifier, VT_TESTF2) && VerifyField(verifier, VT_TESTF3) && + VerifyField(verifier, VT_TESTARRAYOFSTRING2) && + verifier.Verify(testarrayofstring2()) && + verifier.VerifyVectorOfStrings(testarrayofstring2()) && verifier.EndTable(); } }; @@ -342,10 +348,11 @@ struct MonsterBuilder { 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_, 28)); + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 29)); fbb_.Required(o, Monster::VT_NAME); // name return o; } @@ -378,12 +385,14 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder flatbuffers::Offset> testarrayofbools = 0, float testf = 3.14159f, float testf2 = 3.0f, - float testf3 = 0.0f) { + float testf3 = 0.0f, + flatbuffers::Offset>> testarrayofstring2 = 0) { MonsterBuilder builder_(_fbb); builder_.add_testhashu64_fnv1a(testhashu64_fnv1a); builder_.add_testhashs64_fnv1a(testhashs64_fnv1a); builder_.add_testhashu64_fnv1(testhashu64_fnv1); builder_.add_testhashs64_fnv1(testhashs64_fnv1); + builder_.add_testarrayofstring2(testarrayofstring2); builder_.add_testf3(testf3); builder_.add_testf2(testf2); builder_.add_testf(testf); diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js index 8316fbc69..f967b9d83 100644 --- a/tests/monster_test_generated.js +++ b/tests/monster_test_generated.js @@ -701,11 +701,29 @@ MyGame.Example.Monster.prototype.testf3 = function() { return offset ? this.bb.readFloat32(this.bb_pos + offset) : 0.0; }; +/** + * @param {number} index + * @param {flatbuffers.Encoding=} optionalEncoding + * @returns {string|Uint8Array} + */ +MyGame.Example.Monster.prototype.testarrayofstring2 = function(index, optionalEncoding) { + var offset = this.bb.__offset(this.bb_pos, 60); + return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; +}; + +/** + * @returns {number} + */ +MyGame.Example.Monster.prototype.testarrayofstring2Length = function() { + var offset = this.bb.__offset(this.bb_pos, 60); + return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0; +}; + /** * @param {flatbuffers.Builder} builder */ MyGame.Example.Monster.startMonster = function(builder) { - builder.startObject(28); + builder.startObject(29); }; /** @@ -1037,6 +1055,35 @@ MyGame.Example.Monster.addTestf3 = function(builder, testf3) { builder.addFieldFloat32(27, testf3, 0.0); }; +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} testarrayofstring2Offset + */ +MyGame.Example.Monster.addTestarrayofstring2 = function(builder, testarrayofstring2Offset) { + builder.addFieldOffset(28, testarrayofstring2Offset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {Array.} data + * @returns {flatbuffers.Offset} + */ +MyGame.Example.Monster.createTestarrayofstring2Vector = function(builder, data) { + builder.startVector(4, data.length, 4); + for (var i = data.length - 1; i >= 0; i--) { + builder.addOffset(data[i]); + } + return builder.endVector(); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {number} numElems + */ +MyGame.Example.Monster.startTestarrayofstring2Vector = function(builder, numElems) { + builder.startVector(4, numElems, 4); +}; + /** * @param {flatbuffers.Builder} builder * @returns {flatbuffers.Offset} diff --git a/tests/monsterdata_test.mon b/tests/monsterdata_test.mon index 7a7fbf707f84e8b7ef957001da0ce8b3d9a89324..01bd5279453ac6fd4e290c1d5a3b8537275d9619 100644 GIT binary patch delta 156 zcmZo*ZeaHGU|?YI_4f;AV6bDTVc-Dr*cfzxqyZ4KGMF$}FxUWD4nPb7E({(F5ex|o zJ`4d284LvsArN68X*bbRTl5c*@dk*m0C5Wt#{jX*#EHU;8WWc)^8z^x%s|Wtgu5nQ cbOs98fo%jyuuN8D)Sqm?$iiqhIgn8w05${_r~m)} delta 171 zcmZo*ZeaHGU|?YI_4f+~QVcc>4GbJWnvKB(NLm0fD^SdV!3D?ysRIEYh5&{Hh75)f zh6siNh6;ulh%kfAL{Du)D4XF6knseF&j4`)5Jv#90}wl&th@`tg-aUyKv-qsTxCvX gpadfj?wNSjncD{J0H6p1%Vb4HeW0Ap strings[4]; - strings[0] = builder.CreateSharedString("bob"); - strings[1] = builder.CreateSharedString("fred"); - strings[2] = builder.CreateSharedString("bob"); - strings[3] = builder.CreateSharedString("fred"); - auto vecofstrings = builder.CreateVector(strings, 4); + // Create an array of strings. Also test string pooling, and lambdas. + const char *names[] = { "bob", "fred", "bob", "fred" }; + auto vecofstrings = + builder.CreateVector>(4, + [&](size_t i) { + return builder.CreateSharedString(names[i]); + }); + + // Creating vectors of strings in one convenient call. + std::vector names2 = { "jane", "mary" }; + auto vecofstrings2 = builder.CreateVectorOfStrings(names2); // Create an array of sorted tables, can be used with binary search when read: auto vecoftables = builder.CreateVectorOfSortedTables(mlocs, 3); @@ -128,7 +132,9 @@ flatbuffers::unique_ptr_t CreateFlatBufferTest(std::string &buffer) { // shortcut for creating monster with all fields set: auto mloc = CreateMonster(builder, &vec, 150, 80, name, inventory, Color_Blue, Any_Monster, mlocs[1].Union(), // Store a union. - testv, vecofstrings, vecoftables, 0); + testv, vecofstrings, vecoftables, 0, 0, 0, false, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3.14159f, 3.0f, 0.0f, + vecofstrings2); FinishMonsterBuffer(builder, mloc); @@ -198,6 +204,13 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length) { TEST_EQ(vecofstrings->Get(0)->c_str(), vecofstrings->Get(2)->c_str()); TEST_EQ(vecofstrings->Get(1)->c_str(), vecofstrings->Get(3)->c_str()); + auto vecofstrings2 = monster->testarrayofstring2(); + if (vecofstrings2) { + TEST_EQ(vecofstrings2->Length(), 2U); + TEST_EQ_STR(vecofstrings2->Get(0)->c_str(), "jane"); + TEST_EQ_STR(vecofstrings2->Get(1)->c_str(), "mary"); + } + // Example of accessing a vector of tables: auto vecoftables = monster->testarrayoftables(); TEST_EQ(vecoftables->Length(), 3U); From d3ac0bc149a9e62feec8e3a00f10ca88491e2254 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 15 Jun 2016 13:54:17 -0700 Subject: [PATCH 24/42] Added conversion operations that can be used inline in JSON. e.g.: { myfield: cos(rad(180)) } is equivalent to writing { myfield: -1.0 } Bug: 29338398 Change-Id: I6fc4ef1fd10bda3ba78cba464414dd071a2f50ca Tested: on Linux. --- docs/source/Schemas.md | 4 ++++ src/idl_parser.cpp | 34 ++++++++++++++++++++++++++++++++-- tests/test.cpp | 23 ++++++++++++++++------- 3 files changed, 52 insertions(+), 9 deletions(-) diff --git a/docs/source/Schemas.md b/docs/source/Schemas.md index 4004803de..14bd3bd0e 100755 --- a/docs/source/Schemas.md +++ b/docs/source/Schemas.md @@ -333,6 +333,10 @@ JSON: - A field that has the value `null` (e.g. `field: null`) is intended to have the default value for that field (thus has the same effect as if that field wasn't specified at all). +- It has some built in conversion functions, so you can write for example + `rad(180)` where ever you'd normally write `3.14159`. + Currently supports the following functions: `rad`, `deg`, `cos`, `sin`, + `tan`, `acos`, `asin`, `atan`. When parsing JSON, it recognizes the following escape codes in strings: diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index f5badab16..66e794b3d 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -17,6 +17,14 @@ #include #include +#ifdef _WIN32 +#if !defined(_USE_MATH_DEFINES) +#define _USE_MATH_DEFINES // For M_PI. +#endif // !defined(_USE_MATH_DEFINES) +#endif // _WIN32 + +#include + #include "flatbuffers/idl.h" #include "flatbuffers/util.h" @@ -1004,8 +1012,30 @@ CheckedError Parser::ParseHash(Value &e, FieldDef* field) { } CheckedError Parser::ParseSingleValue(Value &e) { - // First check if this could be a string/identifier enum value: - if (e.type.base_type != BASE_TYPE_STRING && + // First see if this could be a conversion function: + if (token_ == kTokenIdentifier && *cursor_ == '(') { + auto functionname = attribute_; + NEXT(); + EXPECT('('); + ECHECK(ParseSingleValue(e)); + EXPECT(')'); + #define FLATBUFFERS_FN_DOUBLE(name, op) \ + if (functionname == name) { \ + auto x = strtod(e.constant.c_str(), nullptr); \ + e.constant = NumToString(op); \ + } + FLATBUFFERS_FN_DOUBLE("deg", x / M_PI * 180); + FLATBUFFERS_FN_DOUBLE("rad", x * M_PI / 180); + FLATBUFFERS_FN_DOUBLE("sin", sin(x)); + FLATBUFFERS_FN_DOUBLE("cos", cos(x)); + FLATBUFFERS_FN_DOUBLE("tan", tan(x)); + FLATBUFFERS_FN_DOUBLE("asin", asin(x)); + FLATBUFFERS_FN_DOUBLE("acos", acos(x)); + FLATBUFFERS_FN_DOUBLE("atan", atan(x)); + // TODO(wvo): add more useful conversion functions here. + #undef FLATBUFFERS_FN_DOUBLE + // Then check if this could be a string/identifier enum value: + } else if (e.type.base_type != BASE_TYPE_STRING && e.type.base_type != BASE_TYPE_NONE && (token_ == kTokenIdentifier || token_ == kTokenStringConstant)) { if (IsIdentifierStart(attribute_[0])) { // Enum value. diff --git a/tests/test.cpp b/tests/test.cpp index bd85da231..73e009c20 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -814,20 +814,29 @@ void ErrorTest() { TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "more than once"); } -// Additional parser testing not covered elsewhere. -void ScientificTest() { +float TestValue(const char *json) { flatbuffers::Parser parser; // Simple schema. TEST_EQ(parser.Parse("table X { Y:float; } root_type X;"), true); - // Test scientific notation numbers. - TEST_EQ(parser.Parse("{ Y:0.0314159e+2 }"), true); + TEST_EQ(parser.Parse(json), true); auto root = flatbuffers::GetRoot(parser.builder_.GetBufferPointer()); // root will point to the table, which is a 32bit vtable offset followed // by a float: - TEST_EQ(sizeof(flatbuffers::soffset_t) == 4 && // Test assumes 32bit offsets - fabs(root[1] - 3.14159) < 0.001, true); + TEST_EQ(sizeof(flatbuffers::soffset_t), 4); // Test assumes 32bit offsets + return root[1]; +} + +bool FloatCompare(float a, float b) { return fabs(a - b) < 0.001; } + +// Additional parser testing not covered elsewhere. +void ValueTest() { + // Test scientific notation numbers. + TEST_EQ(FloatCompare(TestValue("{ Y:0.0314159e+2 }"), 3.14159), true); + + // Test conversion functions. + TEST_EQ(FloatCompare(TestValue("{ Y:cos(rad(180)) }"), -1), true); } void EnumStringsTest() { @@ -963,7 +972,7 @@ int main(int /*argc*/, const char * /*argv*/[]) { FuzzTest2(); ErrorTest(); - ScientificTest(); + ValueTest(); EnumStringsTest(); IntegerOutOfRangeTest(); UnicodeTest(); From fd43d3709e7fd84b201e0a80da0238b8b690191a Mon Sep 17 00:00:00 2001 From: rw Date: Sat, 18 Jun 2016 01:12:56 -0700 Subject: [PATCH 25/42] Fix test using compat.binary_types (from March). --- tests/py_test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/py_test.py b/tests/py_test.py index d12cfb43d..82f839005 100644 --- a/tests/py_test.py +++ b/tests/py_test.py @@ -162,9 +162,10 @@ class TestFuzz(unittest.TestCase): ''' Low level stress/fuzz test: serialize/deserialize a variety of different kinds of data in different combinations ''' - ofInt32Bytes = compat.binary_type([0x83, 0x33, 0x33, 0x33]) - ofInt64Bytes = compat.binary_type([0x84, 0x44, 0x44, 0x44, - 0x44, 0x44, 0x44, 0x44]) + binary_type = compat.binary_types[0] # this will always exist + ofInt32Bytes = binary_type([0x83, 0x33, 0x33, 0x33]) + ofInt64Bytes = binary_type([0x84, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44]) overflowingInt32Val = flatbuffers.encode.Get(flatbuffers.packer.int32, ofInt32Bytes, 0) overflowingInt64Val = flatbuffers.encode.Get(flatbuffers.packer.int64, From 3639032d1e2224663202f79ca33c5039eed95f29 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Fri, 17 Jun 2016 18:16:11 -0700 Subject: [PATCH 26/42] Allow unions of table types with the same name but from different namespaces. Also fixed most codegenerators using the wrong namespace when multiple namespace were used in a file, with some files not being generated. Change-Id: Ib42969221239d7244e431cbd667ef69200fc415f Tested: on Linux. Bug: 29338474 --- include/flatbuffers/code_generators.h | 23 ++-- src/idl_gen_general.cpp | 36 ++++--- src/idl_gen_go.cpp | 5 +- src/idl_gen_php.cpp | 7 +- src/idl_gen_python.cpp | 5 +- src/idl_parser.cpp | 8 +- tests/MyGame/Example/Any.cs | 1 + tests/MyGame/Example/Any.go | 1 + tests/MyGame/Example/Any.java | 3 +- tests/MyGame/Example/Any.php | 2 + tests/MyGame/Example/Any.py | 1 + tests/MyGame/Example2/Monster.cs | 23 ++++ tests/MyGame/Example2/Monster.go | 18 ++++ tests/MyGame/Example2/Monster.java | 23 ++++ tests/MyGame/Example2/Monster.php | 79 ++++++++++++++ tests/MyGame/Example2/Monster.py | 15 +++ tests/monster_test.bfbs | Bin 3008 -> 3152 bytes tests/monster_test.fbs | 6 +- tests/monster_test_generated.h | 43 +++++++- tests/monster_test_generated.js | 59 ++++++++++- tests/namespace_test/NamespaceC/TableInC.cs | 38 +++++++ tests/namespace_test/NamespaceC/TableInC.go | 46 ++++++++ tests/namespace_test/NamespaceC/TableInC.java | 38 +++++++ tests/namespace_test/NamespaceC/TableInC.php | 100 ++++++++++++++++++ tests/namespace_test/NamespaceC/TableInC.py | 39 +++++++ 25 files changed, 584 insertions(+), 35 deletions(-) create mode 100644 tests/MyGame/Example2/Monster.cs create mode 100644 tests/MyGame/Example2/Monster.go create mode 100644 tests/MyGame/Example2/Monster.java create mode 100644 tests/MyGame/Example2/Monster.php create mode 100644 tests/MyGame/Example2/Monster.py create mode 100644 tests/namespace_test/NamespaceC/TableInC.cs create mode 100644 tests/namespace_test/NamespaceC/TableInC.go create mode 100644 tests/namespace_test/NamespaceC/TableInC.java create mode 100644 tests/namespace_test/NamespaceC/TableInC.php create mode 100644 tests/namespace_test/NamespaceC/TableInC.py diff --git a/include/flatbuffers/code_generators.h b/include/flatbuffers/code_generators.h index 95fa0c1ac..dc5f6bdd8 100644 --- a/include/flatbuffers/code_generators.h +++ b/include/flatbuffers/code_generators.h @@ -24,11 +24,12 @@ class BaseGenerator { virtual bool generate() = 0; static const std::string NamespaceDir(const Parser &parser, - const std::string &path) { + const std::string &path, + const Namespace &ns) { EnsureDirExists(path.c_str()); if (parser.opts.one_file) return path; std::string namespace_dir = path; // Either empty or ends in separator. - auto &namespaces = parser.namespaces_.back()->components; + auto &namespaces = ns.components; for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { namespace_dir += *it + kPathSeparator; EnsureDirExists(namespace_dir.c_str()); @@ -41,14 +42,17 @@ class BaseGenerator { const std::string &file_name) : parser_(parser), path_(path), - file_name_(file_name), - namespace_dir_(BaseGenerator::NamespaceDir(parser, path)){}; - virtual ~BaseGenerator(){}; + file_name_(file_name) {}; + virtual ~BaseGenerator() {}; // No copy/assign. BaseGenerator &operator=(const BaseGenerator &); BaseGenerator(const BaseGenerator &); + const std::string NamespaceDir(const Namespace &ns) { + return BaseGenerator::NamespaceDir(parser_, path_, ns); + } + const char *FlatBuffersGeneratedWarning() { return "automatically generated by the FlatBuffers compiler," " do not modify\n\n"; @@ -66,9 +70,9 @@ class BaseGenerator { return true; } - std::string FullNamespace(const char *separator) { + std::string FullNamespace(const char *separator, const Namespace &ns) { std::string namespace_name; - auto &namespaces = parser_.namespaces_.back()->components; + auto &namespaces = ns.components; for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { if (namespace_name.length()) namespace_name += separator; namespace_name += *it; @@ -76,15 +80,14 @@ class BaseGenerator { return namespace_name; } - const std::string LastNamespacePart() { - auto &namespaces = parser_.namespaces_.back()->components; + const std::string LastNamespacePart(const Namespace &ns) { + auto &namespaces = ns.components; if (namespaces.size()) return *(namespaces.end() - 1); else return std::string(""); } const Parser &parser_; const std::string &path_; const std::string &file_name_; - const std::string namespace_dir_; }; } // namespace flatbuffers diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index a0b837a20..36dbd64ba 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -1129,27 +1129,32 @@ class GeneralGenerator : public BaseGenerator { for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); ++it) { std::string enumcode; - GenEnum(lang, parser_, **it, &enumcode); + auto &enum_def = **it; + GenEnum(lang, parser_, enum_def, &enumcode); if (parser_.opts.one_file) { one_file_code += enumcode; } else { - if (!SaveType(lang, (**it).name, enumcode, false)) return false; + if (!SaveType(lang, enum_def.name, *enum_def.defined_namespace, + enumcode, false)) return false; } } for (auto it = parser_.structs_.vec.begin(); it != parser_.structs_.vec.end(); ++it) { std::string declcode; - GenStruct(lang, parser_, **it, &declcode); + auto &struct_def = **it; + GenStruct(lang, parser_, struct_def, &declcode); if (parser_.opts.one_file) { one_file_code += declcode; } else { - if (!SaveType(lang, (**it).name, declcode, true)) return false; + if (!SaveType(lang, struct_def.name, *struct_def.defined_namespace, + declcode, true)) return false; } } if (parser_.opts.one_file) { - return SaveType(lang, file_name_, one_file_code, true); + return SaveType(lang, file_name_, *parser_.namespaces_.back(), + one_file_code, true); } return true; } @@ -1157,12 +1162,13 @@ class GeneralGenerator : public BaseGenerator { // Save out the generated code for a single class while adding // declaration boilerplate. bool SaveType(const LanguageParameters &lang, const std::string &defname, - const std::string &classcode, bool needs_includes) { + const Namespace &ns, const std::string &classcode, + bool needs_includes) { if (!classcode.length()) return true; std::string code; code = code + "// " + FlatBuffersGeneratedWarning(); - std::string namespace_name = FullNamespace("."); + std::string namespace_name = FullNamespace(".", ns); if (!namespace_name.empty()) { code += lang.namespace_ident + namespace_name + lang.namespace_begin; code += "\n\n"; @@ -1170,7 +1176,7 @@ class GeneralGenerator : public BaseGenerator { if (needs_includes) code += lang.includes; code += classcode; if (!namespace_name.empty()) code += lang.namespace_end; - auto filename = namespace_dir_ + defname + lang.file_extension; + auto filename = NamespaceDir(ns) + defname + lang.file_extension; return SaveFile(filename.c_str(), code, false); } }; @@ -1188,19 +1194,25 @@ std::string GeneralMakeRule(const Parser &parser, const std::string &path, auto lang = language_parameters[parser.opts.lang]; std::string make_rule; - std::string directory = - BaseGenerator::NamespaceDir(parser, path) + kPathSeparator; for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end(); ++it) { + auto &enum_def = **it; if (make_rule != "") make_rule += " "; - make_rule += directory + (**it).name + lang.file_extension; + std::string directory = + BaseGenerator::NamespaceDir(parser, path, *enum_def.defined_namespace) + + kPathSeparator; + make_rule += directory + enum_def.name + lang.file_extension; } for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); ++it) { + auto &struct_def = **it; if (make_rule != "") make_rule += " "; - make_rule += directory + (**it).name + lang.file_extension; + std::string directory = + BaseGenerator::NamespaceDir(parser, path, *struct_def.defined_namespace) + + kPathSeparator; + make_rule += directory + struct_def.name + lang.file_extension; } make_rule += ": "; diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 5841e121c..5c60c1052 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -664,9 +664,10 @@ class GoGenerator : public BaseGenerator { if (!classcode.length()) return true; std::string code = ""; - BeginFile(LastNamespacePart(), needs_imports, &code); + BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code); code += classcode; - std::string filename = namespace_dir_ + def.name + ".go"; + std::string filename = + NamespaceDir(*def.defined_namespace) + def.name + ".go"; return SaveFile(filename.c_str(), code, false); } }; diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index 599d5571d..68ddc8171 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -985,11 +985,12 @@ namespace php { if (!classcode.length()) return true; std::string code = ""; - BeginFile(FullNamespace("\\"), needs_imports, &code); + BeginFile(FullNamespace("\\", *def.defined_namespace), + needs_imports, &code); code += classcode; - std::string filename = - namespace_dir_ + kPathSeparator + def.name + ".php"; + std::string filename = NamespaceDir(*def.defined_namespace) + + kPathSeparator + def.name + ".php"; return SaveFile(filename.c_str(), code, false); } }; diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index 7b8d168c1..5f5c6be3b 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -652,9 +652,10 @@ class PythonGenerator : public BaseGenerator { } std::string code = ""; - BeginFile(LastNamespacePart(), needs_imports, &code); + BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code); code += classcode; - std::string filename = namespace_dir_ + kPathSeparator + def.name + ".py"; + std::string filename = NamespaceDir(*def.defined_namespace) + + kPathSeparator + def.name + ".py"; return SaveFile(filename.c_str(), code, false); } }; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 66e794b3d..518283de5 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1180,7 +1180,13 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { auto full_name = value_name; std::vector value_comment = doc_comment_; EXPECT(kTokenIdentifier); - if (is_union) ECHECK(ParseNamespacing(&full_name, &value_name)); + if (is_union) { + ECHECK(ParseNamespacing(&full_name, &value_name)); + // Since we can't namespace the actual enum identifiers, turn + // namespace parts into part of the identifier. + value_name = full_name; + std::replace(value_name.begin(), value_name.end(), '.', '_'); + } auto prevsize = enum_def.vals.vec.size(); auto value = enum_def.vals.vec.size() ? enum_def.vals.vec.back()->value + 1 diff --git a/tests/MyGame/Example/Any.cs b/tests/MyGame/Example/Any.cs index 1f018ad89..8fdc2fca1 100644 --- a/tests/MyGame/Example/Any.cs +++ b/tests/MyGame/Example/Any.cs @@ -8,6 +8,7 @@ public enum Any : byte NONE = 0, Monster = 1, TestSimpleTableWithEnum = 2, + MyGame_Example2_Monster = 3, }; diff --git a/tests/MyGame/Example/Any.go b/tests/MyGame/Example/Any.go index 0322364c6..df9f823fc 100644 --- a/tests/MyGame/Example/Any.go +++ b/tests/MyGame/Example/Any.go @@ -6,4 +6,5 @@ const ( AnyNONE = 0 AnyMonster = 1 AnyTestSimpleTableWithEnum = 2 + AnyMyGame_Example2_Monster = 3 ) diff --git a/tests/MyGame/Example/Any.java b/tests/MyGame/Example/Any.java index 27dc1bcb9..25d74af55 100644 --- a/tests/MyGame/Example/Any.java +++ b/tests/MyGame/Example/Any.java @@ -7,8 +7,9 @@ public final class Any { public static final byte NONE = 0; public static final byte Monster = 1; public static final byte TestSimpleTableWithEnum = 2; + public static final byte MyGame_Example2_Monster = 3; - private static final String[] names = { "NONE", "Monster", "TestSimpleTableWithEnum", }; + private static final String[] names = { "NONE", "Monster", "TestSimpleTableWithEnum", "MyGame_Example2_Monster", }; public static String name(int e) { return names[e]; } }; diff --git a/tests/MyGame/Example/Any.php b/tests/MyGame/Example/Any.php index f04f4ad3f..da691760c 100644 --- a/tests/MyGame/Example/Any.php +++ b/tests/MyGame/Example/Any.php @@ -8,11 +8,13 @@ class Any const NONE = 0; const Monster = 1; const TestSimpleTableWithEnum = 2; + const MyGame_Example2_Monster = 3; private static $names = array( "NONE", "Monster", "TestSimpleTableWithEnum", + "MyGame_Example2_Monster", ); public static function Name($e) diff --git a/tests/MyGame/Example/Any.py b/tests/MyGame/Example/Any.py index b642ede01..f1b8d519d 100644 --- a/tests/MyGame/Example/Any.py +++ b/tests/MyGame/Example/Any.py @@ -6,4 +6,5 @@ class Any(object): NONE = 0 Monster = 1 TestSimpleTableWithEnum = 2 + MyGame_Example2_Monster = 3 diff --git a/tests/MyGame/Example2/Monster.cs b/tests/MyGame/Example2/Monster.cs new file mode 100644 index 000000000..e6c512abc --- /dev/null +++ b/tests/MyGame/Example2/Monster.cs @@ -0,0 +1,23 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +namespace MyGame.Example2 +{ + +using System; +using FlatBuffers; + +public sealed class Monster : Table { + public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } + public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(0); } + public static Offset EndMonster(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return new Offset(o); + } +}; + + +} diff --git a/tests/MyGame/Example2/Monster.go b/tests/MyGame/Example2/Monster.go new file mode 100644 index 000000000..e12b05453 --- /dev/null +++ b/tests/MyGame/Example2/Monster.go @@ -0,0 +1,18 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package Example2 + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) +type Monster struct { + _tab flatbuffers.Table +} + +func (rcv *Monster) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func MonsterStart(builder *flatbuffers.Builder) { builder.StartObject(0) } +func MonsterEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } diff --git a/tests/MyGame/Example2/Monster.java b/tests/MyGame/Example2/Monster.java new file mode 100644 index 000000000..6432494f3 --- /dev/null +++ b/tests/MyGame/Example2/Monster.java @@ -0,0 +1,23 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package MyGame.Example2; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Monster extends Table { + public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); } + public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + + public static void startMonster(FlatBufferBuilder builder) { builder.startObject(0); } + public static int endMonster(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +}; + diff --git a/tests/MyGame/Example2/Monster.php b/tests/MyGame/Example2/Monster.php new file mode 100644 index 000000000..b00f150e5 --- /dev/null +++ b/tests/MyGame/Example2/Monster.php @@ -0,0 +1,79 @@ +init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); + } + + public static function MonsterIdentifier() + { + return "MONS"; + } + + public static function MonsterBufferHasIdentifier(ByteBuffer $buf) + { + return self::__has_identifier($buf, self::MonsterIdentifier()); + } + + public static function MonsterExtension() + { + return "mon"; + } + + /** + * @param int $_i offset + * @param ByteBuffer $_bb + * @return Monster + **/ + public function init($_i, ByteBuffer $_bb) + { + $this->bb_pos = $_i; + $this->bb = $_bb; + return $this; + } + + /** + * @param FlatBufferBuilder $builder + * @return void + */ + public static function startMonster(FlatBufferBuilder $builder) + { + $builder->StartObject(0); + } + + /** + * @param FlatBufferBuilder $builder + * @return Monster + */ + public static function createMonster(FlatBufferBuilder $builder, ) + { + $builder->startObject(0); + $o = $builder->endObject(); + return $o; + } + + /** + * @param FlatBufferBuilder $builder + * @return int table offset + */ + public static function endMonster(FlatBufferBuilder $builder) + { + $o = $builder->endObject(); + return $o; + } +} diff --git a/tests/MyGame/Example2/Monster.py b/tests/MyGame/Example2/Monster.py new file mode 100644 index 000000000..0b98211e4 --- /dev/null +++ b/tests/MyGame/Example2/Monster.py @@ -0,0 +1,15 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: Example2 + +import flatbuffers + +class Monster(object): + __slots__ = ['_tab'] + + # Monster + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + +def MonsterStart(builder): builder.StartObject(0) +def MonsterEnd(builder): return builder.EndObject() diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index e16b2bd13ce4dce50406e3a089d132f4ebf28688..e131ac8c2ee97914bfc1c02ce683ac4f5ecb43d6 100644 GIT binary patch delta 1100 zcmYjPO-NKx82#>>nK$o^Gioy8&y0+#M1wSc5e!Q-Tcj09*h(iF(-=q7A)FwLf`|}F zzLEli7A_1VibM!RL?SdIB&2eYNUIhu+Gve`uXEp3@WFZKo_D_cy>ox&vX-*LK_aR< zQ+El3CzZ0vNd|c-o%~RQH&F>t1Jnbp8j&0PA%*B1#xn+y6XU3dXbs$A5;@?@IYEKC zkt!n!Iwp?DSZ<&8;0Wr);tys)*p`+2% z|Je&q>E(o@SiIy{jsmkoee*2wile|Ys+37d_BfB4AC)vpxY}7@ZYt$&=PszDNxPZn zF+Yd8tdu#&i%<`gGX8K9YFa6GJ{P(|=BiTKS-$8B`DVB5E@@aG#rck_Oib`wSHPER zFM`srctSK+u`Wl>ZBEsXi*i1xA9Gl$-OMR6)c6a-v z*Lg$l5nCK__lp>>xNF60&M_LrCWnns>X%)W1BXZHyF6?Zi8uV-2$(mNp<_3VEb)jp zj4E?pee*@R!mKTf;?lV&*FF~+0e8SYmoo4wJW!g<`h;JYfk7P?4Z@Bz1J{8oDNpq9 z%oEVJ)J*RhSVM)Z@d9!iZUdvrPa*UZ`*-%hPr#qv_kV*A%{@W`Fu(4b3*dLHo=TCC TeyD{C!xyw{Twfv{N-6&j>n02Z delta 964 zcmYjPZ%9*76u)fqNHF+e<1o0VIk2cF(@!77!g8YAQ8*7T)+G73LpIVo!{@Ad+xcsGhbXe2mRQyOG-sdZ6M4}7Xz^Xbwd``OSl4dOC^H=@$fSk7# zm&fp!*Wf`M?FByt?*+0F$YtbX;b%eT5my6gTzMC`4zC5+2E?HIFy<^!EXRee1&;!6 zA#X!Z{mkb>Y@eK-j=R_Le(H2r@Ch1o$3+e~l=(X73%p?}(aOXz%nHw(q(-gG98yXw zEK*8~h$l)KrF0Lab4qzz=snc>U+Ul>3B61-C?y_H4b(-Yj4X9RjVt91(3l<;(@MFj z>4hG)CYGEoMe;SL>6>23M`?>EWSPs#hs`jWr$R0e`>{m*o?Uz^-S_O!@mSVMA5r{D z70aK=`bhVNUEh}};*DC7-%c0j*M6Xc_Z 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 { VT_COLOR = 4 @@ -424,6 +462,7 @@ inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, An case Any_NONE: return true; case Any_Monster: return verifier.VerifyTable(reinterpret_cast(union_obj)); case Any_TestSimpleTableWithEnum: return verifier.VerifyTable(reinterpret_cast(union_obj)); + case Any_MyGame_Example2_Monster: return verifier.VerifyTable(reinterpret_cast(union_obj)); default: return false; } } diff --git a/tests/monster_test_generated.js b/tests/monster_test_generated.js index f967b9d83..f67e84802 100644 --- a/tests/monster_test_generated.js +++ b/tests/monster_test_generated.js @@ -10,6 +10,11 @@ var MyGame = MyGame || {}; */ MyGame.Example = MyGame.Example || {}; +/** + * @const +*/ +MyGame.Example2 = MyGame.Example2 || {}; + /** * @const */ @@ -30,7 +35,59 @@ MyGame.Example.Color = { MyGame.Example.Any = { NONE: 0, Monster: 1, - TestSimpleTableWithEnum: 2 + TestSimpleTableWithEnum: 2, + MyGame_Example2_Monster: 3 +}; + +/** + * @constructor + */ +MyGame.Example2.Monster = function() { + /** + * @type {flatbuffers.ByteBuffer} + */ + this.bb = null; + + /** + * @type {number} + */ + this.bb_pos = 0; +}; + +/** + * @param {number} i + * @param {flatbuffers.ByteBuffer} bb + * @returns {MyGame.Example2.Monster} + */ +MyGame.Example2.Monster.prototype.__init = function(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; +}; + +/** + * @param {flatbuffers.ByteBuffer} bb + * @param {MyGame.Example2.Monster=} obj + * @returns {MyGame.Example2.Monster} + */ +MyGame.Example2.Monster.getRootAsMonster = function(bb, obj) { + return (obj || new MyGame.Example2.Monster).__init(bb.readInt32(bb.position()) + bb.position(), bb); +}; + +/** + * @param {flatbuffers.Builder} builder + */ +MyGame.Example2.Monster.startMonster = function(builder) { + builder.startObject(0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @returns {flatbuffers.Offset} + */ +MyGame.Example2.Monster.endMonster = function(builder) { + var offset = builder.endObject(); + return offset; }; /** diff --git a/tests/namespace_test/NamespaceC/TableInC.cs b/tests/namespace_test/NamespaceC/TableInC.cs new file mode 100644 index 000000000..0f75dfec9 --- /dev/null +++ b/tests/namespace_test/NamespaceC/TableInC.cs @@ -0,0 +1,38 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +namespace NamespaceC +{ + +using System; +using FlatBuffers; + +public sealed class TableInC : Table { + public static TableInC GetRootAsTableInC(ByteBuffer _bb) { return GetRootAsTableInC(_bb, new TableInC()); } + public static TableInC GetRootAsTableInC(ByteBuffer _bb, TableInC obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public TableInC __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public NamespaceA.TableInFirstNS ReferToA1 { get { return GetReferToA1(new NamespaceA.TableInFirstNS()); } } + public NamespaceA.TableInFirstNS GetReferToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + public SecondTableInA ReferToA2 { get { return GetReferToA2(new SecondTableInA()); } } + public SecondTableInA GetReferToA2(SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + + public static Offset CreateTableInC(FlatBufferBuilder builder, + Offset refer_to_a1Offset = default(Offset), + Offset refer_to_a2Offset = default(Offset)) { + builder.StartObject(2); + TableInC.AddReferToA2(builder, refer_to_a2Offset); + TableInC.AddReferToA1(builder, refer_to_a1Offset); + return TableInC.EndTableInC(builder); + } + + public static void StartTableInC(FlatBufferBuilder builder) { builder.StartObject(2); } + public static void AddReferToA1(FlatBufferBuilder builder, Offset referToA1Offset) { builder.AddOffset(0, referToA1Offset.Value, 0); } + public static void AddReferToA2(FlatBufferBuilder builder, Offset referToA2Offset) { builder.AddOffset(1, referToA2Offset.Value, 0); } + public static Offset EndTableInC(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return new Offset(o); + } +}; + + +} diff --git a/tests/namespace_test/NamespaceC/TableInC.go b/tests/namespace_test/NamespaceC/TableInC.go new file mode 100644 index 000000000..dc75c45c2 --- /dev/null +++ b/tests/namespace_test/NamespaceC/TableInC.go @@ -0,0 +1,46 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package NamespaceC + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) +type TableInC struct { + _tab flatbuffers.Table +} + +func (rcv *TableInC) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *TableInC) ReferToA1(obj *TableInFirstNS) *TableInFirstNS { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(TableInFirstNS) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func (rcv *TableInC) ReferToA2(obj *SecondTableInA) *SecondTableInA { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(SecondTableInA) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func TableInCStart(builder *flatbuffers.Builder) { builder.StartObject(2) } +func TableInCAddReferToA1(builder *flatbuffers.Builder, referToA1 flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(referToA1), 0) } +func TableInCAddReferToA2(builder *flatbuffers.Builder, referToA2 flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(referToA2), 0) } +func TableInCEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } diff --git a/tests/namespace_test/NamespaceC/TableInC.java b/tests/namespace_test/NamespaceC/TableInC.java new file mode 100644 index 000000000..cf1bca18c --- /dev/null +++ b/tests/namespace_test/NamespaceC/TableInC.java @@ -0,0 +1,38 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package NamespaceC; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class TableInC extends Table { + public static TableInC getRootAsTableInC(ByteBuffer _bb) { return getRootAsTableInC(_bb, new TableInC()); } + public static TableInC getRootAsTableInC(ByteBuffer _bb, TableInC obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public TableInC __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public NamespaceA.TableInFirstNS referToA1() { return referToA1(new NamespaceA.TableInFirstNS()); } + public NamespaceA.TableInFirstNS referToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + public SecondTableInA referToA2() { return referToA2(new SecondTableInA()); } + public SecondTableInA referToA2(SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + + public static int createTableInC(FlatBufferBuilder builder, + int refer_to_a1Offset, + int refer_to_a2Offset) { + builder.startObject(2); + TableInC.addReferToA2(builder, refer_to_a2Offset); + TableInC.addReferToA1(builder, refer_to_a1Offset); + return TableInC.endTableInC(builder); + } + + public static void startTableInC(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addReferToA1(FlatBufferBuilder builder, int referToA1Offset) { builder.addOffset(0, referToA1Offset, 0); } + public static void addReferToA2(FlatBufferBuilder builder, int referToA2Offset) { builder.addOffset(1, referToA2Offset, 0); } + public static int endTableInC(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +}; + diff --git a/tests/namespace_test/NamespaceC/TableInC.php b/tests/namespace_test/NamespaceC/TableInC.php new file mode 100644 index 000000000..116aea1f9 --- /dev/null +++ b/tests/namespace_test/NamespaceC/TableInC.php @@ -0,0 +1,100 @@ +init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); + } + + /** + * @param int $_i offset + * @param ByteBuffer $_bb + * @return TableInC + **/ + public function init($_i, ByteBuffer $_bb) + { + $this->bb_pos = $_i; + $this->bb = $_bb; + return $this; + } + + public function getReferToA1() + { + $obj = new TableInFirstNS(); + $o = $this->__offset(4); + return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0; + } + + public function getReferToA2() + { + $obj = new SecondTableInA(); + $o = $this->__offset(6); + return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0; + } + + /** + * @param FlatBufferBuilder $builder + * @return void + */ + public static function startTableInC(FlatBufferBuilder $builder) + { + $builder->StartObject(2); + } + + /** + * @param FlatBufferBuilder $builder + * @return TableInC + */ + public static function createTableInC(FlatBufferBuilder $builder, $refer_to_a1, $refer_to_a2) + { + $builder->startObject(2); + self::addReferToA1($builder, $refer_to_a1); + self::addReferToA2($builder, $refer_to_a2); + $o = $builder->endObject(); + return $o; + } + + /** + * @param FlatBufferBuilder $builder + * @param int + * @return void + */ + public static function addReferToA1(FlatBufferBuilder $builder, $referToA1) + { + $builder->addOffsetX(0, $referToA1, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @param int + * @return void + */ + public static function addReferToA2(FlatBufferBuilder $builder, $referToA2) + { + $builder->addOffsetX(1, $referToA2, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @return int table offset + */ + public static function endTableInC(FlatBufferBuilder $builder) + { + $o = $builder->endObject(); + return $o; + } +} diff --git a/tests/namespace_test/NamespaceC/TableInC.py b/tests/namespace_test/NamespaceC/TableInC.py new file mode 100644 index 000000000..5a4376ed8 --- /dev/null +++ b/tests/namespace_test/NamespaceC/TableInC.py @@ -0,0 +1,39 @@ +# automatically generated by the FlatBuffers compiler, do not modify + +# namespace: NamespaceC + +import flatbuffers + +class TableInC(object): + __slots__ = ['_tab'] + + # TableInC + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # TableInC + def ReferToA1(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + x = self._tab.Indirect(o + self._tab.Pos) + from .TableInFirstNS import TableInFirstNS + obj = TableInFirstNS() + obj.Init(self._tab.Bytes, x) + return obj + return None + + # TableInC + def ReferToA2(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + if o != 0: + x = self._tab.Indirect(o + self._tab.Pos) + from .SecondTableInA import SecondTableInA + obj = SecondTableInA() + obj.Init(self._tab.Bytes, x) + return obj + return None + +def TableInCStart(builder): builder.StartObject(2) +def TableInCAddReferToA1(builder, referToA1): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(referToA1), 0) +def TableInCAddReferToA2(builder, referToA2): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(referToA2), 0) +def TableInCEnd(builder): return builder.EndObject() From 9e6c5f9f2c543a5ca608e8c1c4c9205139a87dcd Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 20 Jun 2016 16:06:30 -0700 Subject: [PATCH 27/42] JSON Parser allows union type fields to come after unions. This is useful because many JSON generators will sort the fields, cause X_type to follow X. Change-Id: I00ef3ac05418224fc05aee93e6b3b3597e73ffe3 Tested: on Linux. Bug: 29221752 --- include/flatbuffers/idl.h | 28 +++++++++++------ include/flatbuffers/reflection.h | 4 ++- src/idl_gen_cpp.cpp | 12 ++++---- src/idl_parser.cpp | 53 ++++++++++++++++++++++++-------- tests/test.cpp | 13 +++++++- 5 files changed, 80 insertions(+), 30 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index dc385efa3..e3027259b 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -359,6 +359,19 @@ struct IDLOptions { lang(IDLOptions::kJava) {} }; +// This encapsulates where the parser is in the current source file. +struct ParserState { + ParserState() : cursor_(nullptr), line_(1), token_(-1) {} + + protected: + const char *cursor_; + int line_; // the current line being parsed + int token_; + + std::string attribute_; + std::vector doc_comment_; +}; + // A way to make error propagation less error prone by requiring values to be // checked. // Once you create a value of this type you must either: @@ -400,14 +413,12 @@ class CheckedError { #define FLATBUFFERS_CHECKED_ERROR CheckedError #endif -class Parser { +class Parser : public ParserState { public: explicit Parser(const IDLOptions &options = IDLOptions()) : root_struct_def_(nullptr), opts(options), source_(nullptr), - cursor_(nullptr), - line_(1), anonymous_counter(0) { // Just in case none are declared: namespaces_.push_back(new Namespace()); @@ -478,7 +489,8 @@ private: FieldDef **dest); FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def); FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, - size_t parent_fieldn); + size_t parent_fieldn, + const StructDef *parent_struct_def); FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def, std::string *value, uoffset_t *ovalue); void SerializeStruct(const StructDef &struct_def, const Value &val); @@ -538,13 +550,9 @@ private: IDLOptions opts; private: - const char *source_, *cursor_; - int line_; // the current line being parsed - int token_; - std::string file_being_parsed_; + const char *source_; - std::string attribute_; - std::vector doc_comment_; + std::string file_being_parsed_; std::vector> field_stack_; diff --git a/include/flatbuffers/reflection.h b/include/flatbuffers/reflection.h index ababe6ad4..87091438a 100644 --- a/include/flatbuffers/reflection.h +++ b/include/flatbuffers/reflection.h @@ -335,6 +335,8 @@ template pointer_inside_vector piv(T *ptr, return pointer_inside_vector(ptr, vec); } +inline const char *UnionTypeFieldSuffix() { return "_type"; } + // Helper to figure out the actual table type a union refers to. inline const reflection::Object &GetUnionType( const reflection::Schema &schema, const reflection::Object &parent, @@ -342,7 +344,7 @@ inline const reflection::Object &GetUnionType( auto enumdef = schema.enums()->Get(unionfield.type()->index()); // TODO: this is clumsy and slow, but no other way to find it? auto type_field = parent.fields()->LookupByKey( - (unionfield.name()->str() + "_type").c_str()); + (unionfield.name()->str() + UnionTypeFieldSuffix()).c_str()); assert(type_field); auto union_type = GetFieldI(table, *type_field); auto enumval = enumdef->values()->LookupByKey(union_type); diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index b1402d8e6..6c7981417 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -604,8 +604,8 @@ class CppGenerator : public BaseGenerator { 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())"; + code += "(verifier, " + field.name + "(), " + field.name + + UnionTypeFieldSuffix() + "())"; break; case BASE_TYPE_STRUCT: if (!field.value.type.struct_def->fixed) { @@ -868,8 +868,8 @@ class CppGenerator : public BaseGenerator { // 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, + // 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 = @@ -881,13 +881,13 @@ class CppGenerator : public BaseGenerator { 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 + // 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 + // 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"; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 518283de5..8fddb3c66 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -583,9 +583,9 @@ CheckedError Parser::ParseField(StructDef &struct_def) { FieldDef *typefield = nullptr; if (type.base_type == BASE_TYPE_UNION) { // For union fields, add a second auto-generated field to hold the type, - // with _type appended as the name. - ECHECK(AddField(struct_def, name + "_type", type.enum_def->underlying_type, - &typefield)); + // with a special suffix. + ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(), + type.enum_def->underlying_type, &typefield)); } FieldDef *field; @@ -686,17 +686,45 @@ CheckedError Parser::ParseField(StructDef &struct_def) { } CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, - size_t parent_fieldn) { + size_t parent_fieldn, + const StructDef *parent_struct_def) { switch (val.type.base_type) { case BASE_TYPE_UNION: { assert(field); + std::string constant; if (!parent_fieldn || - field_stack_.back().second->value.type.base_type != BASE_TYPE_UTYPE) - return Error("missing type field before this union value: " + - field->name); + field_stack_.back().second->value.type.base_type != BASE_TYPE_UTYPE) { + // We haven't seen the type field yet. Sadly a lot of JSON writers + // output these in alphabetical order, meaning it comes after this + // value. So we scan past the value to find it, then come back here. + auto type_name = field->name + UnionTypeFieldSuffix(); + assert(parent_struct_def); + auto type_field = parent_struct_def->fields.Lookup(type_name); + assert(type_field); // Guaranteed by ParseField(). + // Remember where we are in the source file, so we can come back here. + auto backup = *static_cast(this); + ECHECK(SkipAnyJsonValue()); // The table. + EXPECT(','); + auto next_name = attribute_; + if (Is(kTokenStringConstant)) { + NEXT(); + } else { + EXPECT(kTokenIdentifier); + } + if (next_name != type_name) + return Error("missing type field after this union value: " + + type_name); + EXPECT(':'); + Value type_val = type_field->value; + ECHECK(ParseAnyValue(type_val, type_field, 0, nullptr)); + constant = type_val.constant; + // Got the information we needed, now rewind: + *static_cast(this) = backup; + } else { + constant = field_stack_.back().first.constant; + } uint8_t enum_idx; - ECHECK(atot(field_stack_.back().first.constant.c_str(), *this, - &enum_idx)); + ECHECK(atot(constant.c_str(), *this, &enum_idx)); auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); if (!enum_val) return Error("illegal type id for: " + field->name); ECHECK(ParseTable(*enum_val->struct_def, &val.constant, nullptr)); @@ -771,7 +799,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, NEXT(); // Ignore this field. } else { Value val = field->value; - ECHECK(ParseAnyValue(val, field, fieldn)); + ECHECK(ParseAnyValue(val, field, fieldn, &struct_def)); size_t i = field_stack_.size(); // Hardcoded insertion-sort with error-check. // If fields are specified in order, then this loop exits immediately. @@ -870,7 +898,7 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { if ((!opts.strict_json || !count) && Is(']')) { NEXT(); break; } Value val; val.type = type; - ECHECK(ParseAnyValue(val, nullptr, 0)); + ECHECK(ParseAnyValue(val, nullptr, 0, nullptr)); field_stack_.push_back(std::make_pair(val, nullptr)); count++; if (Is(']')) { NEXT(); break; } @@ -1324,7 +1352,8 @@ CheckedError Parser::ParseDecl() { } } - ECHECK(CheckClash(fields, struct_def, "_type", BASE_TYPE_UNION)); + ECHECK(CheckClash(fields, struct_def, UnionTypeFieldSuffix(), + BASE_TYPE_UNION)); ECHECK(CheckClash(fields, struct_def, "Type", BASE_TYPE_UNION)); ECHECK(CheckClash(fields, struct_def, "_length", BASE_TYPE_VECTOR)); ECHECK(CheckClash(fields, struct_def, "Length", BASE_TYPE_VECTOR)); diff --git a/tests/test.cpp b/tests/test.cpp index 73e009c20..6f3b06299 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -783,7 +783,7 @@ void ErrorTest() { TestError("table X { Y:int; Y:int; }", "field already"); TestError("struct X { Y:string; }", "only scalar"); TestError("struct X { Y:int (deprecated); }", "deprecate"); - TestError("union Z { X } table X { Y:Z; } root_type X; { Y: {", + TestError("union Z { X } table X { Y:Z; } root_type X; { Y: {}, A:1 }", "missing type field"); TestError("union Z { X } table X { Y:Z; } root_type X; { Y_type: 99, Y: {", "type id"); @@ -951,6 +951,16 @@ void UnknownFieldsTest() { TEST_EQ(jsongen == "{str: \"test\",i: 10}", true); } +void ParseUnionTest() { + // Unions must be parseable with the type field following the object. + flatbuffers::Parser parser; + TEST_EQ(parser.Parse("table T { A:int; }" + "union U { T }" + "table V { X:U; }" + "root_type V;" + "{ X:{ A:1 }, X_type: T }"), true); +} + int main(int /*argc*/, const char * /*argv*/[]) { // Run our various test suites: @@ -979,6 +989,7 @@ int main(int /*argc*/, const char * /*argv*/[]) { UnicodeSurrogatesTest(); UnicodeInvalidSurrogatesTest(); UnknownFieldsTest(); + ParseUnionTest(); if (!testing_fails) { TEST_OUTPUT_LINE("ALL TESTS PASSED"); From 07d406684770f4b3cda6969b9cdd8724c4382a11 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 14:02:26 +0200 Subject: [PATCH 28/42] general: moved methods into the class --- src/idl_gen_general.cpp | 136 ++++++++++++++++++++-------------------- 1 file changed, 67 insertions(+), 69 deletions(-) diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 36dbd64ba..97006a199 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -188,6 +188,72 @@ static_assert(sizeof(language_parameters) / sizeof(LanguageParameters) == IDLOptions::kMAX, "Please add extra elements to the arrays above."); +namespace general { +class GeneralGenerator : public BaseGenerator { + public: + GeneralGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) + : BaseGenerator(parser, path, file_name){}; + bool generate() { + assert(parser_.opts.lang <= IDLOptions::kMAX); + auto lang = language_parameters[parser_.opts.lang]; + std::string one_file_code; + + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + std::string enumcode; + auto &enum_def = **it; + GenEnum(lang, parser_, enum_def, &enumcode); + if (parser_.opts.one_file) { + one_file_code += enumcode; + } else { + if (!SaveType(lang, enum_def.name, *enum_def.defined_namespace, + enumcode, false)) return false; + } + } + + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + std::string declcode; + auto &struct_def = **it; + GenStruct(lang, parser_, struct_def, &declcode); + if (parser_.opts.one_file) { + one_file_code += declcode; + } else { + if (!SaveType(lang, struct_def.name, *struct_def.defined_namespace, + declcode, true)) return false; + } + } + + if (parser_.opts.one_file) { + return SaveType(lang, file_name_, *parser_.namespaces_.back(), + one_file_code, true); + } + return true; + } + + // Save out the generated code for a single class while adding + // declaration boilerplate. + bool SaveType(const LanguageParameters &lang, const std::string &defname, + const Namespace &ns, const std::string &classcode, + bool needs_includes) { + if (!classcode.length()) return true; + + std::string code; + code = code + "// " + FlatBuffersGeneratedWarning(); + std::string namespace_name = FullNamespace(".", ns); + if (!namespace_name.empty()) { + code += lang.namespace_ident + namespace_name + lang.namespace_begin; + code += "\n\n"; + } + if (needs_includes) code += lang.includes; + code += classcode; + if (!namespace_name.empty()) code += lang.namespace_end; + auto filename = NamespaceDir(ns) + defname + lang.file_extension; + return SaveFile(filename.c_str(), code, false); + } + + static std::string FunctionStart(const LanguageParameters &lang, char upper) { return std::string() + (lang.language == IDLOptions::kJava @@ -247,9 +313,6 @@ static std::string GenTypeBasic(const LanguageParameters &lang, const Parser &pa return GenTypeBasic(lang, parser, type, true); } -static std::string GenTypeGet(const LanguageParameters &lang, const Parser &parser, - const Type &type); - static std::string GenTypePointer(const LanguageParameters &lang, const Parser &parser, const Type &type) { switch (type.base_type) { @@ -1113,72 +1176,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, } } code += "};\n\n"; -} - -namespace general { -class GeneralGenerator : public BaseGenerator { - public: - GeneralGenerator(const Parser &parser, const std::string &path, - const std::string &file_name) - : BaseGenerator(parser, path, file_name){}; - bool generate() { - assert(parser_.opts.lang <= IDLOptions::kMAX); - auto lang = language_parameters[parser_.opts.lang]; - std::string one_file_code; - - for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); - ++it) { - std::string enumcode; - auto &enum_def = **it; - GenEnum(lang, parser_, enum_def, &enumcode); - if (parser_.opts.one_file) { - one_file_code += enumcode; - } else { - if (!SaveType(lang, enum_def.name, *enum_def.defined_namespace, - enumcode, false)) return false; - } - } - - for (auto it = parser_.structs_.vec.begin(); - it != parser_.structs_.vec.end(); ++it) { - std::string declcode; - auto &struct_def = **it; - GenStruct(lang, parser_, struct_def, &declcode); - if (parser_.opts.one_file) { - one_file_code += declcode; - } else { - if (!SaveType(lang, struct_def.name, *struct_def.defined_namespace, - declcode, true)) return false; - } - } - - if (parser_.opts.one_file) { - return SaveType(lang, file_name_, *parser_.namespaces_.back(), - one_file_code, true); - } - return true; - } - - // Save out the generated code for a single class while adding - // declaration boilerplate. - bool SaveType(const LanguageParameters &lang, const std::string &defname, - const Namespace &ns, const std::string &classcode, - bool needs_includes) { - if (!classcode.length()) return true; - - std::string code; - code = code + "// " + FlatBuffersGeneratedWarning(); - std::string namespace_name = FullNamespace(".", ns); - if (!namespace_name.empty()) { - code += lang.namespace_ident + namespace_name + lang.namespace_begin; - code += "\n\n"; - } - if (needs_includes) code += lang.includes; - code += classcode; - if (!namespace_name.empty()) code += lang.namespace_end; - auto filename = NamespaceDir(ns) + defname + lang.file_extension; - return SaveFile(filename.c_str(), code, false); - } +} }; } // namespace general From f0695e0edf7806e073e0af1a863af48f658a64eb Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 14:17:58 +0200 Subject: [PATCH 29/42] removed parser & static from method signatures --- src/idl_gen_general.cpp | 229 ++++++++++++++++++---------------------- 1 file changed, 104 insertions(+), 125 deletions(-) diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 97006a199..46f2c4608 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -203,7 +203,7 @@ class GeneralGenerator : public BaseGenerator { ++it) { std::string enumcode; auto &enum_def = **it; - GenEnum(lang, parser_, enum_def, &enumcode); + GenEnum(lang, enum_def, &enumcode); if (parser_.opts.one_file) { one_file_code += enumcode; } else { @@ -216,7 +216,7 @@ class GeneralGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { std::string declcode; auto &struct_def = **it; - GenStruct(lang, parser_, struct_def, &declcode); + GenStruct(lang, struct_def, &declcode); if (parser_.opts.one_file) { one_file_code += declcode; } else { @@ -267,9 +267,8 @@ static bool IsEnum(const Type& type) { // 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 WrapInNameSpace(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) { @@ -281,13 +280,11 @@ static std::string WrapInNameSpace(const Parser &parser, const Namespace *ns, } } -static std::string WrapInNameSpace(const Parser &parser, - const Definition &def) { - return WrapInNameSpace(parser, def.defined_namespace, def.name); +std::string WrapInNameSpace(const Definition &def) { + return WrapInNameSpace(def.defined_namespace, def.name); } -static std::string GenTypeBasic(const LanguageParameters &lang, const Parser &parser, - const Type &type, +std::string GenTypeBasic(const LanguageParameters &lang, const Type &type, bool enableLangOverrides) { static const char *gtypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ @@ -298,9 +295,9 @@ static std::string GenTypeBasic(const LanguageParameters &lang, const Parser &pa if (enableLangOverrides) { if (lang.language == IDLOptions::kCSharp) { - if (IsEnum(type)) return WrapInNameSpace(parser, *type.enum_def); + if (IsEnum(type)) return WrapInNameSpace(*type.enum_def); if (type.base_type == BASE_TYPE_STRUCT) { - return "Offset<" + WrapInNameSpace(parser, *type.struct_def) + ">"; + return "Offset<" + WrapInNameSpace(*type.struct_def) + ">"; } } } @@ -308,20 +305,18 @@ static std::string GenTypeBasic(const LanguageParameters &lang, const Parser &pa return gtypename[type.base_type * IDLOptions::kMAX + lang.language]; } -static std::string GenTypeBasic(const LanguageParameters &lang, const Parser &parser, - const Type &type) { - return GenTypeBasic(lang, parser, type, true); +std::string GenTypeBasic(const LanguageParameters &lang, const Type &type) { + return GenTypeBasic(lang, type, true); } -static std::string GenTypePointer(const LanguageParameters &lang, const Parser &parser, - const Type &type) { +std::string GenTypePointer(const LanguageParameters &lang, const Type &type) { switch (type.base_type) { case BASE_TYPE_STRING: return lang.string_type; case BASE_TYPE_VECTOR: - return GenTypeGet(lang, parser, type.VectorType()); + return GenTypeGet(lang, type.VectorType()); case BASE_TYPE_STRUCT: - return WrapInNameSpace(parser, *type.struct_def); + return WrapInNameSpace(*type.struct_def); case BASE_TYPE_UNION: // Unions in C# use a generic Table-derived type for better type safety if (lang.language == IDLOptions::kCSharp) return "TTable"; @@ -331,16 +326,15 @@ static std::string GenTypePointer(const LanguageParameters &lang, const Parser & } } -static std::string GenTypeGet(const LanguageParameters &lang, const Parser &parser, - const Type &type) { +std::string GenTypeGet(const LanguageParameters &lang, const Type &type) { return IsScalar(type.base_type) - ? GenTypeBasic(lang, parser, type) - : GenTypePointer(lang, parser, type); + ? GenTypeBasic(lang, type) + : GenTypePointer(lang, type); } // Find the destination type the user wants to receive the value in (e.g. // one size higher signed types for unsigned serialized values in Java). -static Type DestinationType(const LanguageParameters &lang, const Parser &parser, const Type &type, +Type DestinationType(const LanguageParameters &lang, const Type &type, bool vectorelem) { if (lang.language != IDLOptions::kJava) return type; switch (type.base_type) { @@ -351,27 +345,26 @@ static Type DestinationType(const LanguageParameters &lang, const Parser &parser case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG); case BASE_TYPE_VECTOR: if (vectorelem) - return DestinationType(lang, parser, type.VectorType(), vectorelem); + return DestinationType(lang, type.VectorType(), vectorelem); // else fall thru: default: return type; } } -static std::string GenOffsetType(const LanguageParameters &lang, const Parser &parser, - const StructDef &struct_def) { +std::string GenOffsetType(const LanguageParameters &lang, const StructDef &struct_def) { if(lang.language == IDLOptions::kCSharp) { - return "Offset<" + WrapInNameSpace(parser, struct_def) + ">"; + return "Offset<" + WrapInNameSpace(struct_def) + ">"; } else { return "int"; } } -static std::string GenOffsetConstruct(const LanguageParameters &lang, const Parser &parser, +std::string GenOffsetConstruct(const LanguageParameters &lang, const StructDef &struct_def, const std::string &variable_name) { if(lang.language == IDLOptions::kCSharp) { - return "new Offset<" + WrapInNameSpace(parser, struct_def) + ">(" + variable_name + ")"; + return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name + ")"; } return variable_name; } @@ -385,9 +378,9 @@ static std::string GenVectorOffsetType(const LanguageParameters &lang) { } // Generate destination type name -static std::string GenTypeNameDest(const LanguageParameters &lang, const Parser &parser, const Type &type) +std::string GenTypeNameDest(const LanguageParameters &lang, const Type &type) { - return GenTypeGet(lang, parser, DestinationType(lang, parser, type, true)); + return GenTypeGet(lang, DestinationType(lang, type, true)); } // Mask to turn serialized value into destination type value. @@ -407,10 +400,10 @@ static std::string DestinationMask(const LanguageParameters &lang, } // Casts necessary to correctly read serialized data -static std::string DestinationCast(const LanguageParameters &lang, const Parser &parser, +std::string DestinationCast(const LanguageParameters &lang, const Type &type) { if (type.base_type == BASE_TYPE_VECTOR) { - return DestinationCast(lang, parser, type.VectorType()); + return DestinationCast(lang, type.VectorType()); } else { switch (lang.language) { case IDLOptions::kJava: @@ -420,7 +413,7 @@ static std::string DestinationCast(const LanguageParameters &lang, const Parser case IDLOptions::kCSharp: // Cast from raw integral types to enum. - if (IsEnum(type)) return "(" + WrapInNameSpace(parser, *type.enum_def) + ")"; + if (IsEnum(type)) return "(" + WrapInNameSpace(*type.enum_def) + ")"; break; default: @@ -434,11 +427,10 @@ static std::string DestinationCast(const LanguageParameters &lang, const Parser // In Java, parameters representing unsigned numbers need to be cast down to their respective type. // For example, a long holding an unsigned int value would be cast down to int before being put onto the buffer. // In C#, one cast directly cast an Enum to its underlying type, which is essential before putting it onto the buffer. -static std::string SourceCast(const LanguageParameters &lang, const Parser &parser, - const Type &type, +std::string SourceCast(const LanguageParameters &lang, const Type &type, bool castFromDest) { if (type.base_type == BASE_TYPE_VECTOR) { - return SourceCast(lang, parser, type.VectorType(), castFromDest); + return SourceCast(lang, type.VectorType(), castFromDest); } else { switch (lang.language) { case IDLOptions::kJava: @@ -449,7 +441,7 @@ static std::string SourceCast(const LanguageParameters &lang, const Parser &pars } break; case IDLOptions::kCSharp: - if (IsEnum(type)) return "(" + GenTypeBasic(lang, parser, type, false) + ")"; + if (IsEnum(type)) return "(" + GenTypeBasic(lang, type, false) + ")"; break; default: break; @@ -458,24 +450,21 @@ static std::string SourceCast(const LanguageParameters &lang, const Parser &pars return ""; } -static std::string SourceCast(const LanguageParameters &lang, const Parser &parser, - const Type &type) { - return SourceCast(lang, parser, type, true); +std::string SourceCast(const LanguageParameters &lang, const Type &type) { + return SourceCast(lang, type, true); } -static std::string SourceCastBasic(const LanguageParameters &lang, const Parser &parser, - const Type &type, +std::string SourceCastBasic(const LanguageParameters &lang, const Type &type, bool castFromDest) { - return IsScalar(type.base_type) ? SourceCast(lang, parser, type, castFromDest) : ""; + return IsScalar(type.base_type) ? SourceCast(lang, type, castFromDest) : ""; } -static std::string SourceCastBasic(const LanguageParameters &lang, const Parser &parser, - const Type &type) { - return SourceCastBasic(lang, parser, type, true); +std::string SourceCastBasic(const LanguageParameters &lang, const Type &type) { + return SourceCastBasic(lang, type, true); } -static std::string GenEnumDefaultValue(const Parser &parser, const Value &value) { +std::string GenEnumDefaultValue(const Value &value) { auto enum_def = value.type.enum_def; auto vec = enum_def->vals.vec; auto default_value = StringToInt(value.constant.c_str()); @@ -484,7 +473,7 @@ static std::string GenEnumDefaultValue(const Parser &parser, const Value &value) for (auto it = vec.begin(); it != vec.end(); ++it) { auto enum_val = **it; if (enum_val.value == default_value) { - result = WrapInNameSpace(parser, *enum_def) + "." + enum_val.name; + result = WrapInNameSpace(*enum_def) + "." + enum_val.name; break; } } @@ -492,14 +481,13 @@ static std::string GenEnumDefaultValue(const Parser &parser, const Value &value) return result; } -static std::string GenDefaultValue(const LanguageParameters &lang, const Parser &parser, - const Value &value, bool enableLangOverrides) { +std::string GenDefaultValue(const LanguageParameters &lang, const Value &value, bool enableLangOverrides) { if (enableLangOverrides) { // handles both enum case and vector of enum case if (lang.language == IDLOptions::kCSharp && value.type.enum_def != nullptr && value.type.base_type != BASE_TYPE_UNION) { - return GenEnumDefaultValue(parser, value); + return GenEnumDefaultValue(value); } } switch (value.type.base_type) { @@ -509,13 +497,11 @@ static std::string GenDefaultValue(const LanguageParameters &lang, const Parser } } -static std::string GenDefaultValue(const LanguageParameters &lang, const Parser &parser, - const Value &value) { - return GenDefaultValue(lang, parser, value, true); +std::string GenDefaultValue(const LanguageParameters &lang, const Value &value) { + return GenDefaultValue(lang, value, true); } -static std::string GenDefaultValueBasic(const LanguageParameters &lang, const Parser &parser, - const Value &value, bool enableLangOverrides) { +std::string GenDefaultValueBasic(const LanguageParameters &lang, const Value &value, bool enableLangOverrides) { if (!IsScalar(value.type.base_type)) { if (enableLangOverrides) { if (lang.language == IDLOptions::kCSharp) { @@ -523,7 +509,7 @@ static std::string GenDefaultValueBasic(const LanguageParameters &lang, const Pa case BASE_TYPE_STRING: return "default(StringOffset)"; case BASE_TYPE_STRUCT: - return "default(Offset<" + WrapInNameSpace(parser, *value.type.struct_def) + ">)"; + return "default(Offset<" + WrapInNameSpace(*value.type.struct_def) + ">)"; case BASE_TYPE_VECTOR: return "default(VectorOffset)"; default: @@ -533,16 +519,14 @@ static std::string GenDefaultValueBasic(const LanguageParameters &lang, const Pa } return "0"; } - return GenDefaultValue(lang, parser, value, enableLangOverrides); + return GenDefaultValue(lang, value, enableLangOverrides); } -static std::string GenDefaultValueBasic(const LanguageParameters &lang, const Parser &parser, - const Value &value) { - return GenDefaultValueBasic(lang, parser, value, true); +std::string GenDefaultValueBasic(const LanguageParameters &lang, const Value &value) { + return GenDefaultValueBasic(lang, value, true); } -static void GenEnum(const LanguageParameters &lang, const Parser &parser, EnumDef &enum_def, - std::string *code_ptr) { +void GenEnum(const LanguageParameters &lang, EnumDef &enum_def, std::string *code_ptr) { std::string &code = *code_ptr; if (enum_def.generated) return; @@ -554,7 +538,7 @@ static void GenEnum(const LanguageParameters &lang, const Parser &parser, EnumDe GenComment(enum_def.doc_comment, code_ptr, &lang.comment_config); code += std::string("public ") + lang.enum_decl + enum_def.name; if (lang.language == IDLOptions::kCSharp) { - code += lang.inheritance_marker + GenTypeBasic(lang, parser, enum_def.underlying_type, false); + code += lang.inheritance_marker + GenTypeBasic(lang, enum_def.underlying_type, false); } code += lang.open_curly; if (lang.language == IDLOptions::kJava) { @@ -568,7 +552,7 @@ static void GenEnum(const LanguageParameters &lang, const Parser &parser, EnumDe if (lang.language != IDLOptions::kCSharp) { code += " public static"; code += lang.const_decl; - code += GenTypeBasic(lang, parser, enum_def.underlying_type, false); + code += GenTypeBasic(lang, enum_def.underlying_type, false); } code += " " + ev.name + " = "; code += NumToString(ev.value); @@ -614,19 +598,18 @@ static void GenEnum(const LanguageParameters &lang, const Parser &parser, EnumDe } // Returns the function name that is able to read a value of the given type. -static std::string GenGetter(const LanguageParameters &lang, const Parser &parser, - const Type &type) { +std::string GenGetter(const LanguageParameters &lang, const Type &type) { switch (type.base_type) { case BASE_TYPE_STRING: return "__string"; case BASE_TYPE_STRUCT: return "__struct"; case BASE_TYPE_UNION: return "__union"; - case BASE_TYPE_VECTOR: return GenGetter(lang, parser, type.VectorType()); + case BASE_TYPE_VECTOR: return GenGetter(lang, type.VectorType()); default: { std::string getter = "bb." + FunctionStart(lang, 'G') + "et"; if (type.base_type == BASE_TYPE_BOOL) { getter = "0!=" + getter; - } else if (GenTypeBasic(lang, parser, type, false) != "byte") { - getter += MakeCamel(GenTypeBasic(lang, parser, type, false)); + } else if (GenTypeBasic(lang, type, false) != "byte") { + getter += MakeCamel(GenTypeBasic(lang, type, false)); } return getter; } @@ -635,13 +618,12 @@ static std::string GenGetter(const LanguageParameters &lang, const Parser &parse // Direct mutation is only allowed for scalar fields. // Hence a setter method will only be generated for such fields. -static std::string GenSetter(const LanguageParameters &lang, const Parser &parser, - const Type &type) { +std::string GenSetter(const LanguageParameters &lang, const Type &type) { if (IsScalar(type.base_type)) { std::string setter = "bb." + FunctionStart(lang, 'P') + "ut"; - if (GenTypeBasic(lang, parser, type, false) != "byte" && + if (GenTypeBasic(lang, type, false) != "byte" && type.base_type != BASE_TYPE_BOOL) { - setter += MakeCamel(GenTypeBasic(lang, parser, type, false)); + setter += MakeCamel(GenTypeBasic(lang, type, false)); } return setter; } else { @@ -650,16 +632,15 @@ static std::string GenSetter(const LanguageParameters &lang, const Parser &parse } // Returns the method name for use with add/put calls. -static std::string GenMethod(const LanguageParameters &lang, const Parser &parser, const Type &type) { +std::string GenMethod(const LanguageParameters &lang, const Type &type) { return IsScalar(type.base_type) - ? MakeCamel(GenTypeBasic(lang, parser, type, false)) + ? MakeCamel(GenTypeBasic(lang, type, false)) : (IsStruct(type) ? "Struct" : "Offset"); } // Recursively generate arguments for a constructor, to deal with nested // structs. -static void GenStructArgs(const LanguageParameters &lang, const Parser &parser, - const StructDef &struct_def, +void GenStructArgs(const LanguageParameters &lang, const StructDef &struct_def, std::string *code_ptr, const char *nameprefix) { std::string &code = *code_ptr; for (auto it = struct_def.fields.vec.begin(); @@ -670,11 +651,11 @@ static void GenStructArgs(const LanguageParameters &lang, const Parser &parser, // Generate arguments for a struct inside a struct. To ensure names // don't clash, and to make it obvious these arguments are constructing // a nested struct, prefix the name with the field name. - GenStructArgs(lang, parser, *field.value.type.struct_def, code_ptr, + GenStructArgs(lang, *field.value.type.struct_def, code_ptr, (nameprefix + (field.name + "_")).c_str()); } else { code += ", "; - code += GenTypeBasic(lang, parser, DestinationType(lang, parser, field.value.type, false)); + code += GenTypeBasic(lang, DestinationType(lang, field.value.type, false)); code += " "; code += nameprefix; code += MakeCamel(field.name, lang.first_camel_upper); @@ -685,8 +666,7 @@ static void GenStructArgs(const LanguageParameters &lang, const Parser &parser, // Recusively generate struct construction statements of the form: // builder.putType(name); // and insert manual padding. -static void GenStructBody(const LanguageParameters &lang, const Parser &parser, - const StructDef &struct_def, +void GenStructBody(const LanguageParameters &lang, const StructDef &struct_def, std::string *code_ptr, const char *nameprefix) { std::string &code = *code_ptr; code += " builder." + FunctionStart(lang, 'P') + "rep("; @@ -700,12 +680,12 @@ static void GenStructBody(const LanguageParameters &lang, const Parser &parser, code += NumToString(field.padding) + ");\n"; } if (IsStruct(field.value.type)) { - GenStructBody(lang, parser, *field.value.type.struct_def, code_ptr, + GenStructBody(lang, *field.value.type.struct_def, code_ptr, (nameprefix + (field.name + "_")).c_str()); } else { code += " builder." + FunctionStart(lang, 'P') + "ut"; - code += GenMethod(lang, parser, field.value.type) + "("; - code += SourceCast(lang, parser, field.value.type); + code += GenMethod(lang, field.value.type) + "("; + code += SourceCast(lang, field.value.type); auto argname = nameprefix + MakeCamel(field.name, lang.first_camel_upper); code += argname; code += ");\n"; @@ -713,8 +693,7 @@ static void GenStructBody(const LanguageParameters &lang, const Parser &parser, } } -static void GenStruct(const LanguageParameters &lang, const Parser &parser, - StructDef &struct_def, std::string *code_ptr) { +void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::string *code_ptr) { if (struct_def.generated) return; std::string &code = *code_ptr; @@ -756,13 +735,13 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += ") + _bb."; code += lang.get_bb_position; code += ", _bb)); }\n"; - if (parser.root_struct_def_ == &struct_def) { - if (parser.file_identifier_.length()) { + if (parser_.root_struct_def_ == &struct_def) { + if (parser_.file_identifier_.length()) { // Check if a buffer has the identifier. code += " public static "; code += lang.bool_type + struct_def.name; code += "BufferHasIdentifier(ByteBuffer _bb) { return "; - code += "__has_identifier(_bb, \"" + parser.file_identifier_; + code += "__has_identifier(_bb, \"" + parser_.file_identifier_; code += "\"); }\n"; } } @@ -778,11 +757,11 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, auto &field = **it; if (field.deprecated) continue; GenComment(field.doc_comment, code_ptr, &lang.comment_config, " "); - std::string type_name = GenTypeGet(lang, parser, field.value.type); - std::string type_name_dest = GenTypeNameDest(lang, parser, field.value.type); + std::string type_name = GenTypeGet(lang, field.value.type); + std::string type_name_dest = GenTypeNameDest(lang, field.value.type); std::string dest_mask = DestinationMask(lang, field.value.type, true); - std::string dest_cast = DestinationCast(lang, parser, field.value.type); - std::string src_cast = SourceCast(lang, parser, field.value.type); + std::string dest_cast = DestinationCast(lang, field.value.type); + std::string src_cast = SourceCast(lang, field.value.type); std::string method_start = " public " + type_name_dest + " " + MakeCamel(field.name, lang.first_camel_upper); @@ -832,7 +811,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, type_name = type_name_dest; } } - std::string getter = dest_cast + GenGetter(lang, parser, field.value.type); + std::string getter = dest_cast + GenGetter(lang, field.value.type); code += method_start; std::string default_cast = ""; // only create default casts for c# scalars or vectors of scalars @@ -857,7 +836,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, } else { code += offset_prefix + getter; code += "(o + bb_pos)" + dest_mask + " : " + default_cast; - code += GenDefaultValue(lang, parser, field.value); + code += GenDefaultValue(lang, field.value); } } else { switch (field.value.type.base_type) { @@ -954,9 +933,9 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, auto nested = field.attributes.Lookup("nested_flatbuffer"); if (nested) { auto nested_qualified_name = - parser.namespaces_.back()->GetFullyQualifiedName(nested->constant); - auto nested_type = parser.structs_.Lookup(nested_qualified_name); - auto nested_type_name = WrapInNameSpace(parser, *nested_type); + parser_.namespaces_.back()->GetFullyQualifiedName(nested->constant); + auto nested_type = parser_.structs_.Lookup(nested_qualified_name); + auto nested_type_name = WrapInNameSpace(*nested_type); auto nestedMethodName = MakeCamel(field.name, lang.first_camel_upper) + "As" + nested_type_name; auto getNestedMethodName = nestedMethodName; @@ -972,7 +951,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += "return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }\n"; } // generate mutators for scalar fields or vectors of scalars - if (parser.opts.mutable_buffer) { + if (parser_.opts.mutable_buffer) { auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR ? field.value.type.VectorType() : field.value.type; @@ -981,7 +960,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, auto mutator_prefix = MakeCamel("mutate", lang.first_camel_upper); //a vector mutator also needs the index of the vector element it should mutate auto mutator_params = (field.value.type.base_type == BASE_TYPE_VECTOR ? "(int j, " : "(") + - GenTypeNameDest(lang, parser, underlying_type) + " " + + GenTypeNameDest(lang, underlying_type) + " " + field.name + ") { "; auto setter_index = field.value.type.base_type == BASE_TYPE_VECTOR ? "__vector(o) + j * " + NumToString(InlineSize(underlying_type)) @@ -994,11 +973,11 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += mutator_prefix + MakeCamel(field.name, true); code += mutator_params; if (struct_def.fixed) { - code += GenSetter(lang, parser, underlying_type) + "(" + setter_index + ", "; + code += GenSetter(lang, underlying_type) + "(" + setter_index + ", "; code += src_cast + setter_parameter + "); }\n"; } else { code += "int o = __offset(" + NumToString(field.value.offset) + ");"; - code += " if (o != 0) { " + GenSetter(lang, parser, underlying_type); + code += " if (o != 0) { " + GenSetter(lang, underlying_type); code += "(" + setter_index + ", " + src_cast + setter_parameter + "); return true; } else { return false; } }\n"; } } @@ -1007,14 +986,14 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += "\n"; if (struct_def.fixed) { // create a struct constructor function - code += " public static " + GenOffsetType(lang, parser, struct_def) + " "; + code += " public static " + GenOffsetType(lang, struct_def) + " "; code += FunctionStart(lang, 'C') + "reate"; code += struct_def.name + "(FlatBufferBuilder builder"; - GenStructArgs(lang, parser, struct_def, code_ptr, ""); + GenStructArgs(lang, struct_def, code_ptr, ""); code += ") {\n"; - GenStructBody(lang, parser, struct_def, code_ptr, ""); + GenStructBody(lang, struct_def, code_ptr, ""); code += " return "; - code += GenOffsetConstruct(lang, parser, struct_def, "builder." + std::string(lang.get_fbb_offset)); + code += GenOffsetConstruct(lang, struct_def, "builder." + std::string(lang.get_fbb_offset)); code += ";\n }\n"; } else { // Generate a method that creates a table in one go. This is only possible @@ -1035,7 +1014,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, if (has_no_struct_fields && num_fields) { // Generate a table constructor of the form: // public static int createName(FlatBufferBuilder builder, args...) - code += " public static " + GenOffsetType(lang, parser, struct_def) + " "; + code += " public static " + GenOffsetType(lang, struct_def) + " "; code += FunctionStart(lang, 'C') + "reate" + struct_def.name; code += "(FlatBufferBuilder builder"; for (auto it = struct_def.fields.vec.begin(); @@ -1043,7 +1022,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, auto &field = **it; if (field.deprecated) continue; code += ",\n "; - code += GenTypeBasic(lang, parser, DestinationType(lang, parser, field.value.type, false)); + code += GenTypeBasic(lang, DestinationType(lang, field.value.type, false)); code += " "; code += field.name; if (!IsScalar(field.value.type.base_type)) code += "Offset"; @@ -1052,7 +1031,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, // supply all arguments, and thus won't compile when fields are added. if (lang.language != IDLOptions::kJava) { code += " = "; - code += GenDefaultValueBasic(lang, parser, field.value); + code += GenDefaultValueBasic(lang, field.value); } } code += ") {\n builder."; @@ -1096,18 +1075,18 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += " public static void " + FunctionStart(lang, 'A') + "dd"; code += MakeCamel(field.name); code += "(FlatBufferBuilder builder, "; - code += GenTypeBasic(lang, parser, DestinationType(lang, parser, field.value.type, false)); + code += GenTypeBasic(lang, DestinationType(lang, field.value.type, false)); auto argname = MakeCamel(field.name, false); if (!IsScalar(field.value.type.base_type)) argname += "Offset"; code += " " + argname + ") { builder." + FunctionStart(lang, 'A') + "dd"; - code += GenMethod(lang, parser, field.value.type) + "("; + code += GenMethod(lang, field.value.type) + "("; code += NumToString(it - struct_def.fields.vec.begin()) + ", "; - code += SourceCastBasic(lang, parser, field.value.type); + code += SourceCastBasic(lang, field.value.type); code += argname; if(!IsScalar(field.value.type.base_type) && field.value.type.base_type != BASE_TYPE_UNION && lang.language == IDLOptions::kCSharp) { code += ".Value"; } - code += ", " + GenDefaultValue(lang, parser, field.value, false); + code += ", " + GenDefaultValue(lang, field.value, false); code += "); }\n"; if (field.value.type.base_type == BASE_TYPE_VECTOR) { auto vector_type = field.value.type.VectorType(); @@ -1118,7 +1097,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += " public static " + GenVectorOffsetType(lang) + " " + FunctionStart(lang, 'C') + "reate"; code += MakeCamel(field.name); code += "Vector(FlatBufferBuilder builder, "; - code += GenTypeBasic(lang, parser, vector_type) + "[] data) "; + code += GenTypeBasic(lang, vector_type) + "[] data) "; code += "{ builder." + FunctionStart(lang, 'S') + "tartVector("; code += NumToString(elem_size); code += ", data." + FunctionStart(lang, 'L') + "ength, "; @@ -1126,9 +1105,9 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += "); for (int i = data."; code += FunctionStart(lang, 'L') + "ength - 1; i >= 0; i--) builder."; code += FunctionStart(lang, 'A') + "dd"; - code += GenMethod(lang, parser, vector_type); + code += GenMethod(lang, vector_type); code += "("; - code += SourceCastBasic(lang, parser, vector_type, false); + code += SourceCastBasic(lang, vector_type, false); code += "data[i]"; if (lang.language == IDLOptions::kCSharp && (vector_type.base_type == BASE_TYPE_STRUCT || vector_type.base_type == BASE_TYPE_STRING)) @@ -1146,7 +1125,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += "); }\n"; } } - code += " public static " + GenOffsetType(lang, parser, struct_def) + " "; + code += " public static " + GenOffsetType(lang, struct_def) + " "; code += FunctionStart(lang, 'E') + "nd" + struct_def.name; code += "(FlatBufferBuilder builder) {\n int o = builder."; code += FunctionStart(lang, 'E') + "ndObject();\n"; @@ -1160,18 +1139,18 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, code += "); // " + field.name + "\n"; } } - code += " return " + GenOffsetConstruct(lang, parser, struct_def, "o") + ";\n }\n"; - if (parser.root_struct_def_ == &struct_def) { + code += " return " + GenOffsetConstruct(lang, struct_def, "o") + ";\n }\n"; + if (parser_.root_struct_def_ == &struct_def) { code += " public static void "; code += FunctionStart(lang, 'F') + "inish" + struct_def.name; - code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(lang, parser, struct_def) + " offset) {"; + code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(lang, struct_def) + " offset) {"; code += " builder." + FunctionStart(lang, 'F') + "inish(offset"; if (lang.language == IDLOptions::kCSharp) { code += ".Value"; } - if (parser.file_identifier_.length()) - code += ", \"" + parser.file_identifier_ + "\""; + if (parser_.file_identifier_.length()) + code += ", \"" + parser_.file_identifier_ + "\""; code += "); }\n"; } } From 4a249752ffeaeea9dc01760baac8a5e961bc8b09 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 17:13:58 +0200 Subject: [PATCH 30/42] removed lang signature method --- src/idl_gen_general.cpp | 403 ++++++++++++++++++++-------------------- 1 file changed, 197 insertions(+), 206 deletions(-) diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 46f2c4608..7567bdcf4 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -193,21 +193,21 @@ class GeneralGenerator : public BaseGenerator { public: GeneralGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, file_name){}; + : BaseGenerator(parser, path, file_name){ + assert(parser_.opts.lang <= IDLOptions::kMAX); + }; bool generate() { - assert(parser_.opts.lang <= IDLOptions::kMAX); - auto lang = language_parameters[parser_.opts.lang]; std::string one_file_code; for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); ++it) { std::string enumcode; auto &enum_def = **it; - GenEnum(lang, enum_def, &enumcode); + GenEnum(enum_def, &enumcode); if (parser_.opts.one_file) { one_file_code += enumcode; } else { - if (!SaveType(lang, enum_def.name, *enum_def.defined_namespace, + if (!SaveType(enum_def.name, *enum_def.defined_namespace, enumcode, false)) return false; } } @@ -216,17 +216,17 @@ class GeneralGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { std::string declcode; auto &struct_def = **it; - GenStruct(lang, struct_def, &declcode); + GenStruct(struct_def, &declcode); if (parser_.opts.one_file) { one_file_code += declcode; } else { - if (!SaveType(lang, struct_def.name, *struct_def.defined_namespace, + if (!SaveType(struct_def.name, *struct_def.defined_namespace, declcode, true)) return false; } } if (parser_.opts.one_file) { - return SaveType(lang, file_name_, *parser_.namespaces_.back(), + return SaveType(file_name_, *parser_.namespaces_.back(), one_file_code, true); } return true; @@ -234,29 +234,28 @@ class GeneralGenerator : public BaseGenerator { // Save out the generated code for a single class while adding // declaration boilerplate. - bool SaveType(const LanguageParameters &lang, const std::string &defname, - const Namespace &ns, const std::string &classcode, - bool needs_includes) { + bool SaveType(const std::string &defname, const Namespace &ns, + const std::string &classcode, bool needs_includes) { if (!classcode.length()) return true; std::string code; code = code + "// " + FlatBuffersGeneratedWarning(); std::string namespace_name = FullNamespace(".", ns); if (!namespace_name.empty()) { - code += lang.namespace_ident + namespace_name + lang.namespace_begin; + code += lang_.namespace_ident + namespace_name + lang_.namespace_begin; code += "\n\n"; } - if (needs_includes) code += lang.includes; + if (needs_includes) code += lang_.includes; code += classcode; - if (!namespace_name.empty()) code += lang.namespace_end; - auto filename = NamespaceDir(ns) + defname + lang.file_extension; + if (!namespace_name.empty()) code += lang_.namespace_end; + auto filename = NamespaceDir(ns) + defname + lang_.file_extension; return SaveFile(filename.c_str(), code, false); } -static std::string FunctionStart(const LanguageParameters &lang, char upper) { +std::string FunctionStart(char upper) { return std::string() + - (lang.language == IDLOptions::kJava + (lang_.language == IDLOptions::kJava ? static_cast(tolower(upper)) : upper); } @@ -284,8 +283,7 @@ std::string WrapInNameSpace(const Definition &def) { return WrapInNameSpace(def.defined_namespace, def.name); } -std::string GenTypeBasic(const LanguageParameters &lang, const Type &type, - bool enableLangOverrides) { +std::string GenTypeBasic(const Type &type, bool enableLangOverrides) { static const char *gtypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ #JTYPE, #NTYPE, #GTYPE, @@ -294,7 +292,7 @@ std::string GenTypeBasic(const LanguageParameters &lang, const Type &type, }; if (enableLangOverrides) { - if (lang.language == IDLOptions::kCSharp) { + if (lang_.language == IDLOptions::kCSharp) { if (IsEnum(type)) return WrapInNameSpace(*type.enum_def); if (type.base_type == BASE_TYPE_STRUCT) { return "Offset<" + WrapInNameSpace(*type.struct_def) + ">"; @@ -302,41 +300,40 @@ std::string GenTypeBasic(const LanguageParameters &lang, const Type &type, } } - return gtypename[type.base_type * IDLOptions::kMAX + lang.language]; + return gtypename[type.base_type * IDLOptions::kMAX + lang_.language]; } -std::string GenTypeBasic(const LanguageParameters &lang, const Type &type) { - return GenTypeBasic(lang, type, true); +std::string GenTypeBasic(const Type &type) { + return GenTypeBasic(type, true); } -std::string GenTypePointer(const LanguageParameters &lang, const Type &type) { +std::string GenTypePointer(const Type &type) { switch (type.base_type) { case BASE_TYPE_STRING: - return lang.string_type; + return lang_.string_type; case BASE_TYPE_VECTOR: - return GenTypeGet(lang, type.VectorType()); + return GenTypeGet(type.VectorType()); case BASE_TYPE_STRUCT: return WrapInNameSpace(*type.struct_def); case BASE_TYPE_UNION: // Unions in C# use a generic Table-derived type for better type safety - if (lang.language == IDLOptions::kCSharp) return "TTable"; + if (lang_.language == IDLOptions::kCSharp) return "TTable"; // fall through default: return "Table"; } } -std::string GenTypeGet(const LanguageParameters &lang, const Type &type) { +std::string GenTypeGet(const Type &type) { return IsScalar(type.base_type) - ? GenTypeBasic(lang, type) - : GenTypePointer(lang, type); + ? GenTypeBasic(type) + : GenTypePointer(type); } // Find the destination type the user wants to receive the value in (e.g. // one size higher signed types for unsigned serialized values in Java). -Type DestinationType(const LanguageParameters &lang, const Type &type, - bool vectorelem) { - if (lang.language != IDLOptions::kJava) return type; +Type DestinationType(const Type &type, bool vectorelem) { + if (lang_.language != IDLOptions::kJava) return type; switch (type.base_type) { // We use int for both uchar/ushort, since that generally means less casting // than using short for uchar. @@ -345,32 +342,31 @@ Type DestinationType(const LanguageParameters &lang, const Type &type, case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG); case BASE_TYPE_VECTOR: if (vectorelem) - return DestinationType(lang, type.VectorType(), vectorelem); + return DestinationType(type.VectorType(), vectorelem); // else fall thru: default: return type; } } -std::string GenOffsetType(const LanguageParameters &lang, const StructDef &struct_def) { - if(lang.language == IDLOptions::kCSharp) { +std::string GenOffsetType(const StructDef &struct_def) { + if(lang_.language == IDLOptions::kCSharp) { return "Offset<" + WrapInNameSpace(struct_def) + ">"; } else { return "int"; } } -std::string GenOffsetConstruct(const LanguageParameters &lang, - const StructDef &struct_def, +std::string GenOffsetConstruct(const StructDef &struct_def, const std::string &variable_name) { - if(lang.language == IDLOptions::kCSharp) { + if(lang_.language == IDLOptions::kCSharp) { return "new Offset<" + WrapInNameSpace(struct_def) + ">(" + variable_name + ")"; } return variable_name; } -static std::string GenVectorOffsetType(const LanguageParameters &lang) { - if(lang.language == IDLOptions::kCSharp) { +std::string GenVectorOffsetType() { + if(lang_.language == IDLOptions::kCSharp) { return "VectorOffset"; } else { return "int"; @@ -378,34 +374,32 @@ static std::string GenVectorOffsetType(const LanguageParameters &lang) { } // Generate destination type name -std::string GenTypeNameDest(const LanguageParameters &lang, const Type &type) +std::string GenTypeNameDest(const Type &type) { - return GenTypeGet(lang, DestinationType(lang, type, true)); + return GenTypeGet(DestinationType(type, true)); } // Mask to turn serialized value into destination type value. -static std::string DestinationMask(const LanguageParameters &lang, - const Type &type, bool vectorelem) { - if (lang.language != IDLOptions::kJava) return ""; +std::string DestinationMask(const Type &type, bool vectorelem) { + if (lang_.language != IDLOptions::kJava) return ""; switch (type.base_type) { case BASE_TYPE_UCHAR: return " & 0xFF"; case BASE_TYPE_USHORT: return " & 0xFFFF"; case BASE_TYPE_UINT: return " & 0xFFFFFFFFL"; case BASE_TYPE_VECTOR: if (vectorelem) - return DestinationMask(lang, type.VectorType(), vectorelem); + return DestinationMask(type.VectorType(), vectorelem); // else fall thru: default: return ""; } } // Casts necessary to correctly read serialized data -std::string DestinationCast(const LanguageParameters &lang, - const Type &type) { +std::string DestinationCast(const Type &type) { if (type.base_type == BASE_TYPE_VECTOR) { - return DestinationCast(lang, type.VectorType()); + return DestinationCast(type.VectorType()); } else { - switch (lang.language) { + switch (lang_.language) { case IDLOptions::kJava: // Cast necessary to correctly read serialized unsigned values. if (type.base_type == BASE_TYPE_UINT) return "(long)"; @@ -427,12 +421,11 @@ std::string DestinationCast(const LanguageParameters &lang, // In Java, parameters representing unsigned numbers need to be cast down to their respective type. // For example, a long holding an unsigned int value would be cast down to int before being put onto the buffer. // In C#, one cast directly cast an Enum to its underlying type, which is essential before putting it onto the buffer. -std::string SourceCast(const LanguageParameters &lang, const Type &type, - bool castFromDest) { +std::string SourceCast(const Type &type, bool castFromDest) { if (type.base_type == BASE_TYPE_VECTOR) { - return SourceCast(lang, type.VectorType(), castFromDest); + return SourceCast(type.VectorType(), castFromDest); } else { - switch (lang.language) { + switch (lang_.language) { case IDLOptions::kJava: if (castFromDest) { if (type.base_type == BASE_TYPE_UINT) return "(int)"; @@ -441,7 +434,7 @@ std::string SourceCast(const LanguageParameters &lang, const Type &type, } break; case IDLOptions::kCSharp: - if (IsEnum(type)) return "(" + GenTypeBasic(lang, type, false) + ")"; + if (IsEnum(type)) return "(" + GenTypeBasic(type, false) + ")"; break; default: break; @@ -450,17 +443,16 @@ std::string SourceCast(const LanguageParameters &lang, const Type &type, return ""; } -std::string SourceCast(const LanguageParameters &lang, const Type &type) { - return SourceCast(lang, type, true); +std::string SourceCast(const Type &type) { + return SourceCast(type, true); } -std::string SourceCastBasic(const LanguageParameters &lang, const Type &type, - bool castFromDest) { - return IsScalar(type.base_type) ? SourceCast(lang, type, castFromDest) : ""; +std::string SourceCastBasic(const Type &type, bool castFromDest) { + return IsScalar(type.base_type) ? SourceCast(type, castFromDest) : ""; } -std::string SourceCastBasic(const LanguageParameters &lang, const Type &type) { - return SourceCastBasic(lang, type, true); +std::string SourceCastBasic(const Type &type) { + return SourceCastBasic(type, true); } @@ -481,10 +473,10 @@ std::string GenEnumDefaultValue(const Value &value) { return result; } -std::string GenDefaultValue(const LanguageParameters &lang, const Value &value, bool enableLangOverrides) { +std::string GenDefaultValue(const Value &value, bool enableLangOverrides) { if (enableLangOverrides) { // handles both enum case and vector of enum case - if (lang.language == IDLOptions::kCSharp && + if (lang_.language == IDLOptions::kCSharp && value.type.enum_def != nullptr && value.type.base_type != BASE_TYPE_UNION) { return GenEnumDefaultValue(value); @@ -497,14 +489,14 @@ std::string GenDefaultValue(const LanguageParameters &lang, const Value &value, } } -std::string GenDefaultValue(const LanguageParameters &lang, const Value &value) { - return GenDefaultValue(lang, value, true); +std::string GenDefaultValue(const Value &value) { + return GenDefaultValue(value, true); } -std::string GenDefaultValueBasic(const LanguageParameters &lang, const Value &value, bool enableLangOverrides) { +std::string GenDefaultValueBasic(const Value &value, bool enableLangOverrides) { if (!IsScalar(value.type.base_type)) { if (enableLangOverrides) { - if (lang.language == IDLOptions::kCSharp) { + if (lang_.language == IDLOptions::kCSharp) { switch (value.type.base_type) { case BASE_TYPE_STRING: return "default(StringOffset)"; @@ -519,14 +511,14 @@ std::string GenDefaultValueBasic(const LanguageParameters &lang, const Value &va } return "0"; } - return GenDefaultValue(lang, value, enableLangOverrides); + return GenDefaultValue(value, enableLangOverrides); } -std::string GenDefaultValueBasic(const LanguageParameters &lang, const Value &value) { - return GenDefaultValueBasic(lang, value, true); +std::string GenDefaultValueBasic(const Value &value) { + return GenDefaultValueBasic(value, true); } -void GenEnum(const LanguageParameters &lang, EnumDef &enum_def, std::string *code_ptr) { +void GenEnum(EnumDef &enum_def, std::string *code_ptr) { std::string &code = *code_ptr; if (enum_def.generated) return; @@ -535,33 +527,33 @@ void GenEnum(const LanguageParameters &lang, EnumDef &enum_def, std::string *cod // In Java, we use ints rather than the Enum feature, because we want them // to map directly to how they're used in C/C++ and file formats. // That, and Java Enums are expensive, and not universally liked. - GenComment(enum_def.doc_comment, code_ptr, &lang.comment_config); - code += std::string("public ") + lang.enum_decl + enum_def.name; - if (lang.language == IDLOptions::kCSharp) { - code += lang.inheritance_marker + GenTypeBasic(lang, enum_def.underlying_type, false); + GenComment(enum_def.doc_comment, code_ptr, &lang_.comment_config); + code += std::string("public ") + lang_.enum_decl + enum_def.name; + if (lang_.language == IDLOptions::kCSharp) { + code += lang_.inheritance_marker + GenTypeBasic(enum_def.underlying_type, false); } - code += lang.open_curly; - if (lang.language == IDLOptions::kJava) { + code += lang_.open_curly; + if (lang_.language == IDLOptions::kJava) { code += " private " + enum_def.name + "() { }\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, &lang.comment_config, " "); - if (lang.language != IDLOptions::kCSharp) { + GenComment(ev.doc_comment, code_ptr, &lang_.comment_config, " "); + if (lang_.language != IDLOptions::kCSharp) { code += " public static"; - code += lang.const_decl; - code += GenTypeBasic(lang, enum_def.underlying_type, false); + code += lang_.const_decl; + code += GenTypeBasic(enum_def.underlying_type, false); } code += " " + ev.name + " = "; code += NumToString(ev.value); - code += lang.enum_separator; + code += lang_.enum_separator; } // Generate a generate string table for enum values. // We do not do that for C# where this functionality is native. - if (lang.language != IDLOptions::kCSharp) { + if (lang_.language != IDLOptions::kCSharp) { // Problem is, if values are very sparse that could generate really big // tables. Ideally in that case we generate a map lookup instead, but for // the moment we simply don't output a table at all. @@ -572,8 +564,8 @@ void GenEnum(const LanguageParameters &lang, EnumDef &enum_def, std::string *cod static const int kMaxSparseness = 5; if (range / static_cast(enum_def.vals.vec.size()) < kMaxSparseness) { code += "\n private static"; - code += lang.const_decl; - code += lang.string_type; + code += lang_.const_decl; + code += lang_.string_type; code += "[] names = { "; auto val = enum_def.vals.vec.front()->value; for (auto it = enum_def.vals.vec.begin(); @@ -584,8 +576,8 @@ void GenEnum(const LanguageParameters &lang, EnumDef &enum_def, std::string *cod } code += "};\n\n"; code += " public static "; - code += lang.string_type; - code += " " + MakeCamel("name", lang.first_camel_upper); + code += lang_.string_type; + code += " " + MakeCamel("name", lang_.first_camel_upper); code += "(int e) { return names[e"; if (enum_def.vals.vec.front()->value) code += " - " + enum_def.vals.vec.front()->name; @@ -598,18 +590,18 @@ void GenEnum(const LanguageParameters &lang, EnumDef &enum_def, std::string *cod } // Returns the function name that is able to read a value of the given type. -std::string GenGetter(const LanguageParameters &lang, const Type &type) { +std::string GenGetter(const Type &type) { switch (type.base_type) { case BASE_TYPE_STRING: return "__string"; case BASE_TYPE_STRUCT: return "__struct"; case BASE_TYPE_UNION: return "__union"; - case BASE_TYPE_VECTOR: return GenGetter(lang, type.VectorType()); + case BASE_TYPE_VECTOR: return GenGetter(type.VectorType()); default: { - std::string getter = "bb." + FunctionStart(lang, 'G') + "et"; + std::string getter = "bb." + FunctionStart('G') + "et"; if (type.base_type == BASE_TYPE_BOOL) { getter = "0!=" + getter; - } else if (GenTypeBasic(lang, type, false) != "byte") { - getter += MakeCamel(GenTypeBasic(lang, type, false)); + } else if (GenTypeBasic(type, false) != "byte") { + getter += MakeCamel(GenTypeBasic(type, false)); } return getter; } @@ -618,12 +610,12 @@ std::string GenGetter(const LanguageParameters &lang, const Type &type) { // Direct mutation is only allowed for scalar fields. // Hence a setter method will only be generated for such fields. -std::string GenSetter(const LanguageParameters &lang, const Type &type) { +std::string GenSetter(const Type &type) { if (IsScalar(type.base_type)) { - std::string setter = "bb." + FunctionStart(lang, 'P') + "ut"; - if (GenTypeBasic(lang, type, false) != "byte" && + std::string setter = "bb." + FunctionStart('P') + "ut"; + if (GenTypeBasic(type, false) != "byte" && type.base_type != BASE_TYPE_BOOL) { - setter += MakeCamel(GenTypeBasic(lang, type, false)); + setter += MakeCamel(GenTypeBasic(type, false)); } return setter; } else { @@ -632,16 +624,15 @@ std::string GenSetter(const LanguageParameters &lang, const Type &type) { } // Returns the method name for use with add/put calls. -std::string GenMethod(const LanguageParameters &lang, const Type &type) { +std::string GenMethod(const Type &type) { return IsScalar(type.base_type) - ? MakeCamel(GenTypeBasic(lang, type, false)) + ? MakeCamel(GenTypeBasic(type, false)) : (IsStruct(type) ? "Struct" : "Offset"); } // Recursively generate arguments for a constructor, to deal with nested // structs. -void GenStructArgs(const LanguageParameters &lang, const StructDef &struct_def, - std::string *code_ptr, const char *nameprefix) { +void GenStructArgs(const StructDef &struct_def, std::string *code_ptr, const char *nameprefix) { std::string &code = *code_ptr; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); @@ -651,14 +642,14 @@ void GenStructArgs(const LanguageParameters &lang, const StructDef &struct_def, // Generate arguments for a struct inside a struct. To ensure names // don't clash, and to make it obvious these arguments are constructing // a nested struct, prefix the name with the field name. - GenStructArgs(lang, *field.value.type.struct_def, code_ptr, + GenStructArgs(*field.value.type.struct_def, code_ptr, (nameprefix + (field.name + "_")).c_str()); } else { code += ", "; - code += GenTypeBasic(lang, DestinationType(lang, field.value.type, false)); + code += GenTypeBasic(DestinationType(field.value.type, false)); code += " "; code += nameprefix; - code += MakeCamel(field.name, lang.first_camel_upper); + code += MakeCamel(field.name, lang_.first_camel_upper); } } } @@ -666,34 +657,33 @@ void GenStructArgs(const LanguageParameters &lang, const StructDef &struct_def, // Recusively generate struct construction statements of the form: // builder.putType(name); // and insert manual padding. -void GenStructBody(const LanguageParameters &lang, const StructDef &struct_def, - std::string *code_ptr, const char *nameprefix) { +void GenStructBody(const StructDef &struct_def, std::string *code_ptr, const char *nameprefix) { std::string &code = *code_ptr; - code += " builder." + FunctionStart(lang, 'P') + "rep("; + code += " builder." + FunctionStart('P') + "rep("; code += NumToString(struct_def.minalign) + ", "; code += NumToString(struct_def.bytesize) + ");\n"; for (auto it = struct_def.fields.vec.rbegin(); it != struct_def.fields.vec.rend(); ++it) { auto &field = **it; if (field.padding) { - code += " builder." + FunctionStart(lang, 'P') + "ad("; + code += " builder." + FunctionStart('P') + "ad("; code += NumToString(field.padding) + ");\n"; } if (IsStruct(field.value.type)) { - GenStructBody(lang, *field.value.type.struct_def, code_ptr, + GenStructBody(*field.value.type.struct_def, code_ptr, (nameprefix + (field.name + "_")).c_str()); } else { - code += " builder." + FunctionStart(lang, 'P') + "ut"; - code += GenMethod(lang, field.value.type) + "("; - code += SourceCast(lang, field.value.type); - auto argname = nameprefix + MakeCamel(field.name, lang.first_camel_upper); + code += " builder." + FunctionStart('P') + "ut"; + code += GenMethod(field.value.type) + "("; + code += SourceCast(field.value.type); + auto argname = nameprefix + MakeCamel(field.name, lang_.first_camel_upper); code += argname; code += ");\n"; } } } -void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::string *code_ptr) { +void GenStruct(StructDef &struct_def, std::string *code_ptr) { if (struct_def.generated) return; std::string &code = *code_ptr; @@ -703,23 +693,23 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin // public type name() { // int o = __offset(offset); return o != 0 ? bb.getType(o + i) : default; // } - GenComment(struct_def.doc_comment, code_ptr, &lang.comment_config); + GenComment(struct_def.doc_comment, code_ptr, &lang_.comment_config); code += "public "; - if (lang.language == IDLOptions::kCSharp && + if (lang_.language == IDLOptions::kCSharp && struct_def.attributes.Lookup("csharp_partial")) { // generate a partial class for this C# struct/table code += "partial "; } else { - code += lang.unsubclassable_decl; + code += lang_.unsubclassable_decl; } - code += "class " + struct_def.name + lang.inheritance_marker; + code += "class " + struct_def.name + lang_.inheritance_marker; code += struct_def.fixed ? "Struct" : "Table"; code += " {\n"; if (!struct_def.fixed) { // Generate a special accessor for the table that when used as the root // of a FlatBuffer - std::string method_name = FunctionStart(lang, 'G') + "etRootAs" + struct_def.name; + std::string method_name = FunctionStart('G') + "etRootAs" + struct_def.name; std::string method_signature = " public static " + struct_def.name + " " + method_name; // create convenience method that doesn't require an existing object @@ -728,18 +718,18 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin // create method that allows object reuse code += method_signature + "(ByteBuffer _bb, " + struct_def.name + " obj) { "; - code += lang.set_bb_byteorder; - code += "return (obj.__init(_bb." + FunctionStart(lang, 'G'); + code += lang_.set_bb_byteorder; + code += "return (obj.__init(_bb." + FunctionStart('G'); code += "etInt(_bb."; - code += lang.get_bb_position; + code += lang_.get_bb_position; code += ") + _bb."; - code += lang.get_bb_position; + code += lang_.get_bb_position; code += ", _bb)); }\n"; if (parser_.root_struct_def_ == &struct_def) { if (parser_.file_identifier_.length()) { // Check if a buffer has the identifier. code += " public static "; - code += lang.bool_type + struct_def.name; + code += lang_.bool_type + struct_def.name; code += "BufferHasIdentifier(ByteBuffer _bb) { return "; code += "__has_identifier(_bb, \"" + parser_.file_identifier_; code += "\"); }\n"; @@ -756,14 +746,14 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin ++it) { auto &field = **it; if (field.deprecated) continue; - GenComment(field.doc_comment, code_ptr, &lang.comment_config, " "); - std::string type_name = GenTypeGet(lang, field.value.type); - std::string type_name_dest = GenTypeNameDest(lang, field.value.type); - std::string dest_mask = DestinationMask(lang, field.value.type, true); - std::string dest_cast = DestinationCast(lang, field.value.type); - std::string src_cast = SourceCast(lang, field.value.type); + GenComment(field.doc_comment, code_ptr, &lang_.comment_config, " "); + std::string type_name = GenTypeGet(field.value.type); + std::string type_name_dest = GenTypeNameDest(field.value.type); + std::string dest_mask = DestinationMask(field.value.type, true); + std::string dest_cast = DestinationCast(field.value.type); + std::string src_cast = SourceCast(field.value.type); std::string method_start = " public " + type_name_dest + " " + - MakeCamel(field.name, lang.first_camel_upper); + MakeCamel(field.name, lang_.first_camel_upper); // Most field accessors need to retrieve and test the field offset first, // this is the prefix code for that: @@ -773,16 +763,16 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin // Generate the accessors that don't do object reuse. if (field.value.type.base_type == BASE_TYPE_STRUCT) { // Calls the accessor that takes an accessor object with a new object. - if (lang.language == IDLOptions::kCSharp) { + if (lang_.language == IDLOptions::kCSharp) { code += method_start + " { get { return Get"; - code += MakeCamel(field.name, lang.first_camel_upper); + code += MakeCamel(field.name, lang_.first_camel_upper); code += "(new "; code += type_name + "()); } }\n"; - method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang.first_camel_upper); + method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper); } else { code += method_start + "() { return "; - code += MakeCamel(field.name, lang.first_camel_upper); + code += MakeCamel(field.name, lang_.first_camel_upper); code += "(new "; code += type_name + "()); }\n"; } @@ -790,32 +780,32 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin field.value.type.element == BASE_TYPE_STRUCT) { // Accessors for vectors of structs also take accessor objects, this // generates a variant without that argument. - if (lang.language == IDLOptions::kCSharp) { - method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang.first_camel_upper); + if (lang_.language == IDLOptions::kCSharp) { + method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper); code += method_start + "(int j) { return Get"; } else { code += method_start + "(int j) { return "; } - code += MakeCamel(field.name, lang.first_camel_upper); + code += MakeCamel(field.name, lang_.first_camel_upper); code += "(new "; code += type_name + "(), j); }\n"; } else if (field.value.type.base_type == BASE_TYPE_VECTOR) { - if (lang.language == IDLOptions::kCSharp) { - method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang.first_camel_upper); + if (lang_.language == IDLOptions::kCSharp) { + method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper); } } else if (field.value.type.base_type == BASE_TYPE_UNION) { - if (lang.language == IDLOptions::kCSharp) { + if (lang_.language == IDLOptions::kCSharp) { // union types in C# use generic Table-derived type for better type safety - method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang.first_camel_upper) + ""; + method_start = " public " + type_name_dest + " Get" + MakeCamel(field.name, lang_.first_camel_upper) + ""; offset_prefix = " where TTable : Table" + offset_prefix; type_name = type_name_dest; } } - std::string getter = dest_cast + GenGetter(lang, field.value.type); + std::string getter = dest_cast + GenGetter(field.value.type); code += method_start; std::string default_cast = ""; // only create default casts for c# scalars or vectors of scalars - if (lang.language == IDLOptions::kCSharp && + if (lang_.language == IDLOptions::kCSharp && (IsScalar(field.value.type.base_type) || (field.value.type.base_type == BASE_TYPE_VECTOR && IsScalar(field.value.type.element)))) { // For scalars, default value will be returned by GetDefaultValue(). If the scalar is an enum, GetDefaultValue() @@ -827,8 +817,8 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin } std::string member_suffix = ""; if (IsScalar(field.value.type.base_type)) { - code += lang.getter_prefix; - member_suffix = lang.getter_suffix; + code += lang_.getter_prefix; + member_suffix = lang_.getter_suffix; if (struct_def.fixed) { code += " { return " + getter; code += "(bb_pos + " + NumToString(field.value.offset) + ")"; @@ -836,7 +826,7 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin } else { code += offset_prefix + getter; code += "(o + bb_pos)" + dest_mask + " : " + default_cast; - code += GenDefaultValue(lang, field.value); + code += GenDefaultValue(field.value); } } else { switch (field.value.type.base_type) { @@ -856,8 +846,8 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin } break; case BASE_TYPE_STRING: - code += lang.getter_prefix; - member_suffix = lang.getter_suffix; + code += lang_.getter_prefix; + member_suffix = lang_.getter_suffix; code += offset_prefix + getter + "(o + bb_pos) : null"; break; case BASE_TYPE_VECTOR: { @@ -896,22 +886,22 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin code += member_suffix; code += "}\n"; if (field.value.type.base_type == BASE_TYPE_VECTOR) { - code += " public int " + MakeCamel(field.name, lang.first_camel_upper); + code += " public int " + MakeCamel(field.name, lang_.first_camel_upper); code += "Length"; - code += lang.getter_prefix; + code += lang_.getter_prefix; code += offset_prefix; code += "__vector_len(o) : 0; "; - code += lang.getter_suffix; + code += lang_.getter_suffix; code += "}\n"; } // Generate a ByteBuffer accessor for strings & vectors of scalars. if ((field.value.type.base_type == BASE_TYPE_VECTOR && IsScalar(field.value.type.VectorType().base_type)) || field.value.type.base_type == BASE_TYPE_STRING) { - switch (lang.language) { + switch (lang_.language) { case IDLOptions::kJava: code += " public ByteBuffer "; - code += MakeCamel(field.name, lang.first_camel_upper); + code += MakeCamel(field.name, lang_.first_camel_upper); code += "AsByteBuffer() { return __vector_as_bytebuffer("; code += NumToString(field.value.offset) + ", "; code += NumToString(field.value.type.base_type == BASE_TYPE_STRING ? 1 : @@ -920,7 +910,7 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin break; case IDLOptions::kCSharp: code += " public ArraySegment? Get"; - code += MakeCamel(field.name, lang.first_camel_upper); + code += MakeCamel(field.name, lang_.first_camel_upper); code += "Bytes() { return __vector_as_arraysegment("; code += NumToString(field.value.offset); code += "); }\n"; @@ -936,10 +926,10 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin parser_.namespaces_.back()->GetFullyQualifiedName(nested->constant); auto nested_type = parser_.structs_.Lookup(nested_qualified_name); auto nested_type_name = WrapInNameSpace(*nested_type); - auto nestedMethodName = MakeCamel(field.name, lang.first_camel_upper) + auto nestedMethodName = MakeCamel(field.name, lang_.first_camel_upper) + "As" + nested_type_name; auto getNestedMethodName = nestedMethodName; - if (lang.language == IDLOptions::kCSharp) { + if (lang_.language == IDLOptions::kCSharp) { getNestedMethodName = "Get" + nestedMethodName; } code += " public " + nested_type_name + " "; @@ -957,10 +947,10 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin : field.value.type; // boolean parameters have to be explicitly converted to byte representation auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL ? "(byte)(" + field.name + " ? 1 : 0)" : field.name; - auto mutator_prefix = MakeCamel("mutate", lang.first_camel_upper); + auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper); //a vector mutator also needs the index of the vector element it should mutate auto mutator_params = (field.value.type.base_type == BASE_TYPE_VECTOR ? "(int j, " : "(") + - GenTypeNameDest(lang, underlying_type) + " " + + GenTypeNameDest(underlying_type) + " " + field.name + ") { "; auto setter_index = field.value.type.base_type == BASE_TYPE_VECTOR ? "__vector(o) + j * " + NumToString(InlineSize(underlying_type)) @@ -969,15 +959,15 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin (field.value.type.base_type == BASE_TYPE_VECTOR && IsScalar(field.value.type.VectorType().base_type))) { code += " public "; - code += struct_def.fixed ? "void " : lang.bool_type; + code += struct_def.fixed ? "void " : lang_.bool_type; code += mutator_prefix + MakeCamel(field.name, true); code += mutator_params; if (struct_def.fixed) { - code += GenSetter(lang, underlying_type) + "(" + setter_index + ", "; + code += GenSetter(underlying_type) + "(" + setter_index + ", "; code += src_cast + setter_parameter + "); }\n"; } else { code += "int o = __offset(" + NumToString(field.value.offset) + ");"; - code += " if (o != 0) { " + GenSetter(lang, underlying_type); + code += " if (o != 0) { " + GenSetter(underlying_type); code += "(" + setter_index + ", " + src_cast + setter_parameter + "); return true; } else { return false; } }\n"; } } @@ -986,14 +976,14 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin code += "\n"; if (struct_def.fixed) { // create a struct constructor function - code += " public static " + GenOffsetType(lang, struct_def) + " "; - code += FunctionStart(lang, 'C') + "reate"; + code += " public static " + GenOffsetType(struct_def) + " "; + code += FunctionStart('C') + "reate"; code += struct_def.name + "(FlatBufferBuilder builder"; - GenStructArgs(lang, struct_def, code_ptr, ""); + GenStructArgs(struct_def, code_ptr, ""); code += ") {\n"; - GenStructBody(lang, struct_def, code_ptr, ""); + GenStructBody(struct_def, code_ptr, ""); code += " return "; - code += GenOffsetConstruct(lang, struct_def, "builder." + std::string(lang.get_fbb_offset)); + code += GenOffsetConstruct(struct_def, "builder." + std::string(lang_.get_fbb_offset)); code += ";\n }\n"; } else { // Generate a method that creates a table in one go. This is only possible @@ -1014,28 +1004,28 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin if (has_no_struct_fields && num_fields) { // Generate a table constructor of the form: // public static int createName(FlatBufferBuilder builder, args...) - code += " public static " + GenOffsetType(lang, struct_def) + " "; - code += FunctionStart(lang, 'C') + "reate" + struct_def.name; + code += " public static " + GenOffsetType(struct_def) + " "; + code += FunctionStart('C') + "reate" + struct_def.name; code += "(FlatBufferBuilder builder"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (field.deprecated) continue; code += ",\n "; - code += GenTypeBasic(lang, DestinationType(lang, field.value.type, false)); + code += GenTypeBasic(DestinationType(field.value.type, false)); code += " "; code += field.name; if (!IsScalar(field.value.type.base_type)) code += "Offset"; // Java doesn't have defaults, which means this method must always // supply all arguments, and thus won't compile when fields are added. - if (lang.language != IDLOptions::kJava) { + if (lang_.language != IDLOptions::kJava) { code += " = "; - code += GenDefaultValueBasic(lang, field.value); + code += GenDefaultValueBasic(field.value); } } code += ") {\n builder."; - code += FunctionStart(lang, 'S') + "tartObject("; + code += FunctionStart('S') + "tartObject("; code += NumToString(struct_def.fields.vec.size()) + ");\n"; for (size_t size = struct_def.sortbysize ? sizeof(largest_scalar_t) : 1; size; @@ -1047,7 +1037,7 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin (!struct_def.sortbysize || size == SizeOf(field.value.type.base_type))) { code += " " + struct_def.name + "."; - code += FunctionStart(lang, 'A') + "dd"; + code += FunctionStart('A') + "dd"; code += MakeCamel(field.name) + "(builder, " + field.name; if (!IsScalar(field.value.type.base_type)) code += "Offset"; code += ");\n"; @@ -1055,7 +1045,7 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin } } code += " return " + struct_def.name + "."; - code += FunctionStart(lang, 'E') + "nd" + struct_def.name; + code += FunctionStart('E') + "nd" + struct_def.name; code += "(builder);\n }\n\n"; } // Generate a set of static methods that allow table construction, @@ -1063,30 +1053,30 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin // public static void addName(FlatBufferBuilder builder, short name) // { builder.addShort(id, name, default); } // Unlike the Create function, these always work. - code += " public static void " + FunctionStart(lang, 'S') + "tart"; + code += " public static void " + FunctionStart('S') + "tart"; code += struct_def.name; code += "(FlatBufferBuilder builder) { builder."; - code += FunctionStart(lang, 'S') + "tartObject("; + code += FunctionStart('S') + "tartObject("; code += NumToString(struct_def.fields.vec.size()) + "); }\n"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (field.deprecated) continue; - code += " public static void " + FunctionStart(lang, 'A') + "dd"; + code += " public static void " + FunctionStart('A') + "dd"; code += MakeCamel(field.name); code += "(FlatBufferBuilder builder, "; - code += GenTypeBasic(lang, DestinationType(lang, field.value.type, false)); + code += GenTypeBasic(DestinationType(field.value.type, false)); auto argname = MakeCamel(field.name, false); if (!IsScalar(field.value.type.base_type)) argname += "Offset"; - code += " " + argname + ") { builder." + FunctionStart(lang, 'A') + "dd"; - code += GenMethod(lang, field.value.type) + "("; + code += " " + argname + ") { builder." + FunctionStart('A') + "dd"; + code += GenMethod(field.value.type) + "("; code += NumToString(it - struct_def.fields.vec.begin()) + ", "; - code += SourceCastBasic(lang, field.value.type); + code += SourceCastBasic(field.value.type); code += argname; - if(!IsScalar(field.value.type.base_type) && field.value.type.base_type != BASE_TYPE_UNION && lang.language == IDLOptions::kCSharp) { + if(!IsScalar(field.value.type.base_type) && field.value.type.base_type != BASE_TYPE_UNION && lang_.language == IDLOptions::kCSharp) { code += ".Value"; } - code += ", " + GenDefaultValue(lang, field.value, false); + code += ", " + GenDefaultValue(field.value, false); code += "); }\n"; if (field.value.type.base_type == BASE_TYPE_VECTOR) { auto vector_type = field.value.type.VectorType(); @@ -1094,58 +1084,58 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin auto elem_size = InlineSize(vector_type); if (!IsStruct(vector_type)) { // Generate a method to create a vector from a Java array. - code += " public static " + GenVectorOffsetType(lang) + " " + FunctionStart(lang, 'C') + "reate"; + code += " public static " + GenVectorOffsetType() + " " + FunctionStart('C') + "reate"; code += MakeCamel(field.name); code += "Vector(FlatBufferBuilder builder, "; - code += GenTypeBasic(lang, vector_type) + "[] data) "; - code += "{ builder." + FunctionStart(lang, 'S') + "tartVector("; + code += GenTypeBasic(vector_type) + "[] data) "; + code += "{ builder." + FunctionStart('S') + "tartVector("; code += NumToString(elem_size); - code += ", data." + FunctionStart(lang, 'L') + "ength, "; + code += ", data." + FunctionStart('L') + "ength, "; code += NumToString(alignment); code += "); for (int i = data."; - code += FunctionStart(lang, 'L') + "ength - 1; i >= 0; i--) builder."; - code += FunctionStart(lang, 'A') + "dd"; - code += GenMethod(lang, vector_type); + code += FunctionStart('L') + "ength - 1; i >= 0; i--) builder."; + code += FunctionStart('A') + "dd"; + code += GenMethod(vector_type); code += "("; - code += SourceCastBasic(lang, vector_type, false); + code += SourceCastBasic(vector_type, false); code += "data[i]"; - if (lang.language == IDLOptions::kCSharp && + if (lang_.language == IDLOptions::kCSharp && (vector_type.base_type == BASE_TYPE_STRUCT || vector_type.base_type == BASE_TYPE_STRING)) code += ".Value"; code += "); return "; - code += "builder." + FunctionStart(lang, 'E') + "ndVector(); }\n"; + code += "builder." + FunctionStart('E') + "ndVector(); }\n"; } // Generate a method to start a vector, data to be added manually after. - code += " public static void " + FunctionStart(lang, 'S') + "tart"; + code += " public static void " + FunctionStart('S') + "tart"; code += MakeCamel(field.name); code += "Vector(FlatBufferBuilder builder, int numElems) "; - code += "{ builder." + FunctionStart(lang, 'S') + "tartVector("; + code += "{ builder." + FunctionStart('S') + "tartVector("; code += NumToString(elem_size); code += ", numElems, " + NumToString(alignment); code += "); }\n"; } } - code += " public static " + GenOffsetType(lang, struct_def) + " "; - code += FunctionStart(lang, 'E') + "nd" + struct_def.name; + code += " public static " + GenOffsetType(struct_def) + " "; + code += FunctionStart('E') + "nd" + struct_def.name; code += "(FlatBufferBuilder builder) {\n int o = builder."; - code += FunctionStart(lang, 'E') + "ndObject();\n"; + code += FunctionStart('E') + "ndObject();\n"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (!field.deprecated && field.required) { - code += " builder." + FunctionStart(lang, 'R') + "equired(o, "; + code += " builder." + FunctionStart('R') + "equired(o, "; code += NumToString(field.value.offset); code += "); // " + field.name + "\n"; } } - code += " return " + GenOffsetConstruct(lang, struct_def, "o") + ";\n }\n"; + code += " return " + GenOffsetConstruct(struct_def, "o") + ";\n }\n"; if (parser_.root_struct_def_ == &struct_def) { code += " public static void "; - code += FunctionStart(lang, 'F') + "inish" + struct_def.name; - code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(lang, struct_def) + " offset) {"; - code += " builder." + FunctionStart(lang, 'F') + "inish(offset"; - if (lang.language == IDLOptions::kCSharp) { + code += FunctionStart('F') + "inish" + struct_def.name; + code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(struct_def) + " offset) {"; + code += " builder." + FunctionStart('F') + "inish(offset"; + if (lang_.language == IDLOptions::kCSharp) { code += ".Value"; } @@ -1156,6 +1146,7 @@ void GenStruct(const LanguageParameters &lang, StructDef &struct_def, std::strin } code += "};\n\n"; } + const LanguageParameters & lang_ = language_parameters[parser_.opts.lang]; }; } // namespace general From 66f2aac26fe28165cb0a2036249954ddbf122d87 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 19:19:55 +0200 Subject: [PATCH 31/42] php:pulled methods inside the generator --- src/idl_gen_php.cpp | 144 +++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 76 deletions(-) diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index 68ddc8171..31b05b505 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -25,14 +25,74 @@ namespace flatbuffers { namespace php { + // Hardcode spaces per indentation. + const std::string Indent = " "; + class PhpGenerator : public BaseGenerator { + public: + PhpGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) + : BaseGenerator(parser, path, file_name){}; + bool generate() { + if (!generateEnums()) return false; + if (!generateStructs()) return false; + return true; + } - static std::string GenGetter(const Type &type); - static std::string GenDefaultValue(const Value &value); - static std::string GenMethod(const FieldDef &field); - static void GenStructBuilder(const StructDef &struct_def, - std::string *code_ptr); - static std::string GenTypeBasic(const Type &type); - static std::string GenTypeGet(const Type &type); + private: + bool generateEnums() { + for (auto it = parser_.enums_.vec.begin(); + it != parser_.enums_.vec.end(); ++it) { + auto &enum_def = **it; + std::string enumcode; + GenEnum(enum_def, &enumcode); + if (!SaveType(enum_def, enumcode, false)) return false; + } + return true; + } + + bool generateStructs() { + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + std::string declcode; + GenStruct(parser_, struct_def, &declcode); + if (!SaveType(struct_def, declcode, true)) return false; + } + return true; + } + + // Begin by declaring namespace and imports. + void BeginFile(const std::string name_space_name, + const bool needs_imports, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "offset();\n"; code += Indent + "}\n"; } - - class PhpGenerator : public BaseGenerator { - public: - PhpGenerator(const Parser &parser, const std::string &path, - const std::string &file_name) - : BaseGenerator(parser, path, file_name){}; - bool generate() { - if (!generateEnums()) return false; - if (!generateStructs()) return false; - return true; - } - - private: - bool generateEnums() { - for (auto it = parser_.enums_.vec.begin(); - it != parser_.enums_.vec.end(); ++it) { - auto &enum_def = **it; - std::string enumcode; - GenEnum(enum_def, &enumcode); - if (!SaveType(enum_def, enumcode, false)) return false; - } - return true; - } - - bool generateStructs() { - for (auto it = parser_.structs_.vec.begin(); - it != parser_.structs_.vec.end(); ++it) { - auto &struct_def = **it; - std::string declcode; - GenStruct(parser_, struct_def, &declcode); - if (!SaveType(struct_def, declcode, true)) return false; - } - return true; - } - - // Begin by declaring namespace and imports. - void BeginFile(const std::string name_space_name, - const bool needs_imports, std::string *code_ptr) { - std::string &code = *code_ptr; - code += " Date: Tue, 14 Jun 2016 19:26:08 +0200 Subject: [PATCH 32/42] php:removed parser from method signatures --- src/idl_gen_php.cpp | 62 ++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index 31b05b505..11eb0fd1c 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -55,7 +55,7 @@ namespace php { it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; std::string declcode; - GenStruct(parser_, struct_def, &declcode); + GenStruct(struct_def, &declcode); if (!SaveType(struct_def, declcode, true)) return false; } return true; @@ -96,8 +96,7 @@ namespace php { // Ensure that a type is prefixed with its namespace whenever it is used // outside of its namespace. - static std::string WrapInNameSpace(const Namespace *ns, - const std::string &name) { + std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { std::string qualified_name = "\\"; for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { @@ -106,7 +105,7 @@ namespace php { return qualified_name + name; } - static std::string WrapInNameSpace(const Definition &def) { + std::string WrapInNameSpace(const Definition &def) { return WrapInNameSpace(def.defined_namespace, def.name); } @@ -246,8 +245,7 @@ namespace php { } // Get the value of a table's scalar. - static void GetScalarFieldOfTable(const FieldDef &field, - std::string *code_ptr) { + void GetScalarFieldOfTable(const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; std::string getter = GenGetter(field.value.type); @@ -270,8 +268,7 @@ namespace php { // Get a struct by initializing an existing struct. // Specific to Struct. - static void GetStructFieldOfStruct(const FieldDef &field, - std::string *code_ptr) { + void GetStructFieldOfStruct(const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; code += Indent + "/**\n"; @@ -290,8 +287,7 @@ namespace php { // Get a struct by initializing an existing struct. // Specific to Table. - static void GetStructFieldOfTable(const FieldDef &field, - std::string *code_ptr) { + void GetStructFieldOfTable(const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; code += Indent + "public function get"; @@ -317,8 +313,7 @@ namespace php { } // Get the value of a string. - static void GetStringField(const FieldDef &field, - std::string *code_ptr) { + void GetStringField(const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; code += Indent + "public function get"; code += MakeCamel(field.name); @@ -335,8 +330,7 @@ namespace php { } // Get the value of a union from an object. - static void GetUnionField(const FieldDef &field, - std::string *code_ptr) { + void GetUnionField(const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; code += Indent + "/**\n"; @@ -355,9 +349,8 @@ namespace php { } // Get the value of a vector's struct member. - static void GetMemberOfVectorOfStruct(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { + void GetMemberOfVectorOfStruct(const StructDef &struct_def, + const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; auto vectortype = field.value.type.VectorType(); @@ -419,7 +412,7 @@ namespace php { // Get the value of a vector's non-struct member. Uses a named return // argument to conveniently set the zero value for the result. - static void GetMemberOfVectorOfNonStruct(const FieldDef &field, + void GetMemberOfVectorOfNonStruct(const FieldDef &field, std::string *code_ptr) { std::string &code = *code_ptr; auto vectortype = field.value.type.VectorType(); @@ -660,9 +653,7 @@ namespace php { } // Get the offset of the end of a table. - static void GetEndOffsetOnTable(const Parser &parser, - const StructDef &struct_def, - std::string *code_ptr) { + void GetEndOffsetOnTable(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; @@ -689,7 +680,7 @@ namespace php { code += Indent + Indent + "return $o;\n"; code += Indent + "}\n"; - if (parser.root_struct_def_ == &struct_def) { + if (parser_.root_struct_def_ == &struct_def) { code += "\n"; code += Indent + "public static function finish"; code += struct_def.name; @@ -697,16 +688,15 @@ namespace php { code += Indent + "{\n"; code += Indent + Indent + "$builder->finish($offset"; - if (parser.file_identifier_.length()) - code += ", \"" + parser.file_identifier_ + "\""; + if (parser_.file_identifier_.length()) + code += ", \"" + parser_.file_identifier_ + "\""; code += ");\n"; code += Indent + "}\n"; } } // Generate a struct field, conditioned on its child type(s). - static void GenStructAccessor(const StructDef &struct_def, - const FieldDef &field, + void GenStructAccessor(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { GenComment(field.doc_comment, code_ptr, nullptr); @@ -753,9 +743,7 @@ namespace php { } // Generate table constructors, conditioned on its members' types. - static void GenTableBuilders(const Parser &parser, - const StructDef &struct_def, - std::string *code_ptr) { + void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { GetStartOfTable(struct_def, code_ptr); for (auto it = struct_def.fields.vec.begin(); @@ -782,11 +770,11 @@ namespace php { } } - GetEndOffsetOnTable(parser, struct_def, code_ptr); + GetEndOffsetOnTable(struct_def, code_ptr); } // Generate struct or table methods. - static void GenStruct(const Parser &parser, const StructDef &struct_def, + void GenStruct(const StructDef &struct_def, std::string *code_ptr) { if (struct_def.generated) return; @@ -801,13 +789,13 @@ namespace php { std::string &code = *code_ptr; if (!struct_def.fixed) { - if (parser.file_identifier_.length()) { + if (parser_.file_identifier_.length()) { // Return the identifier code += Indent + "public static function " + struct_def.name; code += "Identifier()\n"; code += Indent + "{\n"; code += Indent + Indent + "return \""; - code += parser.file_identifier_ + "\";\n"; + code += parser_.file_identifier_ + "\";\n"; code += Indent + "}\n\n"; // Check if a buffer has the identifier. @@ -820,12 +808,12 @@ namespace php { code += Indent + "}\n\n"; } - if (parser.file_extension_.length()) { + if (parser_.file_extension_.length()) { // Return the extension code += Indent + "public static function " + struct_def.name; code += "Extension()\n"; code += Indent + "{\n"; - code += Indent + Indent + "return \"" + parser.file_extension_; + code += Indent + Indent + "return \"" + parser_.file_extension_; code += "\";\n"; code += Indent + "}\n\n"; } @@ -848,7 +836,7 @@ namespace php { GenStructBuilder(struct_def, code_ptr); } else { // Create a set of functions that allow table construction. - GenTableBuilders(parser, struct_def, code_ptr); + GenTableBuilders(struct_def, code_ptr); } EndClass(code_ptr); } @@ -916,7 +904,7 @@ namespace php { return ctypename[type.base_type]; } - static std::string GenDefaultValue(const Value &value) { + std::string GenDefaultValue(const Value &value) { if (value.type.enum_def) { if (auto val = value.type.enum_def->ReverseLookup( atoi(value.constant.c_str()), false)) { From a9e21170bcd43878362dea64d87ab86a6758a049 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 21:41:11 +0200 Subject: [PATCH 33/42] js:pulled methods inside the class --- src/idl_gen_js.cpp | 124 ++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 64 deletions(-) diff --git a/src/idl_gen_js.cpp b/src/idl_gen_js.cpp index d724b80f4..bd593f17d 100644 --- a/src/idl_gen_js.cpp +++ b/src/idl_gen_js.cpp @@ -22,9 +22,67 @@ #include "flatbuffers/code_generators.h" namespace flatbuffers { -namespace js { -static void GenNamespaces(const Parser &parser, std::string *code_ptr, +static std::string GeneratedFileName(const std::string &path, + const std::string &file_name) { + return path + file_name + "_generated.js"; +} + +namespace js { +// Iterate through all definitions we haven't generate code for (enums, structs, +// and tables) and output them to a single file. +class JsGenerator : public BaseGenerator { + public: + JsGenerator(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 enum_code, struct_code, exports_code, code; + generateEnums(&enum_code, &exports_code); + generateStructs(&struct_code, &exports_code); + + code = code + "// " + FlatBuffersGeneratedWarning(); + + // Generate code for all the namespace declarations. + GenNamespaces(parser_, &code, &exports_code); + + // Output the main declaration code from above. + code += enum_code; + code += struct_code; + + if (!exports_code.empty() && !parser_.opts.skip_js_exports) { + code += "// Exports for Node.js and RequireJS\n"; + code += exports_code; + } + + return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false); + } + + private: + // Generate code for all enums. + void generateEnums(std::string *enum_code_ptr, + std::string *exports_code_ptr) { + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + auto &enum_def = **it; + GenEnum(enum_def, enum_code_ptr, exports_code_ptr); + } + } + + // Generate code for all structs. + void generateStructs(std::string *decl_code_ptr, + std::string *exports_code_ptr) { + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr); + } + } + static void GenNamespaces(const Parser &parser, std::string *code_ptr, std::string *exports_ptr) { std::set namespaces; @@ -659,68 +717,6 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, } } } - -} // namespace js - -static std::string GeneratedFileName(const std::string &path, - const std::string &file_name) { - return path + file_name + "_generated.js"; -} - -namespace js { -// Iterate through all definitions we haven't generate code for (enums, structs, -// and tables) and output them to a single file. -class JsGenerator : public BaseGenerator { - public: - JsGenerator(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 enum_code, struct_code, exports_code, code; - generateEnums(&enum_code, &exports_code); - generateStructs(&struct_code, &exports_code); - - code = code + "// " + FlatBuffersGeneratedWarning(); - - // Generate code for all the namespace declarations. - GenNamespaces(parser_, &code, &exports_code); - - // Output the main declaration code from above. - code += enum_code; - code += struct_code; - - if (!exports_code.empty() && !parser_.opts.skip_js_exports) { - code += "// Exports for Node.js and RequireJS\n"; - code += exports_code; - } - - return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false); - } - - private: - // Generate code for all enums. - void generateEnums(std::string *enum_code_ptr, - std::string *exports_code_ptr) { - for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); - ++it) { - auto &enum_def = **it; - GenEnum(enum_def, enum_code_ptr, exports_code_ptr); - } - } - - // Generate code for all structs. - void generateStructs(std::string *decl_code_ptr, - std::string *exports_code_ptr) { - for (auto it = parser_.structs_.vec.begin(); - it != parser_.structs_.vec.end(); ++it) { - auto &struct_def = **it; - GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr); - } - } }; } // namespace js From 2f52618c4e05abffb72e368e134cf894689a0187 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 21:43:35 +0200 Subject: [PATCH 34/42] removed parser from the method signatures --- src/idl_gen_js.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/idl_gen_js.cpp b/src/idl_gen_js.cpp index bd593f17d..d152fa449 100644 --- a/src/idl_gen_js.cpp +++ b/src/idl_gen_js.cpp @@ -48,7 +48,7 @@ class JsGenerator : public BaseGenerator { code = code + "// " + FlatBuffersGeneratedWarning(); // Generate code for all the namespace declarations. - GenNamespaces(parser_, &code, &exports_code); + GenNamespaces(&code, &exports_code); // Output the main declaration code from above. code += enum_code; @@ -79,15 +79,14 @@ class JsGenerator : public BaseGenerator { for (auto it = parser_.structs_.vec.begin(); it != parser_.structs_.vec.end(); ++it) { auto &struct_def = **it; - GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr); + GenStruct(struct_def, decl_code_ptr, exports_code_ptr); } } - static void GenNamespaces(const Parser &parser, std::string *code_ptr, - std::string *exports_ptr) { + void GenNamespaces(std::string *code_ptr, std::string *exports_ptr) { std::set namespaces; - for (auto it = parser.namespaces_.begin(); - it != parser.namespaces_.end(); ++it) { + for (auto it = parser_.namespaces_.begin(); + it != parser_.namespaces_.end(); ++it) { std::string namespace_so_far; // Gather all parent namespaces for this namespace @@ -378,8 +377,7 @@ static void GenStructBody(const StructDef &struct_def, } // Generate an accessor struct with constructor for a flatbuffers struct. -static void GenStruct(const Parser &parser, StructDef &struct_def, - std::string *code_ptr, std::string *exports_ptr) { +void GenStruct(StructDef &struct_def, std::string *code_ptr, std::string *exports_ptr) { if (struct_def.generated) return; std::string &code = *code_ptr; std::string &exports = *exports_ptr; @@ -433,13 +431,13 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, code += "};\n\n"; // Generate the identifier check method - if (parser.root_struct_def_ == &struct_def && - !parser.file_identifier_.empty()) { + if (parser_.root_struct_def_ == &struct_def && + !parser_.file_identifier_.empty()) { GenDocComment(code_ptr, "@param {flatbuffers.ByteBuffer} bb\n" "@returns {boolean}"); code += object_name + ".bufferHasIdentifier = function(bb) {\n"; - code += " return bb.__has_identifier('" + parser.file_identifier_; + code += " return bb.__has_identifier('" + parser_.file_identifier_; code += "');\n};\n\n"; } } @@ -702,15 +700,15 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, code += "};\n\n"; // Generate the method to complete buffer construction - if (parser.root_struct_def_ == &struct_def) { + if (parser_.root_struct_def_ == &struct_def) { GenDocComment(code_ptr, "@param {flatbuffers.Builder} builder\n" "@param {flatbuffers.Offset} offset"); code += object_name + ".finish" + struct_def.name + "Buffer"; code += " = function(builder, offset) {\n"; code += " builder.finish(offset"; - if (!parser.file_identifier_.empty()) { - code += ", '" + parser.file_identifier_ + "'"; + if (!parser_.file_identifier_.empty()) { + code += ", '" + parser_.file_identifier_ + "'"; } code += ");\n"; code += "};\n\n"; From 43fedfa8ba95e6ff3fc867ecd41bab89a3a1aa5e Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 21:47:03 +0200 Subject: [PATCH 35/42] removed static from wrapInNamespace method --- src/idl_gen_js.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/idl_gen_js.cpp b/src/idl_gen_js.cpp index d152fa449..a29337772 100644 --- a/src/idl_gen_js.cpp +++ b/src/idl_gen_js.cpp @@ -121,7 +121,7 @@ class JsGenerator : public BaseGenerator { // Ensure that a type is prefixed with its namespace whenever it is used // outside of its namespace. -static std::string WrapInNameSpace(const Namespace *ns, +std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { std::string qualified_name; for (auto it = ns->components.begin(); @@ -131,7 +131,7 @@ static std::string WrapInNameSpace(const Namespace *ns, return qualified_name + name; } -static std::string WrapInNameSpace(const Definition &def) { +std::string WrapInNameSpace(const Definition &def) { return WrapInNameSpace(def.defined_namespace, def.name); } @@ -180,7 +180,7 @@ static void GenDocComment(std::string *code_ptr, } // Generate an enum declaration and an enum string lookup table. -static void GenEnum(EnumDef &enum_def, std::string *code_ptr, +void GenEnum(EnumDef &enum_def, std::string *code_ptr, std::string *exports_ptr) { if (enum_def.generated) return; std::string &code = *code_ptr; @@ -227,7 +227,7 @@ static std::string GenType(const Type &type) { } } -static std::string GenGetter(const Type &type, const std::string &arguments) { +std::string GenGetter(const Type &type, const std::string &arguments) { switch (type.base_type) { case BASE_TYPE_STRING: return "this.bb.__string" + arguments; case BASE_TYPE_STRUCT: return "this.bb.__struct" + arguments; @@ -247,7 +247,7 @@ static std::string GenGetter(const Type &type, const std::string &arguments) { } } -static std::string GenDefaultValue(const Value &value, const std::string &context) { +std::string GenDefaultValue(const Value &value, const std::string &context) { if (value.type.enum_def) { if (auto val = value.type.enum_def->ReverseLookup( atoi(value.constant.c_str()), false)) { @@ -274,7 +274,7 @@ static std::string GenDefaultValue(const Value &value, const std::string &contex } } -static std::string GenTypeName(const Type &type, bool input) { +std::string GenTypeName(const Type &type, bool input) { if (!input) { if (type.base_type == BASE_TYPE_STRING) { return "string|Uint8Array"; @@ -326,7 +326,7 @@ static std::string MaybeScale(T value) { return value != 1 ? " * " + NumToString(value) : ""; } -static void GenStructArgs(const StructDef &struct_def, +void GenStructArgs(const StructDef &struct_def, std::string *annotations, std::string *arguments, const std::string &nameprefix) { From 03ad8fa4d9574b7e613e10df3fe7fc4d9207a4bb Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Tue, 14 Jun 2016 23:17:43 +0200 Subject: [PATCH 36/42] sharing the WrapInNameSpace methods --- include/flatbuffers/code_generators.h | 32 +++++++++++++++++++++++--- src/idl_gen_cpp.cpp | 20 ++-------------- src/idl_gen_general.cpp | 33 ++++++--------------------- src/idl_gen_go.cpp | 3 ++- src/idl_gen_js.cpp | 18 +-------------- src/idl_gen_php.cpp | 19 +-------------- src/idl_gen_python.cpp | 3 ++- 7 files changed, 44 insertions(+), 84 deletions(-) diff --git a/include/flatbuffers/code_generators.h b/include/flatbuffers/code_generators.h index dc5f6bdd8..e7450a7a0 100644 --- a/include/flatbuffers/code_generators.h +++ b/include/flatbuffers/code_generators.h @@ -39,11 +39,15 @@ class BaseGenerator { protected: BaseGenerator(const Parser &parser, const std::string &path, - const std::string &file_name) + const std::string &file_name, + const std::string qualifying_start, + const std::string qualifying_separator) : parser_(parser), path_(path), - file_name_(file_name) {}; - virtual ~BaseGenerator() {}; + file_name_(file_name), + qualifying_start_(qualifying_start), + qualifying_separator_(qualifying_separator){}; + virtual ~BaseGenerator(){}; // No copy/assign. BaseGenerator &operator=(const BaseGenerator &); @@ -85,9 +89,31 @@ class BaseGenerator { if (namespaces.size()) return *(namespaces.end() - 1); else return std::string(""); } + // tracks the current namespace for early exit in WrapInNameSpace + // c++, java and csharp returns a different namespace from + // the following default (no early exit, always fully qualify), + // which works for js and php + virtual const Namespace *CurrentNameSpace() { return nullptr; } + + // Ensure that a type is prefixed with its namespace whenever it is used + // outside of its namespace. + std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { + if (CurrentNameSpace() == ns) return name; + std::string qualified_name = qualifying_start_; + for (auto it = ns->components.begin(); it != ns->components.end(); ++it) + qualified_name += *it + qualifying_separator_; + return qualified_name + name; + } + + std::string WrapInNameSpace(const Definition &def) { + return WrapInNameSpace(def.defined_namespace, def.name); + } + const Parser &parser_; const std::string &path_; const std::string &file_name_; + const std::string qualifying_start_; + const std::string qualifying_separator_; }; } // namespace flatbuffers diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 6c7981417..3a4476fec 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -39,7 +39,7 @@ class CppGenerator : public BaseGenerator { public: CppGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, 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. @@ -208,23 +208,7 @@ class CppGenerator : public BaseGenerator { // This tracks the current namespace so we can insert namespace declarations. const Namespace *cur_name_space_ = nullptr; - // Ensure that a type is prefixed with its namespace whenever it is used - // outside of its namespace. - std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { - if (cur_name_space_ != 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; - } - } - - std::string WrapInNameSpace(const Definition &def) { - return WrapInNameSpace(def.defined_namespace, def.name); - } + const Namespace * CurrentNameSpace() {return cur_name_space_;} // Translates a qualified name in flatbuffer text format to the same name in // the equivalent C++ namespace. diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 7567bdcf4..a96609c54 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -193,7 +193,7 @@ class GeneralGenerator : public BaseGenerator { public: GeneralGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, file_name){ + : BaseGenerator(parser, path, file_name, "", "."){ assert(parser_.opts.lang <= IDLOptions::kMAX); }; bool generate() { @@ -251,38 +251,19 @@ class GeneralGenerator : public BaseGenerator { auto filename = NamespaceDir(ns) + defname + lang_.file_extension; return SaveFile(filename.c_str(), code, false); } - -std::string FunctionStart(char upper) { - return std::string() + - (lang_.language == IDLOptions::kJava - ? static_cast(tolower(upper)) - : upper); + const Namespace *CurrentNameSpace() { return parser_.namespaces_.back(); } + + std::string FunctionStart(char upper) { + return std::string() + (lang_.language == IDLOptions::kJava + ? static_cast(tolower(upper)) + : upper); } static bool IsEnum(const Type& type) { return type.enum_def != nullptr && IsInteger(type.base_type); } -// Ensure that a type is prefixed with its namespace whenever it is used -// outside of its namespace. -std::string WrapInNameSpace(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; - } -} - -std::string WrapInNameSpace(const Definition &def) { - return WrapInNameSpace(def.defined_namespace, def.name); -} - std::string GenTypeBasic(const Type &type, bool enableLangOverrides) { static const char *gtypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index 5c60c1052..a04b6ba20 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -625,7 +625,8 @@ class GoGenerator : public BaseGenerator { public: GoGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, file_name){}; + : BaseGenerator(parser, path, file_name, "" /* not used*/, + "" /* not used */){}; bool generate() { for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); ++it) { diff --git a/src/idl_gen_js.cpp b/src/idl_gen_js.cpp index a29337772..32a06f1ef 100644 --- a/src/idl_gen_js.cpp +++ b/src/idl_gen_js.cpp @@ -35,7 +35,7 @@ class JsGenerator : public BaseGenerator { public: JsGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, 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() { @@ -119,22 +119,6 @@ class JsGenerator : public BaseGenerator { } } -// Ensure that a type is prefixed with its namespace whenever it is used -// outside of its namespace. -std::string WrapInNameSpace(const Namespace *ns, - const std::string &name) { - std::string qualified_name; - for (auto it = ns->components.begin(); - it != ns->components.end(); ++it) { - qualified_name += *it + "."; - } - return qualified_name + name; -} - -std::string WrapInNameSpace(const Definition &def) { - return WrapInNameSpace(def.defined_namespace, def.name); -} - // Generate a documentation comment, if available. static void GenDocComment(const std::vector &dc, std::string *code_ptr, diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index 11eb0fd1c..af3b06d57 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -31,7 +31,7 @@ namespace php { public: PhpGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, file_name){}; + : BaseGenerator(parser, path, file_name, "\\", "\\"){}; bool generate() { if (!generateEnums()) return false; if (!generateStructs()) return false; @@ -93,23 +93,6 @@ namespace php { return SaveFile(filename.c_str(), code, false); } - - // Ensure that a type is prefixed with its namespace whenever it is used - // outside of its namespace. - std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { - std::string qualified_name = "\\"; - for (auto it = ns->components.begin(); - it != ns->components.end(); ++it) { - qualified_name += *it + "\\"; - } - return qualified_name + name; - } - - std::string WrapInNameSpace(const Definition &def) { - return WrapInNameSpace(def.defined_namespace, def.name); - } - - // Begin a class declaration. static void BeginClass(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index 5f5c6be3b..7e8dc0ebd 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -596,7 +596,8 @@ class PythonGenerator : public BaseGenerator { public: PythonGenerator(const Parser &parser, const std::string &path, const std::string &file_name) - : BaseGenerator(parser, path, file_name){}; + : BaseGenerator(parser, path, file_name, "" /* not used */, + "" /* not used */){}; bool generate() { if (!generateEnums()) return false; if (!generateStructs()) return false; From f794f97d883d1ce2702f086a8f88be693b834415 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Thu, 23 Jun 2016 00:23:11 +0200 Subject: [PATCH 37/42] fixing spaces --- src/idl_gen_cpp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 3a4476fec..c690240d6 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -208,7 +208,7 @@ class CppGenerator : public BaseGenerator { // This tracks the current namespace so we can insert namespace declarations. const Namespace *cur_name_space_ = nullptr; - const Namespace * CurrentNameSpace() {return cur_name_space_;} + const Namespace *CurrentNameSpace() { return cur_name_space_; } // Translates a qualified name in flatbuffer text format to the same name in // the equivalent C++ namespace. From c97abb1eea0ae19bdc7a25adde6f9129a51627c6 Mon Sep 17 00:00:00 2001 From: Yury Bandarchuk Date: Thu, 23 Jun 2016 19:51:55 +0400 Subject: [PATCH 38/42] Added new constants Add new constants in Constants.java All single ints int FlatBufferBuilder.java were replaced by constants from Constants.java --- java/com/google/flatbuffers/Constants.java | 8 ++++++ .../google/flatbuffers/FlatBufferBuilder.java | 28 +++++++++---------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/java/com/google/flatbuffers/Constants.java b/java/com/google/flatbuffers/Constants.java index ac0593ae6..c3b98c5e8 100644 --- a/java/com/google/flatbuffers/Constants.java +++ b/java/com/google/flatbuffers/Constants.java @@ -23,10 +23,18 @@ package com.google.flatbuffers; */ public class Constants { // Java doesn't seem to have these. + /** The number of bytes in an `byte`. */ + static final int SIZEOF_BYTE = 1; /** The number of bytes in a `short`. */ static final int SIZEOF_SHORT = 2; /** The number of bytes in an `int`. */ static final int SIZEOF_INT = 4; + /** The number of bytes in an `float`. */ + static final int SIZEOF_FLOAT = 4; + /** The number of bytes in an `long`. */ + static final int SIZEOF_LONG = 8; + /** The number of bytes in an `double`. */ + static final int SIZEOF_DOUBLE = 4; /** The number of bytes in a file identifier. */ static final int FILE_IDENTIFIER_LENGTH = 4; } diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java index fecb213f6..c2186fa7b 100644 --- a/java/com/google/flatbuffers/FlatBufferBuilder.java +++ b/java/com/google/flatbuffers/FlatBufferBuilder.java @@ -188,7 +188,7 @@ public class FlatBufferBuilder { * * @param x A `boolean` to put into the buffer. */ - public void putBoolean(boolean x) { bb.put (space -= 1, (byte)(x ? 1 : 0)); } + public void putBoolean(boolean x) { bb.put (space -= Constants.SIZEOF_BYTE, (byte)(x ? 1 : 0)); } /** * Add a `byte` to the buffer, backwards from the current location. Doesn't align nor @@ -196,7 +196,7 @@ public class FlatBufferBuilder { * * @param x A `byte` to put into the buffer. */ - public void putByte (byte x) { bb.put (space -= 1, x); } + public void putByte (byte x) { bb.put (space -= Constants.SIZEOF_BYTE, x); } /** * Add a `short` to the buffer, backwards from the current location. Doesn't align nor @@ -204,7 +204,7 @@ public class FlatBufferBuilder { * * @param x A `short` to put into the buffer. */ - public void putShort (short x) { bb.putShort (space -= 2, x); } + public void putShort (short x) { bb.putShort (space -= Constants.SIZEOF_SHORT, x); } /** * Add an `int` to the buffer, backwards from the current location. Doesn't align nor @@ -212,7 +212,7 @@ public class FlatBufferBuilder { * * @param x An `int` to put into the buffer. */ - public void putInt (int x) { bb.putInt (space -= 4, x); } + public void putInt (int x) { bb.putInt (space -= Constants.SIZEOF_INT, x); } /** * Add a `long` to the buffer, backwards from the current location. Doesn't align nor @@ -220,7 +220,7 @@ public class FlatBufferBuilder { * * @param x A `long` to put into the buffer. */ - public void putLong (long x) { bb.putLong (space -= 8, x); } + public void putLong (long x) { bb.putLong (space -= Constants.SIZEOF_LONG, x); } /** * Add a `float` to the buffer, backwards from the current location. Doesn't align nor @@ -228,7 +228,7 @@ public class FlatBufferBuilder { * * @param x A `float` to put into the buffer. */ - public void putFloat (float x) { bb.putFloat (space -= 4, x); } + public void putFloat (float x) { bb.putFloat (space -= Constants.SIZEOF_FLOAT, x); } /** * Add a `double` to the buffer, backwards from the current location. Doesn't align nor @@ -236,7 +236,7 @@ public class FlatBufferBuilder { * * @param x A `double` to put into the buffer. */ - public void putDouble (double x) { bb.putDouble(space -= 8, x); } + public void putDouble (double x) { bb.putDouble(space -= Constants.SIZEOF_DOUBLE, x); } /// @endcond /** @@ -244,49 +244,49 @@ public class FlatBufferBuilder { * * @param x A `boolean` to put into the buffer. */ - public void addBoolean(boolean x) { prep(1, 0); putBoolean(x); } + public void addBoolean(boolean x) { prep(Constants.SIZEOF_BYTE, 0); putBoolean(x); } /** * Add a `byte` to the buffer, properly aligned, and grows the buffer (if necessary). * * @param x A `byte` to put into the buffer. */ - public void addByte (byte x) { prep(1, 0); putByte (x); } + public void addByte (byte x) { prep(Constants.SIZEOF_BYTE, 0); putByte (x); } /** * Add a `short` to the buffer, properly aligned, and grows the buffer (if necessary). * * @param x A `short` to put into the buffer. */ - public void addShort (short x) { prep(2, 0); putShort (x); } + public void addShort (short x) { prep(Constants.SIZEOF_SHORT, 0); putShort (x); } /** * Add an `int` to the buffer, properly aligned, and grows the buffer (if necessary). * * @param x An `int` to put into the buffer. */ - public void addInt (int x) { prep(4, 0); putInt (x); } + public void addInt (int x) { prep(Constants.SIZEOF_INT, 0); putInt (x); } /** * Add a `long` to the buffer, properly aligned, and grows the buffer (if necessary). * * @param x A `long` to put into the buffer. */ - public void addLong (long x) { prep(8, 0); putLong (x); } + public void addLong (long x) { prep(Constants.SIZEOF_LONG, 0); putLong (x); } /** * Add a `float` to the buffer, properly aligned, and grows the buffer (if necessary). * * @param x A `float` to put into the buffer. */ - public void addFloat (float x) { prep(4, 0); putFloat (x); } + public void addFloat (float x) { prep(Constants.SIZEOF_FLOAT, 0); putFloat (x); } /** * Add a `double` to the buffer, properly aligned, and grows the buffer (if necessary). * * @param x A `double` to put into the buffer. */ - public void addDouble (double x) { prep(8, 0); putDouble (x); } + public void addDouble (double x) { prep(Constants.SIZEOF_DOUBLE, 0); putDouble (x); } /** * Adds on offset, relative to where it will be written. From ec59dc026f5bf06b5b56f4d53928d5376281412f Mon Sep 17 00:00:00 2001 From: Yury Bandarchuk Date: Thu, 23 Jun 2016 21:30:32 +0300 Subject: [PATCH 39/42] Update Constants.java --- java/com/google/flatbuffers/Constants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/com/google/flatbuffers/Constants.java b/java/com/google/flatbuffers/Constants.java index c3b98c5e8..f59063145 100644 --- a/java/com/google/flatbuffers/Constants.java +++ b/java/com/google/flatbuffers/Constants.java @@ -34,7 +34,7 @@ public class Constants { /** The number of bytes in an `long`. */ static final int SIZEOF_LONG = 8; /** The number of bytes in an `double`. */ - static final int SIZEOF_DOUBLE = 4; + static final int SIZEOF_DOUBLE = 8; /** The number of bytes in a file identifier. */ static final int FILE_IDENTIFIER_LENGTH = 4; } From 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 13 Apr 2016 18:16:05 -0700 Subject: [PATCH 40/42] Added GRPC code generator to flatc. Also added simple (in-process) test. Change-Id: I38580d554dd52f590e3396ec4846e07546dcf07d Tested: on Linux. --- CMakeLists.txt | 23 + docs/source/Compiler.md | 2 + docs/source/Schemas.md | 3 +- grpc/README.md | 11 + grpc/src/compiler/cpp_generator.cc | 1202 ++++++++++++++++++++++++++++ grpc/src/compiler/cpp_generator.h | 147 ++++ grpc/tests/grpctest.cpp | 124 +++ include/flatbuffers/flatbuffers.h | 23 + include/flatbuffers/grpc.h | 72 ++ include/flatbuffers/idl.h | 8 +- src/flatc.cpp | 6 +- src/idl_gen_grpc.cpp | 216 +++++ src/idl_parser.cpp | 4 + tests/generate_code.bat | 2 +- tests/generate_code.sh | 2 +- tests/monster_test.fbs | 2 +- tests/monster_test.grpc.fb.cc | 85 ++ tests/monster_test.grpc.fb.h | 155 ++++ 18 files changed, 2081 insertions(+), 6 deletions(-) create mode 100644 grpc/README.md create mode 100644 grpc/src/compiler/cpp_generator.cc create mode 100644 grpc/src/compiler/cpp_generator.h create mode 100644 grpc/tests/grpctest.cpp create mode 100644 include/flatbuffers/grpc.h create mode 100644 src/idl_gen_grpc.cpp create mode 100644 tests/monster_test.grpc.fb.cc create mode 100644 tests/monster_test.grpc.fb.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b1e56d6b0..c2dd95085 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ option(FLATBUFFERS_INSTALL "Enable the installation of targets." ON) option(FLATBUFFERS_BUILD_FLATLIB "Enable the build of the flatbuffers library" ON) option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler" ON) option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON) +option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF) if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS) message(WARNING @@ -39,7 +40,10 @@ set(FlatBuffers_Compiler_SRCS src/idl_gen_php.cpp src/idl_gen_python.cpp src/idl_gen_fbs.cpp + src/idl_gen_grpc.cpp src/flatc.cpp + grpc/src/compiler/cpp_generator.h + grpc/src/compiler/cpp_generator.cc ) set(FlatHash_SRCS @@ -76,6 +80,16 @@ set(FlatBuffers_Sample_Text_SRCS ${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h ) +set(FlatBuffers_GRPCTest_SRCS + include/flatbuffers/flatbuffers.h + include/flatbuffers/grpc.h + tests/monster_test.grpc.fb.h + tests/monster_test.grpc.fb.cc + grpc/tests/grpctest.cpp + # file generated by running compiler on samples/monster.fbs + ${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h +) + # source_group(Compiler FILES ${FlatBuffers_Compiler_SRCS}) # source_group(Tests FILES ${FlatBuffers_Tests_SRCS}) @@ -129,6 +143,7 @@ if(BIICODE) endif() include_directories(include) +include_directories(grpc) if(FLATBUFFERS_BUILD_FLATLIB) add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS}) @@ -174,6 +189,14 @@ if(FLATBUFFERS_BUILD_TESTS) add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS}) endif() +if(FLATBUFFERS_BUILD_GRPCTEST) + if(CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") + endif() + add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS}) + target_link_libraries(grpctest grpc++_unsecure grpc pthread dl) +endif() + if(FLATBUFFERS_INSTALL) install(DIRECTORY include/flatbuffers DESTINATION include) if(FLATBUFFERS_BUILD_FLATLIB) diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md index 886fbd9b8..ad584c739 100755 --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@ -33,6 +33,8 @@ For any schema input files, one or more generators can be specified: - `--php`: Generate PHP code. +- `--grpc`: Generate RPC stub code for GRPC. + For any data input files: - `--binary`, `-b` : If data is contained in this file, generate a diff --git a/docs/source/Schemas.md b/docs/source/Schemas.md index 14bd3bd0e..7dcce0711 100755 --- a/docs/source/Schemas.md +++ b/docs/source/Schemas.md @@ -237,7 +237,8 @@ as the response (both of which must be table types): } What code this produces and how it is used depends on language and RPC system -used, FlatBuffers itself does not offer this functionality. +used, there is preliminary support for GRPC through the `--grpc` code generator, +see `grpc/tests` for an example. ### Comments & documentation diff --git a/grpc/README.md b/grpc/README.md new file mode 100644 index 000000000..13485198c --- /dev/null +++ b/grpc/README.md @@ -0,0 +1,11 @@ +GRPC implementation and test +============================ + +NOTE: files in `src/` are shared with the GRPC project, and maintained there +(any changes should be submitted to GRPC instead). These files are copied +from GRPC, and work with both the Protobuf and FlatBuffers code generator. + +`tests/` contains a GRPC specific test, you need to have built and installed +the GRPC libraries for this to compile. This test will build using the +`FLATBUFFERS_BUILD_GRPCTEST` option to the main FlatBuffers CMake project. + diff --git a/grpc/src/compiler/cpp_generator.cc b/grpc/src/compiler/cpp_generator.cc new file mode 100644 index 000000000..9319c4193 --- /dev/null +++ b/grpc/src/compiler/cpp_generator.cc @@ -0,0 +1,1202 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include + +#include "src/compiler/cpp_generator.h" + +#include + +namespace grpc_cpp_generator { +namespace { + +template +grpc::string as_string(T x) { + std::ostringstream out; + out << x; + return out.str(); +} + +grpc::string FilenameIdentifier(const grpc::string &filename) { + grpc::string result; + for (unsigned i = 0; i < filename.size(); i++) { + char c = filename[i]; + if (isalnum(c)) { + result.push_back(c); + } else { + static char hex[] = "0123456789abcdef"; + result.push_back('_'); + result.push_back(hex[(c >> 4) & 0xf]); + result.push_back(hex[c & 0xf]); + } + } + return result; +} +} // namespace + +template +T *array_end(T (&array)[N]) { return array + N; } + +void PrintIncludes(Printer *printer, const std::vector& headers, const Parameters ¶ms) { + std::map vars; + + vars["l"] = params.use_system_headers ? '<' : '"'; + vars["r"] = params.use_system_headers ? '>' : '"'; + + if (!params.grpc_search_path.empty()) { + vars["l"] += params.grpc_search_path; + if (params.grpc_search_path.back() != '/') { + vars["l"] += '/'; + } + } + + for (auto i = headers.begin(); i != headers.end(); i++) { + vars["h"] = *i; + printer->Print(vars, "#include $l$$h$$r$\n"); + } +} + +grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map vars; + + vars["filename"] = file->filename(); + vars["filename_identifier"] = FilenameIdentifier(file->filename()); + vars["filename_base"] = file->filename_without_ext(); + vars["message_header_ext"] = file->message_header_ext(); + + printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); + printer->Print(vars, + "// If you make any local change, they will be lost.\n"); + printer->Print(vars, "// source: $filename$\n"); + printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n"); + printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n"); + printer->Print(vars, "\n"); + printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n"); + printer->Print(vars, "\n"); + } + return output; +} + +grpc::string GetHeaderIncludes(File *file, + const Parameters ¶ms) { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map vars; + + static const char *headers_strs[] = { + "grpc++/impl/codegen/async_stream.h", + "grpc++/impl/codegen/async_unary_call.h", + "grpc++/impl/codegen/proto_utils.h", + "grpc++/impl/codegen/rpc_method.h", + "grpc++/impl/codegen/service_type.h", + "grpc++/impl/codegen/status.h", + "grpc++/impl/codegen/stub_options.h", + "grpc++/impl/codegen/sync_stream.h" + }; + std::vector headers(headers_strs, array_end(headers_strs)); + PrintIncludes(printer.get(), headers, params); + printer->Print(vars, "\n"); + printer->Print(vars, "namespace grpc {\n"); + printer->Print(vars, "class CompletionQueue;\n"); + printer->Print(vars, "class Channel;\n"); + printer->Print(vars, "class RpcService;\n"); + printer->Print(vars, "class ServerCompletionQueue;\n"); + printer->Print(vars, "class ServerContext;\n"); + printer->Print(vars, "} // namespace grpc\n\n"); + + if (!file->package().empty()) { + std::vector parts = file->package_parts(); + + for (auto part = parts.begin(); part != parts.end(); part++) { + vars["part"] = *part; + printer->Print(vars, "namespace $part$ {\n"); + } + printer->Print(vars, "\n"); + } + } + return output; +} + +void PrintHeaderClientMethodInterfaces( + Printer *printer, const Method *method, + std::map *vars, bool is_public) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + + if (is_public) { + if (method->NoStreaming()) { + printer->Print( + *vars, + "virtual ::grpc::Status $Method$(::grpc::ClientContext* context, " + "const $Request$& request, $Response$* response) = 0;\n"); + printer->Print(*vars, + "std::unique_ptr< " + "::grpc::ClientAsyncResponseReaderInterface< $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq) {\n"); + printer->Indent(); + printer->Print(*vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncResponseReaderInterface< $Response$>>(" + "Async$Method$Raw(context, request, cq));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>" + " $Method$(" + "::grpc::ClientContext* context, $Response$* response) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientWriterInterface< $Request$>>" + "($Method$Raw(context, response));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>" + " Async$Method$(::grpc::ClientContext* context, $Response$* " + "response, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print(*vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncWriterInterface< $Request$>>(" + "Async$Method$Raw(context, response, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>" + " $Method$(::grpc::ClientContext* context, const $Request$& request)" + " {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientReaderInterface< $Response$>>" + "($Method$Raw(context, request));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> " + "Async$Method$(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print(*vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncReaderInterface< $Response$>>(" + "Async$Method$Raw(context, request, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (method->BidiStreaming()) { + printer->Print(*vars, + "std::unique_ptr< ::grpc::ClientReaderWriterInterface< " + "$Request$, $Response$>> " + "$Method$(::grpc::ClientContext* context) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientReaderWriterInterface< $Request$, $Response$>>(" + "$Method$Raw(context));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< " + "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>(" + "Async$Method$Raw(context, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } + } else { + if (method->NoStreaming()) { + printer->Print( + *vars, + "virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq) = 0;\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print( + *vars, + "virtual ::grpc::ClientWriterInterface< $Request$>*" + " $Method$Raw(" + "::grpc::ClientContext* context, $Response$* response) = 0;\n"); + printer->Print(*vars, + "virtual ::grpc::ClientAsyncWriterInterface< $Request$>*" + " Async$Method$Raw(::grpc::ClientContext* context, " + "$Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print( + *vars, + "virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request) = 0;\n"); + printer->Print( + *vars, + "virtual ::grpc::ClientAsyncReaderInterface< $Response$>* " + "Async$Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); + } else if (method->BidiStreaming()) { + printer->Print(*vars, + "virtual ::grpc::ClientReaderWriterInterface< $Request$, " + "$Response$>* " + "$Method$Raw(::grpc::ClientContext* context) = 0;\n"); + printer->Print(*vars, + "virtual ::grpc::ClientAsyncReaderWriterInterface< " + "$Request$, $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) = 0;\n"); + } + } +} + +void PrintHeaderClientMethod(Printer *printer, + const Method *method, + std::map *vars, + bool is_public) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (is_public) { + if (method->NoStreaming()) { + printer->Print( + *vars, + "::grpc::Status $Method$(::grpc::ClientContext* context, " + "const $Request$& request, $Response$* response) GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq) {\n"); + printer->Indent(); + printer->Print(*vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncResponseReader< $Response$>>(" + "Async$Method$Raw(context, request, cq));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientWriter< $Request$>>" + " $Method$(" + "::grpc::ClientContext* context, $Response$* response) {\n"); + printer->Indent(); + printer->Print(*vars, + "return std::unique_ptr< ::grpc::ClientWriter< $Request$>>" + "($Method$Raw(context, response));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print(*vars, + "std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>" + " Async$Method$(::grpc::ClientContext* context, " + "$Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>(" + "Async$Method$Raw(context, response, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientReader< $Response$>>" + " $Method$(::grpc::ClientContext* context, const $Request$& request)" + " {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientReader< $Response$>>" + "($Method$Raw(context, request));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> " + "Async$Method$(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print( + *vars, + "return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>(" + "Async$Method$Raw(context, request, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "std::unique_ptr< ::grpc::ClientReaderWriter< $Request$, $Response$>>" + " $Method$(::grpc::ClientContext* context) {\n"); + printer->Indent(); + printer->Print(*vars, + "return std::unique_ptr< " + "::grpc::ClientReaderWriter< $Request$, $Response$>>(" + "$Method$Raw(context));\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print(*vars, + "std::unique_ptr< ::grpc::ClientAsyncReaderWriter< " + "$Request$, $Response$>> " + "Async$Method$(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Indent(); + printer->Print(*vars, + "return std::unique_ptr< " + "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>(" + "Async$Method$Raw(context, cq, tag));\n"); + printer->Outdent(); + printer->Print("}\n"); + } + } else { + if (method->NoStreaming()) { + printer->Print(*vars, + "::grpc::ClientAsyncResponseReader< $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq) GRPC_OVERRIDE;\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print(*vars, + "::grpc::ClientWriter< $Request$>* $Method$Raw(" + "::grpc::ClientContext* context, $Response$* response) " + "GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw(" + "::grpc::ClientContext* context, $Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print(*vars, + "::grpc::ClientReader< $Response$>* $Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request)" + " GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "::grpc::ClientReaderWriter< $Request$, $Response$>* " + "$Method$Raw(::grpc::ClientContext* context) GRPC_OVERRIDE;\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " + "Async$Method$Raw(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;\n"); + } + } +} + +void PrintHeaderClientMethodData(Printer *printer, const Method *method, + std::map *vars) { + (*vars)["Method"] = method->name(); + printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n"); +} + +void PrintHeaderServerMethodSync(Printer *printer, const Method *method, + std::map *vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { + printer->Print(*vars, + "virtual ::grpc::Status $Method$(" + "::grpc::ServerContext* context, const $Request$* request, " + "$Response$* response);\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print(*vars, + "virtual ::grpc::Status $Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReader< $Request$>* reader, " + "$Response$* response);\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print(*vars, + "virtual ::grpc::Status $Method$(" + "::grpc::ServerContext* context, const $Request$* request, " + "::grpc::ServerWriter< $Response$>* writer);\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "virtual ::grpc::Status $Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReaderWriter< $Response$, $Request$>* stream);" + "\n"); + } +} + +void PrintHeaderServerMethodAsync( + Printer *printer, + const Method *method, + std::map *vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + printer->Print(*vars, "template \n"); + printer->Print(*vars, + "class WithAsyncMethod_$Method$ : public BaseClass {\n"); + printer->Print( + " private:\n" + " void BaseClassMustBeDerivedFromService(const Service *service) {}\n"); + printer->Print(" public:\n"); + printer->Indent(); + printer->Print(*vars, + "WithAsyncMethod_$Method$() {\n" + " ::grpc::Service::MarkMethodAsync($Idx$);\n" + "}\n"); + printer->Print(*vars, + "~WithAsyncMethod_$Method$() GRPC_OVERRIDE {\n" + " BaseClassMustBeDerivedFromService(this);\n" + "}\n"); + if (method->NoStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, const $Request$* request, " + "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + printer->Print( + *vars, + "void Request$Method$(" + "::grpc::ServerContext* context, $Request$* request, " + "::grpc::ServerAsyncResponseWriter< $Response$>* response, " + "::grpc::CompletionQueue* new_call_cq, " + "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); + printer->Print(*vars, + " ::grpc::Service::RequestAsyncUnary($Idx$, context, " + "request, response, new_call_cq, notification_cq, tag);\n"); + printer->Print("}\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReader< $Request$>* reader, " + "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + printer->Print( + *vars, + "void Request$Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerAsyncReader< $Response$, $Request$>* reader, " + "::grpc::CompletionQueue* new_call_cq, " + "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); + printer->Print(*vars, + " ::grpc::Service::RequestAsyncClientStreaming($Idx$, " + "context, reader, new_call_cq, notification_cq, tag);\n"); + printer->Print("}\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, const $Request$* request, " + "::grpc::ServerWriter< $Response$>* writer) GRPC_FINAL GRPC_OVERRIDE " + "{\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + printer->Print( + *vars, + "void Request$Method$(" + "::grpc::ServerContext* context, $Request$* request, " + "::grpc::ServerAsyncWriter< $Response$>* writer, " + "::grpc::CompletionQueue* new_call_cq, " + "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); + printer->Print( + *vars, + " ::grpc::Service::RequestAsyncServerStreaming($Idx$, " + "context, request, writer, new_call_cq, notification_cq, tag);\n"); + printer->Print("}\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) " + "GRPC_FINAL GRPC_OVERRIDE {\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + printer->Print( + *vars, + "void Request$Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, " + "::grpc::CompletionQueue* new_call_cq, " + "::grpc::ServerCompletionQueue* notification_cq, void *tag) {\n"); + printer->Print(*vars, + " ::grpc::Service::RequestAsyncBidiStreaming($Idx$, " + "context, stream, new_call_cq, notification_cq, tag);\n"); + printer->Print("}\n"); + } + printer->Outdent(); + printer->Print(*vars, "};\n"); +} + +void PrintHeaderServerMethodGeneric( + Printer *printer, + const Method *method, + std::map *vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + printer->Print(*vars, "template \n"); + printer->Print(*vars, + "class WithGenericMethod_$Method$ : public BaseClass {\n"); + printer->Print( + " private:\n" + " void BaseClassMustBeDerivedFromService(const Service *service) {}\n"); + printer->Print(" public:\n"); + printer->Indent(); + printer->Print(*vars, + "WithGenericMethod_$Method$() {\n" + " ::grpc::Service::MarkMethodGeneric($Idx$);\n" + "}\n"); + printer->Print(*vars, + "~WithGenericMethod_$Method$() GRPC_OVERRIDE {\n" + " BaseClassMustBeDerivedFromService(this);\n" + "}\n"); + if (method->NoStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, const $Request$* request, " + "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReader< $Request$>* reader, " + "$Response$* response) GRPC_FINAL GRPC_OVERRIDE {\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, const $Request$* request, " + "::grpc::ServerWriter< $Response$>* writer) GRPC_FINAL GRPC_OVERRIDE " + "{\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "// disable synchronous version of this method\n" + "::grpc::Status $Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReaderWriter< $Response$, $Request$>* stream) " + "GRPC_FINAL GRPC_OVERRIDE {\n" + " abort();\n" + " return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, \"\");\n" + "}\n"); + } + printer->Outdent(); + printer->Print(*vars, "};\n"); +} + +void PrintHeaderService(Printer *printer, + const Service *service, + std::map *vars) { + (*vars)["Service"] = service->name(); + + printer->Print(*vars, + "class $Service$ GRPC_FINAL {\n" + " public:\n"); + printer->Indent(); + + // Client side + printer->Print( + "class StubInterface {\n" + " public:\n"); + printer->Indent(); + printer->Print("virtual ~StubInterface() {}\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, true); + } + printer->Outdent(); + printer->Print("private:\n"); + printer->Indent(); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethodInterfaces(printer, service->method(i).get(), vars, false); + } + printer->Outdent(); + printer->Print("};\n"); + printer->Print( + "class Stub GRPC_FINAL : public StubInterface" + " {\n public:\n"); + printer->Indent(); + printer->Print("Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethod(printer, service->method(i).get(), vars, true); + } + printer->Outdent(); + printer->Print("\n private:\n"); + printer->Indent(); + printer->Print("std::shared_ptr< ::grpc::ChannelInterface> channel_;\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethod(printer, service->method(i).get(), vars, false); + } + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderClientMethodData(printer, service->method(i).get(), vars); + } + printer->Outdent(); + printer->Print("};\n"); + printer->Print( + "static std::unique_ptr NewStub(const std::shared_ptr< " + "::grpc::ChannelInterface>& channel, " + "const ::grpc::StubOptions& options = ::grpc::StubOptions());\n"); + + printer->Print("\n"); + + // Server side - base + printer->Print( + "class Service : public ::grpc::Service {\n" + " public:\n"); + printer->Indent(); + printer->Print("Service();\n"); + printer->Print("virtual ~Service();\n"); + for (int i = 0; i < service->method_count(); ++i) { + PrintHeaderServerMethodSync(printer, service->method(i).get(), vars); + } + printer->Outdent(); + printer->Print("};\n"); + + // Server side - Asynchronous + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["Idx"] = as_string(i); + PrintHeaderServerMethodAsync(printer, service->method(i).get(), vars); + } + + printer->Print("typedef "); + + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["method_name"] = service->method(i).get()->name(); + printer->Print(*vars, "WithAsyncMethod_$method_name$<"); + } + printer->Print("Service"); + for (int i = 0; i < service->method_count(); ++i) { + printer->Print(" >"); + } + printer->Print(" AsyncService;\n"); + + // Server side - Generic + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["Idx"] = as_string(i); + PrintHeaderServerMethodGeneric(printer, service->method(i).get(), vars); + } + + printer->Outdent(); + printer->Print("};\n"); +} + +grpc::string GetHeaderServices(File *file, + const Parameters ¶ms) { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map vars; + // Package string is empty or ends with a dot. It is used to fully qualify + // method names. + vars["Package"] = file->package(); + if (!file->package().empty()) { + vars["Package"].append("."); + } + + if (!params.services_namespace.empty()) { + vars["services_namespace"] = params.services_namespace; + printer->Print(vars, "\nnamespace $services_namespace$ {\n\n"); + } + + for (int i = 0; i < file->service_count(); ++i) { + PrintHeaderService(printer.get(), file->service(i).get(), &vars); + printer->Print("\n"); + } + + if (!params.services_namespace.empty()) { + printer->Print(vars, "} // namespace $services_namespace$\n\n"); + } + } + return output; +} + +grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map vars; + + vars["filename"] = file->filename(); + vars["filename_identifier"] = FilenameIdentifier(file->filename()); + + if (!file->package().empty()) { + std::vector parts = file->package_parts(); + + for (auto part = parts.rbegin(); part != parts.rend(); part++) { + vars["part"] = *part; + printer->Print(vars, "} // namespace $part$\n"); + } + printer->Print(vars, "\n"); + } + + printer->Print(vars, "\n"); + printer->Print(vars, "#endif // GRPC_$filename_identifier$__INCLUDED\n"); + } + return output; +} + +grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map vars; + + vars["filename"] = file->filename(); + vars["filename_base"] = file->filename_without_ext(); + vars["message_header_ext"] = file->message_header_ext(); + vars["service_header_ext"] = file->service_header_ext(); + + printer->Print(vars, "// Generated by the gRPC protobuf plugin.\n"); + printer->Print(vars, + "// If you make any local change, they will be lost.\n"); + printer->Print(vars, "// source: $filename$\n\n"); + printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n"); + printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n"); + printer->Print(vars, file->additional_headers().c_str()); + printer->Print(vars, "\n"); + } + return output; +} + +grpc::string GetSourceIncludes(File *file, + const Parameters ¶ms) { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map vars; + + static const char *headers_strs[] = { + "grpc++/impl/codegen/async_stream.h", + "grpc++/impl/codegen/async_unary_call.h", + "grpc++/impl/codegen/channel_interface.h", + "grpc++/impl/codegen/client_unary_call.h", + "grpc++/impl/codegen/method_handler_impl.h", + "grpc++/impl/codegen/rpc_service_method.h", + "grpc++/impl/codegen/service_type.h", + "grpc++/impl/codegen/sync_stream.h" + }; + std::vector headers(headers_strs, array_end(headers_strs)); + PrintIncludes(printer.get(), headers, params); + + if (!file->package().empty()) { + std::vector parts = file->package_parts(); + + for (auto part = parts.begin(); part != parts.end(); part++) { + vars["part"] = *part; + printer->Print(vars, "namespace $part$ {\n"); + } + } + + printer->Print(vars, "\n"); + } + return output; +} + +void PrintSourceClientMethod(Printer *printer, + const Method *method, + std::map *vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { + printer->Print(*vars, + "::grpc::Status $ns$$Service$::Stub::$Method$(" + "::grpc::ClientContext* context, " + "const $Request$& request, $Response$* response) {\n"); + printer->Print(*vars, + " return ::grpc::BlockingUnaryCall(channel_.get(), " + "rpcmethod_$Method$_, " + "context, request, response);\n" + "}\n\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncResponseReader< $Response$>* " + "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " + "const $Request$& request, " + "::grpc::CompletionQueue* cq) {\n"); + printer->Print(*vars, + " return new " + "::grpc::ClientAsyncResponseReader< $Response$>(" + "channel_.get(), cq, " + "rpcmethod_$Method$_, " + "context, request);\n" + "}\n\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print(*vars, + "::grpc::ClientWriter< $Request$>* " + "$ns$$Service$::Stub::$Method$Raw(" + "::grpc::ClientContext* context, $Response$* response) {\n"); + printer->Print(*vars, + " return new ::grpc::ClientWriter< $Request$>(" + "channel_.get(), " + "rpcmethod_$Method$_, " + "context, response);\n" + "}\n\n"); + printer->Print(*vars, + "::grpc::ClientAsyncWriter< $Request$>* " + "$ns$$Service$::Stub::Async$Method$Raw(" + "::grpc::ClientContext* context, $Response$* response, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Print(*vars, + " return new ::grpc::ClientAsyncWriter< $Request$>(" + "channel_.get(), cq, " + "rpcmethod_$Method$_, " + "context, response, tag);\n" + "}\n\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print( + *vars, + "::grpc::ClientReader< $Response$>* " + "$ns$$Service$::Stub::$Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request) {\n"); + printer->Print(*vars, + " return new ::grpc::ClientReader< $Response$>(" + "channel_.get(), " + "rpcmethod_$Method$_, " + "context, request);\n" + "}\n\n"); + printer->Print(*vars, + "::grpc::ClientAsyncReader< $Response$>* " + "$ns$$Service$::Stub::Async$Method$Raw(" + "::grpc::ClientContext* context, const $Request$& request, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Print(*vars, + " return new ::grpc::ClientAsyncReader< $Response$>(" + "channel_.get(), cq, " + "rpcmethod_$Method$_, " + "context, request, tag);\n" + "}\n\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "::grpc::ClientReaderWriter< $Request$, $Response$>* " + "$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n"); + printer->Print(*vars, + " return new ::grpc::ClientReaderWriter< " + "$Request$, $Response$>(" + "channel_.get(), " + "rpcmethod_$Method$_, " + "context);\n" + "}\n\n"); + printer->Print( + *vars, + "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* " + "$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, " + "::grpc::CompletionQueue* cq, void* tag) {\n"); + printer->Print(*vars, + " return new " + "::grpc::ClientAsyncReaderWriter< $Request$, $Response$>(" + "channel_.get(), cq, " + "rpcmethod_$Method$_, " + "context, tag);\n" + "}\n\n"); + } +} + +void PrintSourceServerMethod(Printer *printer, + const Method *method, + std::map *vars) { + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { + printer->Print(*vars, + "::grpc::Status $ns$$Service$::Service::$Method$(" + "::grpc::ServerContext* context, " + "const $Request$* request, $Response$* response) {\n"); + printer->Print(" (void) context;\n"); + printer->Print(" (void) request;\n"); + printer->Print(" (void) response;\n"); + printer->Print( + " return ::grpc::Status(" + "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); + printer->Print("}\n\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print(*vars, + "::grpc::Status $ns$$Service$::Service::$Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReader< $Request$>* reader, " + "$Response$* response) {\n"); + printer->Print(" (void) context;\n"); + printer->Print(" (void) reader;\n"); + printer->Print(" (void) response;\n"); + printer->Print( + " return ::grpc::Status(" + "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); + printer->Print("}\n\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print(*vars, + "::grpc::Status $ns$$Service$::Service::$Method$(" + "::grpc::ServerContext* context, " + "const $Request$* request, " + "::grpc::ServerWriter< $Response$>* writer) {\n"); + printer->Print(" (void) context;\n"); + printer->Print(" (void) request;\n"); + printer->Print(" (void) writer;\n"); + printer->Print( + " return ::grpc::Status(" + "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); + printer->Print("}\n\n"); + } else if (method->BidiStreaming()) { + printer->Print(*vars, + "::grpc::Status $ns$$Service$::Service::$Method$(" + "::grpc::ServerContext* context, " + "::grpc::ServerReaderWriter< $Response$, $Request$>* " + "stream) {\n"); + printer->Print(" (void) context;\n"); + printer->Print(" (void) stream;\n"); + printer->Print( + " return ::grpc::Status(" + "::grpc::StatusCode::UNIMPLEMENTED, \"\");\n"); + printer->Print("}\n\n"); + } +} + +void PrintSourceService(Printer *printer, + const Service *service, + std::map *vars) { + (*vars)["Service"] = service->name(); + + printer->Print(*vars, + "static const char* $prefix$$Service$_method_names[] = {\n"); + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["Method"] = service->method(i).get()->name(); + printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n"); + } + printer->Print(*vars, "};\n\n"); + + printer->Print(*vars, + "std::unique_ptr< $ns$$Service$::Stub> $ns$$Service$::NewStub(" + "const std::shared_ptr< ::grpc::ChannelInterface>& channel, " + "const ::grpc::StubOptions& options) {\n" + " std::unique_ptr< $ns$$Service$::Stub> stub(new " + "$ns$$Service$::Stub(channel));\n" + " return stub;\n" + "}\n\n"); + printer->Print(*vars, + "$ns$$Service$::Stub::Stub(const std::shared_ptr< " + "::grpc::ChannelInterface>& channel)\n"); + printer->Indent(); + printer->Print(": channel_(channel)"); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + (*vars)["Method"] = method->name(); + (*vars)["Idx"] = as_string(i); + if (method->NoStreaming()) { + (*vars)["StreamingType"] = "NORMAL_RPC"; + } else if (method->ClientOnlyStreaming()) { + (*vars)["StreamingType"] = "CLIENT_STREAMING"; + } else if (method->ServerOnlyStreaming()) { + (*vars)["StreamingType"] = "SERVER_STREAMING"; + } else { + (*vars)["StreamingType"] = "BIDI_STREAMING"; + } + printer->Print(*vars, + ", rpcmethod_$Method$_(" + "$prefix$$Service$_method_names[$Idx$], " + "::grpc::RpcMethod::$StreamingType$, " + "channel" + ")\n"); + } + printer->Print("{}\n\n"); + printer->Outdent(); + + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["Idx"] = as_string(i); + PrintSourceClientMethod(printer, service->method(i).get(), vars); + } + + printer->Print(*vars, "$ns$$Service$::Service::Service() {\n"); + printer->Indent(); + printer->Print(*vars, "(void)$prefix$$Service$_method_names;\n"); + for (int i = 0; i < service->method_count(); ++i) { + auto method = service->method(i); + (*vars)["Idx"] = as_string(i); + (*vars)["Method"] = method->name(); + (*vars)["Request"] = method->input_type_name(); + (*vars)["Response"] = method->output_type_name(); + if (method->NoStreaming()) { + printer->Print( + *vars, + "AddMethod(new ::grpc::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::RpcMethod::NORMAL_RPC,\n" + " new ::grpc::RpcMethodHandler< $ns$$Service$::Service, " + "$Request$, " + "$Response$>(\n" + " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); + } else if (method->ClientOnlyStreaming()) { + printer->Print( + *vars, + "AddMethod(new ::grpc::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::RpcMethod::CLIENT_STREAMING,\n" + " new ::grpc::ClientStreamingHandler< " + "$ns$$Service$::Service, $Request$, $Response$>(\n" + " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); + } else if (method->ServerOnlyStreaming()) { + printer->Print( + *vars, + "AddMethod(new ::grpc::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::RpcMethod::SERVER_STREAMING,\n" + " new ::grpc::ServerStreamingHandler< " + "$ns$$Service$::Service, $Request$, $Response$>(\n" + " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); + } else if (method->BidiStreaming()) { + printer->Print( + *vars, + "AddMethod(new ::grpc::RpcServiceMethod(\n" + " $prefix$$Service$_method_names[$Idx$],\n" + " ::grpc::RpcMethod::BIDI_STREAMING,\n" + " new ::grpc::BidiStreamingHandler< " + "$ns$$Service$::Service, $Request$, $Response$>(\n" + " std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n"); + } + } + printer->Outdent(); + printer->Print(*vars, "}\n\n"); + printer->Print(*vars, + "$ns$$Service$::Service::~Service() {\n" + "}\n\n"); + for (int i = 0; i < service->method_count(); ++i) { + (*vars)["Idx"] = as_string(i); + PrintSourceServerMethod(printer, service->method(i).get(), vars); + } +} + +grpc::string GetSourceServices(File *file, + const Parameters ¶ms) { + grpc::string output; + { + // Scope the output stream so it closes and finalizes output to the string. + auto printer = file->CreatePrinter(&output); + std::map vars; + // Package string is empty or ends with a dot. It is used to fully qualify + // method names. + vars["Package"] = file->package(); + if (!file->package().empty()) { + vars["Package"].append("."); + } + if (!params.services_namespace.empty()) { + vars["ns"] = params.services_namespace + "::"; + vars["prefix"] = params.services_namespace; + } else { + vars["ns"] = ""; + vars["prefix"] = ""; + } + + for (int i = 0; i < file->service_count(); ++i) { + PrintSourceService(printer.get(), file->service(i).get(), &vars); + printer->Print("\n"); + } + } + return output; +} + +grpc::string GetSourceEpilogue(File *file, const Parameters & /*params*/) { + grpc::string temp; + + if (!file->package().empty()) { + std::vector parts = file->package_parts(); + + for (auto part = parts.begin(); part != parts.end(); part++) { + temp.append("} // namespace "); + temp.append(*part); + temp.append("\n"); + } + temp.append("\n"); + } + + return temp; +} + +} // namespace grpc_cpp_generator diff --git a/grpc/src/compiler/cpp_generator.h b/grpc/src/compiler/cpp_generator.h new file mode 100644 index 000000000..953ddfd56 --- /dev/null +++ b/grpc/src/compiler/cpp_generator.h @@ -0,0 +1,147 @@ +/* + * + * Copyright 2015, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H +#define GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H + +// cpp_generator.h/.cc do not directly depend on GRPC/ProtoBuf, such that they +// can be used to generate code for other serialization systems, such as +// FlatBuffers. + +#include +#include + +#ifndef GRPC_CUSTOM_STRING +#include +#define GRPC_CUSTOM_STRING std::string +#endif + +namespace grpc { + +typedef GRPC_CUSTOM_STRING string; + +} // namespace grpc + +namespace grpc_cpp_generator { + +// Contains all the parameters that are parsed from the command line. +struct Parameters { + // Puts the service into a namespace + grpc::string services_namespace; + // Use system includes (<>) or local includes ("") + bool use_system_headers; + // Prefix to any grpc include + grpc::string grpc_search_path; +}; + +// An abstract interface representing a method. +struct Method { + virtual ~Method() {} + + virtual grpc::string name() const = 0; + + virtual grpc::string input_type_name() const = 0; + virtual grpc::string output_type_name() const = 0; + + virtual bool NoStreaming() const = 0; + virtual bool ClientOnlyStreaming() const = 0; + virtual bool ServerOnlyStreaming() const = 0; + virtual bool BidiStreaming() const = 0; +}; + +// An abstract interface representing a service. +struct Service { + virtual ~Service() {} + + virtual grpc::string name() const = 0; + + virtual int method_count() const = 0; + virtual std::unique_ptr method(int i) const = 0; +}; + +struct Printer { + virtual ~Printer() {} + + virtual void Print(const std::map &vars, + const char *template_string) = 0; + virtual void Print(const char *string) = 0; + virtual void Indent() = 0; + virtual void Outdent() = 0; +}; + +// An interface that allows the source generated to be output using various +// libraries/idls/serializers. +struct File { + virtual ~File() {} + + virtual grpc::string filename() const = 0; + virtual grpc::string filename_without_ext() const = 0; + virtual grpc::string message_header_ext() const = 0; + virtual grpc::string service_header_ext() const = 0; + virtual grpc::string package() const = 0; + virtual std::vector package_parts() const = 0; + virtual grpc::string additional_headers() const = 0; + + virtual int service_count() const = 0; + virtual std::unique_ptr service(int i) const = 0; + + virtual std::unique_ptr CreatePrinter(grpc::string *str) const = 0; +}; + +// Return the prologue of the generated header file. +grpc::string GetHeaderPrologue(File *file, const Parameters ¶ms); + +// Return the includes needed for generated header file. +grpc::string GetHeaderIncludes(File *file, const Parameters ¶ms); + +// Return the includes needed for generated source file. +grpc::string GetSourceIncludes(File *file, const Parameters ¶ms); + +// Return the epilogue of the generated header file. +grpc::string GetHeaderEpilogue(File *file, const Parameters ¶ms); + +// Return the prologue of the generated source file. +grpc::string GetSourcePrologue(File *file, const Parameters ¶ms); + +// Return the services for generated header file. +grpc::string GetHeaderServices(File *file, const Parameters ¶ms); + +// Return the services for generated source file. +grpc::string GetSourceServices(File *file, const Parameters ¶ms); + +// Return the epilogue of the generated source file. +grpc::string GetSourceEpilogue(File *file, const Parameters ¶ms); + +} // namespace grpc_cpp_generator + +#endif // GRPC_INTERNAL_COMPILER_CPP_GENERATOR_H diff --git a/grpc/tests/grpctest.cpp b/grpc/tests/grpctest.cpp new file mode 100644 index 000000000..d1b53776b --- /dev/null +++ b/grpc/tests/grpctest.cpp @@ -0,0 +1,124 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "monster_test_generated.h" +#include "monster_test.grpc.fb.h" + +using namespace MyGame::Example; + +// The callback implementation of our server, that derives from the generated +// code. It implements all rpcs specified in the FlatBuffers schema. +class ServiceImpl final : public MyGame::Example::MonsterStorage::Service { + virtual ::grpc::Status Store(::grpc::ServerContext* context, + const flatbuffers::BufferRef *request, + flatbuffers::BufferRef *response) + override { + // Create a response from the incoming request name. + fbb_.Clear(); + auto stat_offset = CreateStat(fbb_, fbb_.CreateString("Hello, " + + request->GetRoot()->name()->str())); + fbb_.Finish(stat_offset); + // Since we keep reusing the same FlatBufferBuilder, the memory it owns + // remains valid until the next call (this BufferRef doesn't own the + // memory it points to). + *response = flatbuffers::BufferRef(fbb_.GetBufferPointer(), + fbb_.GetSize()); + return grpc::Status::OK; + } + virtual ::grpc::Status Retrieve(::grpc::ServerContext *context, + const flatbuffers::BufferRef *request, + flatbuffers::BufferRef *response) + override { + assert(false); // We're not actually using this RPC. + return grpc::Status::CANCELLED; + } + + private: + flatbuffers::FlatBufferBuilder fbb_; +}; + +// Track the server instance, so we can terminate it later. +grpc::Server *server_instance = nullptr; +// Mutex to protec this variable. +std::mutex wait_for_server; +std::condition_variable server_instance_cv; + +// This function implements the server thread. +void RunServer() { + auto server_address = "0.0.0.0:50051"; + // Callback interface we implemented above. + ServiceImpl service; + grpc::ServerBuilder builder; + builder.AddListeningPort(server_address, grpc::InsecureServerCredentials()); + builder.RegisterService(&service); + + // Start the server. Lock to change the variable we're changing. + wait_for_server.lock(); + server_instance = builder.BuildAndStart().release(); + wait_for_server.unlock(); + server_instance_cv.notify_one(); + + std::cout << "Server listening on " << server_address << std::endl; + // This will block the thread and serve requests. + server_instance->Wait(); +} + +int main(int /*argc*/, const char * /*argv*/[]) { + // Launch server. + std::thread server_thread(RunServer); + + // wait for server to spin up. + std::unique_lock lock(wait_for_server); + while (!server_instance) server_instance_cv.wait(lock); + + // Now connect the client. + auto channel = grpc::CreateChannel("localhost:50051", + grpc::InsecureChannelCredentials()); + auto stub = MyGame::Example::MonsterStorage::NewStub(channel); + + grpc::ClientContext context; + + // Build a request with the name set. + flatbuffers::FlatBufferBuilder fbb; + auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred")); + fbb.Finish(monster_offset); + auto request = flatbuffers::BufferRef(fbb.GetBufferPointer(), + fbb.GetSize()); + flatbuffers::BufferRef response; + + // The actual RPC. + auto status = stub->Store(&context, request, &response); + + if (status.ok()) { + auto resp = response.GetRoot()->id(); + std::cout << "RPC response: " << resp->str() << std::endl; + } else { + std::cout << "RPC failed" << std::endl; + } + + server_instance->Shutdown(); + + server_thread.join(); + + delete server_instance; + + return 0; +} + diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index ae50d57d6..6755ec279 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1334,6 +1334,29 @@ class Verifier FLATBUFFERS_FINAL_CLASS { size_t max_tables_; }; +// Convenient way to bundle a buffer and its length, to pass it around +// typed by its root. +// A BufferRef does not own its buffer. +struct BufferRefBase {}; // for std::is_base_of +template struct BufferRef : BufferRefBase { + BufferRef() : buf(nullptr), len(0), must_free(false) {} + BufferRef(uint8_t *_buf, uoffset_t _len) + : buf(_buf), len(_len), must_free(false) {} + + ~BufferRef() { if (must_free) free(buf); } + + const T *GetRoot() const { return flatbuffers::GetRoot(buf); } + + bool Verify() { + Verifier verifier(buf, len); + return verifier.VerifyBuffer(); + } + + uint8_t *buf; + uoffset_t len; + bool must_free; +}; + // "structs" are flat structures that do not have an offset table, thus // always have all members present and do not support forwards/backwards // compatible extensions. diff --git a/include/flatbuffers/grpc.h b/include/flatbuffers/grpc.h new file mode 100644 index 000000000..52a64408d --- /dev/null +++ b/include/flatbuffers/grpc.h @@ -0,0 +1,72 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_GRPC_H_ +#define FLATBUFFERS_GRPC_H_ + +// Helper functionality to glue FlatBuffers and GRPC. + +#include "grpc++/support/byte_buffer.h" +#include "grpc/byte_buffer_reader.h" + +namespace grpc { + +template +class SerializationTraits::value>::type> { + public: + // The type we're passing here is a BufferRef, which is already serialized + // FlatBuffer data, which then gets passed to GRPC. + static grpc::Status Serialize(const T& msg, + grpc_byte_buffer **buffer, + bool *own_buffer) { + // TODO(wvo): make this work without copying. + auto slice = gpr_slice_from_copied_buffer( + reinterpret_cast(msg.buf), msg.len); + *buffer = grpc_raw_byte_buffer_create(&slice, 1); + *own_buffer = true; + return grpc::Status(); + } + + // There is no de-serialization step in FlatBuffers, so we just receive + // the data from GRPC. + static grpc::Status Deserialize(grpc_byte_buffer *buffer, + T *msg, + int max_message_size) { + // TODO(wvo): make this more efficient / zero copy when possible. + auto len = grpc_byte_buffer_length(buffer); + msg->buf = reinterpret_cast(malloc(len)); + msg->len = static_cast(len); + msg->must_free = true; + uint8_t *current = msg->buf; + grpc_byte_buffer_reader reader; + grpc_byte_buffer_reader_init(&reader, buffer); + gpr_slice slice; + while (grpc_byte_buffer_reader_next(&reader, &slice)) { + memcpy(current, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice)); + current += GPR_SLICE_LENGTH(slice); + gpr_slice_unref(slice); + } + GPR_ASSERT(current == msg->buf + msg->len); + grpc_byte_buffer_reader_destroy(&reader); + grpc_byte_buffer_destroy(buffer); + return grpc::Status(); + } +}; + +} // namespace grpc; + +#endif // FLATBUFFERS_GRPC_H_ diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index e3027259b..b22bc08a1 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -432,7 +432,7 @@ class Parser : public ParserState { known_attributes_["original_order"] = true; known_attributes_["nested_flatbuffer"] = true; known_attributes_["csharp_partial"] = true; - known_attributes_["stream"] = true; + known_attributes_["streaming"] = true; known_attributes_["idempotent"] = true; } @@ -679,6 +679,12 @@ extern std::string BinaryMakeRule(const Parser &parser, const std::string &path, const std::string &file_name); +// Generate GRPC interfaces. +// See idl_gen_grpc.cpp. +bool GenerateGRPC(const Parser &parser, + const std::string &path, + const std::string &file_name); + } // namespace flatbuffers #endif // FLATBUFFERS_IDL_H_ diff --git a/src/flatc.cpp b/src/flatc.cpp index d4be151c8..c7ba29e86 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -74,10 +74,14 @@ const Generator generators[] = { flatbuffers::IDLOptions::kMAX, "Generate Python files for tables/structs", flatbuffers::GeneralMakeRule }, - { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", + { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", flatbuffers::IDLOptions::kMAX, "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; diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp new file mode 100644 index 000000000..0dcc316d6 --- /dev/null +++ b/src/idl_gen_grpc.cpp @@ -0,0 +1,216 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// independent from idl_parser, since this code is not needed for most clients + +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" + +#include "src/compiler/cpp_generator.h" + +namespace flatbuffers { + +class FlatBufMethod : public grpc_cpp_generator::Method { + public: + enum Streaming { kNone, kClient, kServer, kBiDi }; + + FlatBufMethod(const RPCCall *method) + : method_(method) { + streaming_ = kNone; + auto val = method_->attributes.Lookup("streaming"); + if (val) { + if (val->constant == "client") streaming_ = kClient; + if (val->constant == "server") streaming_ = kServer; + if (val->constant == "bidi") streaming_ = kBiDi; + } + } + + std::string name() const { return method_->name; } + + std::string GRPCType(const StructDef &sd) const { + return "flatbuffers::BufferRef<" + sd.name + ">"; + } + + std::string input_type_name() const { + return GRPCType(*method_->request); + } + std::string output_type_name() const { + return GRPCType(*method_->response); + } + + bool NoStreaming() const { return streaming_ == kNone; } + bool ClientOnlyStreaming() const { return streaming_ == kClient; } + bool ServerOnlyStreaming() const { return streaming_ == kServer; } + bool BidiStreaming() const { return streaming_ == kBiDi; } + + private: + const RPCCall *method_; + Streaming streaming_; +}; + +class FlatBufService : public grpc_cpp_generator::Service { + public: + FlatBufService(const ServiceDef *service) : service_(service) {} + + std::string name() const { return service_->name; } + + int method_count() const { + return static_cast(service_->calls.vec.size()); + }; + + std::unique_ptr method(int i) const { + return std::unique_ptr( + new FlatBufMethod(service_->calls.vec[i])); + }; + + private: + const ServiceDef *service_; +}; + +class FlatBufPrinter : public grpc_cpp_generator::Printer { + public: + FlatBufPrinter(std::string *str) + : str_(str), escape_char_('$'), indent_(0) {} + + void Print(const std::map &vars, + const char *string_template) { + std::string s = string_template; + // Replace any occurrences of strings in "vars" that are surrounded + // by the escape character by what they're mapped to. + size_t pos; + while ((pos = s.find(escape_char_)) != std::string::npos) { + // Found an escape char, must also find the closing one. + size_t pos2 = s.find(escape_char_, pos + 1); + // If placeholder not closed, ignore. + if (pos2 == std::string::npos) break; + auto it = vars.find(s.substr(pos + 1, pos2 - pos - 1)); + // If unknown placeholder, ignore. + if (it == vars.end()) break; + // Subtitute placeholder. + s.replace(pos, pos2 - pos + 1, it->second); + } + Print(s.c_str()); + } + + void Print(const char *s) { + // Add this string, but for each part separated by \n, add indentation. + for (;;) { + // Current indentation. + str_->insert(str_->end(), indent_ * 2, ' '); + // See if this contains more than one line. + auto lf = strchr(s, '\n'); + if (lf) { + (*str_) += std::string(s, lf + 1); + s = lf + 1; + if (!*s) break; // Only continue if there's more lines. + } else { + (*str_) += s; + break; + } + } + } + + void Indent() { indent_++; } + void Outdent() { indent_--; assert(indent_ >= 0); } + + private: + std::string *str_; + char escape_char_; + int indent_; +}; + +class FlatBufFile : public grpc_cpp_generator::File { + public: + FlatBufFile(const Parser &parser, const std::string &file_name) + : parser_(parser), file_name_(file_name) {} + + std::string filename() const { return file_name_; } + std::string filename_without_ext() const { + return StripExtension(file_name_); + } + + std::string message_header_ext() const { return "_generated.h"; } + std::string service_header_ext() const { return ".grpc.fb.h"; } + + std::string package() const { + return parser_.namespaces_.back()->GetFullyQualifiedName(""); + } + + std::vector package_parts() const { + return parser_.namespaces_.back()->components; + } + + std::string additional_headers() const { + return "#include \"flatbuffers/grpc.h\"\n"; + } + + int service_count() const { + return static_cast(parser_.services_.vec.size()); + }; + + std::unique_ptr service(int i) const { + return std::unique_ptr ( + new FlatBufService(parser_.services_.vec[i])); + } + + std::unique_ptr CreatePrinter(std::string *str) const { + return std::unique_ptr( + new FlatBufPrinter(str)); + } + + private: + const Parser &parser_; + const std::string &file_name_; +}; + +bool GenerateGRPC(const Parser &parser, + const std::string &/*path*/, + const std::string &file_name) { + + int nservices = 0; + for (auto it = parser.services_.vec.begin(); + it != parser.services_.vec.end(); ++it) { + if (!(*it)->generated) nservices++; + } + if (!nservices) return true; + + grpc_cpp_generator::Parameters generator_parameters; + // TODO(wvo): make the other parameters in this struct configurable. + generator_parameters.use_system_headers = true; + + FlatBufFile fbfile(parser, file_name); + + std::string header_code = + grpc_cpp_generator::GetHeaderPrologue(&fbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderIncludes(&fbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderServices(&fbfile, generator_parameters) + + grpc_cpp_generator::GetHeaderEpilogue(&fbfile, generator_parameters); + + std::string source_code = + grpc_cpp_generator::GetSourcePrologue(&fbfile, generator_parameters) + + grpc_cpp_generator::GetSourceIncludes(&fbfile, generator_parameters) + + grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) + + grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters); + + return flatbuffers::SaveFile((file_name + ".grpc.fb.h").c_str(), + header_code, false) && + flatbuffers::SaveFile((file_name + ".grpc.fb.cc").c_str(), + source_code, false); +} + +} // namespace flatbuffers + diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 8fddb3c66..b758e9592 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1423,6 +1423,10 @@ void Parser::MarkGenerated() { it != structs_.vec.end(); ++it) { (*it)->generated = true; } + for (auto it = services_.vec.begin(); + it != services_.vec.end(); ++it) { + (*it)->generated = true; + } } CheckedError Parser::ParseNamespace() { diff --git a/tests/generate_code.bat b/tests/generate_code.bat index 00b16d900..53d54707b 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -12,6 +12,6 @@ :: See the License for the specific language governing permissions and :: limitations under the License. -..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --gen-mutable --no-includes monster_test.fbs monsterdata_test.json +..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --no-includes monster_test.fbs monsterdata_test.json ..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test\namespace_test1.fbs namespace_test\namespace_test2.fbs ..\flatc.exe --binary --schema monster_test.fbs diff --git a/tests/generate_code.sh b/tests/generate_code.sh index b74c2bec5..3436d8586 100644 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -../flatc --cpp --java --csharp --go --binary --python --js --php --gen-mutable --no-includes monster_test.fbs monsterdata_test.json +../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 diff --git a/tests/monster_test.fbs b/tests/monster_test.fbs index 7ddaa582f..3fecd33cf 100755 --- a/tests/monster_test.fbs +++ b/tests/monster_test.fbs @@ -70,7 +70,7 @@ table Monster { } rpc_service MonsterStorage { - Store(Monster):Stat (stream); + Store(Monster):Stat (streaming: "none"); Retrieve(Stat):Monster (idempotent); } diff --git a/tests/monster_test.grpc.fb.cc b/tests/monster_test.grpc.fb.cc new file mode 100644 index 000000000..71dbd2d4f --- /dev/null +++ b/tests/monster_test.grpc.fb.cc @@ -0,0 +1,85 @@ +// Generated by the gRPC protobuf plugin. +// If you make any local change, they will be lost. +// source: monster_test + +#include "monster_test_generated.h" +#include "monster_test.grpc.fb.h" +#include "flatbuffers/grpc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +namespace MyGame { +namespace Example { + +static const char* MonsterStorage_method_names[] = { + "/MyGame.Example..MonsterStorage/Store", + "/MyGame.Example..MonsterStorage/Retrieve", +}; + +std::unique_ptr< MonsterStorage::Stub> MonsterStorage::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { + std::unique_ptr< MonsterStorage::Stub> stub(new MonsterStorage::Stub(channel)); + return stub; +} + +MonsterStorage::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) + : channel_(channel) , rpcmethod_Store_(MonsterStorage_method_names[0], ::grpc::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Retrieve_(MonsterStorage_method_names[1], ::grpc::RpcMethod::NORMAL_RPC, channel) + {} + +::grpc::Status MonsterStorage::Stub::Store(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, flatbuffers::BufferRef* response) { + return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_Store_, context, request, response); +} + +::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>* MonsterStorage::Stub::AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) { + return new ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>(channel_.get(), cq, rpcmethod_Store_, context, request); +} + +::grpc::Status MonsterStorage::Stub::Retrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, flatbuffers::BufferRef* response) { + return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_Retrieve_, context, request, response); +} + +::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>* MonsterStorage::Stub::AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) { + return new ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>(channel_.get(), cq, rpcmethod_Retrieve_, context, request); +} + +MonsterStorage::Service::Service() { + (void)MonsterStorage_method_names; + AddMethod(new ::grpc::RpcServiceMethod( + MonsterStorage_method_names[0], + ::grpc::RpcMethod::NORMAL_RPC, + new ::grpc::RpcMethodHandler< MonsterStorage::Service, flatbuffers::BufferRef, flatbuffers::BufferRef>( + std::mem_fn(&MonsterStorage::Service::Store), this))); + AddMethod(new ::grpc::RpcServiceMethod( + MonsterStorage_method_names[1], + ::grpc::RpcMethod::NORMAL_RPC, + new ::grpc::RpcMethodHandler< MonsterStorage::Service, flatbuffers::BufferRef, flatbuffers::BufferRef>( + std::mem_fn(&MonsterStorage::Service::Retrieve), this))); +} + +MonsterStorage::Service::~Service() { +} + +::grpc::Status MonsterStorage::Service::Store(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + +::grpc::Status MonsterStorage::Service::Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + + +} // namespace MyGame +} // namespace Example + diff --git a/tests/monster_test.grpc.fb.h b/tests/monster_test.grpc.fb.h new file mode 100644 index 000000000..4269234f3 --- /dev/null +++ b/tests/monster_test.grpc.fb.h @@ -0,0 +1,155 @@ +// Generated by the gRPC protobuf plugin. +// If you make any local change, they will be lost. +// source: monster_test +#ifndef GRPC_monster_5ftest__INCLUDED +#define GRPC_monster_5ftest__INCLUDED + +#include "monster_test_generated.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace grpc { +class CompletionQueue; +class Channel; +class RpcService; +class ServerCompletionQueue; +class ServerContext; +} // namespace grpc + +namespace MyGame { +namespace Example { + +class MonsterStorage GRPC_FINAL { + public: + class StubInterface { + public: + virtual ~StubInterface() {} + virtual ::grpc::Status Store(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, flatbuffers::BufferRef* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef>>(AsyncStoreRaw(context, request, cq)); + } + virtual ::grpc::Status Retrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, flatbuffers::BufferRef* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef>>(AsyncRetrieveRaw(context, request, cq)); + } + private: + virtual ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) = 0; + }; + class Stub GRPC_FINAL : public StubInterface { + public: + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + ::grpc::Status Store(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, flatbuffers::BufferRef* response) GRPC_OVERRIDE; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>>(AsyncStoreRaw(context, request, cq)); + } + ::grpc::Status Retrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, flatbuffers::BufferRef* response) GRPC_OVERRIDE; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>>(AsyncRetrieveRaw(context, request, cq)); + } + + private: + std::shared_ptr< ::grpc::ChannelInterface> channel_; + ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) GRPC_OVERRIDE; + ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef& request, ::grpc::CompletionQueue* cq) GRPC_OVERRIDE; + const ::grpc::RpcMethod rpcmethod_Store_; + const ::grpc::RpcMethod rpcmethod_Retrieve_; + }; + static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); + + class Service : public ::grpc::Service { + public: + Service(); + virtual ~Service(); + virtual ::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response); + virtual ::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response); + }; + template + class WithAsyncMethod_Store : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithAsyncMethod_Store() { + ::grpc::Service::MarkMethodAsync(0); + } + ~WithAsyncMethod_Store() GRPC_OVERRIDE { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response) GRPC_FINAL GRPC_OVERRIDE { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestStore(::grpc::ServerContext* context, flatbuffers::BufferRef* request, ::grpc::ServerAsyncResponseWriter< flatbuffers::BufferRef>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template + class WithAsyncMethod_Retrieve : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithAsyncMethod_Retrieve() { + ::grpc::Service::MarkMethodAsync(1); + } + ~WithAsyncMethod_Retrieve() GRPC_OVERRIDE { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response) GRPC_FINAL GRPC_OVERRIDE { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestRetrieve(::grpc::ServerContext* context, flatbuffers::BufferRef* request, ::grpc::ServerAsyncResponseWriter< flatbuffers::BufferRef>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); + } + }; + typedef WithAsyncMethod_Store< WithAsyncMethod_Retrieve< Service > > AsyncService; + template + class WithGenericMethod_Store : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithGenericMethod_Store() { + ::grpc::Service::MarkMethodGeneric(0); + } + ~WithGenericMethod_Store() GRPC_OVERRIDE { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response) GRPC_FINAL GRPC_OVERRIDE { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template + class WithGenericMethod_Retrieve : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service *service) {} + public: + WithGenericMethod_Retrieve() { + ::grpc::Service::MarkMethodGeneric(1); + } + ~WithGenericMethod_Retrieve() GRPC_OVERRIDE { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef* request, flatbuffers::BufferRef* response) GRPC_FINAL GRPC_OVERRIDE { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; +}; + +} // namespace Example +} // namespace MyGame + + +#endif // GRPC_monster_5ftest__INCLUDED From 5ea2b49f58462728a895bc61ba290f16bed220d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E5=87=A1?= Date: Fri, 1 Jul 2016 11:17:03 +0800 Subject: [PATCH 41/42] Fix some error --- CMakeLists.txt | 9 - docs/html/md__compiler.html | 114 ------ docs/source/Compiler.md | 3 - include/flatbuffers/idl.h | 11 - .../google/flatbuffers/FlatBufferBuilder.java | 32 -- samples/monster_generated.h | 12 - src/flatc.cpp | 64 ---- src/idl_gen_cpp.cpp | 344 ------------------ src/idl_gen_grpc.cpp | 2 +- src/idl_parser.cpp | 27 -- tests/generate_code.sh | 5 - tests/monster_test.bfbs | Bin 2744 -> 3152 bytes tests/monster_test_generated.h | 25 -- 13 files changed, 1 insertion(+), 647 deletions(-) delete mode 100644 docs/html/md__compiler.html diff --git a/CMakeLists.txt b/CMakeLists.txt index 32a5e2141..c2dd95085 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,14 +105,6 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) "${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 @@ -137,7 +129,6 @@ elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsigned-char") ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 endif() if(FLATBUFFERS_CODE_COVERAGE) diff --git a/docs/html/md__compiler.html b/docs/html/md__compiler.html deleted file mode 100644 index 1b3cd1db4..000000000 --- a/docs/html/md__compiler.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - -FlatBuffers: Using the schema compiler - - - - - - - - - - - -
-
- - - - - - - -
-
FlatBuffers -
-
- An open source project by FPL. -
-
-
- - -
-
- -
-
-
- -
-
-
-
Using the schema compiler
-
-
-

Usage:

flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] [ -S ] FILES...
-      [ -- FILES...]
-

The files are read and parsed in order, and can contain either schemas or data (see below). Data files are processed according to the definitions of the most recent schema specified.

-

-- indicates that the following files are binary files in FlatBuffer format conforming to the schema indicated before it.

-

Depending on the flags passed, additional files may be generated for each file processed:

-

For any schema input files, one or more generators can be specified:

-
    -
  • --cpp, -c : Generate a C++ header for all definitions in this file (as filename_generated.h).
  • -
  • --java, -j : Generate Java code.
  • -
  • --csharp, -n : Generate C# code.
  • -
  • --go, -g : Generate Go code.
  • -
  • --python, -p: Generate Python code.
  • -
  • --javascript, -s: Generate JavaScript code.
  • -
  • --php: Generate PHP code.
  • -
-

For any data input files:

-
    -
  • --binary, -b : If data is contained in this file, generate a filename.bin containing the binary flatbuffer (or a different extension if one is specified in the schema).
  • -
  • --json, -t : If data is contained in this file, generate a filename.json representing the data in the flatbuffer.
  • -
-

Additional options:

-
    -
  • -o PATH : Output all generated files to PATH (either absolute, or relative to the current directory). If omitted, PATH will be the current directory. PATH should end in your systems path separator, e.g. / or \.
  • -
  • -I PATH : when encountering include statements, attempt to load the files from this path. Paths will be tried in the order given, and if all fail (or none are specified) it will try to load relative to the path of the schema file being parsed.
  • -
  • -M : Print make rules for generated files.
  • -
  • --strict-json : Require & generate strict JSON (field names are enclosed in quotes, no trailing commas in tables/vectors). By default, no quotes are required/generated, and trailing commas are allowed.
  • -
  • --defaults-json : Output fields whose value is equal to the default value when writing JSON text.
  • -
  • --no-prefix : Don't prefix enum values in generated C++ by their enum type.
  • -
  • --scoped-enums : Use C++11 style scoped and strongly typed enums in generated C++. This also implies --no-prefix.
  • -
  • --gen-includes : (deprecated), this is the default behavior. If the original behavior is required (no include statements) use --no-includes.
  • -
  • --no-includes : Don't generate include statements for included schemas the generated file depends on (C++).
  • -
  • --gen-mutable : Generate additional non-const accessors for mutating FlatBuffers in-place.
  • -
  • --gen-onefile : Generate single output file (useful for C#)
  • -
  • --raw-binary : Allow binaries without a file_indentifier to be read. This may crash flatc given a mismatched schema.
  • -
  • --proto: Expect input files to be .proto files (protocol buffers). Output the corresponding .fbs file. Currently supports: package, message, enum, nested declarations, import (use -I for paths), extend, oneof, group. Does not support, but will skip without error: option, service, extensions, and most everything else.
  • -
  • --schema: Serialize schemas instead of JSON (use with -b). This will output a binary version of the specified schema that itself corresponds to the reflection/reflection.fbs schema. Loading this binary file is the basis for reflection functionality.
  • -
-

NOTE: short-form options for generators are deprecated, use the long form whenever possible.

-
-
- - - - diff --git a/docs/source/Compiler.md b/docs/source/Compiler.md index 5f1427d0c..ad584c739 100755 --- a/docs/source/Compiler.md +++ b/docs/source/Compiler.md @@ -33,11 +33,8 @@ For any schema input files, one or more generators can be specified: - `--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 --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 1b45425b5..b22bc08a1 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -550,18 +550,7 @@ private: 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::string file_being_parsed_; diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java index 3bbd5d32d..c2186fa7b 100644 --- a/java/com/google/flatbuffers/FlatBufferBuilder.java +++ b/java/com/google/flatbuffers/FlatBufferBuilder.java @@ -36,21 +36,6 @@ import java.nio.charset.Charset; * "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. @@ -68,7 +53,6 @@ public class FlatBufferBuilder { CharsetEncoder encoder = utf8charset.newEncoder(); ByteBuffer dst; /// @endcond ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 /** * Start with a buffer of size `initial_size`, then grow as required. @@ -440,16 +424,6 @@ public class FlatBufferBuilder { " 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. @@ -751,11 +725,6 @@ public class FlatBufferBuilder { 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, @@ -763,7 +732,6 @@ public class FlatBufferBuilder { * * @return The {@link ByteBuffer} representing the FlatBuffer */ ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 public ByteBuffer dataBuffer() { finished(); return bb; diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 93bf73fdf..1a16126a5 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -72,12 +72,9 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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); } @@ -91,15 +88,12 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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) && @@ -110,15 +104,12 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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(); } }; @@ -132,12 +123,9 @@ 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 --git a/src/flatc.cpp b/src/flatc.cpp index 6a8d89125..c7ba29e86 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -29,12 +29,7 @@ static void Error(const std::string &err, bool usage = false, 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; @@ -48,41 +43,6 @@ struct Generator { 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 }, @@ -116,7 +76,6 @@ const Generator generators[] = { flatbuffers::GeneralMakeRule }, { flatbuffers::GeneratePhp, nullptr, "--php", "PHP", flatbuffers::IDLOptions::kMAX, ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 "Generate PHP files for tables/structs", flatbuffers::GeneralMakeRule }, { flatbuffers::GenerateGRPC, nullptr, "--grpc", "GRPC", @@ -270,11 +229,7 @@ int main(int argc, const char *argv[]) { } // 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) { @@ -310,23 +265,16 @@ int main(int argc, const char *argv[]) { } } } 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()); @@ -350,11 +298,7 @@ int main(int argc, const char *argv[]) { 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 " + @@ -362,11 +306,7 @@ int main(int argc, const char *argv[]) { } } 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()); @@ -374,15 +314,11 @@ int main(int argc, const char *argv[]) { } } -<<<<<<< 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 --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index c8337af72..c690240d6 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -208,40 +208,6 @@ class CppGenerator : public BaseGenerator { // 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 @@ -283,25 +249,12 @@ static std::string GenTypePointer(const Parser &parser, const Type &type) { return WrapInNameSpace(*type.struct_def); } case BASE_TYPE_UNION: ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 // fall through 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, @@ -313,7 +266,6 @@ static std::string GenTypeWire(const Parser &parser, const Type &type, : "flatbuffers::Offset<" + GenTypePointer(type) + ">" + postfix; } ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 // Return a C++ type for any type (scalar/pointer) that reflects its // serialized size. @@ -324,17 +276,6 @@ static std::string GenTypeWire(const Parser &parser, const Type &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, @@ -344,7 +285,6 @@ static std::string GenTypeGet(const Parser &parser, const Type &type, ? GenTypeBasic(type, user_facing_type) + afterbasic : beforeptr + GenTypePointer(type) + afterptr; } ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 static std::string GenEnumDecl(const EnumDef &enum_def, const IDLOptions &opts) { @@ -387,20 +327,6 @@ static std::string GenTypeGet(const Parser &parser, const Type &type, 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) + " = "; @@ -464,7 +390,6 @@ static std::string GenTypeGet(const Parser &parser, const Type &type, if (enum_def.is_union) { code += EnumSignature(enum_def) + ";\n\n"; } ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } void GenEnumPost(EnumDef &enum_def, std::string *code_ptr_post) { @@ -490,90 +415,6 @@ static std::string GenTypeGet(const Parser &parser, const Type &type, 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 @@ -646,7 +487,6 @@ static void GenTable(const Parser &parser, StructDef &struct_def, } code += " " + GenFieldOffsetName(field) + " = "; code += NumToString(field.value.offset); ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } } code += "\n };\n"; @@ -732,42 +572,6 @@ static void GenTable(const Parser &parser, StructDef &struct_def, } } } -<<<<<<< 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"; @@ -790,7 +594,6 @@ static void GenTable(const Parser &parser, StructDef &struct_def, case BASE_TYPE_STRUCT: if (!field.value.type.struct_def->fixed) { code += prefix + "verifier.VerifyTable(" + field.name; ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 code += "())"; } break; @@ -853,32 +656,6 @@ static void GenTable(const Parser &parser, StructDef &struct_def, 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 += " " + struct_def.name; code += "Builder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) "; @@ -897,7 +674,6 @@ static void GenTable(const Parser &parser, StructDef &struct_def, code += struct_def.name + "::" + GenFieldOffsetName(field); code += "); // " + field.name + "\n"; } ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } code += " return o;\n }\n};\n\n"; @@ -928,13 +704,6 @@ static void GenTable(const Parser &parser, StructDef &struct_def, } else { 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"; @@ -952,118 +721,6 @@ static void GenTable(const Parser &parser, StructDef &struct_def, 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(field.padding) & (1 << i)) f((1 << i) * 8, code, padding_id); assert(!(field.padding & ~0xF)); ->>>>>>> 48f37f9e0a04f2b60046dda7fef20a8b0ebc1a70 } } diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp index 0dcc316d6..2bf0e911d 100644 --- a/src/idl_gen_grpc.cpp +++ b/src/idl_gen_grpc.cpp @@ -112,7 +112,7 @@ class FlatBufPrinter : public grpc_cpp_generator::Printer { // Current indentation. str_->insert(str_->end(), indent_ * 2, ' '); // See if this contains more than one line. - auto lf = strchr(s, '\n'); + const char * lf = strchr(s, '\n'); if (lf) { (*str_) += std::string(s, lf + 1); s = lf + 1; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 36a63c6d0..b758e9592 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1167,11 +1167,7 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { 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(); @@ -1268,11 +1264,7 @@ CheckedError Parser::StartStruct(const std::string &name, StructDef **dest) { 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; @@ -1787,16 +1779,12 @@ 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; @@ -1937,23 +1925,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, 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 --git a/tests/generate_code.sh b/tests/generate_code.sh index eca73aa42..3436d8586 100644 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -1,7 +1,3 @@ -<<<<<<< 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. @@ -22,4 +18,3 @@ ../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 --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index e5f51face696a1ee9b3aa64b70bba83df1c4645a..e131ac8c2ee97914bfc1c02ce683ac4f5ecb43d6 100644 GIT binary patch literal 3152 zcmaJ@PiS0a5T8vp$!`8^(i+<}jS@>KMMTmx1d$wKY+41Af{8J=bd$VwSKhu|cHf4^ zlXxg1QaniT&_fSB6e;4N^b|@dB1NPG3F4^)Pab;c#b|5o^Y@$CZ}(Y(AIzKYd-I$5 zX6Bo3-WwK?=`+*wU>F(6N>WnND+4l!mEb8d3Yr9+1}(LTbb){0Bl0fhTPcww=6<)x zF8D%Pq#bhV3@3mCB{82pH>Z10Rw@U0W?-8;bzv{AbR>GgxE=u!`)07A`dgTP4O#$E zzWGNKfx)`Sk5LqVu5(%iYZ z88BIa&y1CRkAONrZ3Z=O%4ZwL4z@`mD>Tezk8{3(%3kYU-gjq@3j*Y(_K z(?)8Fyora+TMc{`JM)$#RZ6Qicor|nMAJ@i@yNqRFQ=y{<$2T3Jb33{wr>SIi;8lw z&{8axm2%my;gwu^qOr7H0sgRzHSq@;_(HB$s85V9=Y#c=IlRl8{qAk>L%8+MejHzm z;WrJRmPb+ayu7wAzJ6+~Y5xbqr$&Jvlvnq~*JAiR!*`tr{yBN2iFfhF{b#(#fdlLQ z68s>l+xZ{IJO7DaG<^Ct_yIY-FW&i2{6)j39)b_Zv3>E*f8uW%zH8)h6!ptd#j{7y zFP;|lQtSxUv`d=-$Xm<%xp1YP z&uep(P4q0(bn+T>dbI|vU$C~kz$?-Akk-BQo&a;)+(FQ{y^?F^L%v${f;FGV zB9AS$Hl7P{)<06Zzl)K)QZ1INMJ*Ez?j+u2u}^$&b|vm_dnXd@>TfHb0luyfOJMQ# z(RbIcG`SRFP`?clzGLpzKpd>gLPg|T)9;A)yJz(i@WthQQ?>2Eb1mfpwjT=I@eB3@ac{;0SN(pyw4a;rISLURMjqjLVpRadO65N+q@(~dIUG!G*buo(t z@JSHmw?UUd7eLhSXxvTbJMTRe@0)GCFJEDv)bne_NE|*#(y93rt>-P^+BKH{;#fcH zX0LY_+~tcAGru2$tgqk~0`?M!z~zc^7Vk~d@A(}(E@K=&H)MCgY4aF}djI#IMmg_@ zt4n5zIdH?}-sP0J=V;w!_7>g%cN;AS1DYrMdu9DJY&Oq`c6dId1>_J+Ykdja{Nep} z-*rlD(4U0f6ssZnzXH0~$Ui%SWzF#JNj>I^zECHp_tZLv^+f3yfS0X|o6pRn(;?dZ ZvtkN#{13eqV_b)o{C-fc>2D+E{{r&+C1U^p literal 2744 zcmaJ@O^91n6h4{!|4fqBF&(9pAVVodhITp(B1P&*>kl>sCr-hIoi~#g6G`3+$xCQl zhzl39Dy{}sBBc~@DXzK@aUs%05f??Il;TRda5-qLjo)|fyP1auFPxm0d%tt;ch0%z zzIRka)-SAYKw%VRQ4*4of|O+e{{+7x&qH2-oP!kRL{iWR=-1LBUt~qfkT-K8_wYZC zHR2yYc4NRnU%XUP|6J?(9=tE;9%<}Sz#K-5x(qoAA?{^wtoma-Z$UW!aDOs^f>(~5 zaxK6UwpO0I84=K$jw5)gyMth(-R*VUy0hJJFSmo%d2iUoN)9#&>~HM3_bGS|oeM&d zi@rAq+`i-{lL_OX)GpP|L&+BA$eH=6LXwbI{Epv;CjS=XEQEe<{h_?$^!+RBI0vfJ zLBH#rp=&vDjWH1yjfZ=@+IL+Kt7WZ|!I6jM&As1p8(KkD5*5=N6SD|m9`le3eZTv< zx6>ImT(#x=8-{1r?3sf#nVCKKL{6d2rqdDG2j1p@`$u#34E}!&GM~cP5{!2tKjZ(m z&~?afkaPH7fNVi{zJ37q6UaR}gT4X%0FP&(uR=GVKZkw{AwC1lO>kJ0RgIJ}FlPa3 z?)3Z4*l%w8erJFw@&0BFigR~?KO!qr{Gkxvat5v8+Uk|2H#+TL?#Z88vs?nHTX;u_yu$fD@FcMK7$DUn!%^{fPYF(PVqM0D1W$- zZwx;7J@AL+#7w;9PyFv8|9#*O$?=(Z%b)mTe`&m#VJflpqZRa~?_;rR-9sqlbZH-1aB zc@Z|eo#=ZBVrv@O41#{!dk@`|!A;7ZVPApMd>?jMsi+-$m7EyIDi8(5n!5_v5{|xH z2R?&nZ478B#Y4%mo_7sRZUdK=!-`{WY%Z?^?*lN8K|W4!cj2l?!T zcic5&qj%a#6WAgEqrWO^D zeUcSD9R+Y_KI|aR7-npK_Ur;Q^WSwmULW!j@(7jm^jz4R*t{Eh{y^@S^%C_L0?wo;Ae@Nf-z4s%YZ$LhR&^{UV5pBtvXPbt< zm_77NkAO>ry%X($73~3@6?<+(&)!Yo;~LRHAJgw?Aipzy3%7x>Ib+;B=pR7%E{4iK z#Ci;oFkh@I*LiL;+MTvPC4V0{n^R)0Lg-uaMKCzX9lx8n&k}^V|N9Q%I(vp4z#GHV zg&8u#)`c@w2dxUDHnh diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 5038edd10..50fbc28ce 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -138,11 +138,7 @@ 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)); } @@ -176,11 +172,7 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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); } @@ -250,13 +242,10 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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); } @@ -291,11 +280,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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); } @@ -315,8 +300,6 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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); } @@ -325,7 +308,6 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { 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) && @@ -401,12 +383,6 @@ 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); } @@ -415,7 +391,6 @@ struct MonsterBuilder { 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; } From c94cb6dae90712267dd63b563f264f54e0b33a80 Mon Sep 17 00:00:00 2001 From: Louis Cognault Date: Fri, 1 Jul 2016 17:22:36 +0200 Subject: [PATCH 42/42] Fixed typo is => it --- docs/source/Schemas.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Schemas.md b/docs/source/Schemas.md index 7dcce0711..5bcaccb37 100755 --- a/docs/source/Schemas.md +++ b/docs/source/Schemas.md @@ -272,7 +272,7 @@ Current understood attributes: the union field should have id 8, and the unions type field will implicitly be 7. IDs allow the fields to be placed in any order in the schema. - When a new field is added to the schema is must use the next available ID. + When a new field is added to the schema it must use the next available ID. - `deprecated` (on a field): do not generate accessors for this field anymore, code should stop using this data. - `required` (on a non-scalar table field): this field must always be set.