mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-13 16:15:26 +00:00
Merge remote-tracking branch 'refs/remotes/google/master'
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@@ -40,6 +40,8 @@ flatsamplebinary
|
||||
flatsamplebinary.exe
|
||||
flatsampletext
|
||||
flatsampletext.exe
|
||||
grpctest
|
||||
grpctest.exe
|
||||
snapshot.sh
|
||||
tests/go_gen
|
||||
tests/monsterdata_java_wire.mon
|
||||
@@ -55,9 +57,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
|
||||
|
||||
@@ -6,8 +6,10 @@ project(FlatBuffers)
|
||||
option(FLATBUFFERS_CODE_COVERAGE "Enable the code coverage build option." OFF)
|
||||
option(FLATBUFFERS_BUILD_TESTS "Enable the build of tests and samples." ON)
|
||||
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_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)
|
||||
|
||||
@@ -95,7 +97,8 @@ set(FlatBuffers_GRPCTest_SRCS
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -Wall -pedantic -Werror -Wextra")
|
||||
"${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++ -Wall -pedantic -Werror \
|
||||
-Wextra")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CYGWIN)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
@@ -118,7 +121,8 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
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")
|
||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
|
||||
@@ -165,7 +169,9 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable -o "${SRC_FBS_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||
--gen-object-api -o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
endfunction()
|
||||
|
||||
@@ -174,7 +180,8 @@ function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
||||
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BINARY_SCHEMA}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -b --schema -o "${SRC_FBS_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -b --schema -o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
endfunction()
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../include;../../grpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@@ -127,7 +127,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../include;../../grpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
@@ -173,7 +173,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../include;../../grpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
@@ -219,7 +219,7 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../include;../../grpc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
@@ -263,6 +263,8 @@
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\grpc\src\compiler\cpp_generator.cc" />
|
||||
<ClCompile Include="..\..\src\idl_gen_grpc.cpp" />
|
||||
<ClCompile Include="..\..\src\util.cpp" />
|
||||
<ClInclude Include="..\..\include\flatbuffers\flatbuffers.h" />
|
||||
<ClInclude Include="..\..\include\flatbuffers\idl.h" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerWorkingDirectory>..\..\tests</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommandArguments>-j -c -n -g --php --no-includes --gen-mutable monster_test.fbs</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>-j -c -n -g --php --no-includes --gen-mutable --gen-object-api monster_test.fbs</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LocalDebuggerWorkingDirectory>..\..</LocalDebuggerWorkingDirectory>
|
||||
|
||||
@@ -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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
8C547D671D3FF07D00AE7A25 /* cpp_generator.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cpp_generator.cc; path = grpc/src/compiler/cpp_generator.cc; sourceTree = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
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 = "<group>"; };
|
||||
8C8774621B703D4800E693F5 /* reflection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = reflection.cpp; path = src/reflection.cpp; sourceTree = "<group>"; };
|
||||
@@ -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 = (
|
||||
|
||||
@@ -81,6 +81,11 @@ Additional options:
|
||||
- `--gen-mutable` : Generate additional non-const accessors for mutating
|
||||
FlatBuffers in-place.
|
||||
|
||||
`--gen-object-api` : Generate an additional object-based API. This API is
|
||||
more convenient for object construction and mutation than the base API,
|
||||
at the cost of efficiency (object allocation). Recommended only to be used
|
||||
if other options are insufficient.
|
||||
|
||||
- `--gen-onefile` : Generate single output file (useful for C#)
|
||||
|
||||
- `--gen-all`: Generate not just code for the current schema files, but
|
||||
@@ -103,5 +108,9 @@ Additional options:
|
||||
to the reflection/reflection.fbs schema. Loading this binary file is the
|
||||
basis for reflection functionality.
|
||||
|
||||
- `--conform FILE` : Specify a schema the following schemas should be
|
||||
an evolution of. Gives errors if not. Useful to check if schema
|
||||
modifications don't break schema evolution rules.
|
||||
|
||||
NOTE: short-form options for generators are deprecated, use the long form
|
||||
whenever possible.
|
||||
|
||||
@@ -85,6 +85,27 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||
|
||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
||||
|
||||
## Object based API.
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
around using as little as possible of it. This does make the API clumsier
|
||||
(requiring pre-order construction of all data, and making mutation harder).
|
||||
|
||||
For times when efficiency is less important a more convenient object based API
|
||||
can be used (through `--gen-object-api`) that is able to unpack & pack a
|
||||
FlatBuffer into objects and standard STL containers, allowing for convenient
|
||||
construction, access and mutation.
|
||||
|
||||
To use:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
auto monsterobj = GetMonster(buffer)->UnPack();
|
||||
cout << monsterobj->name; // This is now a std::string!
|
||||
monsterobj->name = "Bob"; // Change the name.
|
||||
FlatBufferBuilder fbb;
|
||||
monsterobj->Pack(fbb); // Serialize into new buffer.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Reflection (& Resizing)
|
||||
|
||||
There is experimental support for reflection in FlatBuffers, allowing you to
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
@@ -1881,6 +1881,9 @@ One way to solve this is to call `ForceDefaults` on a FlatBufferBuilder to
|
||||
force all fields you set to actually be written. This, of course, increases the
|
||||
size of the buffer somewhat, but this may be acceptable for a mutable buffer.
|
||||
|
||||
If this is not sufficient, other ways of mutating FlatBuffers may be supported
|
||||
in your language through an object based API (`--gen-object-api`) or reflection.
|
||||
See the individual language documents for support.
|
||||
|
||||
## JSON with FlatBuffers
|
||||
|
||||
|
||||
210
go/table.go
210
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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -24,13 +24,20 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#ifdef _STLPORT_VERSION
|
||||
#define FLATBUFFERS_CPP98_STL
|
||||
#endif
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
#if __cplusplus <= 199711L && \
|
||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||
@@ -123,9 +130,11 @@ typedef uintmax_t largest_scalar_t;
|
||||
// In 32bits, this evaluates to 2GB - 1
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
// Pointer to relinquished memory.
|
||||
typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * /* unused */)>>
|
||||
unique_ptr_t;
|
||||
#endif
|
||||
|
||||
// Wrapper for uoffset_t to allow safe template specialization.
|
||||
template<typename T> struct Offset {
|
||||
@@ -234,23 +243,19 @@ template<typename T> struct IndirectHelper<const T *> {
|
||||
|
||||
// An STL compatible iterator implementation for Vector below, effectively
|
||||
// calling Get() for every element.
|
||||
template<typename T, bool bConst>
|
||||
struct VectorIterator : public
|
||||
std::iterator < std::input_iterator_tag,
|
||||
typename std::conditional < bConst,
|
||||
const typename IndirectHelper<T>::return_type,
|
||||
typename IndirectHelper<T>::return_type > ::type, uoffset_t > {
|
||||
template<typename T, typename IT>
|
||||
struct VectorIterator
|
||||
: public std::iterator<std::input_iterator_tag, IT, uoffset_t> {
|
||||
|
||||
typedef std::iterator<std::input_iterator_tag,
|
||||
typename std::conditional<bConst,
|
||||
const typename IndirectHelper<T>::return_type,
|
||||
typename IndirectHelper<T>::return_type>::type, uoffset_t> super_type;
|
||||
typedef std::iterator<std::input_iterator_tag, IT, uoffset_t> super_type;
|
||||
|
||||
public:
|
||||
VectorIterator(const uint8_t *data, uoffset_t i) :
|
||||
data_(data + IndirectHelper<T>::element_stride * i) {};
|
||||
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
|
||||
#endif
|
||||
|
||||
VectorIterator &operator=(const VectorIterator &other) {
|
||||
data_ = other.data_;
|
||||
@@ -288,7 +293,7 @@ public:
|
||||
}
|
||||
|
||||
VectorIterator operator++(int) {
|
||||
VectorIterator temp(data_);
|
||||
VectorIterator temp(data_,0);
|
||||
data_ += IndirectHelper<T>::element_stride;
|
||||
return temp;
|
||||
}
|
||||
@@ -301,8 +306,10 @@ private:
|
||||
// Vector::data() assumes the vector elements start after the length field.
|
||||
template<typename T> class Vector {
|
||||
public:
|
||||
typedef VectorIterator<T, false> iterator;
|
||||
typedef VectorIterator<T, true> const_iterator;
|
||||
typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
|
||||
iterator;
|
||||
typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
|
||||
const_iterator;
|
||||
|
||||
uoffset_t size() const { return EndianScalar(length_); }
|
||||
|
||||
@@ -471,6 +478,7 @@ class vector_downward {
|
||||
cur_ = buf_ + reserved_;
|
||||
}
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
// Relinquish the pointer to the caller.
|
||||
unique_ptr_t release() {
|
||||
// Actually deallocate from the start of the allocated memory.
|
||||
@@ -486,6 +494,7 @@ class vector_downward {
|
||||
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t growth_policy(size_t bytes) {
|
||||
return (bytes / 2) & ~(sizeof(largest_scalar_t) - 1);
|
||||
@@ -562,6 +571,10 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) {
|
||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||
}
|
||||
|
||||
template <typename T> const T* data(const std::vector<T> &v) {
|
||||
return v.empty() ? nullptr : &v.front();
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
/// @addtogroup flatbuffers_cpp_api
|
||||
@@ -627,6 +640,7 @@ FLATBUFFERS_FINAL_CLASS
|
||||
/// @return Returns a `uint8_t` pointer to the unfinished buffer.
|
||||
uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
/// @brief Get the released pointer to the serialized buffer.
|
||||
/// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
|
||||
/// @return The `unique_ptr` returned has a special allocator that knows how
|
||||
@@ -637,6 +651,7 @@ FLATBUFFERS_FINAL_CLASS
|
||||
Finished();
|
||||
return buf_.release();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
void Finished() const {
|
||||
@@ -674,11 +689,13 @@ FLATBUFFERS_FINAL_CLASS
|
||||
void PopBytes(size_t amount) { buf_.pop(amount); }
|
||||
|
||||
template<typename T> void AssertScalarT() {
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
// The code assumes power of 2 sizes and endian-swap-ability.
|
||||
static_assert(std::is_scalar<T>::value
|
||||
// The Offset<T> type is essentially a scalar but fails is_scalar.
|
||||
|| sizeof(T) == sizeof(Offset<void>),
|
||||
"T must be a scalar type");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Write a single aligned scalar to the buffer
|
||||
@@ -876,7 +893,7 @@ FLATBUFFERS_FINAL_CLASS
|
||||
/// @param[in] str A const pointer to a `String` struct to add to the buffer.
|
||||
/// @return Returns the offset in the buffer where the string starts
|
||||
Offset<String> CreateString(const String *str) {
|
||||
return CreateString(str->c_str(), str->Length());
|
||||
return str ? CreateString(str->c_str(), str->Length()) : 0;
|
||||
}
|
||||
|
||||
/// @brief Store a string in the buffer, which can contain any binary data.
|
||||
@@ -981,9 +998,21 @@ FLATBUFFERS_FINAL_CLASS
|
||||
/// @return Returns a typed `Offset` into the serialized data indicating
|
||||
/// where the vector is stored.
|
||||
template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
|
||||
return CreateVector(v.data(), v.size());
|
||||
return CreateVector(data(v), v.size());
|
||||
}
|
||||
|
||||
// vector<bool> may be implemented using a bit-set, so we can't access it as
|
||||
// an array. Instead, read elements manually.
|
||||
// Background: https://isocpp.org/blog/2012/11/on-vectorbool
|
||||
Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
|
||||
StartVector(v.size(), sizeof(uint8_t));
|
||||
for (auto i = v.size(); i > 0; ) {
|
||||
PushElement(static_cast<uint8_t>(v[--i]));
|
||||
}
|
||||
return Offset<Vector<uint8_t>>(EndVector(v.size()));
|
||||
}
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
/// @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.
|
||||
@@ -995,8 +1024,9 @@ FLATBUFFERS_FINAL_CLASS
|
||||
const std::function<T (size_t i)> &f) {
|
||||
std::vector<T> elems(vector_size);
|
||||
for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
|
||||
return CreateVector(elems.data(), elems.size());
|
||||
return CreateVector(elems);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
|
||||
/// This is a convenience function for a common case.
|
||||
@@ -1008,7 +1038,7 @@ FLATBUFFERS_FINAL_CLASS
|
||||
const std::vector<std::string> &v) {
|
||||
std::vector<Offset<String>> offsets(v.size());
|
||||
for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
|
||||
return CreateVector(offsets.data(), offsets.size());
|
||||
return CreateVector(offsets);
|
||||
}
|
||||
|
||||
/// @brief Serialize an array of structs into a FlatBuffer `vector`.
|
||||
@@ -1033,7 +1063,7 @@ FLATBUFFERS_FINAL_CLASS
|
||||
/// where the vector is stored.
|
||||
template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
|
||||
const std::vector<T> &v) {
|
||||
return CreateVectorOfStructs(v.data(), v.size());
|
||||
return CreateVectorOfStructs(data(v), v.size());
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
@@ -1216,6 +1246,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
size_t _max_tables = 1000000)
|
||||
: buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
|
||||
num_tables_(0), max_tables_(_max_tables)
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
, upper_bound_(buf)
|
||||
#endif
|
||||
{}
|
||||
|
||||
// Central location where any verification failures register.
|
||||
@@ -1223,11 +1256,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
|
||||
assert(ok);
|
||||
#endif
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
if (!ok)
|
||||
upper_bound_ = buf_;
|
||||
#endif
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Verify any range within the buffer.
|
||||
bool Verify(const void *elem, size_t elem_len) const {
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len;
|
||||
if (upper_bound_ < upper_bound)
|
||||
upper_bound_ = upper_bound;
|
||||
#endif
|
||||
return Check(elem_len <= (size_t) (end_ - buf_) &&
|
||||
elem >= buf_ &&
|
||||
elem <= end_ - elem_len);
|
||||
@@ -1302,11 +1344,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
}
|
||||
|
||||
// Verify this whole buffer, starting with root type T.
|
||||
template<typename T> bool VerifyBuffer() {
|
||||
template<typename T> bool VerifyBuffer(const char *identifier) {
|
||||
if (identifier && (size_t(end_ - buf_) < 2 * sizeof(flatbuffers::uoffset_t) ||
|
||||
!BufferHasIdentifier(buf_, identifier))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call T::Verify, which must be in the generated code for this type.
|
||||
return Verify<uoffset_t>(buf_) &&
|
||||
reinterpret_cast<const T *>(buf_ + ReadScalar<uoffset_t>(buf_))->
|
||||
Verify(*this);
|
||||
Verify(*this)
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
&& GetComputedSize()
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
// Called at the start of a table to increase counters measuring data
|
||||
@@ -1325,6 +1376,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
// Returns the message size in bytes
|
||||
size_t GetComputedSize() const {
|
||||
uintptr_t size = upper_bound_ - buf_;
|
||||
// Align the size to uoffset_t
|
||||
size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
|
||||
return (buf_ + size > end_) ? 0 : size;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
const uint8_t *buf_;
|
||||
const uint8_t *end_;
|
||||
@@ -1332,6 +1393,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
size_t max_depth_;
|
||||
size_t num_tables_;
|
||||
size_t max_tables_;
|
||||
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
mutable const uint8_t *upper_bound_;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Convenient way to bundle a buffer and its length, to pass it around
|
||||
@@ -1489,6 +1553,12 @@ class Table {
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
// Base class for native objects (FlatBuffer data de-serialized into native
|
||||
// C++ data structures).
|
||||
// Contains no functionality, purely documentative.
|
||||
struct NativeTable {
|
||||
};
|
||||
|
||||
// Helper function to test if a field is present, using any of the field
|
||||
// enums in the generated code.
|
||||
// `table` must be a generated table type. Since this is a template parameter,
|
||||
|
||||
@@ -311,6 +311,14 @@ struct EnumDef : public Definition {
|
||||
Type underlying_type;
|
||||
};
|
||||
|
||||
inline bool EqualByName(const Type &a, const Type &b) {
|
||||
return a.base_type == b.base_type && a.element == b.element &&
|
||||
(a.struct_def == b.struct_def ||
|
||||
a.struct_def->name == b.struct_def->name) &&
|
||||
(a.enum_def == b.enum_def ||
|
||||
a.enum_def->name == b.enum_def->name);
|
||||
}
|
||||
|
||||
struct RPCCall {
|
||||
std::string name;
|
||||
SymbolTable<Value> attributes;
|
||||
@@ -338,7 +346,8 @@ struct IDLOptions {
|
||||
bool skip_unexpected_fields_in_json;
|
||||
bool generate_name_strings;
|
||||
bool escape_proto_identifiers;
|
||||
|
||||
bool generate_object_based_api;
|
||||
|
||||
// Possible options for the more general generator below.
|
||||
enum Language { kJava, kCSharp, kGo, kMAX };
|
||||
|
||||
@@ -358,6 +367,7 @@ struct IDLOptions {
|
||||
skip_unexpected_fields_in_json(false),
|
||||
generate_name_strings(false),
|
||||
escape_proto_identifiers(false),
|
||||
generate_object_based_api(false),
|
||||
lang(IDLOptions::kJava) {}
|
||||
};
|
||||
|
||||
@@ -471,6 +481,10 @@ class Parser : public ParserState {
|
||||
// See reflection/reflection.fbs
|
||||
void Serialize();
|
||||
|
||||
// Checks that the schema represented by this parser is a safe evolution
|
||||
// of the schema provided. Returns non-empty error on any problems.
|
||||
std::string ConformTo(const Parser &base);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR CheckBitsFit(int64_t val, size_t bits);
|
||||
|
||||
private:
|
||||
|
||||
@@ -370,6 +370,7 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
|
||||
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
|
||||
const reflection::Object *root_table = nullptr);
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
template <typename T>
|
||||
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
||||
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
|
||||
@@ -391,6 +392,7 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Adds any new data (in the form of a new FlatBuffer) to an existing
|
||||
// FlatBuffer. This can be used when any of the above methods are not
|
||||
|
||||
@@ -478,12 +478,12 @@ inline flatbuffers::Offset<Schema> CreateSchema(flatbuffers::FlatBufferBuilder &
|
||||
|
||||
inline const reflection::Schema *GetSchema(const void *buf) { return flatbuffers::GetRoot<reflection::Schema>(buf); }
|
||||
|
||||
inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<reflection::Schema>(); }
|
||||
|
||||
inline const char *SchemaIdentifier() { return "BFBS"; }
|
||||
|
||||
inline bool SchemaBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier()); }
|
||||
|
||||
inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier()); }
|
||||
|
||||
inline const char *SchemaExtension() { return "bfbs"; }
|
||||
|
||||
inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<reflection::Schema> root) { fbb.Finish(root, SchemaIdentifier()); }
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
/// @addtogroup flatbuffers_javascript_api
|
||||
/// @{
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
/**
|
||||
* @const
|
||||
* @namespace
|
||||
*/
|
||||
var flatbuffers = {};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 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 handling 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);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-java</artifactId>
|
||||
<version>1.3.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<packaging>bundle</packaging>
|
||||
<name>FlatBuffers Java API</name>
|
||||
<description>
|
||||
Memory Efficient Serialization Library
|
||||
@@ -33,7 +33,7 @@
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
<build>
|
||||
<sourceDirectory>./</sourceDirectory>
|
||||
<sourceDirectory>java</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
@@ -78,6 +78,12 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<extensions>true</extensions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -46,7 +46,7 @@ you would leave it in.
|
||||
|
||||
<br>
|
||||
|
||||
[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
|
||||
|
||||
@@ -11,8 +11,10 @@ namespace Sample {
|
||||
struct Vec3;
|
||||
|
||||
struct Monster;
|
||||
struct MonsterT;
|
||||
|
||||
struct Weapon;
|
||||
struct WeaponT;
|
||||
|
||||
enum Color {
|
||||
Color_Red = 0,
|
||||
@@ -36,6 +38,21 @@ enum Equipment {
|
||||
Equipment_MAX = Equipment_Weapon
|
||||
};
|
||||
|
||||
struct EquipmentUnion {
|
||||
Equipment type;
|
||||
|
||||
flatbuffers::NativeTable *table;
|
||||
EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
|
||||
EquipmentUnion(const EquipmentUnion &);
|
||||
EquipmentUnion &operator=(const EquipmentUnion &);
|
||||
~EquipmentUnion();
|
||||
|
||||
static flatbuffers::NativeTable *UnPack(const void *union_obj, Equipment type);
|
||||
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb) const;
|
||||
|
||||
WeaponT *AsWeapon() { return type == Equipment_Weapon ? reinterpret_cast<WeaponT *>(table) : nullptr; }
|
||||
};
|
||||
|
||||
inline const char **EnumNamesEquipment() {
|
||||
static const char *names[] = { "NONE", "Weapon", nullptr };
|
||||
return names;
|
||||
@@ -52,6 +69,8 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||
float z_;
|
||||
|
||||
public:
|
||||
Vec3() { memset(this, 0, sizeof(Vec3)); }
|
||||
Vec3(const Vec3 &_o) { memcpy(this, &_o, sizeof(Vec3)); }
|
||||
Vec3(float _x, float _y, float _z)
|
||||
: x_(flatbuffers::EndianScalar(_x)), y_(flatbuffers::EndianScalar(_y)), z_(flatbuffers::EndianScalar(_z)) { }
|
||||
|
||||
@@ -64,6 +83,17 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||
};
|
||||
STRUCT_END(Vec3, 12);
|
||||
|
||||
struct MonsterT : public flatbuffers::NativeTable {
|
||||
std::unique_ptr<Vec3> pos;
|
||||
int16_t mana;
|
||||
int16_t hp;
|
||||
std::string name;
|
||||
std::vector<uint8_t> inventory;
|
||||
Color color;
|
||||
std::vector<std::unique_ptr<WeaponT>> weapons;
|
||||
EquipmentUnion equipped;
|
||||
};
|
||||
|
||||
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
VT_POS = 4,
|
||||
@@ -112,6 +142,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyEquipment(verifier, equipped(), equipped_type()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<MonsterT> UnPack() const;
|
||||
};
|
||||
|
||||
struct MonsterBuilder {
|
||||
@@ -135,15 +166,15 @@ struct MonsterBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0,
|
||||
Color color = Color_Blue,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons = 0,
|
||||
Equipment equipped_type = Equipment_NONE,
|
||||
flatbuffers::Offset<void> equipped = 0) {
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0,
|
||||
Color color = Color_Blue,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons = 0,
|
||||
Equipment equipped_type = Equipment_NONE,
|
||||
flatbuffers::Offset<void> equipped = 0) {
|
||||
MonsterBuilder builder_(_fbb);
|
||||
builder_.add_equipped(equipped);
|
||||
builder_.add_weapons(weapons);
|
||||
@@ -157,6 +188,26 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
const char *name = nullptr,
|
||||
const std::vector<uint8_t> *inventory = nullptr,
|
||||
Color color = Color_Blue,
|
||||
const std::vector<flatbuffers::Offset<Weapon>> *weapons = nullptr,
|
||||
Equipment equipped_type = Equipment_NONE,
|
||||
flatbuffers::Offset<void> equipped = 0) {
|
||||
return CreateMonster(_fbb, pos, mana, hp, name ? 0 : _fbb.CreateString(name), inventory ? 0 : _fbb.CreateVector<uint8_t>(*inventory), color, weapons ? 0 : _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons), equipped_type, equipped);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o);
|
||||
|
||||
struct WeaponT : public flatbuffers::NativeTable {
|
||||
std::string name;
|
||||
int16_t damage;
|
||||
};
|
||||
|
||||
struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
VT_NAME = 4,
|
||||
@@ -173,6 +224,7 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyField<int16_t>(verifier, VT_DAMAGE) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<WeaponT> UnPack() const;
|
||||
};
|
||||
|
||||
struct WeaponBuilder {
|
||||
@@ -189,14 +241,62 @@ struct WeaponBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
int16_t damage = 0) {
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
int16_t damage = 0) {
|
||||
WeaponBuilder builder_(_fbb);
|
||||
builder_.add_name(name);
|
||||
builder_.add_damage(damage);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
int16_t damage = 0) {
|
||||
return CreateWeapon(_fbb, name ? 0 : _fbb.CreateString(name), damage);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o);
|
||||
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
||||
auto _o = new MonsterT();
|
||||
{ auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
|
||||
{ auto _e = mana(); _o->mana = _e; };
|
||||
{ auto _e = hp(); _o->hp = _e; };
|
||||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = inventory(); if (_e) { for (size_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } } };
|
||||
{ auto _e = color(); _o->color = _e; };
|
||||
{ auto _e = weapons(); if (_e) { for (size_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(_e->Get(_i)->UnPack()); } } };
|
||||
{ auto _e = equipped_type(); _o->equipped.type = _e; };
|
||||
{ auto _e = equipped(); if (_e) _o->equipped.table = EquipmentUnion::UnPack(_e, equipped_type()); };
|
||||
return std::unique_ptr<MonsterT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o) {
|
||||
return CreateMonster(_fbb,
|
||||
_o->pos ? _o->pos.get() : 0,
|
||||
_o->mana,
|
||||
_o->hp,
|
||||
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
|
||||
_o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0,
|
||||
_o->color,
|
||||
_o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get()); }) : 0,
|
||||
_o->equipped.type,
|
||||
_o->equipped.Pack(_fbb));
|
||||
}
|
||||
|
||||
inline std::unique_ptr<WeaponT> Weapon::UnPack() const {
|
||||
auto _o = new WeaponT();
|
||||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = damage(); _o->damage = _e; };
|
||||
return std::unique_ptr<WeaponT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o) {
|
||||
return CreateWeapon(_fbb,
|
||||
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
|
||||
_o->damage);
|
||||
}
|
||||
|
||||
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type) {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return true;
|
||||
@@ -205,11 +305,34 @@ inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_o
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *union_obj, Equipment type) {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return nullptr;
|
||||
case Equipment_Weapon: return reinterpret_cast<const Weapon *>(union_obj)->UnPack().release();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb) const {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return 0;
|
||||
case Equipment_Weapon: return CreateWeapon(_fbb, reinterpret_cast<const WeaponT *>(table)).Union();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline EquipmentUnion::~EquipmentUnion() {
|
||||
switch (type) {
|
||||
case Equipment_Weapon: delete reinterpret_cast<WeaponT *>(table); break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf); }
|
||||
|
||||
inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); }
|
||||
|
||||
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Sample::Monster>(); }
|
||||
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Sample::Monster>(nullptr); }
|
||||
|
||||
inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Sample::Monster> root) { fbb.Finish(root); }
|
||||
|
||||
|
||||
@@ -84,14 +84,14 @@ const Generator generators[] = {
|
||||
flatbuffers::CPPMakeRule },
|
||||
};
|
||||
|
||||
const char *program_name = nullptr;
|
||||
flatbuffers::Parser *parser = nullptr;
|
||||
const char *g_program_name = nullptr;
|
||||
flatbuffers::Parser *g_parser = nullptr;
|
||||
|
||||
static void Error(const std::string &err, bool usage, bool show_exe_name) {
|
||||
if (show_exe_name) printf("%s: ", program_name);
|
||||
if (show_exe_name) printf("%s: ", g_program_name);
|
||||
printf("%s\n", err.c_str());
|
||||
if (usage) {
|
||||
printf("usage: %s [OPTION]... FILE... [-- FILE...]\n", program_name);
|
||||
printf("usage: %s [OPTION]... FILE... [-- FILE...]\n", g_program_name);
|
||||
for (size_t i = 0; i < sizeof(generators) / sizeof(generators[0]); ++i)
|
||||
printf(" %-12s %s %s.\n",
|
||||
generators[i].generator_opt_long,
|
||||
@@ -123,23 +123,39 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
|
||||
" --gen-onefile Generate single output file for C#.\n"
|
||||
" --gen-name-strings Generate type name functions for C++.\n"
|
||||
" --escape-proto-ids Disable appending '_' in namespaces names.\n"
|
||||
" --gen-object-api Generate an additional object-based API\n"
|
||||
" --raw-binary Allow binaries without file_indentifier to be read.\n"
|
||||
" This may crash flatc given a mismatched schema.\n"
|
||||
" --proto Input is a .proto, translate to .fbs.\n"
|
||||
" --schema Serialize schemas instead of JSON (use with -b)\n"
|
||||
" --conform FILE Specify a schema the following schemas should be\n"
|
||||
" an evolution of. Gives errors if not.\n"
|
||||
"FILEs may be schemas, or JSON files (conforming to preceding schema)\n"
|
||||
"FILEs after the -- must be binary flatbuffer format files.\n"
|
||||
"Output files are named using the base file name of the input,\n"
|
||||
"and written to the current directory or the path given by -o.\n"
|
||||
"example: %s -c -b schema1.fbs schema2.fbs data.json\n",
|
||||
program_name);
|
||||
g_program_name);
|
||||
}
|
||||
if (parser) delete parser;
|
||||
if (g_parser) delete g_parser;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
|
||||
const std::string &contents,
|
||||
std::vector<const char *> &include_directories) {
|
||||
auto local_include_directory = flatbuffers::StripFileName(filename);
|
||||
include_directories.push_back(local_include_directory.c_str());
|
||||
include_directories.push_back(nullptr);
|
||||
if (!parser.Parse(contents.c_str(), &include_directories[0],
|
||||
filename.c_str()))
|
||||
Error(parser.error_, false, false);
|
||||
include_directories.pop_back();
|
||||
include_directories.pop_back();
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
program_name = argv[0];
|
||||
g_program_name = argv[0];
|
||||
flatbuffers::IDLOptions opts;
|
||||
std::string output_path;
|
||||
const size_t num_generators = sizeof(generators) / sizeof(generators[0]);
|
||||
@@ -151,6 +167,7 @@ int main(int argc, const char *argv[]) {
|
||||
std::vector<std::string> filenames;
|
||||
std::vector<const char *> include_directories;
|
||||
size_t binary_files_from = std::numeric_limits<size_t>::max();
|
||||
std::string conform_to_schema;
|
||||
for (int argi = 1; argi < argc; argi++) {
|
||||
std::string arg = argv[argi];
|
||||
if (arg[0] == '-') {
|
||||
@@ -162,6 +179,9 @@ int main(int argc, const char *argv[]) {
|
||||
} else if(arg == "-I") {
|
||||
if (++argi >= argc) Error("missing path following" + arg, true);
|
||||
include_directories.push_back(argv[argi]);
|
||||
} else if(arg == "--conform") {
|
||||
if (++argi >= argc) Error("missing path following" + arg, true);
|
||||
conform_to_schema = argv[argi];
|
||||
} else if(arg == "--strict-json") {
|
||||
opts.strict_json = true;
|
||||
} else if(arg == "--no-js-exports") {
|
||||
@@ -179,6 +199,8 @@ int main(int argc, const char *argv[]) {
|
||||
opts.mutable_buffer = true;
|
||||
} else if(arg == "--gen-name-strings") {
|
||||
opts.generate_name_strings = true;
|
||||
} else if(arg == "--gen-object-api") {
|
||||
opts.generate_object_based_api = true;
|
||||
} else if(arg == "--gen-all") {
|
||||
opts.generate_all = true;
|
||||
opts.include_dependence_headers = false;
|
||||
@@ -227,12 +249,20 @@ int main(int argc, const char *argv[]) {
|
||||
if (opts.proto_mode) {
|
||||
if (any_generator)
|
||||
Error("cannot generate code directly from .proto files", true);
|
||||
} else if (!any_generator) {
|
||||
} else if (!any_generator && conform_to_schema.empty()) {
|
||||
Error("no options: specify at least one generator.", true);
|
||||
}
|
||||
|
||||
flatbuffers::Parser conform_parser;
|
||||
if (!conform_to_schema.empty()) {
|
||||
std::string contents;
|
||||
if (!flatbuffers::LoadFile(conform_to_schema.c_str(), true, &contents))
|
||||
Error("unable to load schema: " + conform_to_schema);
|
||||
ParseFile(conform_parser, conform_to_schema, contents, include_directories);
|
||||
}
|
||||
|
||||
// Now process the files:
|
||||
parser = new flatbuffers::Parser(opts);
|
||||
g_parser = new flatbuffers::Parser(opts);
|
||||
for (auto file_it = filenames.begin();
|
||||
file_it != filenames.end();
|
||||
++file_it) {
|
||||
@@ -243,8 +273,8 @@ int main(int argc, const char *argv[]) {
|
||||
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >=
|
||||
binary_files_from;
|
||||
if (is_binary) {
|
||||
parser->builder_.Clear();
|
||||
parser->builder_.PushFlatBuffer(
|
||||
g_parser->builder_.Clear();
|
||||
g_parser->builder_.PushFlatBuffer(
|
||||
reinterpret_cast<const uint8_t *>(contents.c_str()),
|
||||
contents.length());
|
||||
if (!raw_binary) {
|
||||
@@ -253,17 +283,17 @@ 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 (!g_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())) {
|
||||
g_parser->file_identifier_.c_str())) {
|
||||
Error("binary \"" +
|
||||
*file_it +
|
||||
"\" does not have expected file_identifier \"" +
|
||||
parser->file_identifier_ +
|
||||
g_parser->file_identifier_ +
|
||||
"\", use --raw-binary to read this file anyway.");
|
||||
}
|
||||
}
|
||||
@@ -272,36 +302,34 @@ int main(int argc, const char *argv[]) {
|
||||
if (contents.length() != strlen(contents.c_str())) {
|
||||
Error("input file appears to be binary: " + *file_it, true);
|
||||
}
|
||||
if (flatbuffers::GetExtension(*file_it) == "fbs") {
|
||||
auto is_schema = flatbuffers::GetExtension(*file_it) == "fbs";
|
||||
if (is_schema) {
|
||||
// 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);
|
||||
delete g_parser;
|
||||
g_parser = new flatbuffers::Parser(opts);
|
||||
}
|
||||
ParseFile(*g_parser, *file_it, contents, include_directories);
|
||||
if (is_schema && !conform_to_schema.empty()) {
|
||||
auto err = g_parser->ConformTo(conform_parser);
|
||||
if (!err.empty()) Error("schemas don\'t conform: " + err);
|
||||
}
|
||||
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],
|
||||
file_it->c_str()))
|
||||
Error(parser->error_, false, false);
|
||||
if (schema_binary) {
|
||||
parser->Serialize();
|
||||
parser->file_extension_ = reflection::SchemaExtension();
|
||||
g_parser->Serialize();
|
||||
g_parser->file_extension_ = reflection::SchemaExtension();
|
||||
}
|
||||
include_directories.pop_back();
|
||||
include_directories.pop_back();
|
||||
}
|
||||
|
||||
std::string filebase = flatbuffers::StripPath(
|
||||
flatbuffers::StripExtension(*file_it));
|
||||
|
||||
for (size_t i = 0; i < num_generators; ++i) {
|
||||
parser->opts.lang = generators[i].lang;
|
||||
g_parser->opts.lang = generators[i].lang;
|
||||
if (generator_enabled[i]) {
|
||||
if (!print_make_rules) {
|
||||
flatbuffers::EnsureDirExists(output_path);
|
||||
if (!generators[i].generate(*parser, output_path, filebase)) {
|
||||
if (!generators[i].generate(*g_parser, output_path, filebase)) {
|
||||
Error(std::string("Unable to generate ") +
|
||||
generators[i].lang_name +
|
||||
" for " +
|
||||
@@ -309,7 +337,7 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
} else {
|
||||
std::string make_rule = generators[i].make_rule(
|
||||
*parser, output_path, *file_it);
|
||||
*g_parser, output_path, *file_it);
|
||||
if (!make_rule.empty())
|
||||
printf("%s\n", flatbuffers::WordWrap(
|
||||
make_rule, 80, " ", " \\").c_str());
|
||||
@@ -317,13 +345,13 @@ int main(int argc, const char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.proto_mode) GenerateFBS(*parser, output_path, filebase);
|
||||
if (opts.proto_mode) GenerateFBS(*g_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();
|
||||
g_parser->MarkGenerated();
|
||||
}
|
||||
|
||||
delete parser;
|
||||
delete g_parser;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -39,7 +37,8 @@ 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, "", "::"),
|
||||
cur_name_space_(nullptr){};
|
||||
// Iterate through all definitions we haven't generate code for (enums,
|
||||
// structs,
|
||||
// and tables) and output them to a single file.
|
||||
@@ -95,7 +94,11 @@ class CppGenerator : public BaseGenerator {
|
||||
auto &struct_def = **it;
|
||||
if (!struct_def.generated) {
|
||||
SetNameSpace(struct_def.defined_namespace, &code);
|
||||
code += "struct " + struct_def.name + ";\n\n";
|
||||
code += "struct " + struct_def.name + ";\n";
|
||||
if (parser_.opts.generate_object_based_api && !struct_def.fixed) {
|
||||
code += "struct " + NativeName(struct_def.name) + ";\n";
|
||||
}
|
||||
code += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +129,14 @@ class CppGenerator : public BaseGenerator {
|
||||
GenTable(struct_def, &code);
|
||||
}
|
||||
}
|
||||
for (auto it = parser_.structs_.vec.begin();
|
||||
it != parser_.structs_.vec.end(); ++it) {
|
||||
auto &struct_def = **it;
|
||||
if (!struct_def.fixed && !struct_def.generated) {
|
||||
SetNameSpace(struct_def.defined_namespace, &code);
|
||||
GenTablePost(struct_def, &code);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate code for union verifiers.
|
||||
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
|
||||
@@ -133,7 +144,7 @@ class CppGenerator : public BaseGenerator {
|
||||
auto &enum_def = **it;
|
||||
if (enum_def.is_union && !enum_def.generated) {
|
||||
SetNameSpace(enum_def.defined_namespace, &code);
|
||||
GenEnumPost(enum_def, &code);
|
||||
GenUnionPost(enum_def, &code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,14 +168,6 @@ class CppGenerator : public BaseGenerator {
|
||||
code += name + ">(buf); }\n\n";
|
||||
}
|
||||
|
||||
// The root verifier:
|
||||
code += "inline bool Verify";
|
||||
code += name;
|
||||
code +=
|
||||
"Buffer(flatbuffers::Verifier &verifier) { "
|
||||
"return verifier.VerifyBuffer<";
|
||||
code += cpp_qualified_name + ">(); }\n\n";
|
||||
|
||||
if (parser_.file_identifier_.length()) {
|
||||
// Return the identifier
|
||||
code += "inline const char *" + name;
|
||||
@@ -178,6 +181,19 @@ class CppGenerator : public BaseGenerator {
|
||||
code += name + "Identifier()); }\n\n";
|
||||
}
|
||||
|
||||
// The root verifier:
|
||||
code += "inline bool Verify";
|
||||
code += name;
|
||||
code +=
|
||||
"Buffer(flatbuffers::Verifier &verifier) { "
|
||||
"return verifier.VerifyBuffer<";
|
||||
code += cpp_qualified_name + ">(";
|
||||
if (parser_.file_identifier_.length())
|
||||
code += name + "Identifier()";
|
||||
else
|
||||
code += "nullptr";
|
||||
code += "); }\n\n";
|
||||
|
||||
if (parser_.file_extension_.length()) {
|
||||
// Return the extension
|
||||
code += "inline const char *" + name;
|
||||
@@ -206,7 +222,7 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
private:
|
||||
// This tracks the current namespace so we can insert namespace declarations.
|
||||
const Namespace *cur_name_space_ = nullptr;
|
||||
const Namespace *cur_name_space_;
|
||||
|
||||
const Namespace *CurrentNameSpace() { return cur_name_space_; }
|
||||
|
||||
@@ -225,9 +241,10 @@ class CppGenerator : public BaseGenerator {
|
||||
// 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,
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
|
||||
#CTYPE,
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
#undef FLATBUFFERS_TD
|
||||
};
|
||||
if (user_facing_type) {
|
||||
if (type.enum_def) return WrapInNameSpace(*type.enum_def);
|
||||
@@ -245,9 +262,8 @@ class CppGenerator : public BaseGenerator {
|
||||
case BASE_TYPE_VECTOR:
|
||||
return "flatbuffers::Vector<" +
|
||||
GenTypeWire(type.VectorType(), "", false) + ">";
|
||||
case BASE_TYPE_STRUCT: {
|
||||
case BASE_TYPE_STRUCT:
|
||||
return WrapInNameSpace(*type.struct_def);
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
// fall through
|
||||
default:
|
||||
@@ -257,30 +273,56 @@ 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";
|
||||
}
|
||||
|
||||
// TODO(wvo): make this configurable.
|
||||
std::string NativeName(const std::string &name) { return name + "T"; }
|
||||
|
||||
std::string GenTypeNative(const Type &type, bool invector) {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_STRING:
|
||||
return "std::string";
|
||||
case BASE_TYPE_VECTOR:
|
||||
return "std::vector<" + GenTypeNative(type.VectorType(), true) + ">";
|
||||
case BASE_TYPE_STRUCT:
|
||||
if (IsStruct(type)) {
|
||||
if (invector) {
|
||||
return WrapInNameSpace(*type.struct_def);
|
||||
} else {
|
||||
return "std::unique_ptr<" +
|
||||
WrapInNameSpace(*type.struct_def) + ">";
|
||||
}
|
||||
} else {
|
||||
return "std::unique_ptr<" +
|
||||
NativeName(WrapInNameSpace(*type.struct_def)) + ">";
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
return type.enum_def->name + "Union";
|
||||
default:
|
||||
return GenTypeBasic(type, true);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
@@ -309,12 +351,37 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
std::string EnumSignature(EnumDef &enum_def) {
|
||||
std::string UnionVerifySignature(EnumDef &enum_def) {
|
||||
return "inline bool Verify" + enum_def.name +
|
||||
"(flatbuffers::Verifier &verifier, " + "const void *union_obj, " +
|
||||
"(flatbuffers::Verifier &verifier, const void *union_obj, " +
|
||||
enum_def.name + " type)";
|
||||
}
|
||||
|
||||
std::string UnionUnPackSignature(EnumDef &enum_def, bool inclass) {
|
||||
return (inclass ? "static " : "") +
|
||||
std::string("flatbuffers::NativeTable *") +
|
||||
(inclass ? "" : enum_def.name + "Union::") +
|
||||
"UnPack(const void *union_obj, " + enum_def.name + " type)";
|
||||
}
|
||||
|
||||
std::string UnionPackSignature(EnumDef &enum_def, bool inclass) {
|
||||
return "flatbuffers::Offset<void> " +
|
||||
(inclass ? "" : enum_def.name + "Union::") +
|
||||
"Pack(flatbuffers::FlatBufferBuilder &_fbb) const";
|
||||
}
|
||||
|
||||
std::string TableCreateSignature(StructDef &struct_def) {
|
||||
return "inline flatbuffers::Offset<" + struct_def.name + "> Create" +
|
||||
struct_def.name +
|
||||
"(flatbuffers::FlatBufferBuilder &_fbb, const " +
|
||||
NativeName(struct_def.name) + " *_o)";
|
||||
}
|
||||
|
||||
std::string TableUnPackSignature(StructDef &struct_def, bool inclass) {
|
||||
return "std::unique_ptr<" + NativeName(struct_def.name) + "> " +
|
||||
(inclass ? "" : struct_def.name + "::") + "UnPack() const";
|
||||
}
|
||||
|
||||
// Generate an enum declaration and an enum string lookup table.
|
||||
void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
@@ -356,6 +423,36 @@ class CppGenerator : public BaseGenerator {
|
||||
GenTypeBasic(enum_def.underlying_type, false) + ")\n";
|
||||
code += "\n";
|
||||
|
||||
if (parser_.opts.generate_object_based_api && enum_def.is_union) {
|
||||
// Generate a union type
|
||||
code += "struct " + enum_def.name + "Union {\n";
|
||||
code += " " + enum_def.name + " type;\n\n";
|
||||
code += " flatbuffers::NativeTable *table;\n";
|
||||
code += " " + enum_def.name + "Union() : type(";
|
||||
code += GenEnumVal(enum_def, "NONE", parser_.opts);
|
||||
code += "), table(nullptr) {}\n";
|
||||
code += " " + enum_def.name + "Union(const ";
|
||||
code += enum_def.name + "Union &);\n";
|
||||
code += " " + enum_def.name + "Union &operator=(const ";
|
||||
code += enum_def.name + "Union &);\n";
|
||||
code += " ~" + enum_def.name + "Union();\n\n";
|
||||
code += " " + UnionUnPackSignature(enum_def, true) + ";\n";
|
||||
code += " " + UnionPackSignature(enum_def, true) + ";\n\n";
|
||||
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
auto &ev = **it;
|
||||
if (ev.value) {
|
||||
auto native_name = NativeName(WrapInNameSpace(*ev.struct_def));
|
||||
code += " " + native_name + " *As";
|
||||
code += ev.name + "() { return type == ";
|
||||
code += GetEnumVal(enum_def, ev, parser_.opts);
|
||||
code += " ? reinterpret_cast<" + native_name;
|
||||
code += " *>(table) : nullptr; }\n";
|
||||
}
|
||||
}
|
||||
code += "};\n\n";
|
||||
}
|
||||
|
||||
// Generate a generate string table for enum values.
|
||||
// Problem is, if values are very sparse that could generate really big
|
||||
// tables. Ideally in that case we generate a map lookup instead, but for
|
||||
@@ -381,38 +478,89 @@ class CppGenerator : public BaseGenerator {
|
||||
code += "()[static_cast<int>(e)";
|
||||
if (enum_def.vals.vec.front()->value) {
|
||||
code += " - static_cast<int>(";
|
||||
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";
|
||||
}
|
||||
|
||||
if (enum_def.is_union) {
|
||||
code += EnumSignature(enum_def) + ";\n\n";
|
||||
code += UnionVerifySignature(enum_def) + ";\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
void GenEnumPost(EnumDef &enum_def, std::string *code_ptr_post) {
|
||||
void GenUnionPost(EnumDef &enum_def, std::string *code_ptr) {
|
||||
// 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";
|
||||
std::string &code = *code_ptr;
|
||||
code += UnionVerifySignature(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);
|
||||
code += " case " + GetEnumVal(enum_def, ev, parser_.opts);
|
||||
if (!ev.value) {
|
||||
code_post += ": return true;\n"; // "NONE" enum value.
|
||||
code += ": return true;\n"; // "NONE" enum value.
|
||||
} else {
|
||||
code_post += ": return verifier.VerifyTable(reinterpret_cast<const ";
|
||||
code_post += WrapInNameSpace(*ev.struct_def);
|
||||
code_post += " *>(union_obj));\n";
|
||||
code += ": return verifier.VerifyTable(reinterpret_cast<const ";
|
||||
code += WrapInNameSpace(*ev.struct_def);
|
||||
code += " *>(union_obj));\n";
|
||||
}
|
||||
}
|
||||
code_post += " default: return false;\n }\n}\n\n";
|
||||
code += " default: return false;\n }\n}\n\n";
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// Generate a union pack & unpack function.
|
||||
code += "inline " + UnionUnPackSignature(enum_def, false);
|
||||
code += " {\n switch (type) {\n";
|
||||
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
auto &ev = **it;
|
||||
code += " case " + GetEnumVal(enum_def, ev, parser_.opts);
|
||||
if (!ev.value) {
|
||||
code += ": return nullptr;\n"; // "NONE" enum value.
|
||||
} else {
|
||||
code += ": return reinterpret_cast<const ";
|
||||
code += WrapInNameSpace(*ev.struct_def);
|
||||
code += " *>(union_obj)->UnPack().release();\n";
|
||||
}
|
||||
}
|
||||
code += " default: return nullptr;\n }\n}\n\n";
|
||||
code += "inline " + UnionPackSignature(enum_def, false);
|
||||
code += " {\n switch (type) {\n";
|
||||
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
auto &ev = **it;
|
||||
code += " case " + GetEnumVal(enum_def, ev, parser_.opts);
|
||||
if (!ev.value) {
|
||||
code += ": return 0;\n"; // "NONE" enum value.
|
||||
} else {
|
||||
code += ": return Create" + ev.struct_def->name;
|
||||
code += "(_fbb, reinterpret_cast<const ";
|
||||
code += NativeName(WrapInNameSpace(*ev.struct_def));
|
||||
code += " *>(table)).Union();\n";
|
||||
}
|
||||
}
|
||||
code += " default: return 0;\n }\n}\n\n";
|
||||
|
||||
// Generate a union destructor.
|
||||
code += "inline " + enum_def.name + "Union::~";
|
||||
code += enum_def.name + "Union() {\n";
|
||||
code += " switch (type) {\n";
|
||||
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
auto &ev = **it;
|
||||
if (ev.value) {
|
||||
code += " case " + GenEnumVal(enum_def, ev.name, parser_.opts);
|
||||
code += ": delete reinterpret_cast<";
|
||||
code += NativeName(WrapInNameSpace(*ev.struct_def));
|
||||
code += " *>(table); break;\n";
|
||||
}
|
||||
}
|
||||
code += " default:;\n }\n}\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Generates a value with optionally a cast applied if the field has a
|
||||
@@ -439,8 +587,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() "
|
||||
@@ -457,9 +604,47 @@ class CppGenerator : public BaseGenerator {
|
||||
: field.value.constant;
|
||||
}
|
||||
|
||||
void GenSimpleParam(std::string &code, FieldDef &field) {
|
||||
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<int>(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);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate an accessor struct, builder structs & function for a table.
|
||||
void GenTable(StructDef &struct_def, std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// Generate a C++ object that can hold an unpacked version of this
|
||||
// table.
|
||||
code += "struct " + NativeName(struct_def.name);
|
||||
code += " : public flatbuffers::NativeTable {\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.
|
||||
field.value.type.base_type != BASE_TYPE_UTYPE) {
|
||||
code += " " + GenTypeNative(field.value.type, false) + " ";
|
||||
code += field.name + ";\n";
|
||||
}
|
||||
}
|
||||
code += "};\n\n";
|
||||
}
|
||||
|
||||
// Generate an accessor struct, with methods of the form:
|
||||
// type name() const { return GetField<type>(offset, defaultval); }
|
||||
GenComment(struct_def.doc_comment, code_ptr, nullptr);
|
||||
@@ -498,8 +683,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 =
|
||||
@@ -507,8 +691,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))
|
||||
@@ -525,8 +709,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 + ")");
|
||||
@@ -627,7 +810,13 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
code += prefix + "verifier.EndTable()";
|
||||
code += ";\n }\n";
|
||||
code += "};\n\n";
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// Generate the UnPack() pre declaration.
|
||||
code += " " + TableUnPackSignature(struct_def, true) + ";\n";
|
||||
}
|
||||
|
||||
code += "};\n\n"; // End of table.
|
||||
|
||||
// Generate a builder struct, with methods of the form:
|
||||
// void add_name(type name) { fbb_.AddElement<type>(offset, name, default);
|
||||
@@ -679,6 +868,7 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
// Generate a convenient CreateX function that uses the above builder
|
||||
// to create a table in one go.
|
||||
bool gen_vector_pars = false;
|
||||
code += "inline flatbuffers::Offset<" + struct_def.name + "> Create";
|
||||
code += struct_def.name;
|
||||
code += "(flatbuffers::FlatBufferBuilder &_fbb";
|
||||
@@ -686,24 +876,11 @@ class CppGenerator : public BaseGenerator {
|
||||
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<int>(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);
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING ||
|
||||
field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||
gen_vector_pars = true;
|
||||
}
|
||||
GenSimpleParam(code, field);
|
||||
}
|
||||
}
|
||||
code += ") {\n " + struct_def.name + "Builder builder_(_fbb);\n";
|
||||
@@ -719,6 +896,212 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
}
|
||||
code += " return builder_.Finish();\n}\n\n";
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
code += ",\n const std::vector<";
|
||||
code += GenTypeWire(field.value.type.VectorType(), "", false);
|
||||
code += "> *" + field.name + " = nullptr";
|
||||
} else {
|
||||
GenSimpleParam(code, field);
|
||||
}
|
||||
}
|
||||
}
|
||||
code += ") {\n ";
|
||||
code += "return Create";
|
||||
code += struct_def.name;
|
||||
code += "(_fbb";
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (!field.deprecated) {
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
code += ", " + field.name + " ? 0 : ";
|
||||
code += "_fbb.CreateString(" + field.name + ")";
|
||||
} else if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||
code += ", " + field.name + " ? 0 : ";
|
||||
code += "_fbb.CreateVector<";
|
||||
code += GenTypeWire(field.value.type.VectorType(), "", false);
|
||||
code += ">(*" + field.name + ")";
|
||||
} else
|
||||
code += ", " + field.name;
|
||||
}
|
||||
}
|
||||
code += ");\n}\n\n";
|
||||
}
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// Generate a pre-declaration for a CreateX method that works with an
|
||||
// unpacked C++ object.
|
||||
code += TableCreateSignature(struct_def) + ";\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Generate code for tables that needs to come after the regular definition.
|
||||
void GenTablePost(StructDef &struct_def, std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// Generate the UnPack() method.
|
||||
code += "inline " + TableUnPackSignature(struct_def, false) + " {\n";
|
||||
code += " auto _o = new " + NativeName(struct_def.name) + "();\n";
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (!field.deprecated) {
|
||||
auto prefix = " { auto _e = " + field.name + "(); ";
|
||||
if (!IsScalar(field.value.type.base_type)) prefix += "if (_e) ";
|
||||
auto deref = "_o->";
|
||||
auto dest = deref + field.name;
|
||||
auto assign = prefix + dest + " = ";
|
||||
auto gen_unpack_val = [&](const Type &type, const std::string &val,
|
||||
bool invector) -> std::string {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_STRING:
|
||||
return val + "->str()";
|
||||
case BASE_TYPE_STRUCT:
|
||||
if (IsStruct(type)) {
|
||||
if (invector) {
|
||||
return "*" + val;
|
||||
} else {
|
||||
return "std::unique_ptr<" + type.struct_def->name +
|
||||
">(new " + type.struct_def->name + "(*" + val + "))";
|
||||
}
|
||||
} else {
|
||||
return val + "->UnPack()";
|
||||
}
|
||||
default:
|
||||
return val;
|
||||
break;
|
||||
}
|
||||
};
|
||||
switch (field.value.type.base_type) {
|
||||
case BASE_TYPE_VECTOR: {
|
||||
code += prefix;
|
||||
code += "{ for (flatbuffers::uoffset_t _i = 0;";
|
||||
code += " _i < _e->size(); _i++) { ";
|
||||
code += dest + ".push_back(";
|
||||
std::string indexing = "_e->Get(_i)";
|
||||
if (field.value.type.element == BASE_TYPE_BOOL)
|
||||
indexing += "!=0";
|
||||
code += gen_unpack_val(field.value.type.VectorType(),
|
||||
indexing, true);
|
||||
code += "); } }";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UTYPE: {
|
||||
auto &union_field = **(it + 1);
|
||||
assert(union_field.value.type.base_type == BASE_TYPE_UNION);
|
||||
code += prefix + deref + union_field.name + ".type = _e;";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
code += prefix + dest + ".table = ";
|
||||
code += field.value.type.enum_def->name;
|
||||
code += "Union::UnPack(_e, ";
|
||||
code += field.name + UnionTypeFieldSuffix() + "());";
|
||||
break;
|
||||
default:
|
||||
code += assign + gen_unpack_val(field.value.type, "_e", false);
|
||||
code += ";";
|
||||
break;
|
||||
}
|
||||
code += " };\n";
|
||||
}
|
||||
}
|
||||
code += " return std::unique_ptr<" + NativeName(struct_def.name);
|
||||
code += ">(_o);\n}\n\n";
|
||||
|
||||
// Generate a CreateX method that works with an unpacked C++ object.
|
||||
code += TableCreateSignature(struct_def) + " {\n";
|
||||
auto before_return_statement = code.size();
|
||||
code += " return Create";
|
||||
code += struct_def.name + "(_fbb";
|
||||
bool any_fields = false;
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
auto &field = **it;
|
||||
if (!field.deprecated) {
|
||||
any_fields = true;
|
||||
auto field_name = field.name;
|
||||
if (field.value.type.base_type == BASE_TYPE_UTYPE) {
|
||||
field_name = field_name.substr(0, field_name.size() -
|
||||
strlen(UnionTypeFieldSuffix()));
|
||||
field_name += ".type";
|
||||
}
|
||||
auto accessor = "_o->" + field_name;
|
||||
auto ptrprefix = accessor + " ? ";
|
||||
auto stlprefix = accessor + ".size() ? ";
|
||||
auto postfix = " : 0";
|
||||
if (field.required &&
|
||||
(field.value.type.base_type == BASE_TYPE_STRING ||
|
||||
field.value.type.base_type == BASE_TYPE_VECTOR)) {
|
||||
stlprefix = "";
|
||||
postfix = "";
|
||||
}
|
||||
code += ",\n ";
|
||||
switch (field.value.type.base_type) {
|
||||
case BASE_TYPE_STRING:
|
||||
code += stlprefix + "_fbb.CreateString(" + accessor + ")";
|
||||
code += postfix;
|
||||
break;
|
||||
case BASE_TYPE_VECTOR: {
|
||||
auto vector_type = field.value.type.VectorType();
|
||||
code += stlprefix;
|
||||
switch (vector_type.base_type) {
|
||||
case BASE_TYPE_STRING:
|
||||
code += "_fbb.CreateVectorOfStrings(" + accessor + ")";
|
||||
break;
|
||||
case BASE_TYPE_STRUCT:
|
||||
if (IsStruct(vector_type)) {
|
||||
code += "_fbb.CreateVectorOfStructs(" + accessor + ")";
|
||||
} else {
|
||||
code += "_fbb.CreateVector<flatbuffers::Offset<";
|
||||
code += vector_type.struct_def->name + ">>(" + accessor;
|
||||
code += ".size(), [&](size_t i) { return Create";
|
||||
code += vector_type.struct_def->name + "(_fbb, " + accessor;
|
||||
code += "[i].get()); })";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
code += "_fbb.CreateVector(" + accessor + ")";
|
||||
break;
|
||||
}
|
||||
code += postfix;
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
code += accessor + ".Pack(_fbb)";
|
||||
break;
|
||||
case BASE_TYPE_STRUCT:
|
||||
if (IsStruct(field.value.type)) {
|
||||
code += ptrprefix + accessor + ".get()" + postfix;
|
||||
} else {
|
||||
code += ptrprefix + "Create";
|
||||
code += field.value.type.struct_def->name;
|
||||
code += "(_fbb, " + accessor + ".get())" + postfix;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
code += accessor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
code += ");\n}\n\n";
|
||||
if (!any_fields) code.insert(before_return_statement, " (void)_o;\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void GenPadding(const FieldDef &field, std::string &code,
|
||||
@@ -775,6 +1158,15 @@ class CppGenerator : public BaseGenerator {
|
||||
code += "\n public:\n";
|
||||
GenFullyQualifiedNameGetter(struct_def.name, code);
|
||||
|
||||
// Generate a default constructor.
|
||||
code += " " + struct_def.name + "() { memset(this, 0, sizeof(";
|
||||
code += struct_def.name + ")); }\n";
|
||||
|
||||
// Generate a copy constructor.
|
||||
code += " " + struct_def.name + "(const " + struct_def.name;
|
||||
code += " &_o) { memcpy(this, &_o, sizeof(";
|
||||
code += struct_def.name + ")); }\n";
|
||||
|
||||
// Generate a constructor that takes all fields as arguments.
|
||||
code += " " + struct_def.name + "(";
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
@@ -817,8 +1209,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
|
||||
@@ -878,6 +1269,7 @@ class CppGenerator : public BaseGenerator {
|
||||
cur_name_space_ = ns;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cpp
|
||||
|
||||
bool GenerateCPP(const Parser &parser, const std::string &path,
|
||||
@@ -886,19 +1278,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
|
||||
|
||||
|
||||
@@ -193,9 +193,11 @@ class GeneralGenerator : public BaseGenerator {
|
||||
public:
|
||||
GeneralGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name)
|
||||
: BaseGenerator(parser, path, file_name, "", "."){
|
||||
assert(parser_.opts.lang <= IDLOptions::kMAX);
|
||||
: BaseGenerator(parser, path, file_name, "", "."),
|
||||
lang_(language_parameters[parser_.opts.lang]) {
|
||||
assert(parser_.opts.lang <= IDLOptions::kMAX);
|
||||
};
|
||||
GeneralGenerator &operator=(const GeneralGenerator &);
|
||||
bool generate() {
|
||||
std::string one_file_code;
|
||||
|
||||
@@ -234,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;
|
||||
|
||||
@@ -544,7 +546,7 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
|
||||
// "too sparse". Change at will.
|
||||
static const int kMaxSparseness = 5;
|
||||
if (range / static_cast<int64_t>(enum_def.vals.vec.size()) < kMaxSparseness) {
|
||||
code += "\n private static";
|
||||
code += "\n public static";
|
||||
code += lang_.const_decl;
|
||||
code += lang_.string_type;
|
||||
code += "[] names = { ";
|
||||
@@ -567,7 +569,10 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr) {
|
||||
}
|
||||
|
||||
// Close the class
|
||||
code += "};\n\n";
|
||||
code += "}";
|
||||
// Java does not need the closing semi-colon on class definitions.
|
||||
code += (lang_.language != IDLOptions::kJava) ? ";" : "";
|
||||
code += "\n\n";
|
||||
}
|
||||
|
||||
// Returns the function name that is able to read a value of the given type.
|
||||
@@ -1125,9 +1130,12 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
|
||||
code += "); }\n";
|
||||
}
|
||||
}
|
||||
code += "};\n\n";
|
||||
}
|
||||
const LanguageParameters & lang_ = language_parameters[parser_.opts.lang];
|
||||
code += "}";
|
||||
// Java does not need the closing semi-colon on class definitions.
|
||||
code += (lang_.language != IDLOptions::kJava) ? ";" : "";
|
||||
code += "\n\n";
|
||||
}
|
||||
const LanguageParameters & lang_;
|
||||
};
|
||||
} // namespace general
|
||||
|
||||
|
||||
@@ -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) {
|
||||
@@ -509,13 +551,12 @@ static void GenTableBuilders(const StructDef &struct_def,
|
||||
|
||||
// Generate struct or table methods.
|
||||
static void GenStruct(const StructDef &struct_def,
|
||||
std::string *code_ptr,
|
||||
StructDef *root_struct_def) {
|
||||
std::string *code_ptr) {
|
||||
if (struct_def.generated) return;
|
||||
|
||||
GenComment(struct_def.doc_comment, code_ptr, nullptr);
|
||||
BeginClass(struct_def, code_ptr);
|
||||
if (&struct_def == root_struct_def) {
|
||||
if (!struct_def.fixed) {
|
||||
// Generate a special accessor for the table that has been declared as
|
||||
// the root type.
|
||||
NewRootTypeFromBuffer(struct_def, code_ptr);
|
||||
@@ -530,6 +571,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) {
|
||||
@@ -638,7 +680,7 @@ class GoGenerator : public BaseGenerator {
|
||||
for (auto it = parser_.structs_.vec.begin();
|
||||
it != parser_.structs_.vec.end(); ++it) {
|
||||
std::string declcode;
|
||||
go::GenStruct(**it, &declcode, parser_.root_struct_def_);
|
||||
go::GenStruct(**it, &declcode);
|
||||
if (!SaveType(**it, declcode, true)) return false;
|
||||
}
|
||||
|
||||
@@ -681,4 +723,3 @@ bool GenerateGo(const Parser &parser, const std::string &path,
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -110,7 +110,7 @@ class JsGenerator : public BaseGenerator {
|
||||
std::string &exports = *exports_ptr;
|
||||
for (auto it = sorted_namespaces.begin();
|
||||
it != sorted_namespaces.end(); it++) {
|
||||
code += "/**\n * @const\n*/\n";
|
||||
code += "/**\n * @const\n * @namespace\n */\n";
|
||||
if (it->find('.') == std::string::npos) {
|
||||
code += "var ";
|
||||
exports += "this." + *it + " = " + *it + ";\n";
|
||||
|
||||
@@ -94,7 +94,7 @@ static void NewRootTypeFromBuffer(const StructDef &struct_def,
|
||||
code += Indent + Indent + "x = " + struct_def.name + "()\n";
|
||||
code += Indent + Indent + "x.Init(buf, n + offset)\n";
|
||||
code += Indent + Indent + "return x\n";
|
||||
code += "\n\n";
|
||||
code += "\n";
|
||||
}
|
||||
|
||||
// Initialize an existing object with other data, to avoid an allocation.
|
||||
@@ -478,13 +478,12 @@ static void GenTableBuilders(const StructDef &struct_def,
|
||||
|
||||
// Generate struct or table methods.
|
||||
static void GenStruct(const StructDef &struct_def,
|
||||
std::string *code_ptr,
|
||||
StructDef *root_struct_def) {
|
||||
std::string *code_ptr) {
|
||||
if (struct_def.generated) return;
|
||||
|
||||
GenComment(struct_def.doc_comment, code_ptr, nullptr, "# ");
|
||||
BeginClass(struct_def, code_ptr);
|
||||
if (&struct_def == root_struct_def) {
|
||||
if (!struct_def.fixed) {
|
||||
// Generate a special accessor for the table that has been declared as
|
||||
// the root type.
|
||||
NewRootTypeFromBuffer(struct_def, code_ptr);
|
||||
@@ -621,7 +620,7 @@ class PythonGenerator : public BaseGenerator {
|
||||
it != parser_.structs_.vec.end(); ++it) {
|
||||
auto &struct_def = **it;
|
||||
std::string declcode;
|
||||
GenStruct(struct_def, &declcode, parser_.root_struct_def_);
|
||||
GenStruct(struct_def, &declcode);
|
||||
if (!SaveType(struct_def, declcode, true)) return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -2093,4 +2093,57 @@ flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
|
||||
}
|
||||
}
|
||||
|
||||
std::string Parser::ConformTo(const Parser &base) {
|
||||
for (auto sit = structs_.vec.begin(); sit != structs_.vec.end(); ++sit) {
|
||||
auto &struct_def = **sit;
|
||||
auto qualified_name =
|
||||
struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name);
|
||||
auto struct_def_base = base.structs_.Lookup(qualified_name);
|
||||
if (!struct_def_base) continue;
|
||||
for (auto fit = struct_def.fields.vec.begin();
|
||||
fit != struct_def.fields.vec.end(); ++fit) {
|
||||
auto &field = **fit;
|
||||
auto field_base = struct_def_base->fields.Lookup(field.name);
|
||||
if (field_base) {
|
||||
if (field.value.offset != field_base->value.offset)
|
||||
return "offsets differ for field: " + field.name;
|
||||
if (field.value.constant != field_base->value.constant)
|
||||
return "defaults differ for field: " + field.name;
|
||||
if (!EqualByName(field.value.type, field_base->value.type))
|
||||
return "types differ for field: " + field.name;
|
||||
} else {
|
||||
// Doesn't have to exist, deleting fields is fine.
|
||||
// But we should check if there is a field that has the same offset
|
||||
// but is incompatible (in the case of field renaming).
|
||||
for (auto fbit = struct_def_base->fields.vec.begin();
|
||||
fbit != struct_def_base->fields.vec.end(); ++fbit) {
|
||||
field_base = *fbit;
|
||||
if (field.value.offset == field_base->value.offset) {
|
||||
if (!EqualByName(field.value.type, field_base->value.type))
|
||||
return "field renamed to different type: " + field.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto eit = enums_.vec.begin(); eit != enums_.vec.end(); ++eit) {
|
||||
auto &enum_def = **eit;
|
||||
auto qualified_name =
|
||||
enum_def.defined_namespace->GetFullyQualifiedName(enum_def.name);
|
||||
auto enum_def_base = base.enums_.Lookup(qualified_name);
|
||||
if (!enum_def_base) continue;
|
||||
for (auto evit = enum_def.vals.vec.begin();
|
||||
evit != enum_def.vals.vec.end(); ++evit) {
|
||||
auto &enum_val = **evit;
|
||||
auto enum_val_base = enum_def_base->vals.Lookup(enum_val.name);
|
||||
if (enum_val_base) {
|
||||
if (enum_val.value != enum_val_base->value)
|
||||
return "values differ for enum: " + enum_val.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
@@ -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]; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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]; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -135,5 +135,5 @@ public final class Monster extends Table {
|
||||
return o;
|
||||
}
|
||||
public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ class Monster(object):
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
|
||||
# Monster
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
@@ -9,6 +9,13 @@ type Stat struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsStat(buf []byte, offset flatbuffers.UOffsetT) *Stat {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &Stat{}
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func (rcv *Stat) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
@@ -30,6 +37,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 +49,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) }
|
||||
|
||||
@@ -39,5 +39,5 @@ public final class Stat extends Table {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,13 @@ import flatbuffers
|
||||
class Stat(object):
|
||||
__slots__ = ['_tab']
|
||||
|
||||
@classmethod
|
||||
def GetRootAsStat(cls, buf, offset):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = Stat()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
# Stat
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -23,5 +23,5 @@ public final class Test extends Struct {
|
||||
builder.putShort(a);
|
||||
return builder.offset();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,13 @@ type TestSimpleTableWithEnum struct {
|
||||
_tab flatbuffers.Table
|
||||
}
|
||||
|
||||
func GetRootAsTestSimpleTableWithEnum(buf []byte, offset flatbuffers.UOffsetT) *TestSimpleTableWithEnum {
|
||||
n := flatbuffers.GetUOffsetT(buf[offset:])
|
||||
x := &TestSimpleTableWithEnum{}
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
}
|
||||
|
||||
func (rcv *TestSimpleTableWithEnum) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
@@ -22,6 +29,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() }
|
||||
|
||||
@@ -29,5 +29,5 @@ public final class TestSimpleTableWithEnum extends Table {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,13 @@ import flatbuffers
|
||||
class TestSimpleTableWithEnum(object):
|
||||
__slots__ = ['_tab']
|
||||
|
||||
@classmethod
|
||||
def GetRootAsTestSimpleTableWithEnum(cls, buf, offset):
|
||||
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||
x = TestSimpleTableWithEnum()
|
||||
x.Init(buf, n + offset)
|
||||
return x
|
||||
|
||||
# TestSimpleTableWithEnum
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -40,5 +40,5 @@ public final class Vec3 extends Struct {
|
||||
builder.putFloat(x);
|
||||
return builder.offset();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -19,5 +19,5 @@ public final class Monster extends Table {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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 --grpc --gen-mutable --no-includes monster_test.fbs monsterdata_test.json
|
||||
..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --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
|
||||
|
||||
@@ -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 --grpc --gen-mutable --no-includes monster_test.fbs monsterdata_test.json
|
||||
../flatc --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --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
|
||||
|
||||
|
||||
290
tests/go_test.go
290
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)
|
||||
@@ -75,6 +76,9 @@ func TestAll(t *testing.T) {
|
||||
CheckStructIsNotInlineError(t.Fatalf)
|
||||
CheckFinishedBytesError(t.Fatalf)
|
||||
|
||||
// Verify that GetRootAs works for non-root tables
|
||||
CheckGetRootAsForNonRootTable(t.Fatalf)
|
||||
|
||||
// Verify that using the generated Go code builds a buffer without
|
||||
// returning errors:
|
||||
generated, off := CheckGeneratedBuild(t.Fatalf)
|
||||
@@ -82,6 +86,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 +95,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 +286,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{})) {
|
||||
@@ -964,6 +1084,31 @@ func CheckManualBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UO
|
||||
return b.Bytes, b.Head()
|
||||
}
|
||||
|
||||
func CheckGetRootAsForNonRootTable(fail func(string, ...interface{})) {
|
||||
b := flatbuffers.NewBuilder(0)
|
||||
str := b.CreateString("MyStat")
|
||||
example.StatStart(b)
|
||||
example.StatAddId(b, str)
|
||||
example.StatAddVal(b, 12345678)
|
||||
example.StatAddCount(b, 12345)
|
||||
stat_end := example.StatEnd(b)
|
||||
b.Finish(stat_end)
|
||||
|
||||
stat := example.GetRootAsStat(b.Bytes, b.Head())
|
||||
|
||||
if got := stat.Id(); !bytes.Equal([]byte("MyStat"), got) {
|
||||
fail(FailString("stat.Id()", "MyStat", got))
|
||||
}
|
||||
|
||||
if got := stat.Val(); 12345678 != got {
|
||||
fail(FailString("stat.Val()", 12345678, got))
|
||||
}
|
||||
|
||||
if got := stat.Count(); 12345 != got {
|
||||
fail(FailString("stat.Count()", 12345, got))
|
||||
}
|
||||
}
|
||||
|
||||
// CheckGeneratedBuild uses generated code to build the example Monster.
|
||||
func CheckGeneratedBuild(fail func(string, ...interface{})) ([]byte, flatbuffers.UOffsetT) {
|
||||
b := flatbuffers.NewBuilder(0)
|
||||
@@ -1248,6 +1393,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.
|
||||
|
||||
Binary file not shown.
@@ -9,6 +9,7 @@ namespace MyGame {
|
||||
namespace Example2 {
|
||||
|
||||
struct Monster;
|
||||
struct MonsterT;
|
||||
|
||||
} // namespace Example2
|
||||
|
||||
@@ -17,12 +18,15 @@ namespace Example {
|
||||
struct Test;
|
||||
|
||||
struct TestSimpleTableWithEnum;
|
||||
struct TestSimpleTableWithEnumT;
|
||||
|
||||
struct Vec3;
|
||||
|
||||
struct Stat;
|
||||
struct StatT;
|
||||
|
||||
struct Monster;
|
||||
struct MonsterT;
|
||||
|
||||
enum Color {
|
||||
Color_Red = 1,
|
||||
@@ -48,6 +52,23 @@ enum Any {
|
||||
Any_MAX = Any_MyGame_Example2_Monster
|
||||
};
|
||||
|
||||
struct AnyUnion {
|
||||
Any type;
|
||||
|
||||
flatbuffers::NativeTable *table;
|
||||
AnyUnion() : type(Any_NONE), table(nullptr) {}
|
||||
AnyUnion(const AnyUnion &);
|
||||
AnyUnion &operator=(const AnyUnion &);
|
||||
~AnyUnion();
|
||||
|
||||
static flatbuffers::NativeTable *UnPack(const void *union_obj, Any type);
|
||||
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb) const;
|
||||
|
||||
MonsterT *AsMonster() { return type == Any_Monster ? reinterpret_cast<MonsterT *>(table) : nullptr; }
|
||||
TestSimpleTableWithEnumT *AsTestSimpleTableWithEnum() { return type == Any_TestSimpleTableWithEnum ? reinterpret_cast<TestSimpleTableWithEnumT *>(table) : nullptr; }
|
||||
MyGame::Example2::MonsterT *AsMyGame_Example2_Monster() { return type == Any_MyGame_Example2_Monster ? reinterpret_cast<MyGame::Example2::MonsterT *>(table) : nullptr; }
|
||||
};
|
||||
|
||||
inline const char **EnumNamesAny() {
|
||||
static const char *names[] = { "NONE", "Monster", "TestSimpleTableWithEnum", "MyGame_Example2_Monster", nullptr };
|
||||
return names;
|
||||
@@ -64,6 +85,8 @@ MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS {
|
||||
int8_t __padding0;
|
||||
|
||||
public:
|
||||
Test() { memset(this, 0, sizeof(Test)); }
|
||||
Test(const Test &_o) { memcpy(this, &_o, sizeof(Test)); }
|
||||
Test(int16_t _a, int8_t _b)
|
||||
: a_(flatbuffers::EndianScalar(_a)), b_(flatbuffers::EndianScalar(_b)), __padding0(0) { (void)__padding0; }
|
||||
|
||||
@@ -87,6 +110,8 @@ MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||
int16_t __padding2;
|
||||
|
||||
public:
|
||||
Vec3() { memset(this, 0, sizeof(Vec3)); }
|
||||
Vec3(const Vec3 &_o) { memcpy(this, &_o, sizeof(Vec3)); }
|
||||
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<int8_t>(_test2))), __padding1(0), test3_(_test3), __padding2(0) { (void)__padding0; (void)__padding1; (void)__padding2; }
|
||||
|
||||
@@ -109,11 +134,15 @@ STRUCT_END(Vec3, 32);
|
||||
|
||||
namespace Example2 {
|
||||
|
||||
struct MonsterT : public flatbuffers::NativeTable {
|
||||
};
|
||||
|
||||
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<MonsterT> UnPack() const;
|
||||
};
|
||||
|
||||
struct MonsterBuilder {
|
||||
@@ -132,10 +161,16 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o);
|
||||
|
||||
} // namespace Example2
|
||||
|
||||
namespace Example {
|
||||
|
||||
struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable {
|
||||
Color color;
|
||||
};
|
||||
|
||||
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
VT_COLOR = 4
|
||||
@@ -147,6 +182,7 @@ struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta
|
||||
VerifyField<int8_t>(verifier, VT_COLOR) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<TestSimpleTableWithEnumT> UnPack() const;
|
||||
};
|
||||
|
||||
struct TestSimpleTableWithEnumBuilder {
|
||||
@@ -162,12 +198,20 @@ struct TestSimpleTableWithEnumBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
Color color = Color_Green) {
|
||||
Color color = Color_Green) {
|
||||
TestSimpleTableWithEnumBuilder builder_(_fbb);
|
||||
builder_.add_color(color);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o);
|
||||
|
||||
struct StatT : public flatbuffers::NativeTable {
|
||||
std::string id;
|
||||
int64_t val;
|
||||
uint16_t count;
|
||||
};
|
||||
|
||||
struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
VT_ID = 4,
|
||||
@@ -188,6 +232,7 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyField<uint16_t>(verifier, VT_COUNT) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<StatT> UnPack() const;
|
||||
};
|
||||
|
||||
struct StatBuilder {
|
||||
@@ -205,9 +250,9 @@ struct StatBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> id = 0,
|
||||
int64_t val = 0,
|
||||
uint16_t count = 0) {
|
||||
flatbuffers::Offset<flatbuffers::String> id = 0,
|
||||
int64_t val = 0,
|
||||
uint16_t count = 0) {
|
||||
StatBuilder builder_(_fbb);
|
||||
builder_.add_val(val);
|
||||
builder_.add_id(id);
|
||||
@@ -215,6 +260,45 @@ inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *id = nullptr,
|
||||
int64_t val = 0,
|
||||
uint16_t count = 0) {
|
||||
return CreateStat(_fbb, id ? 0 : _fbb.CreateString(id), val, count);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o);
|
||||
|
||||
struct MonsterT : public flatbuffers::NativeTable {
|
||||
std::unique_ptr<Vec3> pos;
|
||||
int16_t mana;
|
||||
int16_t hp;
|
||||
std::string name;
|
||||
std::vector<uint8_t> inventory;
|
||||
Color color;
|
||||
AnyUnion test;
|
||||
std::vector<Test> test4;
|
||||
std::vector<std::string> testarrayofstring;
|
||||
std::vector<std::unique_ptr<MonsterT>> testarrayoftables;
|
||||
std::unique_ptr<MonsterT> enemy;
|
||||
std::vector<uint8_t> testnestedflatbuffer;
|
||||
std::unique_ptr<StatT> testempty;
|
||||
bool testbool;
|
||||
int32_t testhashs32_fnv1;
|
||||
uint32_t testhashu32_fnv1;
|
||||
int64_t testhashs64_fnv1;
|
||||
uint64_t testhashu64_fnv1;
|
||||
int32_t testhashs32_fnv1a;
|
||||
uint32_t testhashu32_fnv1a;
|
||||
int64_t testhashs64_fnv1a;
|
||||
uint64_t testhashu64_fnv1a;
|
||||
std::vector<bool> testarrayofbools;
|
||||
float testf;
|
||||
float testf2;
|
||||
float testf3;
|
||||
std::vector<std::string> testarrayofstring2;
|
||||
};
|
||||
|
||||
/// an example documentation comment: monster object
|
||||
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
@@ -354,6 +438,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
verifier.VerifyVectorOfStrings(testarrayofstring2()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<MonsterT> UnPack() const;
|
||||
};
|
||||
|
||||
struct MonsterBuilder {
|
||||
@@ -397,34 +482,34 @@ struct MonsterBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0,
|
||||
Color color = Color_Blue,
|
||||
Any test_type = Any_NONE,
|
||||
flatbuffers::Offset<void> test = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<const Test *>> test4 = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Monster>>> testarrayoftables = 0,
|
||||
flatbuffers::Offset<Monster> enemy = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testnestedflatbuffer = 0,
|
||||
flatbuffers::Offset<Stat> testempty = 0,
|
||||
bool testbool = false,
|
||||
int32_t testhashs32_fnv1 = 0,
|
||||
uint32_t testhashu32_fnv1 = 0,
|
||||
int64_t testhashs64_fnv1 = 0,
|
||||
uint64_t testhashu64_fnv1 = 0,
|
||||
int32_t testhashs32_fnv1a = 0,
|
||||
uint32_t testhashu32_fnv1a = 0,
|
||||
int64_t testhashs64_fnv1a = 0,
|
||||
uint64_t testhashu64_fnv1a = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testarrayofbools = 0,
|
||||
float testf = 3.14159f,
|
||||
float testf2 = 3.0f,
|
||||
float testf3 = 0.0f,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring2 = 0) {
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory = 0,
|
||||
Color color = Color_Blue,
|
||||
Any test_type = Any_NONE,
|
||||
flatbuffers::Offset<void> test = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<const Test *>> test4 = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Monster>>> testarrayoftables = 0,
|
||||
flatbuffers::Offset<Monster> enemy = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testnestedflatbuffer = 0,
|
||||
flatbuffers::Offset<Stat> testempty = 0,
|
||||
bool testbool = false,
|
||||
int32_t testhashs32_fnv1 = 0,
|
||||
uint32_t testhashu32_fnv1 = 0,
|
||||
int64_t testhashs64_fnv1 = 0,
|
||||
uint64_t testhashu64_fnv1 = 0,
|
||||
int32_t testhashs32_fnv1a = 0,
|
||||
uint32_t testhashu32_fnv1a = 0,
|
||||
int64_t testhashs64_fnv1a = 0,
|
||||
uint64_t testhashu64_fnv1a = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> testarrayofbools = 0,
|
||||
float testf = 3.14159f,
|
||||
float testf2 = 3.0f,
|
||||
float testf3 = 0.0f,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring2 = 0) {
|
||||
MonsterBuilder builder_(_fbb);
|
||||
builder_.add_testhashu64_fnv1a(testhashu64_fnv1a);
|
||||
builder_.add_testhashs64_fnv1a(testhashs64_fnv1a);
|
||||
@@ -457,6 +542,149 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
const char *name = nullptr,
|
||||
const std::vector<uint8_t> *inventory = nullptr,
|
||||
Color color = Color_Blue,
|
||||
Any test_type = Any_NONE,
|
||||
flatbuffers::Offset<void> test = 0,
|
||||
const std::vector<const Test *> *test4 = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *testarrayofstring = nullptr,
|
||||
const std::vector<flatbuffers::Offset<Monster>> *testarrayoftables = nullptr,
|
||||
flatbuffers::Offset<Monster> enemy = 0,
|
||||
const std::vector<uint8_t> *testnestedflatbuffer = nullptr,
|
||||
flatbuffers::Offset<Stat> testempty = 0,
|
||||
bool testbool = false,
|
||||
int32_t testhashs32_fnv1 = 0,
|
||||
uint32_t testhashu32_fnv1 = 0,
|
||||
int64_t testhashs64_fnv1 = 0,
|
||||
uint64_t testhashu64_fnv1 = 0,
|
||||
int32_t testhashs32_fnv1a = 0,
|
||||
uint32_t testhashu32_fnv1a = 0,
|
||||
int64_t testhashs64_fnv1a = 0,
|
||||
uint64_t testhashu64_fnv1a = 0,
|
||||
const std::vector<uint8_t> *testarrayofbools = nullptr,
|
||||
float testf = 3.14159f,
|
||||
float testf2 = 3.0f,
|
||||
float testf3 = 0.0f,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *testarrayofstring2 = nullptr) {
|
||||
return CreateMonster(_fbb, pos, mana, hp, name ? 0 : _fbb.CreateString(name), inventory ? 0 : _fbb.CreateVector<uint8_t>(*inventory), color, test_type, test, test4 ? 0 : _fbb.CreateVector<const Test *>(*test4), testarrayofstring ? 0 : _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring), testarrayoftables ? 0 : _fbb.CreateVector<flatbuffers::Offset<Monster>>(*testarrayoftables), enemy, testnestedflatbuffer ? 0 : _fbb.CreateVector<uint8_t>(*testnestedflatbuffer), testempty, testbool, testhashs32_fnv1, testhashu32_fnv1, testhashs64_fnv1, testhashu64_fnv1, testhashs32_fnv1a, testhashu32_fnv1a, testhashs64_fnv1a, testhashu64_fnv1a, testarrayofbools ? 0 : _fbb.CreateVector<uint8_t>(*testarrayofbools), testf, testf2, testf3, testarrayofstring2 ? 0 : _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring2));
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o);
|
||||
|
||||
} // namespace Example
|
||||
|
||||
namespace Example2 {
|
||||
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
||||
auto _o = new MonsterT();
|
||||
return std::unique_ptr<MonsterT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o) {
|
||||
(void)_o;
|
||||
return CreateMonster(_fbb);
|
||||
}
|
||||
|
||||
} // namespace Example2
|
||||
|
||||
namespace Example {
|
||||
|
||||
inline std::unique_ptr<TestSimpleTableWithEnumT> TestSimpleTableWithEnum::UnPack() const {
|
||||
auto _o = new TestSimpleTableWithEnumT();
|
||||
{ auto _e = color(); _o->color = _e; };
|
||||
return std::unique_ptr<TestSimpleTableWithEnumT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o) {
|
||||
return CreateTestSimpleTableWithEnum(_fbb,
|
||||
_o->color);
|
||||
}
|
||||
|
||||
inline std::unique_ptr<StatT> Stat::UnPack() const {
|
||||
auto _o = new StatT();
|
||||
{ auto _e = id(); if (_e) _o->id = _e->str(); };
|
||||
{ auto _e = val(); _o->val = _e; };
|
||||
{ auto _e = count(); _o->count = _e; };
|
||||
return std::unique_ptr<StatT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o) {
|
||||
return CreateStat(_fbb,
|
||||
_o->id.size() ? _fbb.CreateString(_o->id) : 0,
|
||||
_o->val,
|
||||
_o->count);
|
||||
}
|
||||
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
||||
auto _o = new MonsterT();
|
||||
{ auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
|
||||
{ auto _e = mana(); _o->mana = _e; };
|
||||
{ auto _e = hp(); _o->hp = _e; };
|
||||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = inventory(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } } };
|
||||
{ auto _e = color(); _o->color = _e; };
|
||||
{ auto _e = test_type(); _o->test.type = _e; };
|
||||
{ auto _e = test(); if (_e) _o->test.table = AnyUnion::UnPack(_e, test_type()); };
|
||||
{ auto _e = test4(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test4.push_back(*_e->Get(_i)); } } };
|
||||
{ auto _e = testarrayofstring(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring.push_back(_e->Get(_i)->str()); } } };
|
||||
{ auto _e = testarrayoftables(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables.push_back(_e->Get(_i)->UnPack()); } } };
|
||||
{ auto _e = enemy(); if (_e) _o->enemy = _e->UnPack(); };
|
||||
{ auto _e = testnestedflatbuffer(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer.push_back(_e->Get(_i)); } } };
|
||||
{ auto _e = testempty(); if (_e) _o->testempty = _e->UnPack(); };
|
||||
{ auto _e = testbool(); _o->testbool = _e; };
|
||||
{ auto _e = testhashs32_fnv1(); _o->testhashs32_fnv1 = _e; };
|
||||
{ auto _e = testhashu32_fnv1(); _o->testhashu32_fnv1 = _e; };
|
||||
{ auto _e = testhashs64_fnv1(); _o->testhashs64_fnv1 = _e; };
|
||||
{ auto _e = testhashu64_fnv1(); _o->testhashu64_fnv1 = _e; };
|
||||
{ auto _e = testhashs32_fnv1a(); _o->testhashs32_fnv1a = _e; };
|
||||
{ auto _e = testhashu32_fnv1a(); _o->testhashu32_fnv1a = _e; };
|
||||
{ auto _e = testhashs64_fnv1a(); _o->testhashs64_fnv1a = _e; };
|
||||
{ auto _e = testhashu64_fnv1a(); _o->testhashu64_fnv1a = _e; };
|
||||
{ auto _e = testarrayofbools(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofbools.push_back(_e->Get(_i)!=0); } } };
|
||||
{ auto _e = testf(); _o->testf = _e; };
|
||||
{ auto _e = testf2(); _o->testf2 = _e; };
|
||||
{ auto _e = testf3(); _o->testf3 = _e; };
|
||||
{ auto _e = testarrayofstring2(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring2.push_back(_e->Get(_i)->str()); } } };
|
||||
return std::unique_ptr<MonsterT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o) {
|
||||
return CreateMonster(_fbb,
|
||||
_o->pos ? _o->pos.get() : 0,
|
||||
_o->mana,
|
||||
_o->hp,
|
||||
_fbb.CreateString(_o->name),
|
||||
_o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0,
|
||||
_o->color,
|
||||
_o->test.type,
|
||||
_o->test.Pack(_fbb),
|
||||
_o->test4.size() ? _fbb.CreateVectorOfStructs(_o->test4) : 0,
|
||||
_o->testarrayofstring.size() ? _fbb.CreateVectorOfStrings(_o->testarrayofstring) : 0,
|
||||
_o->testarrayoftables.size() ? _fbb.CreateVector<flatbuffers::Offset<Monster>>(_o->testarrayoftables.size(), [&](size_t i) { return CreateMonster(_fbb, _o->testarrayoftables[i].get()); }) : 0,
|
||||
_o->enemy ? CreateMonster(_fbb, _o->enemy.get()) : 0,
|
||||
_o->testnestedflatbuffer.size() ? _fbb.CreateVector(_o->testnestedflatbuffer) : 0,
|
||||
_o->testempty ? CreateStat(_fbb, _o->testempty.get()) : 0,
|
||||
_o->testbool,
|
||||
_o->testhashs32_fnv1,
|
||||
_o->testhashu32_fnv1,
|
||||
_o->testhashs64_fnv1,
|
||||
_o->testhashu64_fnv1,
|
||||
_o->testhashs32_fnv1a,
|
||||
_o->testhashu32_fnv1a,
|
||||
_o->testhashs64_fnv1a,
|
||||
_o->testhashu64_fnv1a,
|
||||
_o->testarrayofbools.size() ? _fbb.CreateVector(_o->testarrayofbools) : 0,
|
||||
_o->testf,
|
||||
_o->testf2,
|
||||
_o->testf3,
|
||||
_o->testarrayofstring2.size() ? _fbb.CreateVectorOfStrings(_o->testarrayofstring2) : 0);
|
||||
}
|
||||
|
||||
inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, Any type) {
|
||||
switch (type) {
|
||||
case Any_NONE: return true;
|
||||
@@ -467,16 +695,45 @@ inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, An
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *union_obj, Any type) {
|
||||
switch (type) {
|
||||
case Any_NONE: return nullptr;
|
||||
case Any_Monster: return reinterpret_cast<const Monster *>(union_obj)->UnPack().release();
|
||||
case Any_TestSimpleTableWithEnum: return reinterpret_cast<const TestSimpleTableWithEnum *>(union_obj)->UnPack().release();
|
||||
case Any_MyGame_Example2_Monster: return reinterpret_cast<const MyGame::Example2::Monster *>(union_obj)->UnPack().release();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<void> AnyUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb) const {
|
||||
switch (type) {
|
||||
case Any_NONE: return 0;
|
||||
case Any_Monster: return CreateMonster(_fbb, reinterpret_cast<const MonsterT *>(table)).Union();
|
||||
case Any_TestSimpleTableWithEnum: return CreateTestSimpleTableWithEnum(_fbb, reinterpret_cast<const TestSimpleTableWithEnumT *>(table)).Union();
|
||||
case Any_MyGame_Example2_Monster: return CreateMonster(_fbb, reinterpret_cast<const MyGame::Example2::MonsterT *>(table)).Union();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline AnyUnion::~AnyUnion() {
|
||||
switch (type) {
|
||||
case Any_Monster: delete reinterpret_cast<MonsterT *>(table); break;
|
||||
case Any_TestSimpleTableWithEnum: delete reinterpret_cast<TestSimpleTableWithEnumT *>(table); break;
|
||||
case Any_MyGame_Example2_Monster: delete reinterpret_cast<MyGame::Example2::MonsterT *>(table); break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
inline const MyGame::Example::Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<MyGame::Example::Monster>(buf); }
|
||||
|
||||
inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); }
|
||||
|
||||
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Example::Monster>(); }
|
||||
|
||||
inline const char *MonsterIdentifier() { return "MONS"; }
|
||||
|
||||
inline bool MonsterBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, MonsterIdentifier()); }
|
||||
|
||||
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Example::Monster>(MonsterIdentifier()); }
|
||||
|
||||
inline const char *MonsterExtension() { return "mon"; }
|
||||
|
||||
inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Example::Monster> root) { fbb.Finish(root, MonsterIdentifier()); }
|
||||
|
||||
@@ -2,22 +2,26 @@
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
var MyGame = MyGame || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
MyGame.Example = MyGame.Example || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
MyGame.Example2 = MyGame.Example2 || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
MyGame.OtherNameSpace = MyGame.OtherNameSpace || {};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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]; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,11 @@ func (rcv *StructInNestedNS) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
}
|
||||
|
||||
func (rcv *StructInNestedNS) A() int32 { return rcv._tab.GetInt32(rcv._tab.Pos + flatbuffers.UOffsetT(0)) }
|
||||
func (rcv *StructInNestedNS) MutateA(n int32) bool { return rcv._tab.MutateInt32(rcv._tab.Pos + flatbuffers.UOffsetT(0), n) }
|
||||
|
||||
func (rcv *StructInNestedNS) B() int32 { return rcv._tab.GetInt32(rcv._tab.Pos + flatbuffers.UOffsetT(4)) }
|
||||
func (rcv *StructInNestedNS) MutateB(n int32) bool { return rcv._tab.MutateInt32(rcv._tab.Pos + flatbuffers.UOffsetT(4), n) }
|
||||
|
||||
|
||||
func CreateStructInNestedNS(builder *flatbuffers.Builder, a int32, b int32) flatbuffers.UOffsetT {
|
||||
builder.Prep(4, 8)
|
||||
|
||||
@@ -22,5 +22,5 @@ public final class StructInNestedNS extends Struct {
|
||||
builder.putInt(a);
|
||||
return builder.offset();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ func (rcv *TableInNestedNS) Foo() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *TableInNestedNS) MutateFoo(n int32) bool {
|
||||
return rcv._tab.MutateInt32Slot(4, n)
|
||||
}
|
||||
|
||||
func TableInNestedNSStart(builder *flatbuffers.Builder) { builder.StartObject(1) }
|
||||
func TableInNestedNSAddFoo(builder *flatbuffers.Builder, foo int32) { builder.PrependInt32Slot(0, foo, 0) }
|
||||
func TableInNestedNSEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() }
|
||||
|
||||
@@ -29,5 +29,5 @@ public final class TableInNestedNS extends Table {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -29,5 +29,5 @@ public final class SecondTableInA extends Table {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,10 @@ func (rcv *TableInFirstNS) FooEnum() int8 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *TableInFirstNS) MutateFooEnum(n int8) bool {
|
||||
return rcv._tab.MutateInt8Slot(6, n)
|
||||
}
|
||||
|
||||
func (rcv *TableInFirstNS) FooStruct(obj *StructInNestedNS) *StructInNestedNS {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
|
||||
if o != 0 {
|
||||
|
||||
@@ -28,5 +28,5 @@ public final class TableInFirstNS extends Table {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -34,5 +34,5 @@ public final class TableInC extends Table {
|
||||
int o = builder.endObject();
|
||||
return o;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ MANUALLY_ALIGNED_STRUCT(4) StructInNestedNS FLATBUFFERS_FINAL_CLASS {
|
||||
int32_t b_;
|
||||
|
||||
public:
|
||||
StructInNestedNS() { memset(this, 0, sizeof(StructInNestedNS)); }
|
||||
StructInNestedNS(const StructInNestedNS &_o) { memcpy(this, &_o, sizeof(StructInNestedNS)); }
|
||||
StructInNestedNS(int32_t _a, int32_t _b)
|
||||
: a_(flatbuffers::EndianScalar(_a)), b_(flatbuffers::EndianScalar(_b)) { }
|
||||
|
||||
@@ -69,7 +71,7 @@ struct TableInNestedNSBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<TableInNestedNS> CreateTableInNestedNS(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
int32_t foo = 0) {
|
||||
int32_t foo = 0) {
|
||||
TableInNestedNSBuilder builder_(_fbb);
|
||||
builder_.add_foo(foo);
|
||||
return builder_.Finish();
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
var NamespaceA = NamespaceA || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
NamespaceA.NamespaceB = NamespaceA.NamespaceB || {};
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,9 +60,9 @@ struct TableInFirstNSBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<TableInFirstNS> CreateTableInFirstNS(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<NamespaceA::NamespaceB::TableInNestedNS> foo_table = 0,
|
||||
NamespaceA::NamespaceB::EnumInNestedNS foo_enum = NamespaceA::NamespaceB::EnumInNestedNS_A,
|
||||
const NamespaceA::NamespaceB::StructInNestedNS *foo_struct = 0) {
|
||||
flatbuffers::Offset<NamespaceA::NamespaceB::TableInNestedNS> foo_table = 0,
|
||||
NamespaceA::NamespaceB::EnumInNestedNS foo_enum = NamespaceA::NamespaceB::EnumInNestedNS_A,
|
||||
const NamespaceA::NamespaceB::StructInNestedNS *foo_struct = 0) {
|
||||
TableInFirstNSBuilder builder_(_fbb);
|
||||
builder_.add_foo_struct(foo_struct);
|
||||
builder_.add_foo_table(foo_table);
|
||||
@@ -107,8 +107,8 @@ struct TableInCBuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<TableInC> CreateTableInC(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<NamespaceA::TableInFirstNS> refer_to_a1 = 0,
|
||||
flatbuffers::Offset<NamespaceA::SecondTableInA> refer_to_a2 = 0) {
|
||||
flatbuffers::Offset<NamespaceA::TableInFirstNS> refer_to_a1 = 0,
|
||||
flatbuffers::Offset<NamespaceA::SecondTableInA> refer_to_a2 = 0) {
|
||||
TableInCBuilder builder_(_fbb);
|
||||
builder_.add_refer_to_a2(refer_to_a2);
|
||||
builder_.add_refer_to_a1(refer_to_a1);
|
||||
@@ -146,7 +146,7 @@ struct SecondTableInABuilder {
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<SecondTableInA> CreateSecondTableInA(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<NamespaceC::TableInC> refer_to_c = 0) {
|
||||
flatbuffers::Offset<NamespaceC::TableInC> refer_to_c = 0) {
|
||||
SecondTableInABuilder builder_(_fbb);
|
||||
builder_.add_refer_to_c(refer_to_c);
|
||||
return builder_.Finish();
|
||||
@@ -154,4 +154,12 @@ inline flatbuffers::Offset<SecondTableInA> CreateSecondTableInA(flatbuffers::Fla
|
||||
|
||||
} // namespace NamespaceA
|
||||
|
||||
namespace NamespaceC {
|
||||
|
||||
} // namespace NamespaceC
|
||||
|
||||
namespace NamespaceA {
|
||||
|
||||
} // namespace NamespaceA
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_NAMESPACETEST2_NAMESPACEA_H_
|
||||
|
||||
@@ -2,17 +2,20 @@
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
var NamespaceA = NamespaceA || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
NamespaceA.NamespaceB = NamespaceA.NamespaceB || {};
|
||||
|
||||
/**
|
||||
* @const
|
||||
*/
|
||||
* @namespace
|
||||
*/
|
||||
var NamespaceC = NamespaceC || {};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1034,6 +1034,23 @@ class TestAllCodePathsOfExampleSchema(unittest.TestCase):
|
||||
self.assertEqual(7, mon2.Testhashs64Fnv1a())
|
||||
self.assertEqual(8, mon2.Testhashu64Fnv1a())
|
||||
|
||||
def test_getrootas_for_nonroot_table(self):
|
||||
b = flatbuffers.Builder(0)
|
||||
string = b.CreateString("MyStat")
|
||||
|
||||
MyGame.Example.Stat.StatStart(b)
|
||||
MyGame.Example.Stat.StatAddId(b, string)
|
||||
MyGame.Example.Stat.StatAddVal(b, 12345678)
|
||||
MyGame.Example.Stat.StatAddCount(b, 12345)
|
||||
stat = MyGame.Example.Stat.StatEnd(b)
|
||||
b.Finish(stat)
|
||||
|
||||
stat2 = MyGame.Example.Stat.Stat.GetRootAsStat(b.Bytes, b.Head())
|
||||
|
||||
self.assertEqual(b"MyStat", stat2.Id())
|
||||
self.assertEqual(12345678, stat2.Val())
|
||||
self.assertEqual(12345, stat2.Count())
|
||||
|
||||
|
||||
class TestVtableDeduplication(unittest.TestCase):
|
||||
''' TestVtableDeduplication verifies that vtables are deduplicated. '''
|
||||
|
||||
142
tests/test.cpp
142
tests/test.cpp
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#define FLATBUFFERS_DEBUG_VERIFICATION_FAILURE 1
|
||||
#define FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
@@ -24,7 +25,9 @@
|
||||
#include "namespace_test/namespace_test1_generated.h"
|
||||
#include "namespace_test/namespace_test2_generated.h"
|
||||
|
||||
#include <random>
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#include <random>
|
||||
#endif
|
||||
|
||||
using namespace MyGame::Example;
|
||||
|
||||
@@ -123,7 +126,9 @@ flatbuffers::unique_ptr_t CreateFlatBufferTest(std::string &buffer) {
|
||||
});
|
||||
|
||||
// Creating vectors of strings in one convenient call.
|
||||
std::vector<std::string> names2 = { "jane", "mary" };
|
||||
std::vector<std::string> 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:
|
||||
@@ -154,12 +159,30 @@ flatbuffers::unique_ptr_t CreateFlatBufferTest(std::string &buffer) {
|
||||
}
|
||||
|
||||
// example of accessing a buffer loaded in memory:
|
||||
void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length) {
|
||||
void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length,
|
||||
bool pooled = true) {
|
||||
|
||||
// First, verify the buffers integrity (optional)
|
||||
flatbuffers::Verifier verifier(flatbuf, length);
|
||||
TEST_EQ(VerifyMonsterBuffer(verifier), true);
|
||||
|
||||
std::vector<uint8_t> test_buff;
|
||||
test_buff.resize(length * 2);
|
||||
std::memcpy(&test_buff[0], flatbuf , length);
|
||||
std::memcpy(&test_buff[length], flatbuf , length);
|
||||
|
||||
flatbuffers::Verifier verifierl(&test_buff[0], length - 1);
|
||||
TEST_EQ(VerifyMonsterBuffer(verifierl), false);
|
||||
TEST_EQ(verifierl.GetComputedSize(), 0);
|
||||
|
||||
flatbuffers::Verifier verifier1(&test_buff[0], length);
|
||||
TEST_EQ(VerifyMonsterBuffer(verifier1), true);
|
||||
TEST_EQ(verifier1.GetComputedSize(), length);
|
||||
|
||||
flatbuffers::Verifier verifier2(&test_buff[length], length);
|
||||
TEST_EQ(VerifyMonsterBuffer(verifier2), true);
|
||||
TEST_EQ(verifier2.GetComputedSize(), length);
|
||||
|
||||
TEST_EQ(strcmp(MonsterIdentifier(), "MONS"), 0);
|
||||
TEST_EQ(MonsterBufferHasIdentifier(flatbuf), true);
|
||||
TEST_EQ(strcmp(MonsterExtension(), "mon"), 0);
|
||||
@@ -200,9 +223,11 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length) {
|
||||
TEST_EQ(vecofstrings->Length(), 4U);
|
||||
TEST_EQ_STR(vecofstrings->Get(0)->c_str(), "bob");
|
||||
TEST_EQ_STR(vecofstrings->Get(1)->c_str(), "fred");
|
||||
// These should have pointer equality because of string pooling.
|
||||
TEST_EQ(vecofstrings->Get(0)->c_str(), vecofstrings->Get(2)->c_str());
|
||||
TEST_EQ(vecofstrings->Get(1)->c_str(), vecofstrings->Get(3)->c_str());
|
||||
if (pooled) {
|
||||
// These should have pointer equality because of string pooling.
|
||||
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) {
|
||||
@@ -287,6 +312,77 @@ void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) {
|
||||
AccessFlatBufferTest(flatbuf, length);
|
||||
}
|
||||
|
||||
// Unpack a FlatBuffer into objects.
|
||||
void ObjectFlatBuffersTest(uint8_t *flatbuf) {
|
||||
// Turn a buffer into C++ objects.
|
||||
auto monster1 = GetMonster(flatbuf)->UnPack();
|
||||
|
||||
// Re-serialize the data.
|
||||
flatbuffers::FlatBufferBuilder fbb1;
|
||||
fbb1.Finish(CreateMonster(fbb1, monster1.get()), MonsterIdentifier());
|
||||
|
||||
// Unpack again, and re-serialize again.
|
||||
auto monster2 = GetMonster(fbb1.GetBufferPointer())->UnPack();
|
||||
flatbuffers::FlatBufferBuilder fbb2;
|
||||
fbb2.Finish(CreateMonster(fbb2, monster2.get()), MonsterIdentifier());
|
||||
|
||||
// Now we've gone full round-trip, the two buffers should match.
|
||||
auto len1 = fbb1.GetSize();
|
||||
auto len2 = fbb2.GetSize();
|
||||
TEST_EQ(len1, len2);
|
||||
TEST_EQ(memcmp(fbb1.GetBufferPointer(), fbb2.GetBufferPointer(),
|
||||
len1), 0);
|
||||
|
||||
// Test it with the original buffer test to make sure all data survived.
|
||||
AccessFlatBufferTest(fbb2.GetBufferPointer(), len2, false);
|
||||
|
||||
// Test accessing fields, similar to AccessFlatBufferTest above.
|
||||
TEST_EQ(monster2->hp, 80);
|
||||
TEST_EQ(monster2->mana, 150); // default
|
||||
TEST_EQ_STR(monster2->name.c_str(), "MyMonster");
|
||||
|
||||
auto &pos = monster2->pos;
|
||||
TEST_NOTNULL(pos);
|
||||
TEST_EQ(pos->z(), 3);
|
||||
TEST_EQ(pos->test3().a(), 10);
|
||||
TEST_EQ(pos->test3().b(), 20);
|
||||
|
||||
auto &inventory = monster2->inventory;
|
||||
TEST_EQ(inventory.size(), 10UL);
|
||||
unsigned char inv_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
for (auto it = inventory.begin(); it != inventory.end(); ++it)
|
||||
TEST_EQ(*it, inv_data[it - inventory.begin()]);
|
||||
|
||||
TEST_EQ(monster2->color, Color_Blue);
|
||||
|
||||
auto monster3 = monster2->test.AsMonster();
|
||||
TEST_NOTNULL(monster3);
|
||||
TEST_EQ_STR(monster3->name.c_str(), "Fred");
|
||||
|
||||
auto &vecofstrings = monster2->testarrayofstring;
|
||||
TEST_EQ(vecofstrings.size(), 4U);
|
||||
TEST_EQ_STR(vecofstrings[0].c_str(), "bob");
|
||||
TEST_EQ_STR(vecofstrings[1].c_str(), "fred");
|
||||
|
||||
auto &vecofstrings2 = monster2->testarrayofstring2;
|
||||
TEST_EQ(vecofstrings2.size(), 2U);
|
||||
TEST_EQ_STR(vecofstrings2[0].c_str(), "jane");
|
||||
TEST_EQ_STR(vecofstrings2[1].c_str(), "mary");
|
||||
|
||||
auto &vecoftables = monster2->testarrayoftables;
|
||||
TEST_EQ(vecoftables.size(), 3U);
|
||||
TEST_EQ_STR(vecoftables[0]->name.c_str(), "Barney");
|
||||
TEST_EQ(vecoftables[0]->hp, 1000);
|
||||
TEST_EQ_STR(vecoftables[1]->name.c_str(), "Fred");
|
||||
TEST_EQ_STR(vecoftables[2]->name.c_str(), "Wilma");
|
||||
|
||||
auto &tests = monster2->test4;
|
||||
TEST_EQ(tests[0].a(), 10);
|
||||
TEST_EQ(tests[0].b(), 20);
|
||||
TEST_EQ(tests[1].a(), 30);
|
||||
TEST_EQ(tests[1].b(), 40);
|
||||
}
|
||||
|
||||
// example of parsing text straight into a buffer, and generating
|
||||
// text back from it:
|
||||
void ParseAndGenerateTextTest() {
|
||||
@@ -814,14 +910,14 @@ void ErrorTest() {
|
||||
TestError("table X { Y:byte; } root_type X; { Y:1, Y:2 }", "more than once");
|
||||
}
|
||||
|
||||
float TestValue(const char *json) {
|
||||
template<typename T> T TestValue(const char *json, const char *type_name) {
|
||||
flatbuffers::Parser parser;
|
||||
|
||||
// Simple schema.
|
||||
TEST_EQ(parser.Parse("table X { Y:float; } root_type X;"), true);
|
||||
TEST_EQ(parser.Parse(std::string("table X { Y:" + std::string(type_name) + "; } root_type X;").c_str()), true);
|
||||
|
||||
TEST_EQ(parser.Parse(json), true);
|
||||
auto root = flatbuffers::GetRoot<float>(parser.builder_.GetBufferPointer());
|
||||
auto root = flatbuffers::GetRoot<T>(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
|
||||
@@ -833,10 +929,13 @@ 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_EQ(FloatCompare(TestValue<float>("{ Y:0.0314159e+2 }","float"), (float)3.14159), true);
|
||||
|
||||
// Test conversion functions.
|
||||
TEST_EQ(FloatCompare(TestValue("{ Y:cos(rad(180)) }"), -1), true);
|
||||
TEST_EQ(FloatCompare(TestValue<float>("{ Y:cos(rad(180)) }","float"), -1), true);
|
||||
|
||||
// Test negative hex constant.
|
||||
TEST_EQ(TestValue<int>("{ Y:-0x80 }","int") == -128, true);
|
||||
}
|
||||
|
||||
void EnumStringsTest() {
|
||||
@@ -961,6 +1060,24 @@ void ParseUnionTest() {
|
||||
"{ X:{ A:1 }, X_type: T }"), true);
|
||||
}
|
||||
|
||||
void ConformTest() {
|
||||
flatbuffers::Parser parser;
|
||||
TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true);
|
||||
|
||||
auto test_conform = [&](const char *test, const char *expected_err) {
|
||||
flatbuffers::Parser parser2;
|
||||
TEST_EQ(parser2.Parse(test), true);
|
||||
auto err = parser2.ConformTo(parser);
|
||||
TEST_NOTNULL(strstr(err.c_str(), expected_err));
|
||||
};
|
||||
|
||||
test_conform("table T { A:byte; }", "types differ for field");
|
||||
test_conform("table T { B:int; A:int; }", "offsets differ for field");
|
||||
test_conform("table T { A:int = 1; }", "defaults differ for field");
|
||||
test_conform("table T { B:float; }", "field renamed to different type");
|
||||
test_conform("enum E:byte { B, A }", "values differ for enum");
|
||||
}
|
||||
|
||||
int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
// Run our various test suites:
|
||||
|
||||
@@ -972,6 +1089,8 @@ int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
|
||||
MutateFlatBuffersTest(flatbuf.get(), rawbuf.length());
|
||||
|
||||
ObjectFlatBuffersTest(flatbuf.get());
|
||||
|
||||
#ifndef FLATBUFFERS_NO_FILE_TESTS
|
||||
ParseAndGenerateTextTest();
|
||||
ReflectionTest(flatbuf.get(), rawbuf.length());
|
||||
@@ -990,6 +1109,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
UnicodeInvalidSurrogatesTest();
|
||||
UnknownFieldsTest();
|
||||
ParseUnionTest();
|
||||
ConformTest();
|
||||
|
||||
if (!testing_fails) {
|
||||
TEST_OUTPUT_LINE("ALL TESTS PASSED");
|
||||
|
||||
Reference in New Issue
Block a user