From 9875b0e0f8af5781a793fb93807641c9cebfb903 Mon Sep 17 00:00:00 2001 From: Romain Gilles Date: Tue, 7 Jun 2016 09:05:56 +0200 Subject: [PATCH 01/13] Create a maven like project structure for java development. Make it OSGi compliant. Generate the flatbuffers code for testing (example). Java developer are mostly comfortable with maven project structure. One one the main concept behind maven is convention. If you follow the maven project convention then your development team will get more effective as they now this project structure and can easily find the production code versus the test code. In this pull request I have structured the java project around 2 main parts: * the `flatbuffers` project. This project is the api / lib project and contains the test code structure + an example of code generation for testing. This avoid to commit generated code. Pre-configure JUnit for test driven development and make this project OSGi compliant. * the `jmh` project. This project aims to provide a placeholder for micro-benchmarking. JMH is a 'de facto' standard for micro benchmarking you can find more details here: http://openjdk.java.net/projects/code-tools/jmh/ For now I didn't move the JavaTest class but it could be a next step with a migration to the JUnit framework. The only impacts are the move of the class and the project structure => no code change. --- .gitignore | 4 +- java/flatbuffers/pom.xml | 65 ++++++++++++++++ .../com/google/flatbuffers/Constants.java | 0 .../google/flatbuffers/FlatBufferBuilder.java | 0 .../java}/com/google/flatbuffers/Struct.java | 0 .../java}/com/google/flatbuffers/Table.java | 0 java/flatbuffers/src/test/fbs/test.fbs | 19 +++++ .../google/flatbuffers/test/DummyTest.java | 25 ++++++ java/jmh/pom.xml | 77 +++++++++++++++++++ java/pom.xml | 53 +++++++++++-- 10 files changed, 233 insertions(+), 10 deletions(-) create mode 100644 java/flatbuffers/pom.xml rename java/{ => flatbuffers/src/main/java}/com/google/flatbuffers/Constants.java (100%) rename java/{ => flatbuffers/src/main/java}/com/google/flatbuffers/FlatBufferBuilder.java (100%) rename java/{ => flatbuffers/src/main/java}/com/google/flatbuffers/Struct.java (100%) rename java/{ => flatbuffers/src/main/java}/com/google/flatbuffers/Table.java (100%) create mode 100644 java/flatbuffers/src/test/fbs/test.fbs create mode 100644 java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java create mode 100644 java/jmh/pom.xml diff --git a/.gitignore b/.gitignore index 6f3894d06..1ba56a0e5 100755 --- a/.gitignore +++ b/.gitignore @@ -54,8 +54,8 @@ build/Xcode/FlatBuffers.xcodeproj/project.xcworkspace/** build/Xcode/FlatBuffers.xcodeproj/xcuserdata/** FlatBuffers.xcodeproj/ java/.idea -java/*.iml -java/target +*.iml +target **/*.pyc .idea build/VS2010/FlatBuffers.sdf diff --git a/java/flatbuffers/pom.xml b/java/flatbuffers/pom.xml new file mode 100644 index 000000000..7b6ea7933 --- /dev/null +++ b/java/flatbuffers/pom.xml @@ -0,0 +1,65 @@ + + + + com.google.flatbuffers + flatbuffers + 1.3.0-SNAPSHOT + + + 4.0.0 + flatbuffers-java + bundle + FlatBuffers Java API + + Memory Efficient Serialization Library + + + + + junit + junit + test + + + + ${basedir}/../.. + ${project.build.directory}/generated-test-sources/flatbuffers + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + org.codehaus.mojo + exec-maven-plugin + + + generate-test-sources + generate-test-sources + + exec + + + ${flatbuffers.root.dir}/flatc + + --java + -o + ${generated.test.sources.directory} + ${basedir}/src/test/fbs/test.fbs + + ${generated.test.sources.directory} + + + + + + + + diff --git a/java/com/google/flatbuffers/Constants.java b/java/flatbuffers/src/main/java/com/google/flatbuffers/Constants.java similarity index 100% rename from java/com/google/flatbuffers/Constants.java rename to java/flatbuffers/src/main/java/com/google/flatbuffers/Constants.java diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/flatbuffers/src/main/java/com/google/flatbuffers/FlatBufferBuilder.java similarity index 100% rename from java/com/google/flatbuffers/FlatBufferBuilder.java rename to java/flatbuffers/src/main/java/com/google/flatbuffers/FlatBufferBuilder.java diff --git a/java/com/google/flatbuffers/Struct.java b/java/flatbuffers/src/main/java/com/google/flatbuffers/Struct.java similarity index 100% rename from java/com/google/flatbuffers/Struct.java rename to java/flatbuffers/src/main/java/com/google/flatbuffers/Struct.java diff --git a/java/com/google/flatbuffers/Table.java b/java/flatbuffers/src/main/java/com/google/flatbuffers/Table.java similarity index 100% rename from java/com/google/flatbuffers/Table.java rename to java/flatbuffers/src/main/java/com/google/flatbuffers/Table.java diff --git a/java/flatbuffers/src/test/fbs/test.fbs b/java/flatbuffers/src/test/fbs/test.fbs new file mode 100644 index 000000000..695b94e43 --- /dev/null +++ b/java/flatbuffers/src/test/fbs/test.fbs @@ -0,0 +1,19 @@ +namespace com.google.flatbuffer.test; + +table MyTable +{ + foo:int; +} + +enum MyEnum:byte +{ + A, B, C +} + +struct MyStruct +{ + a:int; + b:int; +} + +root_type MyTable; \ No newline at end of file diff --git a/java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java b/java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java new file mode 100644 index 000000000..627050b5f --- /dev/null +++ b/java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java @@ -0,0 +1,25 @@ +package com.google.flatbuffers.test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.Test; + +import com.google.flatbuffer.test.MyTable; +import com.google.flatbuffers.FlatBufferBuilder; + +/** + * Dummy Test to demo JUnit usage. + */ +public class DummyTest { + @Test + public void testDummy() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + + int tableOffSet = MyTable.createMyTable(builder, 42); + MyTable.finishMyTableBuffer(builder, tableOffSet); + MyTable myTable = MyTable.getRootAsMyTable(builder.dataBuffer()); + + assertThat(myTable.foo(), is(42)); + } +} diff --git a/java/jmh/pom.xml b/java/jmh/pom.xml new file mode 100644 index 000000000..9be798421 --- /dev/null +++ b/java/jmh/pom.xml @@ -0,0 +1,77 @@ + + + + com.google.flatbuffers + flatbuffers + 1.3.0-SNAPSHOT + + + 4.0.0 + flatbuffers-jmh + jar + FlatBuffers JMH micro-benchmark + + Micro benchmark to help in technical design decisions. + + + + 1.12 + benchmarks + + + + + org.openjdk.jmh + jmh-core + ${jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh.version} + provided + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + ${uberjar.name} + + + org.openjdk.jmh.Main + + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + + + diff --git a/java/pom.xml b/java/pom.xml index dd92b9d55..2297dbe37 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -1,13 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 com.google.flatbuffers - flatbuffers-java + flatbuffers 1.3.0-SNAPSHOT - jar - FlatBuffers Java API + pom + FlatBuffers Memory Efficient Serialization Library @@ -30,10 +30,47 @@ scm:git:https://github.com/google/flatbuffers.git - - + + + 3.0 + + + + + flatbuffers + jmh + + + + + + junit + junit + 4.12 + + + + - ./ + + + + org.apache.maven.plugins + maven-shade-plugin + 2.2 + + + org.codehaus.mojo + exec-maven-plugin + 1.5.0 + + + org.apache.felix + maven-bundle-plugin + 3.0.1 + + + maven-compiler-plugin From cf7e4b027ada723c782f0e25615c080f0bdac006 Mon Sep 17 00:00:00 2001 From: Antoine Descamps Date: Wed, 8 Jun 2016 09:32:37 +0200 Subject: [PATCH 02/13] Fix typo "your platform can't handling..." => "your platform can't handle" --- php/FlatbufferBuilder.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/php/FlatbufferBuilder.php b/php/FlatbufferBuilder.php index 3738582e2..fce4a718e 100644 --- a/php/FlatbufferBuilder.php +++ b/php/FlatbufferBuilder.php @@ -233,7 +233,7 @@ class FlatbufferBuilder public function putUint($x) { if ($x > PHP_INT_MAX) { - throw new \InvalidArgumentException("your platform can't handling uint correctly. use 64bit machine."); + throw new \InvalidArgumentException("your platform can't handle uint correctly. use 64bit machine."); } $this->bb->putUint($this->space -= 4, $x); @@ -245,7 +245,7 @@ class FlatbufferBuilder public function putLong($x) { if ($x > PHP_INT_MAX) { - throw new \InvalidArgumentException("your platform can't handling long correctly. use 64bit machine."); + throw new \InvalidArgumentException("your platform can't handle long correctly. use 64bit machine."); } $this->bb->putLong($this->space -= 8, $x); @@ -257,7 +257,7 @@ class FlatbufferBuilder public function putUlong($x) { if ($x > PHP_INT_MAX) { - throw new \InvalidArgumentException("your platform can't handling ulong correctly. this is php limitations. please wait extension release."); + throw new \InvalidArgumentException("your platform can't handle ulong correctly. this is php limitations. please wait extension release."); } $this->bb->putUlong($this->space -= 8, $x); From cc2b04ce1c0cdb96e6f9671f84e4cee5b94ffe46 Mon Sep 17 00:00:00 2001 From: Romain Gilles Date: Tue, 5 Jul 2016 11:38:17 +0200 Subject: [PATCH 03/13] Revert "Create a maven like project structure for java development. Make it OSGi compliant. Generate the flatbuffers code for testing (example)." This reverts commit 9875b0e0f8af5781a793fb93807641c9cebfb903. --- .gitignore | 4 +- .../com/google/flatbuffers/Constants.java | 0 .../google/flatbuffers/FlatBufferBuilder.java | 0 .../com/google/flatbuffers/Struct.java | 0 .../com/google/flatbuffers/Table.java | 0 java/flatbuffers/pom.xml | 65 ---------------- java/flatbuffers/src/test/fbs/test.fbs | 19 ----- .../google/flatbuffers/test/DummyTest.java | 25 ------ java/jmh/pom.xml | 77 ------------------- java/pom.xml | 53 ++----------- 10 files changed, 10 insertions(+), 233 deletions(-) rename java/{flatbuffers/src/main/java => }/com/google/flatbuffers/Constants.java (100%) rename java/{flatbuffers/src/main/java => }/com/google/flatbuffers/FlatBufferBuilder.java (100%) rename java/{flatbuffers/src/main/java => }/com/google/flatbuffers/Struct.java (100%) rename java/{flatbuffers/src/main/java => }/com/google/flatbuffers/Table.java (100%) delete mode 100644 java/flatbuffers/pom.xml delete mode 100644 java/flatbuffers/src/test/fbs/test.fbs delete mode 100644 java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java delete mode 100644 java/jmh/pom.xml diff --git a/.gitignore b/.gitignore index 1ba56a0e5..6f3894d06 100755 --- a/.gitignore +++ b/.gitignore @@ -54,8 +54,8 @@ build/Xcode/FlatBuffers.xcodeproj/project.xcworkspace/** build/Xcode/FlatBuffers.xcodeproj/xcuserdata/** FlatBuffers.xcodeproj/ java/.idea -*.iml -target +java/*.iml +java/target **/*.pyc .idea build/VS2010/FlatBuffers.sdf diff --git a/java/flatbuffers/src/main/java/com/google/flatbuffers/Constants.java b/java/com/google/flatbuffers/Constants.java similarity index 100% rename from java/flatbuffers/src/main/java/com/google/flatbuffers/Constants.java rename to java/com/google/flatbuffers/Constants.java diff --git a/java/flatbuffers/src/main/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java similarity index 100% rename from java/flatbuffers/src/main/java/com/google/flatbuffers/FlatBufferBuilder.java rename to java/com/google/flatbuffers/FlatBufferBuilder.java diff --git a/java/flatbuffers/src/main/java/com/google/flatbuffers/Struct.java b/java/com/google/flatbuffers/Struct.java similarity index 100% rename from java/flatbuffers/src/main/java/com/google/flatbuffers/Struct.java rename to java/com/google/flatbuffers/Struct.java diff --git a/java/flatbuffers/src/main/java/com/google/flatbuffers/Table.java b/java/com/google/flatbuffers/Table.java similarity index 100% rename from java/flatbuffers/src/main/java/com/google/flatbuffers/Table.java rename to java/com/google/flatbuffers/Table.java diff --git a/java/flatbuffers/pom.xml b/java/flatbuffers/pom.xml deleted file mode 100644 index 7b6ea7933..000000000 --- a/java/flatbuffers/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - com.google.flatbuffers - flatbuffers - 1.3.0-SNAPSHOT - - - 4.0.0 - flatbuffers-java - bundle - FlatBuffers Java API - - Memory Efficient Serialization Library - - - - - junit - junit - test - - - - ${basedir}/../.. - ${project.build.directory}/generated-test-sources/flatbuffers - - - - - - - org.apache.felix - maven-bundle-plugin - true - - - org.codehaus.mojo - exec-maven-plugin - - - generate-test-sources - generate-test-sources - - exec - - - ${flatbuffers.root.dir}/flatc - - --java - -o - ${generated.test.sources.directory} - ${basedir}/src/test/fbs/test.fbs - - ${generated.test.sources.directory} - - - - - - - - diff --git a/java/flatbuffers/src/test/fbs/test.fbs b/java/flatbuffers/src/test/fbs/test.fbs deleted file mode 100644 index 695b94e43..000000000 --- a/java/flatbuffers/src/test/fbs/test.fbs +++ /dev/null @@ -1,19 +0,0 @@ -namespace com.google.flatbuffer.test; - -table MyTable -{ - foo:int; -} - -enum MyEnum:byte -{ - A, B, C -} - -struct MyStruct -{ - a:int; - b:int; -} - -root_type MyTable; \ No newline at end of file diff --git a/java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java b/java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java deleted file mode 100644 index 627050b5f..000000000 --- a/java/flatbuffers/src/test/java/com/google/flatbuffers/test/DummyTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.google.flatbuffers.test; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import org.junit.Test; - -import com.google.flatbuffer.test.MyTable; -import com.google.flatbuffers.FlatBufferBuilder; - -/** - * Dummy Test to demo JUnit usage. - */ -public class DummyTest { - @Test - public void testDummy() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - - int tableOffSet = MyTable.createMyTable(builder, 42); - MyTable.finishMyTableBuffer(builder, tableOffSet); - MyTable myTable = MyTable.getRootAsMyTable(builder.dataBuffer()); - - assertThat(myTable.foo(), is(42)); - } -} diff --git a/java/jmh/pom.xml b/java/jmh/pom.xml deleted file mode 100644 index 9be798421..000000000 --- a/java/jmh/pom.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - com.google.flatbuffers - flatbuffers - 1.3.0-SNAPSHOT - - - 4.0.0 - flatbuffers-jmh - jar - FlatBuffers JMH micro-benchmark - - Micro benchmark to help in technical design decisions. - - - - 1.12 - benchmarks - - - - - org.openjdk.jmh - jmh-core - ${jmh.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - provided - - - - - - - org.apache.maven.plugins - maven-shade-plugin - - - package - - shade - - - ${uberjar.name} - - - org.openjdk.jmh.Main - - - - - - *:* - - META-INF/*.SF - META-INF/*.DSA - META-INF/*.RSA - - - - - - - - - - - diff --git a/java/pom.xml b/java/pom.xml index 2297dbe37..dd92b9d55 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -1,13 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 com.google.flatbuffers - flatbuffers + flatbuffers-java 1.3.0-SNAPSHOT - pom - FlatBuffers + jar + FlatBuffers Java API Memory Efficient Serialization Library @@ -30,47 +30,10 @@ scm:git:https://github.com/google/flatbuffers.git - - - 3.0 - - - - - flatbuffers - jmh - - - - - - junit - junit - 4.12 - - - - + + - - - - org.apache.maven.plugins - maven-shade-plugin - 2.2 - - - org.codehaus.mojo - exec-maven-plugin - 1.5.0 - - - org.apache.felix - maven-bundle-plugin - 3.0.1 - - - + ./ maven-compiler-plugin From 7a955a09f43f271a5dec1221e2a74fa2da9825cd Mon Sep 17 00:00:00 2001 From: Romain Gilles Date: Tue, 5 Jul 2016 14:29:12 +0200 Subject: [PATCH 04/13] Move maven `pom.xml` from the java folder to the root folder. This avoid to put the pom.xml file into the source directory. Normally the pom file is in a parent (/parent) folder and it is not mixed with the java source code. An other thing is: this will make import of the project more easy from a IDE. The side effect is that the target folder where maven build artifacts will move from the /java/target to /target therefore the gitignore file has been updated in consequences. --- .gitignore | 5 +++-- java/pom.xml => pom.xml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) rename java/pom.xml => pom.xml (98%) diff --git a/.gitignore b/.gitignore index 6f3894d06..c14aad97b 100755 --- a/.gitignore +++ b/.gitignore @@ -55,9 +55,10 @@ build/Xcode/FlatBuffers.xcodeproj/xcuserdata/** FlatBuffers.xcodeproj/ java/.idea java/*.iml -java/target -**/*.pyc .idea +*.iml +target +**/*.pyc build/VS2010/FlatBuffers.sdf build/VS2010/FlatBuffers.opensdf build/VS2010/ipch/**/*.ipch diff --git a/java/pom.xml b/pom.xml similarity index 98% rename from java/pom.xml rename to pom.xml index dd92b9d55..28d50d283 100644 --- a/java/pom.xml +++ b/pom.xml @@ -33,7 +33,7 @@ - ./ + java maven-compiler-plugin From 9605dc59812781f60e1f2e308c5d7284d8dd756d Mon Sep 17 00:00:00 2001 From: Romain Gilles Date: Fri, 15 Jul 2016 14:34:56 +0200 Subject: [PATCH 05/13] Added OSGi header generation for maven project. This allow jar generated with maven to be used in OSGi environment. --- pom.xml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 28d50d283..8e32feec3 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ com.google.flatbuffers flatbuffers-java 1.3.0-SNAPSHOT - jar + bundle FlatBuffers Java API Memory Efficient Serialization Library @@ -78,6 +78,12 @@ + + org.apache.felix + maven-bundle-plugin + 3.0.1 + true + From 0328dedab53989f3354dbb56fedf2a721dade16b Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Fri, 15 Jul 2016 15:21:09 +0200 Subject: [PATCH 06/13] clangFormating base class --- include/flatbuffers/code_generators.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/flatbuffers/code_generators.h b/include/flatbuffers/code_generators.h index e7450a7a0..8b097ef7e 100644 --- a/include/flatbuffers/code_generators.h +++ b/include/flatbuffers/code_generators.h @@ -39,8 +39,8 @@ class BaseGenerator { protected: BaseGenerator(const Parser &parser, const std::string &path, - const std::string &file_name, - const std::string qualifying_start, + const std::string &file_name, + const std::string qualifying_start, const std::string qualifying_separator) : parser_(parser), path_(path), @@ -86,15 +86,18 @@ class BaseGenerator { const std::string LastNamespacePart(const Namespace &ns) { auto &namespaces = ns.components; - if (namespaces.size()) return *(namespaces.end() - 1); else return std::string(""); + 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), + // 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) { From e750268f0cb3386ab8c6324cf18de4f8d95e6bf3 Mon Sep 17 00:00:00 2001 From: lakedaemon Date: Fri, 15 Jul 2016 15:35:24 +0200 Subject: [PATCH 07/13] clang formating cpp code generator and add missing generated classes --- src/idl_gen_cpp.cpp | 88 ++++++++----------- tests/MyGame/Example/Any.java | 4 +- tests/MyGame/Example/Color.java | 4 +- tests/MyGame/Example/Monster.java | 2 +- tests/MyGame/Example/Stat.java | 2 +- tests/MyGame/Example/Test.java | 2 +- .../Example/TestSimpleTableWithEnum.java | 2 +- tests/MyGame/Example/Vec3.java | 2 +- tests/MyGame/Example2/Monster.java | 2 +- .../NamespaceA/NamespaceB/EnumInNestedNS.java | 4 +- .../NamespaceB/StructInNestedNS.java | 2 +- .../NamespaceB/TableInNestedNS.java | 2 +- .../NamespaceA/SecondTableInA.java | 2 +- .../NamespaceA/TableInFirstNS.java | 2 +- tests/namespace_test/NamespaceC/TableInC.java | 2 +- 15 files changed, 53 insertions(+), 69 deletions(-) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index e12e8a34a..ae82164e0 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -24,9 +24,7 @@ namespace flatbuffers { struct IsAlnum { - bool operator()(char c) { - return !isalnum(c); - } + bool operator()(char c) { return !isalnum(c); } }; static std::string GeneratedFileName(const std::string &path, @@ -184,7 +182,6 @@ class CppGenerator : public BaseGenerator { code += "nullptr"; code += "); }\n\n"; - if (parser_.file_extension_.length()) { // Return the extension code += "inline const char *" + name; @@ -264,30 +261,28 @@ class CppGenerator : public BaseGenerator { // 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) { + 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; + : 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 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) { + 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; @@ -388,8 +383,8 @@ class CppGenerator : public BaseGenerator { 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 += GetEnumVal(enum_def, *enum_def.vals.vec.front(), parser_.opts) + + ")"; } code += "]; }\n\n"; } @@ -446,8 +441,7 @@ class CppGenerator : public BaseGenerator { return "VT_" + uname; } - void GenFullyQualifiedNameGetter(const std::string &name, - std::string &code) { + void GenFullyQualifiedNameGetter(const std::string &name, std::string &code) { if (parser_.opts.generate_name_strings) { code += " static FLATBUFFERS_CONSTEXPR const char *GetFullyQualifiedName() " @@ -469,21 +463,17 @@ class CppGenerator : public BaseGenerator { 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); + 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 { + 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) { + } else if (field.value.type.base_type == BASE_TYPE_BOOL) { code += field.value.constant == "0" ? "false" : "true"; - } - else { + } else { code += GenDefaultConstant(field); } } @@ -529,8 +519,7 @@ class CppGenerator : public BaseGenerator { 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 += " " + GenTypeGet(field.value.type, " ", "const ", " *", true); code += field.name + "() const { return "; // Call a different accessor for pointers, that indirects. auto accessor = @@ -538,8 +527,8 @@ class CppGenerator : public BaseGenerator { ? "GetField<" : (IsStruct(field.value.type) ? "GetStruct<" : "GetPointer<"); auto offsetstr = GenFieldOffsetName(field); - auto call = accessor + GenTypeGet(field.value.type, "", - "const ", " *", false) + + 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)) @@ -556,8 +545,7 @@ class CppGenerator : public BaseGenerator { code += GenUnderlyingCast(field, false, "_" + field.name); code += "); }\n"; } else { - auto type = - GenTypeGet(field.value.type, " ", "", " *", true); + auto type = GenTypeGet(field.value.type, " ", "", " *", true); code += " " + type + "mutable_" + field.name + "() { return "; code += GenUnderlyingCast(field, true, accessor + type + ">(" + offsetstr + ")"); @@ -739,20 +727,19 @@ class CppGenerator : public BaseGenerator { } code += " return builder_.Finish();\n}\n\n"; - //Generate a CreateX function with vector types as parameters + // Generate a CreateX function with vector types as parameters if (gen_vector_pars) { 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) { + it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (!field.deprecated) { if (field.value.type.base_type == BASE_TYPE_STRING) { code += ",\n const char *"; code += field.name + " = nullptr"; - } - else if (field.value.type.base_type == BASE_TYPE_VECTOR) { + } else if (field.value.type.base_type == BASE_TYPE_VECTOR) { code += ",\n const std::vector<"; code += GenTypeWire(field.value.type.VectorType(), "", false); code += "> *" + field.name + " = nullptr"; @@ -766,7 +753,7 @@ class CppGenerator : public BaseGenerator { code += struct_def.name; code += "(_fbb"; for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); ++it) { + it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (!field.deprecated) { if (field.value.type.base_type == BASE_TYPE_STRING) { @@ -777,7 +764,8 @@ class CppGenerator : public BaseGenerator { code += "_fbb.CreateVector<"; code += GenTypeWire(field.value.type.VectorType(), "", false); code += ">(*" + field.name + ")"; - } else code += ", " + field.name; + } else + code += ", " + field.name; } } code += ");\n}\n\n"; @@ -880,8 +868,7 @@ class CppGenerator : public BaseGenerator { 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 += " " + GenTypeGet(field.value.type, " ", "const ", " &", true); code += field.name + "() const { return "; code += GenUnderlyingCast( field, true, is_scalar @@ -949,19 +936,16 @@ bool GenerateCPP(const Parser &parser, const std::string &path, return generator.generate(); } -std::string CPPMakeRule(const Parser &parser, - const std::string &path, +std::string CPPMakeRule(const Parser &parser, const std::string &path, const std::string &file_name) { - std::string filebase = flatbuffers::StripPath( - flatbuffers::StripExtension(file_name)); + std::string filebase = + flatbuffers::StripPath(flatbuffers::StripExtension(file_name)); std::string make_rule = GeneratedFileName(path, filebase) + ": "; auto included_files = parser.GetIncludedFilesRecursive(file_name); - for (auto it = included_files.begin(); - it != included_files.end(); ++it) { + for (auto it = included_files.begin(); it != included_files.end(); ++it) { make_rule += " " + *it; } return make_rule; } } // namespace flatbuffers - diff --git a/tests/MyGame/Example/Any.java b/tests/MyGame/Example/Any.java index 25d74af55..6e4fb76ca 100644 --- a/tests/MyGame/Example/Any.java +++ b/tests/MyGame/Example/Any.java @@ -9,8 +9,8 @@ public final class Any { public static final byte TestSimpleTableWithEnum = 2; public static final byte MyGame_Example2_Monster = 3; - private static final String[] names = { "NONE", "Monster", "TestSimpleTableWithEnum", "MyGame_Example2_Monster", }; + public 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/Color.java b/tests/MyGame/Example/Color.java index 502ec9fbf..7c113b72f 100644 --- a/tests/MyGame/Example/Color.java +++ b/tests/MyGame/Example/Color.java @@ -8,8 +8,8 @@ public final class Color { public static final byte Green = 2; public static final byte Blue = 8; - private static final String[] names = { "Red", "Green", "", "", "", "", "", "Blue", }; + public static final String[] names = { "Red", "Green", "", "", "", "", "", "Blue", }; public static String name(int e) { return names[e - Red]; } -}; +} diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java index bfd4be1c9..dc27f8447 100644 --- a/tests/MyGame/Example/Monster.java +++ b/tests/MyGame/Example/Monster.java @@ -135,5 +135,5 @@ public final class Monster extends Table { return o; } public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); } -}; +} diff --git a/tests/MyGame/Example/Stat.java b/tests/MyGame/Example/Stat.java index 3cac509b7..cd339c62d 100644 --- a/tests/MyGame/Example/Stat.java +++ b/tests/MyGame/Example/Stat.java @@ -39,5 +39,5 @@ public final class Stat extends Table { int o = builder.endObject(); return o; } -}; +} diff --git a/tests/MyGame/Example/Test.java b/tests/MyGame/Example/Test.java index 52474152f..6e33da9b3 100644 --- a/tests/MyGame/Example/Test.java +++ b/tests/MyGame/Example/Test.java @@ -23,5 +23,5 @@ public final class Test extends Struct { builder.putShort(a); return builder.offset(); } -}; +} diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.java b/tests/MyGame/Example/TestSimpleTableWithEnum.java index 85e18c2b3..a1de020ea 100644 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.java +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.java @@ -29,5 +29,5 @@ public final class TestSimpleTableWithEnum extends Table { int o = builder.endObject(); return o; } -}; +} diff --git a/tests/MyGame/Example/Vec3.java b/tests/MyGame/Example/Vec3.java index 7ae1ce209..261947cc3 100644 --- a/tests/MyGame/Example/Vec3.java +++ b/tests/MyGame/Example/Vec3.java @@ -40,5 +40,5 @@ public final class Vec3 extends Struct { builder.putFloat(x); return builder.offset(); } -}; +} diff --git a/tests/MyGame/Example2/Monster.java b/tests/MyGame/Example2/Monster.java index 6432494f3..968eee563 100644 --- a/tests/MyGame/Example2/Monster.java +++ b/tests/MyGame/Example2/Monster.java @@ -19,5 +19,5 @@ public final class Monster extends Table { int o = builder.endObject(); return o; } -}; +} diff --git a/tests/namespace_test/NamespaceA/NamespaceB/EnumInNestedNS.java b/tests/namespace_test/NamespaceA/NamespaceB/EnumInNestedNS.java index ff5559544..e23cecc06 100644 --- a/tests/namespace_test/NamespaceA/NamespaceB/EnumInNestedNS.java +++ b/tests/namespace_test/NamespaceA/NamespaceB/EnumInNestedNS.java @@ -8,8 +8,8 @@ public final class EnumInNestedNS { public static final byte B = 1; public static final byte C = 2; - private static final String[] names = { "A", "B", "C", }; + public static final String[] names = { "A", "B", "C", }; public static String name(int e) { return names[e]; } -}; +} diff --git a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java index 93f805224..fede07a02 100644 --- a/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java +++ b/tests/namespace_test/NamespaceA/NamespaceB/StructInNestedNS.java @@ -22,5 +22,5 @@ public final class StructInNestedNS extends Struct { builder.putInt(a); return builder.offset(); } -}; +} diff --git a/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java b/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java index 2cfb1bacc..fc518563d 100644 --- a/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java +++ b/tests/namespace_test/NamespaceA/NamespaceB/TableInNestedNS.java @@ -29,5 +29,5 @@ public final class TableInNestedNS extends Table { int o = builder.endObject(); return o; } -}; +} diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.java b/tests/namespace_test/NamespaceA/SecondTableInA.java index acabc3931..e6f390a9f 100644 --- a/tests/namespace_test/NamespaceA/SecondTableInA.java +++ b/tests/namespace_test/NamespaceA/SecondTableInA.java @@ -29,5 +29,5 @@ public final class SecondTableInA extends Table { int o = builder.endObject(); return o; } -}; +} diff --git a/tests/namespace_test/NamespaceA/TableInFirstNS.java b/tests/namespace_test/NamespaceA/TableInFirstNS.java index 873979307..b44df9786 100644 --- a/tests/namespace_test/NamespaceA/TableInFirstNS.java +++ b/tests/namespace_test/NamespaceA/TableInFirstNS.java @@ -28,5 +28,5 @@ public final class TableInFirstNS extends Table { int o = builder.endObject(); return o; } -}; +} diff --git a/tests/namespace_test/NamespaceC/TableInC.java b/tests/namespace_test/NamespaceC/TableInC.java index cf1bca18c..19bb4cd57 100644 --- a/tests/namespace_test/NamespaceC/TableInC.java +++ b/tests/namespace_test/NamespaceC/TableInC.java @@ -34,5 +34,5 @@ public final class TableInC extends Table { int o = builder.endObject(); return o; } -}; +} From 58924538a39e8ceb657426cf2be241b8be0abd88 Mon Sep 17 00:00:00 2001 From: Morton Fox Date: Sat, 16 Jul 2016 00:26:50 -0400 Subject: [PATCH 08/13] Fix link to CONTRIBUTING --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 15dd41b11..3a7f929ef 100755 --- a/readme.md +++ b/readme.md @@ -46,7 +46,7 @@ you would leave it in.
- [CONTRIBUTING]: http://github.com/google/flatbuffers/blob/master/CONTRIBUTING + [CONTRIBUTING]: http://github.com/google/flatbuffers/blob/master/CONTRIBUTING.md [`flatbuffers` tag]: https://stackoverflow.com/questions/tagged/flatbuffers [FlatBuffers Google Group]: https://groups.google.com/forum/#!forum/flatbuffers [FlatBuffers Issues Tracker]: http://github.com/google/flatbuffers/issues From 64fa8ba9a99234edd7cf8b09820603c0a2c287ea Mon Sep 17 00:00:00 2001 From: Antoine Descamps Date: Tue, 19 Jul 2016 12:22:37 +0200 Subject: [PATCH 09/13] Fix typo Related to https://github.com/google/flatbuffers/pull/3904#issuecomment-224724181 --- php/FlatbufferBuilder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/php/FlatbufferBuilder.php b/php/FlatbufferBuilder.php index fce4a718e..6f0ee4831 100644 --- a/php/FlatbufferBuilder.php +++ b/php/FlatbufferBuilder.php @@ -245,7 +245,7 @@ class FlatbufferBuilder public function putLong($x) { if ($x > PHP_INT_MAX) { - throw new \InvalidArgumentException("your platform can't handle long correctly. use 64bit machine."); + throw new \InvalidArgumentException("Your platform can't handle long correctly. Use a 64bit machine."); } $this->bb->putLong($this->space -= 8, $x); @@ -257,7 +257,7 @@ class FlatbufferBuilder public function putUlong($x) { if ($x > PHP_INT_MAX) { - throw new \InvalidArgumentException("your platform can't handle ulong correctly. this is php limitations. please wait extension release."); + throw new \InvalidArgumentException("Your platform can't handle ulong correctly. This is a php limitation. Please wait for the extension release."); } $this->bb->putUlong($this->space -= 8, $x); From 298dd21ec8a0a1328eb0d9830fb3a8248363ddb8 Mon Sep 17 00:00:00 2001 From: Yakir Buskilla Date: Wed, 20 Jul 2016 10:46:43 +0300 Subject: [PATCH 10/13] fixed ArrayOutOfBoundsException in java example --- docs/source/Tutorial.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md index 6f6ac9a51..0157985a2 100644 --- a/docs/source/Tutorial.md +++ b/docs/source/Tutorial.md @@ -727,8 +727,8 @@ offsets. // Place the two weapons into an array, and pass it to the `createWeaponsVector()` method to // create a FlatBuffer vector. int[] weaps = new int[2]; - weaps[1] = sword; - weaps[2] = axe; + weaps[0] = sword; + weaps[1] = axe; // Pass the `weaps` array into the `createWeaponsVector()` method to create a FlatBuffer vector. int weapons = Monster.createWeaponsVector(builder, weaps); From 53e9606ea20d25e1da074edaa00901272173e334 Mon Sep 17 00:00:00 2001 From: Muhammed Thanish Date: Wed, 20 Jul 2016 22:58:22 +0530 Subject: [PATCH 11/13] Implement mutators for Go --- docs/source/GoUsage.md | 23 ++ go/table.go | 210 ++++++++++++++ src/idl_gen_go.cpp | 46 ++- tests/MyGame/Example/Monster.go | 66 +++++ tests/MyGame/Example/Stat.go | 8 + tests/MyGame/Example/Test.go | 4 + .../MyGame/Example/TestSimpleTableWithEnum.go | 4 + tests/MyGame/Example/Vec3.go | 10 + tests/go_test.go | 262 ++++++++++++++++++ 9 files changed, 631 insertions(+), 2 deletions(-) diff --git a/docs/source/GoUsage.md b/docs/source/GoUsage.md index a3a0e928a..ab6ddbd82 100644 --- a/docs/source/GoUsage.md +++ b/docs/source/GoUsage.md @@ -67,6 +67,29 @@ Now you can access values like this: pos := monster.Pos(nil) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated. + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.go} + monster := example.GetRootAsMonster(buf, 0) + + // Set table field. + if ok := monster.MutateHp(10); !ok { + panic("failed to mutate Hp") + } + + // Set struct field. + monster.Pos().MutateZ(4) + + // This mutation will fail because the mana field is not available in + // the buffer. It should be set when creating the buffer. + if ok := monster.MutateMana(20); !ok { + panic("failed to mutate Hp") + } +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer. + ## Text Parsing There currently is no support for parsing text (Schema's and JSON) directly diff --git a/go/table.go b/go/table.go index 976a7dba1..01d3db122 100644 --- a/go/table.go +++ b/go/table.go @@ -293,3 +293,213 @@ func (t *Table) GetVOffsetTSlot(slot VOffsetT, d VOffsetT) VOffsetT { } return VOffsetT(off) } + +// MutateBool updates a bool at the given offset. +func (t *Table) MutateBool(off UOffsetT, n bool) bool { + WriteBool(t.Bytes[off:], n) + return true +} + +// MutateByte updates a Byte at the given offset. +func (t *Table) MutateByte(off UOffsetT, n byte) bool { + WriteByte(t.Bytes[off:], n) + return true +} + +// MutateUint8 updates a Uint8 at the given offset. +func (t *Table) MutateUint8(off UOffsetT, n uint8) bool { + WriteUint8(t.Bytes[off:], n) + return true +} + +// MutateUint16 updates a Uint16 at the given offset. +func (t *Table) MutateUint16(off UOffsetT, n uint16) bool { + WriteUint16(t.Bytes[off:], n) + return true +} + +// MutateUint32 updates a Uint32 at the given offset. +func (t *Table) MutateUint32(off UOffsetT, n uint32) bool { + WriteUint32(t.Bytes[off:], n) + return true +} + +// MutateUint64 updates a Uint64 at the given offset. +func (t *Table) MutateUint64(off UOffsetT, n uint64) bool { + WriteUint64(t.Bytes[off:], n) + return true +} + +// MutateInt8 updates a Int8 at the given offset. +func (t *Table) MutateInt8(off UOffsetT, n int8) bool { + WriteInt8(t.Bytes[off:], n) + return true +} + +// MutateInt16 updates a Int16 at the given offset. +func (t *Table) MutateInt16(off UOffsetT, n int16) bool { + WriteInt16(t.Bytes[off:], n) + return true +} + +// MutateInt32 updates a Int32 at the given offset. +func (t *Table) MutateInt32(off UOffsetT, n int32) bool { + WriteInt32(t.Bytes[off:], n) + return true +} + +// MutateInt64 updates a Int64 at the given offset. +func (t *Table) MutateInt64(off UOffsetT, n int64) bool { + WriteInt64(t.Bytes[off:], n) + return true +} + +// MutateFloat32 updates a Float32 at the given offset. +func (t *Table) MutateFloat32(off UOffsetT, n float32) bool { + WriteFloat32(t.Bytes[off:], n) + return true +} + +// MutateFloat64 updates a Float64 at the given offset. +func (t *Table) MutateFloat64(off UOffsetT, n float64) bool { + WriteFloat64(t.Bytes[off:], n) + return true +} + +// MutateUOffsetT updates a UOffsetT at the given offset. +func (t *Table) MutateUOffsetT(off UOffsetT, n UOffsetT) bool { + WriteUOffsetT(t.Bytes[off:], n) + return true +} + +// MutateVOffsetT updates a VOffsetT at the given offset. +func (t *Table) MutateVOffsetT(off UOffsetT, n VOffsetT) bool { + WriteVOffsetT(t.Bytes[off:], n) + return true +} + +// MutateSOffsetT updates a SOffsetT at the given offset. +func (t *Table) MutateSOffsetT(off UOffsetT, n SOffsetT) bool { + WriteSOffsetT(t.Bytes[off:], n) + return true +} + +// MutateBoolSlot updates the bool at given vtable location +func (t *Table) MutateBoolSlot(slot VOffsetT, n bool) bool { + if off := t.Offset(slot); off != 0 { + t.MutateBool(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateByteSlot updates the byte at given vtable location +func (t *Table) MutateByteSlot(slot VOffsetT, n byte) bool { + if off := t.Offset(slot); off != 0 { + t.MutateByte(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt8Slot updates the int8 at given vtable location +func (t *Table) MutateInt8Slot(slot VOffsetT, n int8) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt8(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint8Slot updates the uint8 at given vtable location +func (t *Table) MutateUint8Slot(slot VOffsetT, n uint8) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint8(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt16Slot updates the int16 at given vtable location +func (t *Table) MutateInt16Slot(slot VOffsetT, n int16) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt16(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint16Slot updates the uint16 at given vtable location +func (t *Table) MutateUint16Slot(slot VOffsetT, n uint16) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint16(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt32Slot updates the int32 at given vtable location +func (t *Table) MutateInt32Slot(slot VOffsetT, n int32) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt32(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint32Slot updates the uint32 at given vtable location +func (t *Table) MutateUint32Slot(slot VOffsetT, n uint32) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint32(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateInt64Slot updates the int64 at given vtable location +func (t *Table) MutateInt64Slot(slot VOffsetT, n int64) bool { + if off := t.Offset(slot); off != 0 { + t.MutateInt64(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateUint64Slot updates the uint64 at given vtable location +func (t *Table) MutateUint64Slot(slot VOffsetT, n uint64) bool { + if off := t.Offset(slot); off != 0 { + t.MutateUint64(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateFloat32Slot updates the float32 at given vtable location +func (t *Table) MutateFloat32Slot(slot VOffsetT, n float32) bool { + if off := t.Offset(slot); off != 0 { + t.MutateFloat32(t.Pos+UOffsetT(off), n) + return true + } + + return false +} + +// MutateFloat64Slot updates the float64 at given vtable location +func (t *Table) MutateFloat64Slot(slot VOffsetT, n float64) bool { + if off := t.Offset(slot); off != 0 { + t.MutateFloat64(t.Pos+UOffsetT(off), n) + return true + } + + return false +} diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index a04b6ba20..0920b7727 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -439,7 +439,7 @@ static void GenReceiver(const StructDef &struct_def, std::string *code_ptr) { code += "func (rcv *" + struct_def.name + ")"; } -// Generate a struct field, conditioned on its child type(s). +// Generate a struct field getter, conditioned on its child type(s). static void GenStructAccessor(const StructDef &struct_def, const FieldDef &field, std::string *code_ptr) { @@ -486,6 +486,48 @@ static void GenStructAccessor(const StructDef &struct_def, } } +// Mutate the value of a struct's scalar. +static void MutateScalarFieldOfStruct(const StructDef &struct_def, + const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string type = MakeCamel(GenTypeBasic(field.value.type)); + std::string setter = "rcv._tab.Mutate" + type; + GenReceiver(struct_def, code_ptr); + code += " Mutate" + MakeCamel(field.name); + code += "(n " + TypeName(field) + ") bool { return " + setter; + code += "(rcv._tab.Pos + flatbuffers.UOffsetT("; + code += NumToString(field.value.offset) + "), n) }\n\n"; +} + +// Mutate the value of a table's scalar. +static void MutateScalarFieldOfTable(const StructDef &struct_def, + const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string type = MakeCamel(GenTypeBasic(field.value.type)); + std::string setter = "rcv._tab.Mutate" + type + "Slot"; + GenReceiver(struct_def, code_ptr); + code += " Mutate" + MakeCamel(field.name); + code += "(n " + TypeName(field) + ") bool {\n\treturn "; + code += setter + "(" + NumToString(field.value.offset) + ", n)\n"; + code += "}\n\n"; +} + +// Generate a struct field setter, conditioned on its child type(s). +static void GenStructMutator(const StructDef &struct_def, + const FieldDef &field, + std::string *code_ptr) { + GenComment(field.doc_comment, code_ptr, nullptr, ""); + if (IsScalar(field.value.type.base_type)) { + if (struct_def.fixed) { + MutateScalarFieldOfStruct(struct_def, field, code_ptr); + } else { + MutateScalarFieldOfTable(struct_def, field, code_ptr); + } + } +} + // Generate table constructors, conditioned on its members' types. static void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { @@ -530,6 +572,7 @@ static void GenStruct(const StructDef &struct_def, if (field.deprecated) continue; GenStructAccessor(struct_def, field, code_ptr); + GenStructMutator(struct_def, field, code_ptr); } if (struct_def.fixed) { @@ -681,4 +724,3 @@ bool GenerateGo(const Parser &parser, const std::string &path, } } // namespace flatbuffers - diff --git a/tests/MyGame/Example/Monster.go b/tests/MyGame/Example/Monster.go index 0c42f45a5..f4cd18c18 100644 --- a/tests/MyGame/Example/Monster.go +++ b/tests/MyGame/Example/Monster.go @@ -43,6 +43,10 @@ func (rcv *Monster) Mana() int16 { return 150 } +func (rcv *Monster) MutateMana(n int16) bool { + return rcv._tab.MutateInt16Slot(6, n) +} + func (rcv *Monster) Hp() int16 { o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) if o != 0 { @@ -51,6 +55,10 @@ func (rcv *Monster) Hp() int16 { return 100 } +func (rcv *Monster) MutateHp(n int16) bool { + return rcv._tab.MutateInt16Slot(8, n) +} + func (rcv *Monster) Name() []byte { o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { @@ -92,6 +100,10 @@ func (rcv *Monster) Color() int8 { return 8 } +func (rcv *Monster) MutateColor(n int8) bool { + return rcv._tab.MutateInt8Slot(16, n) +} + func (rcv *Monster) TestType() byte { o := flatbuffers.UOffsetT(rcv._tab.Offset(18)) if o != 0 { @@ -100,6 +112,10 @@ func (rcv *Monster) TestType() byte { return 0 } +func (rcv *Monster) MutateTestType(n byte) bool { + return rcv._tab.MutateByteSlot(18, n) +} + func (rcv *Monster) Test(obj *flatbuffers.Table) bool { o := flatbuffers.UOffsetT(rcv._tab.Offset(20)) if o != 0 { @@ -173,6 +189,8 @@ func (rcv *Monster) TestarrayoftablesLength() int { return 0 } +/// an example documentation comment: this will end up in the generated code +/// multiline too func (rcv *Monster) Enemy(obj *Monster) *Monster { o := flatbuffers.UOffsetT(rcv._tab.Offset(28)) if o != 0 { @@ -232,6 +250,10 @@ func (rcv *Monster) Testbool() byte { return 0 } +func (rcv *Monster) MutateTestbool(n byte) bool { + return rcv._tab.MutateByteSlot(34, n) +} + func (rcv *Monster) Testhashs32Fnv1() int32 { o := flatbuffers.UOffsetT(rcv._tab.Offset(36)) if o != 0 { @@ -240,6 +262,10 @@ func (rcv *Monster) Testhashs32Fnv1() int32 { return 0 } +func (rcv *Monster) MutateTesthashs32Fnv1(n int32) bool { + return rcv._tab.MutateInt32Slot(36, n) +} + func (rcv *Monster) Testhashu32Fnv1() uint32 { o := flatbuffers.UOffsetT(rcv._tab.Offset(38)) if o != 0 { @@ -248,6 +274,10 @@ func (rcv *Monster) Testhashu32Fnv1() uint32 { return 0 } +func (rcv *Monster) MutateTesthashu32Fnv1(n uint32) bool { + return rcv._tab.MutateUint32Slot(38, n) +} + func (rcv *Monster) Testhashs64Fnv1() int64 { o := flatbuffers.UOffsetT(rcv._tab.Offset(40)) if o != 0 { @@ -256,6 +286,10 @@ func (rcv *Monster) Testhashs64Fnv1() int64 { return 0 } +func (rcv *Monster) MutateTesthashs64Fnv1(n int64) bool { + return rcv._tab.MutateInt64Slot(40, n) +} + func (rcv *Monster) Testhashu64Fnv1() uint64 { o := flatbuffers.UOffsetT(rcv._tab.Offset(42)) if o != 0 { @@ -264,6 +298,10 @@ func (rcv *Monster) Testhashu64Fnv1() uint64 { return 0 } +func (rcv *Monster) MutateTesthashu64Fnv1(n uint64) bool { + return rcv._tab.MutateUint64Slot(42, n) +} + func (rcv *Monster) Testhashs32Fnv1a() int32 { o := flatbuffers.UOffsetT(rcv._tab.Offset(44)) if o != 0 { @@ -272,6 +310,10 @@ func (rcv *Monster) Testhashs32Fnv1a() int32 { return 0 } +func (rcv *Monster) MutateTesthashs32Fnv1a(n int32) bool { + return rcv._tab.MutateInt32Slot(44, n) +} + func (rcv *Monster) Testhashu32Fnv1a() uint32 { o := flatbuffers.UOffsetT(rcv._tab.Offset(46)) if o != 0 { @@ -280,6 +322,10 @@ func (rcv *Monster) Testhashu32Fnv1a() uint32 { return 0 } +func (rcv *Monster) MutateTesthashu32Fnv1a(n uint32) bool { + return rcv._tab.MutateUint32Slot(46, n) +} + func (rcv *Monster) Testhashs64Fnv1a() int64 { o := flatbuffers.UOffsetT(rcv._tab.Offset(48)) if o != 0 { @@ -288,6 +334,10 @@ func (rcv *Monster) Testhashs64Fnv1a() int64 { return 0 } +func (rcv *Monster) MutateTesthashs64Fnv1a(n int64) bool { + return rcv._tab.MutateInt64Slot(48, n) +} + func (rcv *Monster) Testhashu64Fnv1a() uint64 { o := flatbuffers.UOffsetT(rcv._tab.Offset(50)) if o != 0 { @@ -296,6 +346,10 @@ func (rcv *Monster) Testhashu64Fnv1a() uint64 { return 0 } +func (rcv *Monster) MutateTesthashu64Fnv1a(n uint64) bool { + return rcv._tab.MutateUint64Slot(50, n) +} + func (rcv *Monster) Testarrayofbools(j int) byte { o := flatbuffers.UOffsetT(rcv._tab.Offset(52)) if o != 0 { @@ -321,6 +375,10 @@ func (rcv *Monster) Testf() float32 { return 3.14159 } +func (rcv *Monster) MutateTestf(n float32) bool { + return rcv._tab.MutateFloat32Slot(54, n) +} + func (rcv *Monster) Testf2() float32 { o := flatbuffers.UOffsetT(rcv._tab.Offset(56)) if o != 0 { @@ -329,6 +387,10 @@ func (rcv *Monster) Testf2() float32 { return 3.0 } +func (rcv *Monster) MutateTestf2(n float32) bool { + return rcv._tab.MutateFloat32Slot(56, n) +} + func (rcv *Monster) Testf3() float32 { o := flatbuffers.UOffsetT(rcv._tab.Offset(58)) if o != 0 { @@ -337,6 +399,10 @@ func (rcv *Monster) Testf3() float32 { return 0.0 } +func (rcv *Monster) MutateTestf3(n float32) bool { + return rcv._tab.MutateFloat32Slot(58, n) +} + func (rcv *Monster) Testarrayofstring2(j int) []byte { o := flatbuffers.UOffsetT(rcv._tab.Offset(60)) if o != 0 { diff --git a/tests/MyGame/Example/Stat.go b/tests/MyGame/Example/Stat.go index 7c33716b4..4ccca3446 100644 --- a/tests/MyGame/Example/Stat.go +++ b/tests/MyGame/Example/Stat.go @@ -30,6 +30,10 @@ func (rcv *Stat) Val() int64 { return 0 } +func (rcv *Stat) MutateVal(n int64) bool { + return rcv._tab.MutateInt64Slot(6, n) +} + func (rcv *Stat) Count() uint16 { o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) if o != 0 { @@ -38,6 +42,10 @@ func (rcv *Stat) Count() uint16 { return 0 } +func (rcv *Stat) MutateCount(n uint16) bool { + return rcv._tab.MutateUint16Slot(8, n) +} + func StatStart(builder *flatbuffers.Builder) { builder.StartObject(3) } func StatAddId(builder *flatbuffers.Builder, id flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(id), 0) } func StatAddVal(builder *flatbuffers.Builder, val int64) { builder.PrependInt64Slot(1, val, 0) } diff --git a/tests/MyGame/Example/Test.go b/tests/MyGame/Example/Test.go index e849488d9..ee0d9aaec 100644 --- a/tests/MyGame/Example/Test.go +++ b/tests/MyGame/Example/Test.go @@ -15,7 +15,11 @@ func (rcv *Test) Init(buf []byte, i flatbuffers.UOffsetT) { } func (rcv *Test) A() int16 { return rcv._tab.GetInt16(rcv._tab.Pos + flatbuffers.UOffsetT(0)) } +func (rcv *Test) MutateA(n int16) bool { return rcv._tab.MutateInt16(rcv._tab.Pos + flatbuffers.UOffsetT(0), n) } + func (rcv *Test) B() int8 { return rcv._tab.GetInt8(rcv._tab.Pos + flatbuffers.UOffsetT(2)) } +func (rcv *Test) MutateB(n int8) bool { return rcv._tab.MutateInt8(rcv._tab.Pos + flatbuffers.UOffsetT(2), n) } + func CreateTest(builder *flatbuffers.Builder, a int16, b int8) flatbuffers.UOffsetT { builder.Prep(2, 4) diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.go b/tests/MyGame/Example/TestSimpleTableWithEnum.go index fe9cf2dbb..d59fa6b19 100644 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.go +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.go @@ -22,6 +22,10 @@ func (rcv *TestSimpleTableWithEnum) Color() int8 { return 2 } +func (rcv *TestSimpleTableWithEnum) MutateColor(n int8) bool { + return rcv._tab.MutateInt8Slot(4, n) +} + func TestSimpleTableWithEnumStart(builder *flatbuffers.Builder) { builder.StartObject(1) } func TestSimpleTableWithEnumAddColor(builder *flatbuffers.Builder, color int8) { builder.PrependInt8Slot(0, color, 2) } func TestSimpleTableWithEnumEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } diff --git a/tests/MyGame/Example/Vec3.go b/tests/MyGame/Example/Vec3.go index 082945ed3..8bf97da32 100644 --- a/tests/MyGame/Example/Vec3.go +++ b/tests/MyGame/Example/Vec3.go @@ -15,10 +15,20 @@ func (rcv *Vec3) Init(buf []byte, i flatbuffers.UOffsetT) { } func (rcv *Vec3) X() float32 { return rcv._tab.GetFloat32(rcv._tab.Pos + flatbuffers.UOffsetT(0)) } +func (rcv *Vec3) MutateX(n float32) bool { return rcv._tab.MutateFloat32(rcv._tab.Pos + flatbuffers.UOffsetT(0), n) } + func (rcv *Vec3) Y() float32 { return rcv._tab.GetFloat32(rcv._tab.Pos + flatbuffers.UOffsetT(4)) } +func (rcv *Vec3) MutateY(n float32) bool { return rcv._tab.MutateFloat32(rcv._tab.Pos + flatbuffers.UOffsetT(4), n) } + func (rcv *Vec3) Z() float32 { return rcv._tab.GetFloat32(rcv._tab.Pos + flatbuffers.UOffsetT(8)) } +func (rcv *Vec3) MutateZ(n float32) bool { return rcv._tab.MutateFloat32(rcv._tab.Pos + flatbuffers.UOffsetT(8), n) } + func (rcv *Vec3) Test1() float64 { return rcv._tab.GetFloat64(rcv._tab.Pos + flatbuffers.UOffsetT(16)) } +func (rcv *Vec3) MutateTest1(n float64) bool { return rcv._tab.MutateFloat64(rcv._tab.Pos + flatbuffers.UOffsetT(16), n) } + func (rcv *Vec3) Test2() int8 { return rcv._tab.GetInt8(rcv._tab.Pos + flatbuffers.UOffsetT(24)) } +func (rcv *Vec3) MutateTest2(n int8) bool { return rcv._tab.MutateInt8(rcv._tab.Pos + flatbuffers.UOffsetT(24), n) } + func (rcv *Vec3) Test3(obj *Test) *Test { if obj == nil { obj = new(Test) diff --git a/tests/go_test.go b/tests/go_test.go index 9d94277f7..b816eb297 100644 --- a/tests/go_test.go +++ b/tests/go_test.go @@ -67,6 +67,7 @@ func TestAll(t *testing.T) { // Verify that the Go FlatBuffers runtime library generates the // expected bytes (does not use any schema): CheckByteLayout(t.Fatalf) + CheckMutateMethods(t.Fatalf) // Verify that panics are raised during exceptional conditions: CheckNotInObjectError(t.Fatalf) @@ -82,6 +83,7 @@ func TestAll(t *testing.T) { // Verify that the buffer generated by Go code is readable by the // generated Go code: CheckReadBuffer(generated, off, t.Fatalf) + CheckMutateBuffer(generated, off, t.Fatalf) // Verify that the buffer generated by C++ code is readable by the // generated Go code: @@ -90,6 +92,7 @@ func TestAll(t *testing.T) { t.Fatal(err) } CheckReadBuffer(monsterDataCpp, 0, t.Fatalf) + CheckMutateBuffer(monsterDataCpp, 0, t.Fatalf) // Verify that vtables are deduplicated when written: CheckVtableDeduplication(t.Fatalf) @@ -280,6 +283,120 @@ func CheckReadBuffer(buf []byte, offset flatbuffers.UOffsetT, fail func(string, } } +// CheckMutateBuffer checks that the given buffer can be mutated correctly +// as the example Monster. Only available scalar values are mutated. +func CheckMutateBuffer(org []byte, offset flatbuffers.UOffsetT, fail func(string, ...interface{})) { + // make a copy to mutate + buf := make([]byte, len(org)) + copy(buf, org) + + // load monster data from the buffer + monster := example.GetRootAsMonster(buf, offset) + + // test case struct + type testcase struct { + field string + testfn func() bool + } + + testForOriginalValues := []testcase{ + testcase{"Hp", func() bool { return monster.Hp() == 80 }}, + testcase{"Mana", func() bool { return monster.Mana() == 150 }}, + testcase{"Pos.X'", func() bool { return monster.Pos(nil).X() == float32(1.0) }}, + testcase{"Pos.Y'", func() bool { return monster.Pos(nil).Y() == float32(2.0) }}, + testcase{"Pos.Z'", func() bool { return monster.Pos(nil).Z() == float32(3.0) }}, + testcase{"Pos.Test1'", func() bool { return monster.Pos(nil).Test1() == float64(3.0) }}, + testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == int8(2) }}, + testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(5) }}, + testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(6) }}, + } + + testMutability := []testcase{ + testcase{"Hp", func() bool { return monster.MutateHp(70) }}, + testcase{"Mana", func() bool { return !monster.MutateMana(140) }}, + testcase{"Pos.X", func() bool { return monster.Pos(nil).MutateX(10.0) }}, + testcase{"Pos.Y", func() bool { return monster.Pos(nil).MutateY(20.0) }}, + testcase{"Pos.Z", func() bool { return monster.Pos(nil).MutateZ(30.0) }}, + testcase{"Pos.Test1", func() bool { return monster.Pos(nil).MutateTest1(30.0) }}, + testcase{"Pos.Test2", func() bool { return monster.Pos(nil).MutateTest2(20) }}, + testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).MutateA(50) }}, + testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).MutateB(60) }}, + } + + testForMutatedValues := []testcase{ + testcase{"Hp", func() bool { return monster.Hp() == 70 }}, + testcase{"Mana", func() bool { return monster.Mana() == 150 }}, + testcase{"Pos.X'", func() bool { return monster.Pos(nil).X() == float32(10.0) }}, + testcase{"Pos.Y'", func() bool { return monster.Pos(nil).Y() == float32(20.0) }}, + testcase{"Pos.Z'", func() bool { return monster.Pos(nil).Z() == float32(30.0) }}, + testcase{"Pos.Test1'", func() bool { return monster.Pos(nil).Test1() == float64(30.0) }}, + testcase{"Pos.Test2'", func() bool { return monster.Pos(nil).Test2() == int8(20) }}, + testcase{"Pos.Test3.A", func() bool { return monster.Pos(nil).Test3(nil).A() == int16(50) }}, + testcase{"Pos.Test3.B", func() bool { return monster.Pos(nil).Test3(nil).B() == int8(60) }}, + } + + // make sure original values are okay + for _, t := range testForOriginalValues { + if !t.testfn() { + fail("field '" + t.field + "' doesn't have the expected original value") + } + } + + // try to mutate fields and check mutability + for _, t := range testMutability { + if !t.testfn() { + fail(FailString("field '"+t.field+"' failed mutability test", true, false)) + } + } + + // test whether values have changed + for _, t := range testForMutatedValues { + if !t.testfn() { + fail("field '" + t.field + "' doesn't have the expected mutated value") + } + } + + // make sure the buffer has changed + if reflect.DeepEqual(buf, org) { + fail("mutate buffer failed") + } + + // To make sure the buffer has changed accordingly + // Read data from the buffer and verify all fields + monster = example.GetRootAsMonster(buf, offset) + for _, t := range testForMutatedValues { + if !t.testfn() { + fail("field '" + t.field + "' doesn't have the expected mutated value") + } + } + + // reverting all fields to original values should + // re-create the original buffer. Mutate all fields + // back to their original values and compare buffers. + // This test is done to make sure mutations do not do + // any unnecessary changes to the buffer. + monster = example.GetRootAsMonster(buf, offset) + monster.MutateHp(80) + monster.Pos(nil).MutateX(1.0) + monster.Pos(nil).MutateY(2.0) + monster.Pos(nil).MutateZ(3.0) + monster.Pos(nil).MutateTest1(3.0) + monster.Pos(nil).MutateTest2(2) + monster.Pos(nil).Test3(nil).MutateA(5) + monster.Pos(nil).Test3(nil).MutateB(6) + + for _, t := range testForOriginalValues { + if !t.testfn() { + fail("field '" + t.field + "' doesn't have the expected original value") + } + } + + // buffer should have original values + if !reflect.DeepEqual(buf, org) { + fail("revert changes failed") + } +} + // Low level stress/fuzz test: serialize/deserialize a variety of // different kinds of data in different combinations func checkFuzz(fuzzFields, fuzzObjects int, fail func(string, ...interface{})) { @@ -1248,6 +1365,151 @@ func CheckByteEquality(a, b []byte, fail func(string, ...interface{})) { } } +// CheckMutateMethods checks all mutate methods one by one +func CheckMutateMethods(fail func(string, ...interface{})) { + b := flatbuffers.NewBuilder(0) + b.StartObject(15) + b.PrependBoolSlot(0, true, false) + b.PrependByteSlot(1, 1, 0) + b.PrependUint8Slot(2, 2, 0) + b.PrependUint16Slot(3, 3, 0) + b.PrependUint32Slot(4, 4, 0) + b.PrependUint64Slot(5, 5, 0) + b.PrependInt8Slot(6, 6, 0) + b.PrependInt16Slot(7, 7, 0) + b.PrependInt32Slot(8, 8, 0) + b.PrependInt64Slot(9, 9, 0) + b.PrependFloat32Slot(10, 10, 0) + b.PrependFloat64Slot(11, 11, 0) + + b.PrependUOffsetTSlot(12, 12, 0) + uoVal := b.Offset() - 12 + + b.PrependVOffsetT(13) + b.Slot(13) + + b.PrependSOffsetT(14) + b.Slot(14) + soVal := flatbuffers.SOffsetT(b.Offset() - 14) + + offset := b.EndObject() + + t := &flatbuffers.Table{ + Bytes: b.Bytes, + Pos: flatbuffers.UOffsetT(len(b.Bytes)) - offset, + } + + calcVOffsetT := func(slot int) (vtableOffset flatbuffers.VOffsetT) { + return flatbuffers.VOffsetT((flatbuffers.VtableMetadataFields + slot) * flatbuffers.SizeVOffsetT) + } + calcUOffsetT := func(vtableOffset flatbuffers.VOffsetT) (valueOffset flatbuffers.UOffsetT) { + return t.Pos + flatbuffers.UOffsetT(t.Offset(vtableOffset)) + } + + type testcase struct { + field string + testfn func() bool + } + + testForOriginalValues := []testcase{ + testcase{"BoolSlot", func() bool { return t.GetBoolSlot(calcVOffsetT(0), true) == true }}, + testcase{"ByteSlot", func() bool { return t.GetByteSlot(calcVOffsetT(1), 1) == 1 }}, + testcase{"Uint8Slot", func() bool { return t.GetUint8Slot(calcVOffsetT(2), 2) == 2 }}, + testcase{"Uint16Slot", func() bool { return t.GetUint16Slot(calcVOffsetT(3), 3) == 3 }}, + testcase{"Uint32Slot", func() bool { return t.GetUint32Slot(calcVOffsetT(4), 4) == 4 }}, + testcase{"Uint64Slot", func() bool { return t.GetUint64Slot(calcVOffsetT(5), 5) == 5 }}, + testcase{"Int8Slot", func() bool { return t.GetInt8Slot(calcVOffsetT(6), 6) == 6 }}, + testcase{"Int16Slot", func() bool { return t.GetInt16Slot(calcVOffsetT(7), 7) == 7 }}, + testcase{"Int32Slot", func() bool { return t.GetInt32Slot(calcVOffsetT(8), 8) == 8 }}, + testcase{"Int64Slot", func() bool { return t.GetInt64Slot(calcVOffsetT(9), 9) == 9 }}, + testcase{"Float32Slot", func() bool { return t.GetFloat32Slot(calcVOffsetT(10), 10) == 10 }}, + testcase{"Float64Slot", func() bool { return t.GetFloat64Slot(calcVOffsetT(11), 11) == 11 }}, + testcase{"UOffsetTSlot", func() bool { return t.GetUOffsetT(calcUOffsetT(calcVOffsetT(12))) == uoVal }}, + testcase{"VOffsetTSlot", func() bool { return t.GetVOffsetT(calcUOffsetT(calcVOffsetT(13))) == 13 }}, + testcase{"SOffsetTSlot", func() bool { return t.GetSOffsetT(calcUOffsetT(calcVOffsetT(14))) == soVal }}, + } + + testMutability := []testcase{ + testcase{"BoolSlot", func() bool { return t.MutateBoolSlot(calcVOffsetT(0), false) }}, + testcase{"ByteSlot", func() bool { return t.MutateByteSlot(calcVOffsetT(1), 2) }}, + testcase{"Uint8Slot", func() bool { return t.MutateUint8Slot(calcVOffsetT(2), 4) }}, + testcase{"Uint16Slot", func() bool { return t.MutateUint16Slot(calcVOffsetT(3), 6) }}, + testcase{"Uint32Slot", func() bool { return t.MutateUint32Slot(calcVOffsetT(4), 8) }}, + testcase{"Uint64Slot", func() bool { return t.MutateUint64Slot(calcVOffsetT(5), 10) }}, + testcase{"Int8Slot", func() bool { return t.MutateInt8Slot(calcVOffsetT(6), 12) }}, + testcase{"Int16Slot", func() bool { return t.MutateInt16Slot(calcVOffsetT(7), 14) }}, + testcase{"Int32Slot", func() bool { return t.MutateInt32Slot(calcVOffsetT(8), 16) }}, + testcase{"Int64Slot", func() bool { return t.MutateInt64Slot(calcVOffsetT(9), 18) }}, + testcase{"Float32Slot", func() bool { return t.MutateFloat32Slot(calcVOffsetT(10), 20) }}, + testcase{"Float64Slot", func() bool { return t.MutateFloat64Slot(calcVOffsetT(11), 22) }}, + testcase{"UOffsetTSlot", func() bool { return t.MutateUOffsetT(calcUOffsetT(calcVOffsetT(12)), 24) }}, + testcase{"VOffsetTSlot", func() bool { return t.MutateVOffsetT(calcUOffsetT(calcVOffsetT(13)), 26) }}, + testcase{"SOffsetTSlot", func() bool { return t.MutateSOffsetT(calcUOffsetT(calcVOffsetT(14)), 28) }}, + } + + testMutabilityWithoutSlot := []testcase{ + testcase{"BoolSlot", func() bool { return t.MutateBoolSlot(calcVOffsetT(16), false) }}, + testcase{"ByteSlot", func() bool { return t.MutateByteSlot(calcVOffsetT(16), 2) }}, + testcase{"Uint8Slot", func() bool { return t.MutateUint8Slot(calcVOffsetT(16), 2) }}, + testcase{"Uint16Slot", func() bool { return t.MutateUint16Slot(calcVOffsetT(16), 2) }}, + testcase{"Uint32Slot", func() bool { return t.MutateUint32Slot(calcVOffsetT(16), 2) }}, + testcase{"Uint64Slot", func() bool { return t.MutateUint64Slot(calcVOffsetT(16), 2) }}, + testcase{"Int8Slot", func() bool { return t.MutateInt8Slot(calcVOffsetT(16), 2) }}, + testcase{"Int16Slot", func() bool { return t.MutateInt16Slot(calcVOffsetT(16), 2) }}, + testcase{"Int32Slot", func() bool { return t.MutateInt32Slot(calcVOffsetT(16), 2) }}, + testcase{"Int64Slot", func() bool { return t.MutateInt64Slot(calcVOffsetT(16), 2) }}, + testcase{"Float32Slot", func() bool { return t.MutateFloat32Slot(calcVOffsetT(16), 2) }}, + testcase{"Float64Slot", func() bool { return t.MutateFloat64Slot(calcVOffsetT(16), 2) }}, + } + + testForMutatedValues := []testcase{ + testcase{"BoolSlot", func() bool { return t.GetBoolSlot(calcVOffsetT(0), true) == false }}, + testcase{"ByteSlot", func() bool { return t.GetByteSlot(calcVOffsetT(1), 1) == 2 }}, + testcase{"Uint8Slot", func() bool { return t.GetUint8Slot(calcVOffsetT(2), 1) == 4 }}, + testcase{"Uint16Slot", func() bool { return t.GetUint16Slot(calcVOffsetT(3), 1) == 6 }}, + testcase{"Uint32Slot", func() bool { return t.GetUint32Slot(calcVOffsetT(4), 1) == 8 }}, + testcase{"Uint64Slot", func() bool { return t.GetUint64Slot(calcVOffsetT(5), 1) == 10 }}, + testcase{"Int8Slot", func() bool { return t.GetInt8Slot(calcVOffsetT(6), 1) == 12 }}, + testcase{"Int16Slot", func() bool { return t.GetInt16Slot(calcVOffsetT(7), 1) == 14 }}, + testcase{"Int32Slot", func() bool { return t.GetInt32Slot(calcVOffsetT(8), 1) == 16 }}, + testcase{"Int64Slot", func() bool { return t.GetInt64Slot(calcVOffsetT(9), 1) == 18 }}, + testcase{"Float32Slot", func() bool { return t.GetFloat32Slot(calcVOffsetT(10), 1) == 20 }}, + testcase{"Float64Slot", func() bool { return t.GetFloat64Slot(calcVOffsetT(11), 1) == 22 }}, + testcase{"UOffsetTSlot", func() bool { return t.GetUOffsetT(calcUOffsetT(calcVOffsetT(12))) == 24 }}, + testcase{"VOffsetTSlot", func() bool { return t.GetVOffsetT(calcUOffsetT(calcVOffsetT(13))) == 26 }}, + testcase{"SOffsetTSlot", func() bool { return t.GetSOffsetT(calcUOffsetT(calcVOffsetT(14))) == 28 }}, + } + + // make sure original values are okay + for _, t := range testForOriginalValues { + if !t.testfn() { + fail(t.field + "' field doesn't have the expected original value") + } + } + + // try to mutate fields and check mutability + for _, t := range testMutability { + if !t.testfn() { + fail(FailString(t.field+"' field failed mutability test", "passed", "failed")) + } + } + + // try to mutate fields and check mutability + // these have wrong slots so should fail + for _, t := range testMutabilityWithoutSlot { + if t.testfn() { + fail(FailString(t.field+"' field failed no slot mutability test", "failed", "passed")) + } + } + + // test whether values have changed + for _, t := range testForMutatedValues { + if !t.testfn() { + fail(t.field + "' field doesn't have the expected mutated value") + } + } +} + // BenchmarkVtableDeduplication measures the speed of vtable deduplication // by creating prePop vtables, then populating b.N objects with a // different single vtable. From ce3e7fbd72191da6602e910818c46018df08a515 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 20 Jul 2016 10:41:26 -0700 Subject: [PATCH 12/13] VS2010 fixes --- build_ide/VS2010/flatc.vcxproj | 10 ++++++---- include/flatbuffers/flatbuffers.h | 2 +- src/idl_gen_general.cpp | 5 +++-- src/idl_gen_grpc.cpp | 1 + tests/test.cpp | 6 ++++-- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/build_ide/VS2010/flatc.vcxproj b/build_ide/VS2010/flatc.vcxproj index 31cd01345..5aef2384a 100755 --- a/build_ide/VS2010/flatc.vcxproj +++ b/build_ide/VS2010/flatc.vcxproj @@ -81,7 +81,7 @@ - ../../include;%(AdditionalIncludeDirectories) + ../../include;../../grpc;%(AdditionalIncludeDirectories) EnableFastChecks CompileAsCpp ProgramDatabase @@ -127,7 +127,7 @@ - ../../include;%(AdditionalIncludeDirectories) + ../../include;../../grpc;%(AdditionalIncludeDirectories) EnableFastChecks CompileAsCpp ProgramDatabase @@ -173,7 +173,7 @@ - ../../include;%(AdditionalIncludeDirectories) + ../../include;../../grpc;%(AdditionalIncludeDirectories) CompileAsCpp Sync AnySuitable @@ -219,7 +219,7 @@ - ../../include;%(AdditionalIncludeDirectories) + ../../include;../../grpc;%(AdditionalIncludeDirectories) CompileAsCpp Sync AnySuitable @@ -263,6 +263,8 @@ + + diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 01ab6db04..4cf1c0b48 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1351,7 +1351,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS { size_t GetComputedSize() const { uintptr_t size = upper_bound_ - buf_; // Align the size to uoffset_t - size = (size - 1 + sizeof(uoffset_t)) & -uintptr_t(sizeof(uoffset_t)); + size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1); return (buf_ + size > end_) ? 0 : size; } #endif diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 34ca2c3e4..7e8e8c577 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -197,6 +197,7 @@ class GeneralGenerator : public BaseGenerator { lang_(language_parameters[parser_.opts.lang]) { assert(parser_.opts.lang <= IDLOptions::kMAX); }; + GeneralGenerator &operator=(const GeneralGenerator &); bool generate() { std::string one_file_code; @@ -235,7 +236,7 @@ class GeneralGenerator : public BaseGenerator { // Save out the generated code for a single class while adding // declaration boilerplate. - bool SaveType(const std::string &defname, const Namespace &ns, + bool SaveType(const std::string &defname, const Namespace &ns, const std::string &classcode, bool needs_includes) { if (!classcode.length()) return true; @@ -1133,7 +1134,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) { // Java does not need the closing semi-colon on class definitions. code += (lang_.language != IDLOptions::kJava) ? ";" : ""; code += "\n\n"; -} +} const LanguageParameters & lang_; }; } // namespace general diff --git a/src/idl_gen_grpc.cpp b/src/idl_gen_grpc.cpp index 2bf0e911d..6ada3e873 100644 --- a/src/idl_gen_grpc.cpp +++ b/src/idl_gen_grpc.cpp @@ -137,6 +137,7 @@ class FlatBufFile : public grpc_cpp_generator::File { public: FlatBufFile(const Parser &parser, const std::string &file_name) : parser_(parser), file_name_(file_name) {} + FlatBufFile &operator=(const FlatBufFile &); std::string filename() const { return file_name_; } std::string filename_without_ext() const { diff --git a/tests/test.cpp b/tests/test.cpp index 402843a6f..70a07d480 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -124,7 +124,9 @@ flatbuffers::unique_ptr_t CreateFlatBufferTest(std::string &buffer) { }); // Creating vectors of strings in one convenient call. - std::vector names2 = { "jane", "mary" }; + std::vector names2; + names2.push_back("jane"); + names2.push_back("mary"); auto vecofstrings2 = builder.CreateVectorOfStrings(names2); // Create an array of sorted tables, can be used with binary search when read: @@ -855,7 +857,7 @@ void ValueTest() { // Test conversion functions. TEST_EQ(FloatCompare(TestValue("{ Y:cos(rad(180)) }","float"), -1), true); - + // Test negative hex constant. TEST_EQ(TestValue("{ Y:-0x80 }","int") == -128, true); } From 694725beb0efa448841348bcf36bae5c483f291d Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Wed, 20 Jul 2016 10:48:37 -0700 Subject: [PATCH 13/13] Xcode fixes --- .../FlatBuffers.xcodeproj/project.pbxproj | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/build_ide/Xcode/FlatBuffers.xcodeproj/project.pbxproj b/build_ide/Xcode/FlatBuffers.xcodeproj/project.pbxproj index ee18e9e29..e67f73565 100644 --- a/build_ide/Xcode/FlatBuffers.xcodeproj/project.pbxproj +++ b/build_ide/Xcode/FlatBuffers.xcodeproj/project.pbxproj @@ -11,10 +11,12 @@ 5AC48C391ACA9A0A008132C5 /* idl_gen_general.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */; }; 61823BBC53544106B6DBC38E /* idl_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3709AC883348409592530AE6 /* idl_parser.cpp */; settings = {COMPILER_FLAGS = ""; }; }; 61FF3C34FBEC4819A1C30F92 /* sample_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECCEBFFA6977404F858F9739 /* sample_text.cpp */; settings = {COMPILER_FLAGS = ""; }; }; - 8C2AAE0A1CB338A8000CC78D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2AAE091CB338A8000CC78D /* util.cpp */; settings = {ASSET_TAGS = (); }; }; - 8C2AAE0B1CB338CD000CC78D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2AAE091CB338A8000CC78D /* util.cpp */; settings = {ASSET_TAGS = (); }; }; - 8C2AAE0C1CB338CE000CC78D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2AAE091CB338A8000CC78D /* util.cpp */; settings = {ASSET_TAGS = (); }; }; + 8C2AAE0A1CB338A8000CC78D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2AAE091CB338A8000CC78D /* util.cpp */; }; + 8C2AAE0B1CB338CD000CC78D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2AAE091CB338A8000CC78D /* util.cpp */; }; + 8C2AAE0C1CB338CE000CC78D /* util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C2AAE091CB338A8000CC78D /* util.cpp */; }; 8C303C591975D6A700D7C1C5 /* idl_gen_go.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C303C581975D6A700D7C1C5 /* idl_gen_go.cpp */; }; + 8C547D661D3FF05C00AE7A25 /* idl_gen_grpc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C547D651D3FF05C00AE7A25 /* idl_gen_grpc.cpp */; }; + 8C547D681D3FF07D00AE7A25 /* cpp_generator.cc in Sources */ = {isa = PBXBuildFile; fileRef = 8C547D671D3FF07D00AE7A25 /* cpp_generator.cc */; }; 8C6905FD19F835B400CB8866 /* idl_gen_fbs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C6905EC19F8357300CB8866 /* idl_gen_fbs.cpp */; }; 8C78573E1BD5AE2C00C53C34 /* idl_gen_js.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C78573D1BD5AE2C00C53C34 /* idl_gen_js.cpp */; }; 8C8774631B703D4800E693F5 /* reflection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C8774621B703D4800E693F5 /* reflection.cpp */; }; @@ -43,6 +45,8 @@ 6AD24EEB3D024825A37741FF /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test.cpp; path = tests/test.cpp; sourceTree = SOURCE_ROOT; }; 8C2AAE091CB338A8000CC78D /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = util.cpp; path = src/util.cpp; sourceTree = ""; }; 8C303C581975D6A700D7C1C5 /* idl_gen_go.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_go.cpp; path = src/idl_gen_go.cpp; sourceTree = ""; }; + 8C547D651D3FF05C00AE7A25 /* idl_gen_grpc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_grpc.cpp; path = src/idl_gen_grpc.cpp; sourceTree = ""; }; + 8C547D671D3FF07D00AE7A25 /* cpp_generator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cpp_generator.cc; path = grpc/src/compiler/cpp_generator.cc; sourceTree = ""; }; 8C6905EC19F8357300CB8866 /* idl_gen_fbs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_fbs.cpp; path = src/idl_gen_fbs.cpp; sourceTree = ""; }; 8C78573D1BD5AE2C00C53C34 /* idl_gen_js.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_js.cpp; path = src/idl_gen_js.cpp; sourceTree = ""; }; 8C8774621B703D4800E693F5 /* reflection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = reflection.cpp; path = src/reflection.cpp; sourceTree = ""; }; @@ -62,6 +66,8 @@ 28237E300FE042DEADA302D3 /* Source Files */ = { isa = PBXGroup; children = ( + 8C547D671D3FF07D00AE7A25 /* cpp_generator.cc */, + 8C547D651D3FF05C00AE7A25 /* idl_gen_grpc.cpp */, 8C2AAE091CB338A8000CC78D /* util.cpp */, D2DA271C1BFFBC06000F9168 /* idl_gen_php.cpp */, 8C78573D1BD5AE2C00C53C34 /* idl_gen_js.cpp */, @@ -267,12 +273,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8C547D681D3FF07D00AE7A25 /* cpp_generator.cc in Sources */, 8C303C591975D6A700D7C1C5 /* idl_gen_go.cpp in Sources */, AA9BACF55EB3456BA2F633BB /* flatc.cpp in Sources */, BE03D7B0C9584DD58B50ED34 /* idl_gen_cpp.cpp in Sources */, AD71FEBEE4E846529002C1F0 /* idl_gen_text.cpp in Sources */, 8C2AAE0A1CB338A8000CC78D /* util.cpp in Sources */, 8C8774641B703E1200E693F5 /* idl_gen_fbs.cpp in Sources */, + 8C547D661D3FF05C00AE7A25 /* idl_gen_grpc.cpp in Sources */, A9C9A99F719A4ED58DC2D2FC /* idl_parser.cpp in Sources */, 8CA854B31B04244A00040A06 /* idl_gen_python.cpp in Sources */, 8CD8717B19CB937D0012A827 /* idl_gen_general.cpp in Sources */, @@ -715,7 +723,10 @@ GCC_OPTIMIZATION_LEVEL = 3; GCC_PREPROCESSOR_DEFINITIONS = "'CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"'"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; - HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/include", + "$(PROJECT_DIR)/grpc", + ); INSTALL_PATH = ""; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = ( @@ -754,7 +765,10 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = "'CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"'"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; - HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/include", + "$(PROJECT_DIR)/grpc", + ); INSTALL_PATH = ""; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = " -std=c++0x"; @@ -787,7 +801,10 @@ GCC_OPTIMIZATION_LEVEL = 2; GCC_PREPROCESSOR_DEFINITIONS = "'CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"'"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; - HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/include", + "$(PROJECT_DIR)/grpc", + ); INSTALL_PATH = ""; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = ( @@ -919,7 +936,10 @@ GCC_OPTIMIZATION_LEVEL = s; GCC_PREPROCESSOR_DEFINITIONS = "'CMAKE_INTDIR=\"$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)\"'"; GCC_SYMBOLS_PRIVATE_EXTERN = NO; - HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include"; + HEADER_SEARCH_PATHS = ( + "$(PROJECT_DIR)/include", + "$(PROJECT_DIR)/grpc", + ); INSTALL_PATH = ""; LIBRARY_SEARCH_PATHS = ""; OTHER_CFLAGS = (