Merge remote-tracking branch 'refs/remotes/google/master'

This commit is contained in:
TGIshib
2016-07-26 00:07:23 +03:00
66 changed files with 2158 additions and 285 deletions

7
.gitignore vendored
View File

@@ -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

View File

@@ -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()

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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 = (

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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:

View File

@@ -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

View File

@@ -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()); }

View File

@@ -2,6 +2,10 @@
/// @addtogroup flatbuffers_javascript_api
/// @{
/// @cond FLATBUFFERS_INTERNAL
/**
* @const
* @namespace
*/
var flatbuffers = {};
/**

View File

@@ -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);

View File

@@ -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>

View File

@@ -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

View File

@@ -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); }

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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";

View File

@@ -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;

View File

@@ -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

View File

@@ -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]; }
};
}

View File

@@ -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]; }
};
}

View File

@@ -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 {

View File

@@ -135,5 +135,5 @@ public final class Monster extends Table {
return o;
}
public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); }
};
}

View File

@@ -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)

View File

@@ -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) }

View File

@@ -39,5 +39,5 @@ public final class Stat extends Table {
int o = builder.endObject();
return o;
}
};
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -23,5 +23,5 @@ public final class Test extends Struct {
builder.putShort(a);
return builder.offset();
}
};
}

View File

@@ -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() }

View File

@@ -29,5 +29,5 @@ public final class TestSimpleTableWithEnum extends Table {
int o = builder.endObject();
return o;
}
};
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -40,5 +40,5 @@ public final class Vec3 extends Struct {
builder.putFloat(x);
return builder.offset();
}
};
}

View File

@@ -19,5 +19,5 @@ public final class Monster extends Table {
int o = builder.endObject();
return o;
}
};
}

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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()); }

View File

@@ -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 || {};
/**

View File

@@ -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]; }
};
}

View File

@@ -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)

View File

@@ -22,5 +22,5 @@ public final class StructInNestedNS extends Struct {
builder.putInt(a);
return builder.offset();
}
};
}

View File

@@ -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() }

View File

@@ -29,5 +29,5 @@ public final class TableInNestedNS extends Table {
int o = builder.endObject();
return o;
}
};
}

View File

@@ -29,5 +29,5 @@ public final class SecondTableInA extends Table {
int o = builder.endObject();
return o;
}
};
}

View File

@@ -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 {

View File

@@ -28,5 +28,5 @@ public final class TableInFirstNS extends Table {
int o = builder.endObject();
return o;
}
};
}

View File

@@ -34,5 +34,5 @@ public final class TableInC extends Table {
int o = builder.endObject();
return o;
}
};
}

View File

@@ -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();

View File

@@ -2,12 +2,14 @@
/**
* @const
*/
* @namespace
*/
var NamespaceA = NamespaceA || {};
/**
* @const
*/
* @namespace
*/
NamespaceA.NamespaceB = NamespaceA.NamespaceB || {};
/**

View File

@@ -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_

View File

@@ -2,17 +2,20 @@
/**
* @const
*/
* @namespace
*/
var NamespaceA = NamespaceA || {};
/**
* @const
*/
* @namespace
*/
NamespaceA.NamespaceB = NamespaceA.NamespaceB || {};
/**
* @const
*/
* @namespace
*/
var NamespaceC = NamespaceC || {};
/**

View File

@@ -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. '''

View File

@@ -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");