Commit b062af4c authored by Maor Itzkovitch's avatar Maor Itzkovitch

rebased fork

parents 09567197 e1511605
...@@ -25,6 +25,7 @@ set(FlatBuffers_Library_SRCS ...@@ -25,6 +25,7 @@ set(FlatBuffers_Library_SRCS
include/flatbuffers/reflection_generated.h include/flatbuffers/reflection_generated.h
src/idl_parser.cpp src/idl_parser.cpp
src/idl_gen_text.cpp src/idl_gen_text.cpp
src/reflection.cpp
) )
set(FlatBuffers_Compiler_SRCS set(FlatBuffers_Compiler_SRCS
...@@ -43,14 +44,9 @@ set(FlatHash_SRCS ...@@ -43,14 +44,9 @@ set(FlatHash_SRCS
) )
set(FlatBuffers_Tests_SRCS set(FlatBuffers_Tests_SRCS
include/flatbuffers/flatbuffers.h ${FlatBuffers_Library_SRCS}
include/flatbuffers/hash.h
include/flatbuffers/idl.h
include/flatbuffers/util.h
src/idl_parser.cpp
src/idl_gen_general.cpp
src/idl_gen_text.cpp
src/idl_gen_fbs.cpp src/idl_gen_fbs.cpp
src/idl_gen_general.cpp
tests/test.cpp tests/test.cpp
# file generate by running compiler on tests/monster_test.fbs # file generate by running compiler on tests/monster_test.fbs
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h ${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
......
...@@ -31,7 +31,9 @@ LOCAL_SRC_FILES := main.cpp \ ...@@ -31,7 +31,9 @@ LOCAL_SRC_FILES := main.cpp \
../../tests/test.cpp \ ../../tests/test.cpp \
../../src/idl_parser.cpp \ ../../src/idl_parser.cpp \
../../src/idl_gen_text.cpp \ ../../src/idl_gen_text.cpp \
../../src/idl_gen_fbs.cpp ../../src/idl_gen_fbs.cpp \
../../src/idl_gen_general.cpp \
../../src/reflection.cpp
LOCAL_LDLIBS := -llog -landroid LOCAL_LDLIBS := -llog -landroid
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers
LOCAL_ARM_MODE := arm LOCAL_ARM_MODE := arm
......
...@@ -66,7 +66,7 @@ FLATBUFFERS_FLATC_PATH?=$(FLATBUFFERS_CMAKELISTS_DIR) ...@@ -66,7 +66,7 @@ FLATBUFFERS_FLATC_PATH?=$(FLATBUFFERS_CMAKELISTS_DIR)
FLATBUFFERS_FLATC := $(FLATBUFFERS_FLATC_PATH)/Debug/flatc FLATBUFFERS_FLATC := $(FLATBUFFERS_FLATC_PATH)/Debug/flatc
endif endif
FLATBUFFERS_FLATC_ARGS?=--gen-includes FLATBUFFERS_FLATC_ARGS?=
# Search for cmake. # Search for cmake.
CMAKE_ROOT := $(realpath $(LOCAL_PATH)/../../../../../../prebuilts/cmake) CMAKE_ROOT := $(realpath $(LOCAL_PATH)/../../../../../../prebuilts/cmake)
......
...@@ -272,6 +272,7 @@ ...@@ -272,6 +272,7 @@
<ClCompile Include="..\..\src\idl_gen_general.cpp" /> <ClCompile Include="..\..\src\idl_gen_general.cpp" />
<ClCompile Include="..\..\src\idl_parser.cpp" /> <ClCompile Include="..\..\src\idl_parser.cpp" />
<ClCompile Include="..\..\src\idl_gen_text.cpp" /> <ClCompile Include="..\..\src\idl_gen_text.cpp" />
<ClCompile Include="..\..\src\reflection.cpp" />
<ClCompile Include="..\..\tests\test.cpp" /> <ClCompile Include="..\..\tests\test.cpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
......
...@@ -12,8 +12,9 @@ ...@@ -12,8 +12,9 @@
61823BBC53544106B6DBC38E /* idl_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3709AC883348409592530AE6 /* idl_parser.cpp */; settings = {COMPILER_FLAGS = ""; }; }; 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 = ""; }; }; 61FF3C34FBEC4819A1C30F92 /* sample_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ECCEBFFA6977404F858F9739 /* sample_text.cpp */; settings = {COMPILER_FLAGS = ""; }; };
8C303C591975D6A700D7C1C5 /* idl_gen_go.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C303C581975D6A700D7C1C5 /* idl_gen_go.cpp */; }; 8C303C591975D6A700D7C1C5 /* idl_gen_go.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C303C581975D6A700D7C1C5 /* idl_gen_go.cpp */; };
8C6905F819F835A900CB8866 /* idl_gen_fbs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C6905F119F835A900CB8866 /* idl_gen_fbs.cpp */; };
8C6905FD19F835B400CB8866 /* idl_gen_fbs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C6905EC19F8357300CB8866 /* idl_gen_fbs.cpp */; }; 8C6905FD19F835B400CB8866 /* idl_gen_fbs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C6905EC19F8357300CB8866 /* idl_gen_fbs.cpp */; };
8C8774631B703D4800E693F5 /* reflection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C8774621B703D4800E693F5 /* reflection.cpp */; };
8C8774641B703E1200E693F5 /* idl_gen_fbs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C6905EC19F8357300CB8866 /* idl_gen_fbs.cpp */; };
8CA854B31B04244A00040A06 /* idl_gen_python.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CA854B21B04244A00040A06 /* idl_gen_python.cpp */; }; 8CA854B31B04244A00040A06 /* idl_gen_python.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CA854B21B04244A00040A06 /* idl_gen_python.cpp */; };
8CD8717B19CB937D0012A827 /* idl_gen_general.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */; }; 8CD8717B19CB937D0012A827 /* idl_gen_general.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */; };
A9C9A99F719A4ED58DC2D2FC /* idl_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3709AC883348409592530AE6 /* idl_parser.cpp */; settings = {COMPILER_FLAGS = ""; }; }; A9C9A99F719A4ED58DC2D2FC /* idl_parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3709AC883348409592530AE6 /* idl_parser.cpp */; settings = {COMPILER_FLAGS = ""; }; };
...@@ -33,23 +34,15 @@ ...@@ -33,23 +34,15 @@
3709AC883348409592530AE6 /* idl_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_parser.cpp; path = src/idl_parser.cpp; sourceTree = SOURCE_ROOT; }; 3709AC883348409592530AE6 /* idl_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_parser.cpp; path = src/idl_parser.cpp; sourceTree = SOURCE_ROOT; };
3863042BCEC64791BFB48625 /* flatsamplebinary */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = flatsamplebinary; sourceTree = BUILT_PRODUCTS_DIR; }; 3863042BCEC64791BFB48625 /* flatsamplebinary */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = flatsamplebinary; sourceTree = BUILT_PRODUCTS_DIR; };
420E3BC724ED4A008D79297F /* flatsampletext */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = flatsampletext; sourceTree = BUILT_PRODUCTS_DIR; }; 420E3BC724ED4A008D79297F /* flatsampletext */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = flatsampletext; sourceTree = BUILT_PRODUCTS_DIR; };
423CA92401AE442B91546E63 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = /Users/wvo/flatbuffers_snapshot9/CMakeLists.txt; sourceTree = "<absolute>"; };
5EE44BFFAF8E43F485859145 /* sample_binary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sample_binary.cpp; path = samples/sample_binary.cpp; sourceTree = SOURCE_ROOT; }; 5EE44BFFAF8E43F485859145 /* sample_binary.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sample_binary.cpp; path = samples/sample_binary.cpp; sourceTree = SOURCE_ROOT; };
6AD24EEB3D024825A37741FF /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test.cpp; path = tests/test.cpp; sourceTree = SOURCE_ROOT; }; 6AD24EEB3D024825A37741FF /* test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = test.cpp; path = tests/test.cpp; sourceTree = SOURCE_ROOT; };
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>"; }; 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>"; };
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>"; }; 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>"; };
8C6905EF19F835A900CB8866 /* flatc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flatc.cpp; sourceTree = "<group>"; }; 8C8774621B703D4800E693F5 /* reflection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = reflection.cpp; path = src/reflection.cpp; sourceTree = "<group>"; };
8C6905F019F835A900CB8866 /* idl_gen_cpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idl_gen_cpp.cpp; sourceTree = "<group>"; };
8C6905F119F835A900CB8866 /* idl_gen_fbs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idl_gen_fbs.cpp; sourceTree = "<group>"; };
8C6905F219F835A900CB8866 /* idl_gen_general.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idl_gen_general.cpp; sourceTree = "<group>"; };
8C6905F319F835A900CB8866 /* idl_gen_go.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idl_gen_go.cpp; sourceTree = "<group>"; };
8C6905F419F835A900CB8866 /* idl_gen_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idl_gen_text.cpp; sourceTree = "<group>"; };
8C6905F519F835A900CB8866 /* idl_parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idl_parser.cpp; sourceTree = "<group>"; };
8CA854B21B04244A00040A06 /* idl_gen_python.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_python.cpp; path = src/idl_gen_python.cpp; sourceTree = "<group>"; }; 8CA854B21B04244A00040A06 /* idl_gen_python.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_python.cpp; path = src/idl_gen_python.cpp; sourceTree = "<group>"; };
8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_general.cpp; path = src/idl_gen_general.cpp; sourceTree = "<group>"; }; 8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_general.cpp; path = src/idl_gen_general.cpp; sourceTree = "<group>"; };
A13F25CDAD23435DA293690D /* flattests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = flattests; sourceTree = BUILT_PRODUCTS_DIR; }; A13F25CDAD23435DA293690D /* flattests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; path = flattests; sourceTree = BUILT_PRODUCTS_DIR; };
AB70F1FBA50E4120BCF37C8D /* monster_test_generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = monster_test_generated.h; path = tests/monster_test_generated.h; sourceTree = SOURCE_ROOT; }; AB70F1FBA50E4120BCF37C8D /* monster_test_generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = monster_test_generated.h; path = tests/monster_test_generated.h; sourceTree = SOURCE_ROOT; };
AD3682C6E1DD4EABB822C0CC /* monster_generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = monster_generated.h; path = samples/monster_generated.h; sourceTree = SOURCE_ROOT; };
C0E7B66C3FF849A0AD9A7168 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = include/flatbuffers/util.h; sourceTree = SOURCE_ROOT; }; C0E7B66C3FF849A0AD9A7168 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = include/flatbuffers/util.h; sourceTree = SOURCE_ROOT; };
CD90A7F6B2BE4D0384294DD1 /* idl_gen_cpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_cpp.cpp; path = src/idl_gen_cpp.cpp; sourceTree = SOURCE_ROOT; }; CD90A7F6B2BE4D0384294DD1 /* idl_gen_cpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = idl_gen_cpp.cpp; path = src/idl_gen_cpp.cpp; sourceTree = SOURCE_ROOT; };
DD8B353D4756412195777FBA /* flatbuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = flatbuffers.h; path = include/flatbuffers/flatbuffers.h; sourceTree = SOURCE_ROOT; }; DD8B353D4756412195777FBA /* flatbuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = flatbuffers.h; path = include/flatbuffers/flatbuffers.h; sourceTree = SOURCE_ROOT; };
...@@ -58,13 +51,6 @@ ...@@ -58,13 +51,6 @@
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
194905BCBB5C451DB092EB08 /* Resources */ = {
isa = PBXGroup;
children = (
);
name = Resources;
sourceTree = "<group>";
};
28237E300FE042DEADA302D3 /* Source Files */ = { 28237E300FE042DEADA302D3 /* Source Files */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
...@@ -72,19 +58,10 @@ ...@@ -72,19 +58,10 @@
8C6905EC19F8357300CB8866 /* idl_gen_fbs.cpp */, 8C6905EC19F8357300CB8866 /* idl_gen_fbs.cpp */,
8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */, 8CD8717A19CB937D0012A827 /* idl_gen_general.cpp */,
8C303C581975D6A700D7C1C5 /* idl_gen_go.cpp */, 8C303C581975D6A700D7C1C5 /* idl_gen_go.cpp */,
0DFD29781D8E490284B06504 /* flatc.cpp */,
CD90A7F6B2BE4D0384294DD1 /* idl_gen_cpp.cpp */,
);
name = "Source Files";
sourceTree = "<group>";
};
355DCA17961E4B2FB2C71403 /* Source Files */ = {
isa = PBXGroup;
children = (
8C6905EE19F835A900CB8866 /* src */,
F6C5D81DBF864365B12E269D /* idl_gen_text.cpp */, F6C5D81DBF864365B12E269D /* idl_gen_text.cpp */,
3709AC883348409592530AE6 /* idl_parser.cpp */, 3709AC883348409592530AE6 /* idl_parser.cpp */,
6AD24EEB3D024825A37741FF /* test.cpp */, CD90A7F6B2BE4D0384294DD1 /* idl_gen_cpp.cpp */,
8C8774621B703D4800E693F5 /* reflection.cpp */,
); );
name = "Source Files"; name = "Source Files";
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -92,49 +69,17 @@ ...@@ -92,49 +69,17 @@
378446B9D5EF46EF92B35E21 /* flatc */ = { 378446B9D5EF46EF92B35E21 /* flatc */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5FEA84E7D39645988300317C /* Header Files */, 0DFD29781D8E490284B06504 /* flatc.cpp */,
28237E300FE042DEADA302D3 /* Source Files */,
); );
name = flatc; name = flatc;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
40E30B8480BD493EA459E9B4 /* Header Files */ = { 5FEA84E7D39645988300317C /* Header Files */ = {
isa = PBXGroup;
children = (
AD3682C6E1DD4EABB822C0CC /* monster_generated.h */,
);
name = "Header Files";
sourceTree = "<group>";
};
4D1151F6FE594E40A1C177FF /* Header Files */ = {
isa = PBXGroup;
children = (
);
name = "Header Files";
sourceTree = "<group>";
};
5235469653ED4BC88A6C504D /* Header Files */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
DD8B353D4756412195777FBA /* flatbuffers.h */, DD8B353D4756412195777FBA /* flatbuffers.h */,
00154BD8654B4B5B9FF45FA6 /* idl.h */, 00154BD8654B4B5B9FF45FA6 /* idl.h */,
C0E7B66C3FF849A0AD9A7168 /* util.h */, C0E7B66C3FF849A0AD9A7168 /* util.h */,
AB70F1FBA50E4120BCF37C8D /* monster_test_generated.h */,
);
name = "Header Files";
sourceTree = "<group>";
};
5648A71028E14478841372D3 /* Source Files */ = {
isa = PBXGroup;
children = (
5EE44BFFAF8E43F485859145 /* sample_binary.cpp */,
);
name = "Source Files";
sourceTree = "<group>";
};
5FEA84E7D39645988300317C /* Header Files */ = {
isa = PBXGroup;
children = (
); );
name = "Header Files"; name = "Header Files";
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -142,6 +87,8 @@ ...@@ -142,6 +87,8 @@
866694F9F2F7451382D236B3 /* Sources */ = { 866694F9F2F7451382D236B3 /* Sources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
28237E300FE042DEADA302D3 /* Source Files */,
5FEA84E7D39645988300317C /* Header Files */,
378446B9D5EF46EF92B35E21 /* flatc */, 378446B9D5EF46EF92B35E21 /* flatc */,
DB9DE41C20F349F694A488F3 /* flatsamplebinary */, DB9DE41C20F349F694A488F3 /* flatsamplebinary */,
8FA1F43C78914AE5AD04E24E /* flatsampletext */, 8FA1F43C78914AE5AD04E24E /* flatsampletext */,
...@@ -153,31 +100,16 @@ ...@@ -153,31 +100,16 @@
88421F5F87584EE3B67C979A /* flattests */ = { 88421F5F87584EE3B67C979A /* flattests */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5235469653ED4BC88A6C504D /* Header Files */, AB70F1FBA50E4120BCF37C8D /* monster_test_generated.h */,
355DCA17961E4B2FB2C71403 /* Source Files */, 6AD24EEB3D024825A37741FF /* test.cpp */,
); );
name = flattests; name = flattests;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
8C6905EE19F835A900CB8866 /* src */ = {
isa = PBXGroup;
children = (
8C6905EF19F835A900CB8866 /* flatc.cpp */,
8C6905F019F835A900CB8866 /* idl_gen_cpp.cpp */,
8C6905F119F835A900CB8866 /* idl_gen_fbs.cpp */,
8C6905F219F835A900CB8866 /* idl_gen_general.cpp */,
8C6905F319F835A900CB8866 /* idl_gen_go.cpp */,
8C6905F419F835A900CB8866 /* idl_gen_text.cpp */,
8C6905F519F835A900CB8866 /* idl_parser.cpp */,
);
path = src;
sourceTree = "<group>";
};
8F5E926B72104F4194B3BD5A = { 8F5E926B72104F4194B3BD5A = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
866694F9F2F7451382D236B3 /* Sources */, 866694F9F2F7451382D236B3 /* Sources */,
194905BCBB5C451DB092EB08 /* Resources */,
99CC11E382B8420AA79A8A14 /* Products */, 99CC11E382B8420AA79A8A14 /* Products */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -185,8 +117,7 @@ ...@@ -185,8 +117,7 @@
8FA1F43C78914AE5AD04E24E /* flatsampletext */ = { 8FA1F43C78914AE5AD04E24E /* flatsampletext */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
40E30B8480BD493EA459E9B4 /* Header Files */, ECCEBFFA6977404F858F9739 /* sample_text.cpp */,
A1C826615F904FDE8F0CA154 /* Source Files */,
); );
name = flatsampletext; name = flatsampletext;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -202,20 +133,10 @@ ...@@ -202,20 +133,10 @@
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A1C826615F904FDE8F0CA154 /* Source Files */ = {
isa = PBXGroup;
children = (
ECCEBFFA6977404F858F9739 /* sample_text.cpp */,
);
name = "Source Files";
sourceTree = "<group>";
};
DB9DE41C20F349F694A488F3 /* flatsamplebinary */ = { DB9DE41C20F349F694A488F3 /* flatsamplebinary */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
4D1151F6FE594E40A1C177FF /* Header Files */, 5EE44BFFAF8E43F485859145 /* sample_binary.cpp */,
5648A71028E14478841372D3 /* Source Files */,
423CA92401AE442B91546E63 /* CMakeLists.txt */,
); );
name = flatsamplebinary; name = flatsamplebinary;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -338,8 +259,8 @@ ...@@ -338,8 +259,8 @@
AA9BACF55EB3456BA2F633BB /* flatc.cpp in Sources */, AA9BACF55EB3456BA2F633BB /* flatc.cpp in Sources */,
BE03D7B0C9584DD58B50ED34 /* idl_gen_cpp.cpp in Sources */, BE03D7B0C9584DD58B50ED34 /* idl_gen_cpp.cpp in Sources */,
AD71FEBEE4E846529002C1F0 /* idl_gen_text.cpp in Sources */, AD71FEBEE4E846529002C1F0 /* idl_gen_text.cpp in Sources */,
8C8774641B703E1200E693F5 /* idl_gen_fbs.cpp in Sources */,
A9C9A99F719A4ED58DC2D2FC /* idl_parser.cpp in Sources */, A9C9A99F719A4ED58DC2D2FC /* idl_parser.cpp in Sources */,
8C6905F819F835A900CB8866 /* idl_gen_fbs.cpp in Sources */,
8CA854B31B04244A00040A06 /* idl_gen_python.cpp in Sources */, 8CA854B31B04244A00040A06 /* idl_gen_python.cpp in Sources */,
8CD8717B19CB937D0012A827 /* idl_gen_general.cpp in Sources */, 8CD8717B19CB937D0012A827 /* idl_gen_general.cpp in Sources */,
); );
...@@ -349,6 +270,7 @@ ...@@ -349,6 +270,7 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
8C8774631B703D4800E693F5 /* reflection.cpp in Sources */,
5AC48C391ACA9A0A008132C5 /* idl_gen_general.cpp in Sources */, 5AC48C391ACA9A0A008132C5 /* idl_gen_general.cpp in Sources */,
8C6905FD19F835B400CB8866 /* idl_gen_fbs.cpp in Sources */, 8C6905FD19F835B400CB8866 /* idl_gen_fbs.cpp in Sources */,
E0680D6B5BFD484BA9D88EE8 /* idl_gen_text.cpp in Sources */, E0680D6B5BFD484BA9D88EE8 /* idl_gen_text.cpp in Sources */,
......
...@@ -21,7 +21,7 @@ $extrastylesheet ...@@ -21,7 +21,7 @@ $extrastylesheet
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA--> <!--BEGIN TITLEAREA-->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -36,6 +36,9 @@ $extrastylesheet ...@@ -36,6 +36,9 @@ $extrastylesheet
<div id="projectname">$projectname <div id="projectname">$projectname
<!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER--> <!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF--> <!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
</td> </td>
<!--END PROJECT_NAME--> <!--END PROJECT_NAME-->
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -75,7 +78,7 @@ $(document).ready(function(){initNavTree('md__compiler.html','');}); ...@@ -75,7 +78,7 @@ $(document).ready(function(){initNavTree('md__compiler.html','');});
<li><code>--strict-json</code> : Require &amp; generate strict JSON (field names are enclosed in quotes, no trailing commas in tables/vectors). By default, no quotes are required/generated, and trailing commas are allowed.</li> <li><code>--strict-json</code> : Require &amp; generate strict JSON (field names are enclosed in quotes, no trailing commas in tables/vectors). By default, no quotes are required/generated, and trailing commas are allowed.</li>
<li><code>--defaults-json</code> : Output fields whose value is equal to the default value when writing JSON text.</li> <li><code>--defaults-json</code> : Output fields whose value is equal to the default value when writing JSON text.</li>
<li><code>--no-prefix</code> : Don't prefix enum values in generated C++ by their enum type.</li> <li><code>--no-prefix</code> : Don't prefix enum values in generated C++ by their enum type.</li>
<li><code>--gen-includes</code> : (deprecated), instead use:</li> <li><code>--gen-includes</code> : (deprecated), this is the default behavior. If the original behavior is required (no include statements) use <code>--no-includes.</code></li>
<li><code>--no-includes</code> : Don't generate include statements for included schemas the generated file depends on (C++).</li> <li><code>--no-includes</code> : Don't generate include statements for included schemas the generated file depends on (C++).</li>
<li><code>--gen-mutable</code> : Generate additional non-const accessors for mutating FlatBuffers in-place.</li> <li><code>--gen-mutable</code> : Generate additional non-const accessors for mutating FlatBuffers in-place.</li>
<li><code>--gen-onefile</code> : Generate single output file (useful for C#)</li> <li><code>--gen-onefile</code> : Generate single output file (useful for C#)</li>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/> <meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/> <meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.7"/> <meta name="generator" content="Doxygen 1.8.7"/>
<title>FlatBuffers: Formal Grammar of the schema language</title> <title>FlatBuffers: Grammar of the schema language</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/> <link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script> <script type="text/javascript" src="dynsections.js"></script>
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -55,7 +58,7 @@ $(document).ready(function(){initNavTree('md__grammar.html','');}); ...@@ -55,7 +58,7 @@ $(document).ready(function(){initNavTree('md__grammar.html','');});
<div id="doc-content"> <div id="doc-content">
<div class="header"> <div class="header">
<div class="headertitle"> <div class="headertitle">
<div class="title">Formal Grammar of the schema language </div> </div> <div class="title">Grammar of the schema language </div> </div>
</div><!--header--> </div><!--header-->
<div class="contents"> <div class="contents">
<div class="textblock"><p>schema = include* ( namespace_decl | type_decl | enum_decl | root_decl | file_extension_decl | file_identifier_decl | attribute_decl | object )*</p> <div class="textblock"><p>schema = include* ( namespace_decl | type_decl | enum_decl | root_decl | file_extension_decl | file_identifier_decl | attribute_decl | object )*</p>
...@@ -68,13 +71,16 @@ $(document).ready(function(){initNavTree('md__grammar.html','');}); ...@@ -68,13 +71,16 @@ $(document).ready(function(){initNavTree('md__grammar.html','');});
<p>field_decl = ident <code>:</code> type [ <code>=</code> scalar ] metadata <code>;</code></p> <p>field_decl = ident <code>:</code> type [ <code>=</code> scalar ] metadata <code>;</code></p>
<p>type = <code>bool</code> | <code>byte</code> | <code>ubyte</code> | <code>short</code> | <code>ushort</code> | <code>int</code> | <code>uint</code> | <code>float</code> | <code>long</code> | <code>ulong</code> | <code>double</code> | <code>string</code> | <code>[</code> type <code>]</code> | ident</p> <p>type = <code>bool</code> | <code>byte</code> | <code>ubyte</code> | <code>short</code> | <code>ushort</code> | <code>int</code> | <code>uint</code> | <code>float</code> | <code>long</code> | <code>ulong</code> | <code>double</code> | <code>string</code> | <code>[</code> type <code>]</code> | ident</p>
<p>enumval_decl = ident [ <code>=</code> integer_constant ]</p> <p>enumval_decl = ident [ <code>=</code> integer_constant ]</p>
<p>metadata = [ <code>(</code> commasep( ident [ <code>:</code> scalar ] ) <code>)</code> ]</p> <p>metadata = [ <code>(</code> commasep( ident [ <code>:</code> single_value ] ) <code>)</code> ]</p>
<p>scalar = integer_constant | float_constant | <code>true</code> | <code>false</code></p> <p>scalar = integer_constant | float_constant</p>
<p>object = { commasep( ident <code>:</code> value ) }</p> <p>object = { commasep( ident <code>:</code> value ) }</p>
<p>value = scalar | object | string_constant | <code>[</code> commasep( value ) <code>]</code></p> <p>single_value = scalar | string_constant</p>
<p>value = single_value | object | <code>[</code> commasep( value ) <code>]</code></p>
<p>commasep(x) = [ x ( <code>,</code> x )* ]</p> <p>commasep(x) = [ x ( <code>,</code> x )* ]</p>
<p>file_extension_decl = <code>file_extension</code> string_constant <code>;</code></p> <p>file_extension_decl = <code>file_extension</code> string_constant <code>;</code></p>
<p>file_identifier_decl = <code>file_identifier</code> string_constant <code>;</code> </p> <p>file_identifier_decl = <code>file_identifier</code> string_constant <code>;</code></p>
<p>integer_constant = -?[0-9]+ | <code>true</code> | <code>false</code></p>
<p>float_constant = -?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)? </p>
</div></div><!-- contents --> </div></div><!-- contents -->
</div><!-- doc-content --> </div><!-- doc-content -->
<!-- Google Analytics --> <!-- Google Analytics -->
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
......
...@@ -11,7 +11,7 @@ var NAVTREE = ...@@ -11,7 +11,7 @@ var NAVTREE =
[ "Benchmarks", "md__benchmarks.html", null ], [ "Benchmarks", "md__benchmarks.html", null ],
[ "FlatBuffers white paper", "md__white_paper.html", null ], [ "FlatBuffers white paper", "md__white_paper.html", null ],
[ "FlatBuffer Internals", "md__internals.html", null ], [ "FlatBuffer Internals", "md__internals.html", null ],
[ "Formal Grammar of the schema language", "md__grammar.html", null ] [ "Grammar of the schema language", "md__grammar.html", null ]
] ] ] ]
]; ];
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
</head> </head>
<body> <body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! --> <div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea"> <div id="titlearea" style="height: 110px;">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 56px;">
...@@ -31,6 +31,9 @@ ...@@ -31,6 +31,9 @@
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">
<div id="projectname">FlatBuffers <div id="projectname">FlatBuffers
</div> </div>
<div style="font-size:12px;">
An open source project by <a href="https://developers.google.com/games/#Tools">FPL</a>.
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
...@@ -70,7 +73,7 @@ $(document).ready(function(){initNavTree('pages.html','');}); ...@@ -70,7 +73,7 @@ $(document).ready(function(){initNavTree('pages.html','');});
<tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__benchmarks.html" target="_self">Benchmarks</a></td><td class="desc"></td></tr> <tr id="row_7_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__benchmarks.html" target="_self">Benchmarks</a></td><td class="desc"></td></tr>
<tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__white_paper.html" target="_self">FlatBuffers white paper</a></td><td class="desc"></td></tr> <tr id="row_8_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__white_paper.html" target="_self">FlatBuffers white paper</a></td><td class="desc"></td></tr>
<tr id="row_9_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__internals.html" target="_self">FlatBuffer Internals</a></td><td class="desc"></td></tr> <tr id="row_9_"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__internals.html" target="_self">FlatBuffer Internals</a></td><td class="desc"></td></tr>
<tr id="row_10_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__grammar.html" target="_self">Formal Grammar of the schema language</a></td><td class="desc"></td></tr> <tr id="row_10_" class="even"><td class="entry"><span style="width:16px;display:inline-block;">&#160;</span><a class="el" href="md__grammar.html" target="_self">Grammar of the schema language</a></td><td class="desc"></td></tr>
</table> </table>
</div><!-- directory --> </div><!-- directory -->
</div><!-- contents --> </div><!-- contents -->
......
...@@ -51,7 +51,10 @@ be generated for each file processed: ...@@ -51,7 +51,10 @@ be generated for each file processed:
- `--no-prefix` : Don't prefix enum values in generated C++ by their enum - `--no-prefix` : Don't prefix enum values in generated C++ by their enum
type. type.
- `--gen-includes` : (deprecated), instead use: - `--gen-includes` : (deprecated), this is the default behavior.
If the original behavior is required (no include
statements) use `--no-includes.`
- `--no-includes` : Don't generate include statements for included schemas the - `--no-includes` : Don't generate include statements for included schemas the
generated file depends on (C++). generated file depends on (C++).
......
# Formal Grammar of the schema language # Grammar of the schema language
schema = include* schema = include*
( namespace\_decl | type\_decl | enum\_decl | root\_decl | ( namespace\_decl | type\_decl | enum\_decl | root\_decl |
...@@ -26,13 +26,15 @@ type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` | ...@@ -26,13 +26,15 @@ type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
enumval\_decl = ident [ `=` integer\_constant ] enumval\_decl = ident [ `=` integer\_constant ]
metadata = [ `(` commasep( ident [ `:` scalar ] ) `)` ] metadata = [ `(` commasep( ident [ `:` single\_value ] ) `)` ]
scalar = integer\_constant | float\_constant | `true` | `false` scalar = integer\_constant | float\_constant
object = { commasep( ident `:` value ) } object = { commasep( ident `:` value ) }
value = scalar | object | string\_constant | `[` commasep( value ) `]` single\_value = scalar | string\_constant
value = single\_value | object | `[` commasep( value ) `]`
commasep(x) = [ x ( `,` x )\* ] commasep(x) = [ x ( `,` x )\* ]
...@@ -40,3 +42,6 @@ file_extension_decl = `file_extension` string\_constant `;` ...@@ -40,3 +42,6 @@ file_extension_decl = `file_extension` string\_constant `;`
file_identifier_decl = `file_identifier` string\_constant `;` file_identifier_decl = `file_identifier` string\_constant `;`
integer\_constant = -?[0-9]+ | `true` | `false`
float\_constant = -?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?
...@@ -293,11 +293,21 @@ public: ...@@ -293,11 +293,21 @@ public:
const_iterator end() const { return const_iterator(Data(), size()); } const_iterator end() const { return const_iterator(Data(), size()); }
// Change elements if you have a non-const pointer to this object. // Change elements if you have a non-const pointer to this object.
// Scalars only. See reflection.h, and the documentation.
void Mutate(uoffset_t i, T val) { void Mutate(uoffset_t i, T val) {
assert(i < size()); assert(i < size());
WriteScalar(data() + i, val); WriteScalar(data() + i, val);
} }
// Change an element of a vector of tables (or strings).
// "val" points to the new table/string, as you can obtain from
// e.g. reflection::AddFlatBuffer().
void MutateOffset(uoffset_t i, const uint8_t *val) {
assert(i < size());
assert(sizeof(T) == sizeof(uoffset_t));
WriteScalar(data() + i, val - (Data() + i * sizeof(uoffset_t)));
}
// The raw data in little endian format. Use with care. // The raw data in little endian format. Use with care.
const uint8_t *Data() const { const uint8_t *Data() const {
return reinterpret_cast<const uint8_t *>(&length_ + 1); return reinterpret_cast<const uint8_t *>(&length_ + 1);
...@@ -343,6 +353,24 @@ private: ...@@ -343,6 +353,24 @@ private:
} }
}; };
// Represent a vector much like the template above, but in this case we
// don't know what the element types are (used with reflection.h).
class VectorOfAny {
public:
uoffset_t size() const { return EndianScalar(length_); }
const uint8_t *Data() const {
return reinterpret_cast<const uint8_t *>(&length_ + 1);
}
uint8_t *Data() {
return reinterpret_cast<uint8_t *>(&length_ + 1);
}
protected:
VectorOfAny();
uoffset_t length_;
};
// Convenient helper function to get the length of any vector, regardless // Convenient helper function to get the length of any vector, regardless
// of wether it is null or not (the field is not set). // of wether it is null or not (the field is not set).
template<typename T> static inline size_t VectorLength(const Vector<T> *v) { template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
...@@ -985,6 +1013,9 @@ class Struct FLATBUFFERS_FINAL_CLASS { ...@@ -985,6 +1013,9 @@ class Struct FLATBUFFERS_FINAL_CLASS {
return reinterpret_cast<T>(&data_[o]); return reinterpret_cast<T>(&data_[o]);
} }
const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
private: private:
uint8_t data_[1]; uint8_t data_[1];
}; };
...@@ -1017,7 +1048,6 @@ class Table { ...@@ -1017,7 +1048,6 @@ class Table {
? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p)) ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
: nullptr; : nullptr;
} }
template<typename P> P GetPointer(voffset_t field) const { template<typename P> P GetPointer(voffset_t field) const {
return const_cast<Table *>(this)->GetPointer<P>(field); return const_cast<Table *>(this)->GetPointer<P>(field);
} }
...@@ -1035,6 +1065,21 @@ class Table { ...@@ -1035,6 +1065,21 @@ class Table {
return true; return true;
} }
bool SetPointer(voffset_t field, const uint8_t *val) {
auto field_offset = GetOptionalFieldOffset(field);
if (!field_offset) return false;
WriteScalar(data_ + field_offset, val - (data_ + field_offset));
return true;
}
uint8_t *GetAddressOf(voffset_t field) {
auto field_offset = GetOptionalFieldOffset(field);
return field_offset ? data_ + field_offset : nullptr;
}
const uint8_t *GetAddressOf(voffset_t field) const {
return const_cast<Table *>(this)->GetAddressOf(field);
}
uint8_t *GetVTable() { return data_ - ReadScalar<soffset_t>(data_); } uint8_t *GetVTable() { return data_ - ReadScalar<soffset_t>(data_); }
bool CheckField(voffset_t field) const { bool CheckField(voffset_t field) const {
......
...@@ -50,8 +50,8 @@ namespace flatbuffers { ...@@ -50,8 +50,8 @@ namespace flatbuffers {
TD(FLOAT, "float", float, float, float32, float, float32) /* begin float */ \ TD(FLOAT, "float", float, float, float32, float, float32) /* begin float */ \
TD(DOUBLE, "double", double, double, float64, double, float64) /* end float/scalar */ TD(DOUBLE, "double", double, double, float64, double, float64) /* end float/scalar */
#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \ #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
TD(STRING, "string", Offset<void>, int, int, int, int) \ TD(STRING, "string", Offset<void>, int, int, StringOffset, int) \
TD(VECTOR, "", Offset<void>, int, int, int, int) \ TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int) \
TD(STRUCT, "", Offset<void>, int, int, int, int) \ TD(STRUCT, "", Offset<void>, int, int, int, int) \
TD(UNION, "", Offset<void>, int, int, int, int) TD(UNION, "", Offset<void>, int, int, int, int)
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#ifndef FLATBUFFERS_REFLECTION_H_ #ifndef FLATBUFFERS_REFLECTION_H_
#define FLATBUFFERS_REFLECTION_H_ #define FLATBUFFERS_REFLECTION_H_
#include "flatbuffers/util.h"
// This is somewhat of a circular dependency because flatc (and thus this // This is somewhat of a circular dependency because flatc (and thus this
// file) is needed to generate this header in the first place. // file) is needed to generate this header in the first place.
// Should normally not be a problem since it can be generated by the // Should normally not be a problem since it can be generated by the
...@@ -30,12 +28,28 @@ ...@@ -30,12 +28,28 @@
namespace flatbuffers { namespace flatbuffers {
// ------------------------- GETTERS -------------------------
// Size of a basic type, don't use with structs.
inline size_t GetTypeSize(reflection::BaseType base_type) { inline size_t GetTypeSize(reflection::BaseType base_type) {
// This needs to correspond to the BaseType enum. // This needs to correspond to the BaseType enum.
static size_t sizes[] = { 0, 1, 1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 4, 4, 4, 4 }; static size_t sizes[] = { 0, 1, 1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 4, 4, 4, 4 };
return sizes[base_type]; return sizes[base_type];
} }
// Same as above, but now correctly returns the size of a struct if
// the field (or vector element) is a struct.
inline size_t GetTypeSizeInline(reflection::BaseType base_type,
int type_index,
const reflection::Schema &schema) {
if (base_type == reflection::Obj &&
schema.objects()->Get(type_index)->is_struct()) {
return schema.objects()->Get(type_index)->bytesize();
} else {
return GetTypeSize(base_type);
}
}
// Get the root, regardless of what type it is. // Get the root, regardless of what type it is.
inline Table *GetAnyRoot(uint8_t *flatbuf) { inline Table *GetAnyRoot(uint8_t *flatbuf) {
return GetMutableRoot<Table>(flatbuf); return GetMutableRoot<Table>(flatbuf);
...@@ -68,108 +82,147 @@ inline const String *GetFieldS(const Table &table, ...@@ -68,108 +82,147 @@ inline const String *GetFieldS(const Table &table,
} }
// Get a field, if you know it's a vector. // Get a field, if you know it's a vector.
template<typename T> const Vector<T> *GetFieldV(const Table &table, template<typename T> Vector<T> *GetFieldV(const Table &table,
const reflection::Field &field) { const reflection::Field &field) {
assert(field.type()->base_type() == reflection::Vector && assert(field.type()->base_type() == reflection::Vector &&
sizeof(T) == GetTypeSize(field.type()->element())); sizeof(T) == GetTypeSize(field.type()->element()));
return table.GetPointer<const Vector<T> *>(field.offset()); return table.GetPointer<Vector<T> *>(field.offset());
}
// Get a field, if you know it's a vector, generically.
// To actually access elements, use the return value together with
// field.type()->element() in any of GetAnyVectorElemI below etc.
inline VectorOfAny *GetFieldAnyV(const Table &table,
const reflection::Field &field) {
return table.GetPointer<VectorOfAny *>(field.offset());
} }
// Get a field, if you know it's a table. // Get a field, if you know it's a table.
inline const Table *GetFieldT(const Table &table, inline Table *GetFieldT(const Table &table,
const reflection::Field &field) { const reflection::Field &field) {
assert(field.type()->base_type() == reflection::Obj || assert(field.type()->base_type() == reflection::Obj ||
field.type()->base_type() == reflection::Union); field.type()->base_type() == reflection::Union);
return table.GetPointer<const Table *>(field.offset()); return table.GetPointer<Table *>(field.offset());
} }
// Get any field as a 64bit int, regardless of what it is (bool/int/float/str). // Raw helper functions used below: get any value in memory as a 64bit int, a
// double or a string.
// All scalars get static_cast to an int64_t, strings use strtoull, every other
// data type returns 0.
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data);
// All scalars static cast to double, strings use strtod, every other data
// type is 0.0.
double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
// All scalars converted using stringstream, strings as-is, and all other
// data types provide some level of debug-pretty-printing.
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
const reflection::Schema *schema,
int type_index);
// Get any table field as a 64bit int, regardless of what type it is.
inline int64_t GetAnyFieldI(const Table &table, inline int64_t GetAnyFieldI(const Table &table,
const reflection::Field &field) { const reflection::Field &field) {
# define FLATBUFFERS_GET(C, T) \ auto field_ptr = table.GetAddressOf(field.offset());
static_cast<int64_t>(GetField##C<T>(table, field)) return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr)
switch (field.type()->base_type()) { : field.default_integer();
case reflection::UType:
case reflection::Bool:
case reflection::UByte: return FLATBUFFERS_GET(I, uint8_t);
case reflection::Byte: return FLATBUFFERS_GET(I, int8_t);
case reflection::Short: return FLATBUFFERS_GET(I, int16_t);
case reflection::UShort: return FLATBUFFERS_GET(I, uint16_t);
case reflection::Int: return FLATBUFFERS_GET(I, int32_t);
case reflection::UInt: return FLATBUFFERS_GET(I, uint32_t);
case reflection::Long: return FLATBUFFERS_GET(I, int64_t);
case reflection::ULong: return FLATBUFFERS_GET(I, uint64_t);
case reflection::Float: return FLATBUFFERS_GET(F, float);
case reflection::Double: return FLATBUFFERS_GET(F, double);
case reflection::String: {
auto s = GetFieldS(table, field);
return s ? StringToInt(s->c_str()) : 0;
}
default: return 0;
}
# undef FLATBUFFERS_GET
} }
// Get any field as a double, regardless of what it is (bool/int/float/str). // Get any table field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Table &table, inline double GetAnyFieldF(const Table &table,
const reflection::Field &field) { const reflection::Field &field) {
switch (field.type()->base_type()) { auto field_ptr = table.GetAddressOf(field.offset());
case reflection::Float: return GetFieldF<float>(table, field); return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
case reflection::Double: return GetFieldF<double>(table, field); : field.default_real();
case reflection::String: {
auto s = GetFieldS(table, field);
return s ? strtod(s->c_str(), nullptr) : 0.0;
}
default: return static_cast<double>(GetAnyFieldI(table, field));
}
} }
// Get any field as a string, regardless of what it is (bool/int/float/str).
// Get any table field as a string, regardless of what type it is.
// You may pass nullptr for the schema if you don't care to have fields that
// are of table type pretty-printed.
inline std::string GetAnyFieldS(const Table &table, inline std::string GetAnyFieldS(const Table &table,
const reflection::Field &field, const reflection::Field &field,
const reflection::Schema &schema) { const reflection::Schema *schema) {
switch (field.type()->base_type()) { auto field_ptr = table.GetAddressOf(field.offset());
case reflection::Float: return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema,
case reflection::Double: return NumToString(GetAnyFieldF(table, field)); field.type()->index())
case reflection::String: { : "";
auto s = GetFieldS(table, field); }
return s ? s->c_str() : "";
} // Get any struct field as a 64bit int, regardless of what type it is.
case reflection::Obj: { inline int64_t GetAnyFieldI(const Struct &st,
// Convert the table to a string. This is mostly for debugging purposes, const reflection::Field &field) {
// and does NOT promise to be JSON compliant. return GetAnyValueI(field.type()->base_type(),
// Also prefixes the type. st.GetAddressOf(field.offset()));
auto &objectdef = *schema.objects()->Get(field.type()->index());
auto s = objectdef.name()->str();
if (objectdef.is_struct()) {
s += "(struct)"; // TODO: implement this as well.
} else {
auto table_field = GetFieldT(table, field);
s += " { ";
auto fielddefs = objectdef.fields();
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
if (!table.CheckField(fielddef.offset())) continue;
auto val = GetAnyFieldS(*table_field, fielddef, schema);
if (fielddef.type()->base_type() == reflection::String)
val = "\"" + val + "\""; // Doesn't deal with escape codes etc.
s += fielddef.name()->str();
s += ": ";
s += val;
s += ", ";
}
s += "}";
}
return s;
}
case reflection::Vector:
return "[(elements)]"; // TODO: implement this as well.
case reflection::Union:
return "(union)"; // TODO: implement this as well.
default: return NumToString(GetAnyFieldI(table, field));
}
} }
// Get any struct field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Struct &st,
const reflection::Field &field) {
return GetAnyValueF(field.type()->base_type(),
st.GetAddressOf(field.offset()));
}
// Get any struct field as a string, regardless of what type it is.
inline std::string GetAnyFieldS(const Struct &st,
const reflection::Field &field) {
return GetAnyValueS(field.type()->base_type(),
st.GetAddressOf(field.offset()), nullptr, -1);
}
// Get any vector element as a 64bit int, regardless of what type it is.
inline int64_t GetAnyVectorElemI(const VectorOfAny *vec,
reflection::BaseType elem_type, size_t i) {
return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
}
// Get any vector element as a double, regardless of what type it is.
inline double GetAnyVectorElemF(const VectorOfAny *vec,
reflection::BaseType elem_type, size_t i) {
return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i);
}
// Get any vector element as a string, regardless of what type it is.
inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
reflection::BaseType elem_type, size_t i) {
return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i,
nullptr, -1);
}
// Get a vector element that's a table/string/vector from a generic vector.
// Pass Table/String/VectorOfAny as template parameter.
// Warning: does no typechecking.
template<typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec,
size_t i) {
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
return (T *)(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
}
// Get the inline-address of a vector element. Useful for Structs (pass Struct
// as template arg), or being able to address a range of scalars in-line.
// Get elem_size from GetTypeSizeInline().
// Note: little-endian data on all platforms, use EndianScalar() instead of
// raw pointer access with scalars).
template<typename T> T *GetAnyVectorElemAddressOf(const VectorOfAny *vec,
size_t i,
size_t elem_size) {
// C-cast to allow const conversion.
return (T *)(vec->Data() + elem_size * i);
}
// Similarly, for elements of tables.
template<typename T> T *GetAnyFieldAddressOf(const Table &table,
const reflection::Field &field) {
return (T *)table.GetAddressOf(field.offset());
}
// Similarly, for elements of structs.
template<typename T> T *GetAnyFieldAddressOf(const Struct &st,
const reflection::Field &field) {
return (T *)st.GetAddressOf(field.offset());
}
// ------------------------- SETTERS -------------------------
// Set any scalar field, if you know its exact type. // Set any scalar field, if you know its exact type.
template<typename T> bool SetField(Table *table, const reflection::Field &field, template<typename T> bool SetField(Table *table, const reflection::Field &field,
T val) { T val) {
...@@ -177,77 +230,108 @@ template<typename T> bool SetField(Table *table, const reflection::Field &field, ...@@ -177,77 +230,108 @@ template<typename T> bool SetField(Table *table, const reflection::Field &field,
return table->SetField(field.offset(), val); return table->SetField(field.offset(), val);
} }
// Set any field as a 64bit int, regardless of what it is (bool/int/float/str). // Raw helper functions used below: set any value in memory as a 64bit int, a
inline void SetAnyFieldI(Table *table, const reflection::Field &field, // double or a string.
// These work for all scalar values, but do nothing for other data types.
// To set a string, see SetString below.
void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val);
void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val);
void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
// Set any table field as a 64bit int, regardless of type what it is.
inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
int64_t val) { int64_t val) {
# define FLATBUFFERS_SET(T) SetField<T>(table, field, static_cast<T>(val)) auto field_ptr = table->GetAddressOf(field.offset());
switch (field.type()->base_type()) { if (!field_ptr) return false;
case reflection::UType: SetAnyValueI(field.type()->base_type(), field_ptr, val);
case reflection::Bool: return true;
case reflection::UByte: FLATBUFFERS_SET(uint8_t ); break;
case reflection::Byte: FLATBUFFERS_SET(int8_t ); break;
case reflection::Short: FLATBUFFERS_SET(int16_t ); break;
case reflection::UShort: FLATBUFFERS_SET(uint16_t ); break;
case reflection::Int: FLATBUFFERS_SET(int32_t ); break;
case reflection::UInt: FLATBUFFERS_SET(uint32_t ); break;
case reflection::Long: FLATBUFFERS_SET(int64_t ); break;
case reflection::ULong: FLATBUFFERS_SET(uint64_t ); break;
case reflection::Float: FLATBUFFERS_SET(float ); break;
case reflection::Double: FLATBUFFERS_SET(double ); break;
// TODO: support strings
default: break;
}
# undef FLATBUFFERS_SET
} }
// Set any field as a double, regardless of what it is (bool/int/float/str). // Set any table field as a double, regardless of what type it is.
inline void SetAnyFieldF(Table *table, const reflection::Field &field, inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
double val) { double val) {
switch (field.type()->base_type()) { auto field_ptr = table->GetAddressOf(field.offset());
case reflection::Float: SetField<float> (table, field, if (!field_ptr) return false;
static_cast<float>(val)); break; SetAnyValueF(field.type()->base_type(), field_ptr, val);
case reflection::Double: SetField<double>(table, field, val); break; return true;
// TODO: support strings. }
default: SetAnyFieldI(table, field, static_cast<int64_t>(val)); break;
} // Set any table field as a string, regardless of what type it is.
inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
const char *val) {
auto field_ptr = table->GetAddressOf(field.offset());
if (!field_ptr) return false;
SetAnyValueS(field.type()->base_type(), field_ptr, val);
return true;
} }
// Set any field as a string, regardless of what it is (bool/int/float/str). // Set any struct field as a 64bit int, regardless of type what it is.
inline void SetAnyFieldS(Table *table, const reflection::Field &field, inline void SetAnyFieldI(Struct *st, const reflection::Field &field,
int64_t val) {
SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()),
val);
}
// Set any struct field as a double, regardless of type what it is.
inline void SetAnyFieldF(Struct *st, const reflection::Field &field,
double val) {
SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()),
val);
}
// Set any struct field as a string, regardless of type what it is.
inline void SetAnyFieldS(Struct *st, const reflection::Field &field,
const char *val) { const char *val) {
switch (field.type()->base_type()) { SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()),
case reflection::Float: val);
case reflection::Double: SetAnyFieldF(table, field, strtod(val, nullptr)); }
// TODO: support strings.
default: SetAnyFieldI(table, field, StringToInt(val)); break; // Set any vector element as a 64bit int, regardless of type what it is.
} inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type,
size_t i, int64_t val) {
SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
}
// Set any vector element as a double, regardless of type what it is.
inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type,
size_t i, double val) {
SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
}
// Set any vector element as a string, regardless of type what it is.
inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
size_t i, const char *val) {
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
} }
// ------------------------- RESIZING SETTERS -------------------------
// "smart" pointer for use with resizing vectors: turns a pointer inside // "smart" pointer for use with resizing vectors: turns a pointer inside
// a vector into a relative offset, such that it is not affected by resizes. // a vector into a relative offset, such that it is not affected by resizes.
template<typename T, typename U> class pointer_inside_vector { template<typename T, typename U> class pointer_inside_vector {
public: public:
pointer_inside_vector(const T *ptr, const std::vector<U> &vec) pointer_inside_vector(T *ptr, std::vector<U> &vec)
: offset_(reinterpret_cast<const uint8_t *>(ptr) - : offset_(reinterpret_cast<uint8_t *>(ptr) -
reinterpret_cast<const uint8_t *>(vec.data())), reinterpret_cast<uint8_t *>(vec.data())),
vec_(vec) {} vec_(vec) {}
const T *operator*() const { T *operator*() const {
return reinterpret_cast<const T *>( return reinterpret_cast<T *>(
reinterpret_cast<const uint8_t *>(vec_.data()) + offset_); reinterpret_cast<uint8_t *>(vec_.data()) + offset_);
} }
const T *operator->() const { T *operator->() const {
return operator*(); return operator*();
} }
void operator=(const pointer_inside_vector &piv); void operator=(const pointer_inside_vector &piv);
private: private:
size_t offset_; size_t offset_;
const std::vector<U> &vec_; std::vector<U> &vec_;
}; };
// Helper to create the above easily without specifying template args. // Helper to create the above easily without specifying template args.
template<typename T, typename U> pointer_inside_vector<T, U> piv( template<typename T, typename U> pointer_inside_vector<T, U> piv(T *ptr,
const T *ptr, const std::vector<U> &vec) { std::vector<U> &vec) {
return pointer_inside_vector<T, U>(ptr, vec); return pointer_inside_vector<T, U>(ptr, vec);
} }
...@@ -265,194 +349,66 @@ inline const reflection::Object &GetUnionType( ...@@ -265,194 +349,66 @@ inline const reflection::Object &GetUnionType(
return *enumval->object(); return *enumval->object();
} }
// Resize a FlatBuffer in-place by iterating through all offsets in the buffer
// and adjusting them by "delta" if they straddle the start offset.
// Once that is done, bytes can now be inserted/deleted safely.
// "delta" may be negative (shrinking).
// Unless "delta" is a multiple of the largest alignment, you'll create a small
// amount of garbage space in the buffer (usually 0..7 bytes).
// If your FlatBuffer's root table is not the schema's root table, you should
// pass in your root_table type as well.
class ResizeContext {
public:
ResizeContext(const reflection::Schema &schema, uoffset_t start, int delta,
std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr)
: schema_(schema), startptr_(flatbuf->data() + start),
delta_(delta), buf_(*flatbuf),
dag_check_(flatbuf->size() / sizeof(uoffset_t), false) {
auto mask = static_cast<int>(sizeof(largest_scalar_t) - 1);
delta_ = (delta_ + mask) & ~mask;
if (!delta_) return; // We can't shrink by less than largest_scalar_t.
// Now change all the offsets by delta_.
auto root = GetAnyRoot(buf_.data());
Straddle<uoffset_t, 1>(buf_.data(), root, buf_.data());
ResizeTable(root_table ? *root_table : *schema.root_table(), root);
// We can now add or remove bytes at start.
if (delta_ > 0) buf_.insert(buf_.begin() + start, delta_, 0);
else buf_.erase(buf_.begin() + start, buf_.begin() + start - delta_);
}
// Check if the range between first (lower address) and second straddles
// the insertion point. If it does, change the offset at offsetloc (of
// type T, with direction D).
template<typename T, int D> void Straddle(void *first, void *second,
void *offsetloc) {
if (first <= startptr_ && second >= startptr_) {
WriteScalar<T>(offsetloc, ReadScalar<T>(offsetloc) + delta_ * D);
DagCheck(offsetloc) = true;
}
}
// This returns a boolean that records if the corresponding offset location
// has been modified already. If so, we can't even read the corresponding
// offset, since it is pointing to a location that is illegal until the
// resize actually happens.
// This must be checked for every offset, since we can't know which offsets
// will straddle and which won't.
uint8_t &DagCheck(void *offsetloc) {
auto dag_idx = reinterpret_cast<uoffset_t *>(offsetloc) -
reinterpret_cast<uoffset_t *>(buf_.data());
return dag_check_[dag_idx];
}
void ResizeTable(const reflection::Object &objectdef, Table *table) {
if (DagCheck(table))
return; // Table already visited.
auto vtable = table->GetVTable();
// Check if the vtable offset points beyond the insertion point.
Straddle<soffset_t, -1>(table, vtable, table);
// This direction shouldn't happen because vtables that sit before tables
// are always directly adjacent, but check just in case we ever change the
// way flatbuffers are built.
Straddle<soffset_t, -1>(vtable, table, table);
// Early out: since all fields inside the table must point forwards in
// memory, if the insertion point is before the table we can stop here.
auto tableloc = reinterpret_cast<uint8_t *>(table);
if (startptr_ <= tableloc) return;
// Check each field.
auto fielddefs = objectdef.fields();
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
auto base_type = fielddef.type()->base_type();
// Ignore scalars.
if (base_type <= reflection::Double) continue;
// Ignore fields that are not stored.
auto offset = table->GetOptionalFieldOffset(fielddef.offset());
if (!offset) continue;
// Ignore structs.
auto subobjectdef = base_type == reflection::Obj ?
schema_.objects()->Get(fielddef.type()->index()) : nullptr;
if (subobjectdef && subobjectdef->is_struct()) continue;
// Get this fields' offset, and read it if safe.
auto offsetloc = tableloc + offset;
if (DagCheck(offsetloc))
continue; // This offset already visited.
auto ref = offsetloc + ReadScalar<uoffset_t>(offsetloc);
Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc);
// Recurse.
switch (base_type) {
case reflection::Obj: {
ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
break;
}
case reflection::Vector: {
auto elem_type = fielddef.type()->element();
if (elem_type != reflection::Obj && elem_type != reflection::String)
break;
auto vec = reinterpret_cast<Vector<uoffset_t> *>(ref);
auto elemobjectdef = elem_type == reflection::Obj
? schema_.objects()->Get(fielddef.type()->index())
: nullptr;
if (elemobjectdef && elemobjectdef->is_struct()) break;
for (uoffset_t i = 0; i < vec->size(); i++) {
auto loc = vec->Data() + i * sizeof(uoffset_t);
if (DagCheck(loc))
continue; // This offset already visited.
auto dest = loc + vec->Get(i);
Straddle<uoffset_t, 1>(loc, dest ,loc);
if (elemobjectdef)
ResizeTable(*elemobjectdef, reinterpret_cast<Table *>(dest));
}
break;
}
case reflection::Union: {
ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table),
reinterpret_cast<Table *>(ref));
break;
}
case reflection::String:
break;
default:
assert(false);
}
}
}
void operator=(const ResizeContext &rc);
private:
const reflection::Schema &schema_;
uint8_t *startptr_;
int delta_;
std::vector<uint8_t> &buf_;
std::vector<uint8_t> dag_check_;
};
// Changes the contents of a string inside a FlatBuffer. FlatBuffer must // Changes the contents of a string inside a FlatBuffer. FlatBuffer must
// live inside a std::vector so we can resize the buffer if needed. // live inside a std::vector so we can resize the buffer if needed.
// "str" must live inside "flatbuf" and may be invalidated after this call. // "str" must live inside "flatbuf" and may be invalidated after this call.
// If your FlatBuffer's root table is not the schema's root table, you should // If your FlatBuffer's root table is not the schema's root table, you should
// pass in your root_table type as well. // pass in your root_table type as well.
inline void SetString(const reflection::Schema &schema, const std::string &val, void SetString(const reflection::Schema &schema, const std::string &val,
const String *str, std::vector<uint8_t> *flatbuf, const String *str, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr) { const reflection::Object *root_table = nullptr);
auto delta = static_cast<int>(val.size()) - static_cast<int>(str->Length());
auto start = static_cast<uoffset_t>(reinterpret_cast<const uint8_t *>(str) -
flatbuf->data() +
sizeof(uoffset_t));
if (delta) {
// Different size, we must expand (or contract).
ResizeContext(schema, start, delta, flatbuf, root_table);
if (delta < 0) {
// Clear the old string, since we don't want parts of it remaining.
memset(flatbuf->data() + start, 0, str->Length());
}
}
// Copy new data. Safe because we created the right amount of space.
memcpy(flatbuf->data() + start, val.c_str(), val.size() + 1);
}
// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must // Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must
// live inside a std::vector so we can resize the buffer if needed. // live inside a std::vector so we can resize the buffer if needed.
// "vec" must live inside "flatbuf" and may be invalidated after this call. // "vec" must live inside "flatbuf" and may be invalidated after this call.
// If your FlatBuffer's root table is not the schema's root table, you should // If your FlatBuffer's root table is not the schema's root table, you should
// pass in your root_table type as well. // pass in your root_table type as well.
uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
const VectorOfAny *vec, uoffset_t num_elems,
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr);
template <typename T> template <typename T>
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
const Vector<T> *vec, std::vector<uint8_t> *flatbuf, const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr) { const reflection::Object *root_table = nullptr) {
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size()); auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
auto delta_bytes = delta_elem * static_cast<int>(sizeof(T)); auto newelems = ResizeAnyVector(schema, newsize,
auto vec_start = reinterpret_cast<const uint8_t *>(vec) - flatbuf->data(); reinterpret_cast<const VectorOfAny *>(vec),
auto start = static_cast<uoffset_t>(vec_start + sizeof(uoffset_t) + vec->size(),
sizeof(T) * vec->size()); static_cast<uoffset_t>(sizeof(T)), flatbuf,
if (delta_bytes) { root_table);
ResizeContext(schema, start, delta_bytes, flatbuf, root_table); // Set new elements to "val".
WriteScalar(flatbuf->data() + vec_start, newsize); // Length field. for (int i = 0; i < delta_elem; i++) {
// Set new elements to "val". auto loc = newelems + i * sizeof(T);
for (int i = 0; i < delta_elem; i++) { auto is_scalar = std::is_scalar<T>::value;
auto loc = flatbuf->data() + start + i * sizeof(T); if (is_scalar) {
auto is_scalar = std::is_scalar<T>::value; WriteScalar(loc, val);
if (is_scalar) { } else { // struct
WriteScalar(loc, val); *reinterpret_cast<T *>(loc) = val;
} else { // struct
*reinterpret_cast<T *>(loc) = val;
}
} }
} }
} }
// 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
// sufficient, in particular for adding new tables and new fields.
// This is potentially slightly less efficient than a FlatBuffer constructed
// in one piece, since the new FlatBuffer doesn't share any vtables with the
// existing one.
// The return value can now be set using Vector::MutateOffset or SetFieldT
// below.
const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
const uint8_t *newbuf, size_t newlen);
inline bool SetFieldT(Table *table, const reflection::Field &field,
const uint8_t *val) {
assert(sizeof(uoffset_t) == GetTypeSize(field.type()->base_type()));
return table->SetPointer(field.offset(), val);
}
// ------------------------- COPYING -------------------------
// Generic copying of tables from a FlatBuffer into a FlatBuffer builder. // Generic copying of tables from a FlatBuffer into a FlatBuffer builder.
// Can be used to do any kind of merging/selecting you may want to do out // Can be used to do any kind of merging/selecting you may want to do out
// of existing buffers. Also useful to reconstruct a whole buffer if the // of existing buffers. Also useful to reconstruct a whole buffer if the
...@@ -461,134 +417,10 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, ...@@ -461,134 +417,10 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
// Note: this does not deal with DAGs correctly. If the table passed forms a // Note: this does not deal with DAGs correctly. If the table passed forms a
// DAG, the copy will be a tree instead (with duplicates). // DAG, the copy will be a tree instead (with duplicates).
inline void CopyInline(FlatBufferBuilder &fbb, Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Field &fielddef, const reflection::Schema &schema,
const Table &table, const reflection::Object &objectdef,
size_t align, size_t size) { const Table &table);
fbb.Align(align);
fbb.PushBytes(table.GetStruct<const uint8_t *>(fielddef.offset()), size);
fbb.TrackField(fielddef.offset(), fbb.GetSize());
}
inline Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema,
const reflection::Object &objectdef,
const Table &table) {
// Before we can construct the table, we have to first generate any
// subobjects, and collect their offsets.
std::vector<uoffset_t> offsets;
auto fielddefs = objectdef.fields();
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
// Skip if field is not present in the source.
if (!table.CheckField(fielddef.offset())) continue;
uoffset_t offset = 0;
switch (fielddef.type()->base_type()) {
case reflection::String: {
offset = fbb.CreateString(GetFieldS(table, fielddef)).o;
break;
}
case reflection::Obj: {
auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index());
if (!subobjectdef.is_struct()) {
offset = CopyTable(fbb, schema, subobjectdef,
*GetFieldT(table, fielddef)).o;
}
break;
}
case reflection::Union: {
auto &subobjectdef = GetUnionType(schema, objectdef, fielddef, table);
offset = CopyTable(fbb, schema, subobjectdef,
*GetFieldT(table, fielddef)).o;
break;
}
case reflection::Vector: {
auto vec = table.GetPointer<const Vector<Offset<Table>> *>(
fielddef.offset());
auto element_base_type = fielddef.type()->element();
auto elemobjectdef = element_base_type == reflection::Obj
? schema.objects()->Get(fielddef.type()->index())
: nullptr;
switch (element_base_type) {
case reflection::String: {
std::vector<Offset<const String *>> elements(vec->size());
auto vec_s = reinterpret_cast<const Vector<Offset<String>> *>(vec);
for (uoffset_t i = 0; i < vec_s->size(); i++) {
elements[i] = fbb.CreateString(vec_s->Get(i)).o;
}
offset = fbb.CreateVector(elements).o;
break;
}
case reflection::Obj: {
if (!elemobjectdef->is_struct()) {
std::vector<Offset<const Table *>> elements(vec->size());
for (uoffset_t i = 0; i < vec->size(); i++) {
elements[i] =
CopyTable(fbb, schema, *elemobjectdef, *vec->Get(i));
}
offset = fbb.CreateVector(elements).o;
break;
}
// FALL-THRU:
}
default: { // Scalars and structs.
auto element_size = GetTypeSize(element_base_type);
if (elemobjectdef && elemobjectdef->is_struct())
element_size = elemobjectdef->bytesize();
fbb.StartVector(element_size, vec->size());
fbb.PushBytes(vec->Data(), element_size * vec->size());
offset = fbb.EndVector(vec->size());
break;
}
}
break;
}
default: // Scalars.
break;
}
if (offset) {
offsets.push_back(offset);
}
}
// Now we can build the actual table from either offsets or scalar data.
auto start = objectdef.is_struct()
? fbb.StartStruct(objectdef.minalign())
: fbb.StartTable();
size_t offset_idx = 0;
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
if (!table.CheckField(fielddef.offset())) continue;
auto base_type = fielddef.type()->base_type();
switch (base_type) {
case reflection::Obj: {
auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index());
if (subobjectdef.is_struct()) {
CopyInline(fbb, fielddef, table, subobjectdef.minalign(),
subobjectdef.bytesize());
break;
}
// else: FALL-THRU:
}
case reflection::Union:
case reflection::String:
case reflection::Vector:
fbb.AddOffset(fielddef.offset(), Offset<void>(offsets[offset_idx++]));
break;
default: { // Scalars.
auto size = GetTypeSize(base_type);
CopyInline(fbb, fielddef, table, size, size);
break;
}
}
}
assert(offset_idx == offsets.size());
if (objectdef.is_struct()) {
fbb.ClearOffsets();
return fbb.EndStruct();
} else {
return fbb.EndTable(start, static_cast<voffset_t>(fielddefs->size()));
}
}
} // namespace flatbuffers } // namespace flatbuffers
......
...@@ -48,6 +48,11 @@ namespace FlatBuffers ...@@ -48,6 +48,11 @@ namespace FlatBuffers
set { _pos = value; } set { _pos = value; }
} }
public void Reset()
{
_pos = 0;
}
// Pre-allocated helper arrays for convertion. // Pre-allocated helper arrays for convertion.
private float[] floathelper = new[] { 0.0f }; private float[] floathelper = new[] { 0.0f };
private int[] inthelper = new[] { 0 }; private int[] inthelper = new[] { 0 };
......
/* /*
* Copyright 2014 Google Inc. All rights reserved. * Copyright 2014 Google Inc. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
...@@ -49,6 +49,17 @@ namespace FlatBuffers ...@@ -49,6 +49,17 @@ namespace FlatBuffers
_bb = new ByteBuffer(new byte[initialSize]); _bb = new ByteBuffer(new byte[initialSize]);
} }
public void Clear()
{
_space = _bb.Length;
_bb.Reset();
_minAlign = 1;
_vtable = null;
_objectStart = 0;
_vtables = new int[16];
_numVtables = 0;
_vectorNumElems = 0;
}
public int Offset { get { return _bb.Length - _space; } } public int Offset { get { return _bb.Length - _space; } }
...@@ -195,10 +206,10 @@ namespace FlatBuffers ...@@ -195,10 +206,10 @@ namespace FlatBuffers
Prep(alignment, elemSize * count); // Just in case alignment > int. Prep(alignment, elemSize * count); // Just in case alignment > int.
} }
public int EndVector() public VectorOffset EndVector()
{ {
PutInt(_vectorNumElems); PutInt(_vectorNumElems);
return Offset; return new VectorOffset(Offset);
} }
public void Nested(int obj) public void Nested(int obj)
...@@ -249,7 +260,7 @@ namespace FlatBuffers ...@@ -249,7 +260,7 @@ namespace FlatBuffers
public void AddDouble(int o, double x, double d) { if (x != d) { AddDouble(x); Slot(o); } } public void AddDouble(int o, double x, double d) { if (x != d) { AddDouble(x); Slot(o); } }
public void AddOffset(int o, int x, int d) { if (x != d) { AddOffset(x); Slot(o); } } public void AddOffset(int o, int x, int d) { if (x != d) { AddOffset(x); Slot(o); } }
public int CreateString(string s) public StringOffset CreateString(string s)
{ {
NotNested(); NotNested();
byte[] utf8 = Encoding.UTF8.GetBytes(s); byte[] utf8 = Encoding.UTF8.GetBytes(s);
...@@ -257,7 +268,7 @@ namespace FlatBuffers ...@@ -257,7 +268,7 @@ namespace FlatBuffers
StartVector(1, utf8.Length, 1); StartVector(1, utf8.Length, 1);
Buffer.BlockCopy(utf8, 0, _bb.Data, _space -= utf8.Length, Buffer.BlockCopy(utf8, 0, _bb.Data, _space -= utf8.Length,
utf8.Length); utf8.Length);
return EndVector(); return new StringOffset(EndVector().Value);
} }
// Structs are stored inline, so nothing additional is being added. // Structs are stored inline, so nothing additional is being added.
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
<Compile Include="ByteBuffer.cs" /> <Compile Include="ByteBuffer.cs" />
<Compile Include="FlatBufferBuilder.cs" /> <Compile Include="FlatBufferBuilder.cs" />
<Compile Include="FlatBufferConstants.cs" /> <Compile Include="FlatBufferConstants.cs" />
<Compile Include="Offset.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Struct.cs" /> <Compile Include="Struct.cs" />
<Compile Include="Table.cs" /> <Compile Include="Table.cs" />
......
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace FlatBuffers
{
/// <summary>
/// Offset class for typesafe assignments.
/// </summary>
public struct Offset<T> where T : class
{
public int Value;
public Offset(int value)
{
Value = value;
}
}
public struct StringOffset
{
public int Value;
public StringOffset(int value)
{
Value = value;
}
}
public struct VectorOffset
{
public int Value;
public VectorOffset(int value)
{
Value = value;
}
}
}
...@@ -90,7 +90,9 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) { ...@@ -90,7 +90,9 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
" --defaults-json Output fields whose value is the default when\n" " --defaults-json Output fields whose value is the default when\n"
" writing JSON\n" " writing JSON\n"
" --no-prefix Don\'t prefix enum values with the enum type in C++.\n" " --no-prefix Don\'t prefix enum values with the enum type in C++.\n"
" --gen-includes (deprecated), instead use:\n" " --gen-includes (deprecated), this is the default behavior.\n"
" If the original behavior is required (no include\n"
" statements) use --no-includes.\n"
" --no-includes Don\'t generate include statements for included\n" " --no-includes Don\'t generate include statements for included\n"
" schemas the generated file depends on (C++).\n" " schemas the generated file depends on (C++).\n"
" --gen-mutable Generate accessors that can mutate buffers in-place.\n" " --gen-mutable Generate accessors that can mutate buffers in-place.\n"
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h" #include "flatbuffers/idl.h"
#include "flatbuffers/util.h" #include "flatbuffers/util.h"
#include <algorithm>
namespace flatbuffers { namespace flatbuffers {
...@@ -202,6 +203,10 @@ static std::string GenTypeBasic(const LanguageParameters &lang, ...@@ -202,6 +203,10 @@ static std::string GenTypeBasic(const LanguageParameters &lang,
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
}; };
if(lang.language == GeneratorOptions::kCSharp && type.base_type == BASE_TYPE_STRUCT) {
return "Offset<" + type.struct_def->name + ">";
}
return gtypename[type.base_type * GeneratorOptions::kMAX + lang.language]; return gtypename[type.base_type * GeneratorOptions::kMAX + lang.language];
} }
...@@ -258,6 +263,32 @@ static Type DestinationType(const LanguageParameters &lang, const Type &type, ...@@ -258,6 +263,32 @@ static Type DestinationType(const LanguageParameters &lang, const Type &type,
} }
} }
static std::string GenOffsetType(const LanguageParameters &lang, const StructDef &struct_def) {
if(lang.language == GeneratorOptions::kCSharp) {
return "Offset<" + struct_def.name + ">";
} else {
return "int";
}
}
static std::string GenOffsetConstruct(const LanguageParameters &lang,
const StructDef &struct_def,
const std::string &variable_name)
{
if(lang.language == GeneratorOptions::kCSharp) {
return "new Offset<" + struct_def.name + ">(" + variable_name + ")";
}
return variable_name;
}
static std::string GenVectorOffsetType(const LanguageParameters &lang) {
if(lang.language == GeneratorOptions::kCSharp) {
return "VectorOffset";
} else {
return "int";
}
}
// Generate destination type name // Generate destination type name
static std::string GenTypeNameDest(const LanguageParameters &lang, const Type &type) static std::string GenTypeNameDest(const LanguageParameters &lang, const Type &type)
{ {
...@@ -353,7 +384,20 @@ static std::string SourceCast(const LanguageParameters &lang, ...@@ -353,7 +384,20 @@ static std::string SourceCast(const LanguageParameters &lang,
return ""; return "";
} }
static std::string GenDefaultValue(const Value &value) { static std::string GenDefaultValue(const LanguageParameters &lang, const Value &value, bool for_buffer) {
if(lang.language == GeneratorOptions::kCSharp && !for_buffer) {
switch(value.type.base_type) {
case BASE_TYPE_STRING:
return "default(StringOffset)";
case BASE_TYPE_STRUCT:
return "default(Offset<" + value.type.struct_def->name + ">)";
case BASE_TYPE_VECTOR:
return "default(VectorOffset)";
default:
break;
}
}
return value.type.base_type == BASE_TYPE_BOOL return value.type.base_type == BASE_TYPE_BOOL
? (value.constant == "0" ? "false" : "true") ? (value.constant == "0" ? "false" : "true")
: value.constant; : value.constant;
...@@ -658,7 +702,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -658,7 +702,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
} else { } else {
code += offset_prefix + getter; code += offset_prefix + getter;
code += "(o + bb_pos)" + dest_mask + " : " + default_cast; code += "(o + bb_pos)" + dest_mask + " : " + default_cast;
code += GenDefaultValue(field.value); code += GenDefaultValue(lang, field.value, false);
} }
} else { } else {
switch (field.value.type.base_type) { switch (field.value.type.base_type) {
...@@ -765,13 +809,14 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -765,13 +809,14 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
code += "\n"; code += "\n";
if (struct_def.fixed) { if (struct_def.fixed) {
// create a struct constructor function // create a struct constructor function
code += " public static int " + FunctionStart(lang, 'C') + "reate"; code += " public static " + GenOffsetType(lang, struct_def) + " ";
code += FunctionStart(lang, 'C') + "reate";
code += struct_def.name + "(FlatBufferBuilder builder"; code += struct_def.name + "(FlatBufferBuilder builder";
GenStructArgs(lang, struct_def, code_ptr, ""); GenStructArgs(lang, struct_def, code_ptr, "");
code += ") {\n"; code += ") {\n";
GenStructBody(lang, struct_def, code_ptr, ""); GenStructBody(lang, struct_def, code_ptr, "");
code += " return builder."; code += " return ";
code += lang.get_fbb_offset; code += GenOffsetConstruct(lang, struct_def, "builder." + std::string(lang.get_fbb_offset));
code += ";\n }\n"; code += ";\n }\n";
} else { } else {
// Generate a method that creates a table in one go. This is only possible // Generate a method that creates a table in one go. This is only possible
...@@ -791,9 +836,9 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -791,9 +836,9 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
} }
if (has_no_struct_fields && num_fields) { if (has_no_struct_fields && num_fields) {
// Generate a table constructor of the form: // Generate a table constructor of the form:
// public static void createName(FlatBufferBuilder builder, args...) // public static int createName(FlatBufferBuilder builder, args...)
code += " public static int " + FunctionStart(lang, 'C') + "reate"; code += " public static " + GenOffsetType(lang, struct_def) + " ";
code += struct_def.name; code += FunctionStart(lang, 'C') + "reate" + struct_def.name;
code += "(FlatBufferBuilder builder"; code += "(FlatBufferBuilder builder";
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
...@@ -807,7 +852,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -807,7 +852,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
// Java doesn't have defaults, which means this method must always // Java doesn't have defaults, which means this method must always
// supply all arguments, and thus won't compile when fields are added. // supply all arguments, and thus won't compile when fields are added.
if (lang.language != GeneratorOptions::kJava) { if (lang.language != GeneratorOptions::kJava) {
code += " = " + GenDefaultValue(field.value); code += " = " + GenDefaultValue(lang, field.value, false);
} }
} }
code += ") {\n builder."; code += ") {\n builder.";
...@@ -857,7 +902,10 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -857,7 +902,10 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
code += GenMethod(lang, field.value.type) + "("; code += GenMethod(lang, field.value.type) + "(";
code += NumToString(it - struct_def.fields.vec.begin()) + ", "; code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
code += DestinationValue(lang, argname, field.value.type); code += DestinationValue(lang, argname, field.value.type);
code += ", " + GenDefaultValue(field.value); if(!IsScalar(field.value.type.base_type) && field.value.type.base_type != BASE_TYPE_UNION && lang.language == GeneratorOptions::kCSharp) {
code += ".Value";
}
code += ", " + GenDefaultValue(lang, field.value, true);
code += "); }\n"; code += "); }\n";
if (field.value.type.base_type == BASE_TYPE_VECTOR) { if (field.value.type.base_type == BASE_TYPE_VECTOR) {
auto vector_type = field.value.type.VectorType(); auto vector_type = field.value.type.VectorType();
...@@ -865,7 +913,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -865,7 +913,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
auto elem_size = InlineSize(vector_type); auto elem_size = InlineSize(vector_type);
if (!IsStruct(vector_type)) { if (!IsStruct(vector_type)) {
// Generate a method to create a vector from a Java array. // Generate a method to create a vector from a Java array.
code += " public static int " + FunctionStart(lang, 'C') + "reate"; code += " public static " + GenVectorOffsetType(lang) + " " + FunctionStart(lang, 'C') + "reate";
code += MakeCamel(field.name); code += MakeCamel(field.name);
code += "Vector(FlatBufferBuilder builder, "; code += "Vector(FlatBufferBuilder builder, ";
code += GenTypeBasic(lang, vector_type) + "[] data) "; code += GenTypeBasic(lang, vector_type) + "[] data) ";
...@@ -877,8 +925,12 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -877,8 +925,12 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
code += FunctionStart(lang, 'L') + "ength - 1; i >= 0; i--) builder."; code += FunctionStart(lang, 'L') + "ength - 1; i >= 0; i--) builder.";
code += FunctionStart(lang, 'A') + "dd"; code += FunctionStart(lang, 'A') + "dd";
code += GenMethod(lang, vector_type); code += GenMethod(lang, vector_type);
code += "(data[i]); return builder."; code += "(data[i]";
code += FunctionStart(lang, 'E') + "ndVector(); }\n"; if(lang.language == GeneratorOptions::kCSharp &&
(vector_type.base_type == BASE_TYPE_STRUCT || vector_type.base_type == BASE_TYPE_STRING))
code += ".Value";
code += "); return ";
code += "builder." + FunctionStart(lang, 'E') + "ndVector(); }\n";
} }
// Generate a method to start a vector, data to be added manually after. // Generate a method to start a vector, data to be added manually after.
code += " public static void " + FunctionStart(lang, 'S') + "tart"; code += " public static void " + FunctionStart(lang, 'S') + "tart";
...@@ -890,7 +942,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -890,7 +942,7 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
code += "); }\n"; code += "); }\n";
} }
} }
code += " public static int "; code += " public static " + GenOffsetType(lang, struct_def) + " ";
code += FunctionStart(lang, 'E') + "nd" + struct_def.name; code += FunctionStart(lang, 'E') + "nd" + struct_def.name;
code += "(FlatBufferBuilder builder) {\n int o = builder."; code += "(FlatBufferBuilder builder) {\n int o = builder.";
code += FunctionStart(lang, 'E') + "ndObject();\n"; code += FunctionStart(lang, 'E') + "ndObject();\n";
...@@ -904,12 +956,16 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser, ...@@ -904,12 +956,16 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
code += "); // " + field.name + "\n"; code += "); // " + field.name + "\n";
} }
} }
code += " return o;\n }\n"; code += " return " + GenOffsetConstruct(lang, struct_def, "o") + ";\n }\n";
if (parser.root_struct_def_ == &struct_def) { if (parser.root_struct_def_ == &struct_def) {
code += " public static void "; code += " public static void ";
code += FunctionStart(lang, 'F') + "inish" + struct_def.name; code += FunctionStart(lang, 'F') + "inish" + struct_def.name;
code += "Buffer(FlatBufferBuilder builder, int offset) { "; code += "Buffer(FlatBufferBuilder builder, " + GenOffsetType(lang, struct_def) + " offset) {";
code += "builder." + FunctionStart(lang, 'F') + "inish(offset"; code += " builder." + FunctionStart(lang, 'F') + "inish(offset";
if (lang.language == GeneratorOptions::kCSharp) {
code += ".Value";
}
if (parser.file_identifier_.length()) if (parser.file_identifier_.length())
code += ", \"" + parser.file_identifier_ + "\""; code += ", \"" + parser.file_identifier_ + "\"";
code += "); }\n"; code += "); }\n";
......
...@@ -918,10 +918,10 @@ void Parser::ParseDecl() { ...@@ -918,10 +918,10 @@ void Parser::ParseDecl() {
auto align = static_cast<size_t>(atoi(force_align->constant.c_str())); auto align = static_cast<size_t>(atoi(force_align->constant.c_str()));
if (force_align->type.base_type != BASE_TYPE_INT || if (force_align->type.base_type != BASE_TYPE_INT ||
align < struct_def.minalign || align < struct_def.minalign ||
align > 256 || align > 16 ||
align & (align - 1)) align & (align - 1))
Error("force_align must be a power of two integer ranging from the" Error("force_align must be a power of two integer ranging from the"
"struct\'s natural alignment to 256"); "struct\'s natural alignment to 16");
struct_def.minalign = align; struct_def.minalign = align;
} }
struct_def.PadLastField(struct_def.minalign); struct_def.PadLastField(struct_def.minalign);
......
/*
* Copyright 2015 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "flatbuffers/reflection.h"
#include "flatbuffers/util.h"
// Helper functionality for reflection.
namespace flatbuffers {
int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data) {
# define FLATBUFFERS_GET(T) static_cast<int64_t>(ReadScalar<T>(data))
switch (type) {
case reflection::UType:
case reflection::Bool:
case reflection::UByte: return FLATBUFFERS_GET(uint8_t);
case reflection::Byte: return FLATBUFFERS_GET(int8_t);
case reflection::Short: return FLATBUFFERS_GET(int16_t);
case reflection::UShort: return FLATBUFFERS_GET(uint16_t);
case reflection::Int: return FLATBUFFERS_GET(int32_t);
case reflection::UInt: return FLATBUFFERS_GET(uint32_t);
case reflection::Long: return FLATBUFFERS_GET(int64_t);
case reflection::ULong: return FLATBUFFERS_GET(uint64_t);
case reflection::Float: return FLATBUFFERS_GET(float);
case reflection::Double: return FLATBUFFERS_GET(double);
case reflection::String: {
auto s = reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) +
data);
return s ? StringToInt(s->c_str()) : 0;
}
default: return 0; // Tables & vectors do not make sense.
}
# undef FLATBUFFERS_GET
}
double GetAnyValueF(reflection::BaseType type, const uint8_t *data) {
switch (type) {
case reflection::Float: return static_cast<double>(ReadScalar<float>(data));
case reflection::Double: return ReadScalar<double>(data);
case reflection::String: {
auto s = reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) +
data);
return s ? strtod(s->c_str(), nullptr) : 0.0;
}
default: return static_cast<double>(GetAnyValueI(type, data));
}
}
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
const reflection::Schema *schema, int type_index) {
switch (type) {
case reflection::Float:
case reflection::Double: return NumToString(GetAnyValueF(type, data));
case reflection::String: {
auto s = reinterpret_cast<const String *>(ReadScalar<uoffset_t>(data) +
data);
return s ? s->c_str() : "";
}
case reflection::Obj:
if (schema) {
// Convert the table to a string. This is mostly for debugging purposes,
// and does NOT promise to be JSON compliant.
// Also prefixes the type.
auto &objectdef = *schema->objects()->Get(type_index);
auto s = objectdef.name()->str();
if (objectdef.is_struct()) {
s += "(struct)"; // TODO: implement this as well.
} else {
auto table_field = reinterpret_cast<const Table *>(
ReadScalar<uoffset_t>(data) + data);
s += " { ";
auto fielddefs = objectdef.fields();
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
if (!table_field->CheckField(fielddef.offset())) continue;
auto val = GetAnyFieldS(*table_field, fielddef, schema);
if (fielddef.type()->base_type() == reflection::String)
val = "\"" + val + "\""; // Doesn't deal with escape codes etc.
s += fielddef.name()->str();
s += ": ";
s += val;
s += ", ";
}
s += "}";
}
return s;
} else {
return "(table)";
}
case reflection::Vector:
return "[(elements)]"; // TODO: implement this as well.
case reflection::Union:
return "(union)"; // TODO: implement this as well.
default: return NumToString(GetAnyValueI(type, data));
}
}
void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val) {
# define FLATBUFFERS_SET(T) WriteScalar(data, static_cast<T>(val))
switch (type) {
case reflection::UType:
case reflection::Bool:
case reflection::UByte: FLATBUFFERS_SET(uint8_t ); break;
case reflection::Byte: FLATBUFFERS_SET(int8_t ); break;
case reflection::Short: FLATBUFFERS_SET(int16_t ); break;
case reflection::UShort: FLATBUFFERS_SET(uint16_t); break;
case reflection::Int: FLATBUFFERS_SET(int32_t ); break;
case reflection::UInt: FLATBUFFERS_SET(uint32_t); break;
case reflection::Long: FLATBUFFERS_SET(int64_t ); break;
case reflection::ULong: FLATBUFFERS_SET(uint64_t); break;
case reflection::Float: FLATBUFFERS_SET(float ); break;
case reflection::Double: FLATBUFFERS_SET(double ); break;
// TODO: support strings
default: break;
}
# undef FLATBUFFERS_SET
}
void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val) {
switch (type) {
case reflection::Float: WriteScalar(data, static_cast<float>(val)); break;
case reflection::Double: WriteScalar(data, val); break;
// TODO: support strings.
default: SetAnyValueI(type, data, static_cast<int64_t>(val)); break;
}
}
void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val) {
switch (type) {
case reflection::Float:
case reflection::Double:
SetAnyValueF(type, data, strtod(val, nullptr));
break;
// TODO: support strings.
default: SetAnyValueI(type, data, StringToInt(val)); break;
}
}
// Resize a FlatBuffer in-place by iterating through all offsets in the buffer
// and adjusting them by "delta" if they straddle the start offset.
// Once that is done, bytes can now be inserted/deleted safely.
// "delta" may be negative (shrinking).
// Unless "delta" is a multiple of the largest alignment, you'll create a small
// amount of garbage space in the buffer (usually 0..7 bytes).
// If your FlatBuffer's root table is not the schema's root table, you should
// pass in your root_table type as well.
class ResizeContext {
public:
ResizeContext(const reflection::Schema &schema, uoffset_t start, int delta,
std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr)
: schema_(schema), startptr_(flatbuf->data() + start),
delta_(delta), buf_(*flatbuf),
dag_check_(flatbuf->size() / sizeof(uoffset_t), false) {
auto mask = static_cast<int>(sizeof(largest_scalar_t) - 1);
delta_ = (delta_ + mask) & ~mask;
if (!delta_) return; // We can't shrink by less than largest_scalar_t.
// Now change all the offsets by delta_.
auto root = GetAnyRoot(buf_.data());
Straddle<uoffset_t, 1>(buf_.data(), root, buf_.data());
ResizeTable(root_table ? *root_table : *schema.root_table(), root);
// We can now add or remove bytes at start.
if (delta_ > 0) buf_.insert(buf_.begin() + start, delta_, 0);
else buf_.erase(buf_.begin() + start, buf_.begin() + start - delta_);
}
// Check if the range between first (lower address) and second straddles
// the insertion point. If it does, change the offset at offsetloc (of
// type T, with direction D).
template<typename T, int D> void Straddle(void *first, void *second,
void *offsetloc) {
if (first <= startptr_ && second >= startptr_) {
WriteScalar<T>(offsetloc, ReadScalar<T>(offsetloc) + delta_ * D);
DagCheck(offsetloc) = true;
}
}
// This returns a boolean that records if the corresponding offset location
// has been modified already. If so, we can't even read the corresponding
// offset, since it is pointing to a location that is illegal until the
// resize actually happens.
// This must be checked for every offset, since we can't know which offsets
// will straddle and which won't.
uint8_t &DagCheck(void *offsetloc) {
auto dag_idx = reinterpret_cast<uoffset_t *>(offsetloc) -
reinterpret_cast<uoffset_t *>(buf_.data());
return dag_check_[dag_idx];
}
void ResizeTable(const reflection::Object &objectdef, Table *table) {
if (DagCheck(table))
return; // Table already visited.
auto vtable = table->GetVTable();
// Check if the vtable offset points beyond the insertion point.
Straddle<soffset_t, -1>(table, vtable, table);
// This direction shouldn't happen because vtables that sit before tables
// are always directly adjacent, but check just in case we ever change the
// way flatbuffers are built.
Straddle<soffset_t, -1>(vtable, table, table);
// Early out: since all fields inside the table must point forwards in
// memory, if the insertion point is before the table we can stop here.
auto tableloc = reinterpret_cast<uint8_t *>(table);
if (startptr_ <= tableloc) return;
// Check each field.
auto fielddefs = objectdef.fields();
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
auto base_type = fielddef.type()->base_type();
// Ignore scalars.
if (base_type <= reflection::Double) continue;
// Ignore fields that are not stored.
auto offset = table->GetOptionalFieldOffset(fielddef.offset());
if (!offset) continue;
// Ignore structs.
auto subobjectdef = base_type == reflection::Obj ?
schema_.objects()->Get(fielddef.type()->index()) : nullptr;
if (subobjectdef && subobjectdef->is_struct()) continue;
// Get this fields' offset, and read it if safe.
auto offsetloc = tableloc + offset;
if (DagCheck(offsetloc))
continue; // This offset already visited.
auto ref = offsetloc + ReadScalar<uoffset_t>(offsetloc);
Straddle<uoffset_t, 1>(offsetloc, ref, offsetloc);
// Recurse.
switch (base_type) {
case reflection::Obj: {
ResizeTable(*subobjectdef, reinterpret_cast<Table *>(ref));
break;
}
case reflection::Vector: {
auto elem_type = fielddef.type()->element();
if (elem_type != reflection::Obj && elem_type != reflection::String)
break;
auto vec = reinterpret_cast<Vector<uoffset_t> *>(ref);
auto elemobjectdef = elem_type == reflection::Obj
? schema_.objects()->Get(fielddef.type()->index())
: nullptr;
if (elemobjectdef && elemobjectdef->is_struct()) break;
for (uoffset_t i = 0; i < vec->size(); i++) {
auto loc = vec->Data() + i * sizeof(uoffset_t);
if (DagCheck(loc))
continue; // This offset already visited.
auto dest = loc + vec->Get(i);
Straddle<uoffset_t, 1>(loc, dest ,loc);
if (elemobjectdef)
ResizeTable(*elemobjectdef, reinterpret_cast<Table *>(dest));
}
break;
}
case reflection::Union: {
ResizeTable(GetUnionType(schema_, objectdef, fielddef, *table),
reinterpret_cast<Table *>(ref));
break;
}
case reflection::String:
break;
default:
assert(false);
}
}
}
void operator=(const ResizeContext &rc);
private:
const reflection::Schema &schema_;
uint8_t *startptr_;
int delta_;
std::vector<uint8_t> &buf_;
std::vector<uint8_t> dag_check_;
};
void SetString(const reflection::Schema &schema, const std::string &val,
const String *str, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table) {
auto delta = static_cast<int>(val.size()) - static_cast<int>(str->Length());
auto start = static_cast<uoffset_t>(reinterpret_cast<const uint8_t *>(str) -
flatbuf->data() +
sizeof(uoffset_t));
if (delta) {
// Clear the old string, since we don't want parts of it remaining.
memset(flatbuf->data() + start, 0, str->Length());
// Different size, we must expand (or contract).
ResizeContext(schema, start, delta, flatbuf, root_table);
}
// Copy new data. Safe because we created the right amount of space.
memcpy(flatbuf->data() + start, val.c_str(), val.size() + 1);
}
uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
const VectorOfAny *vec, uoffset_t num_elems,
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table) {
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(num_elems);
auto delta_bytes = delta_elem * static_cast<int>(elem_size);
auto vec_start = reinterpret_cast<const uint8_t *>(vec) - flatbuf->data();
auto start = static_cast<uoffset_t>(vec_start + sizeof(uoffset_t) +
elem_size * num_elems);
if (delta_bytes) {
if (delta_elem < 0) {
// Clear elements we're throwing away, since some might remain in the
// buffer.
auto size_clear = -delta_elem * elem_size;
memset(flatbuf->data() + start - size_clear, 0, size_clear);
}
ResizeContext(schema, start, delta_bytes, flatbuf, root_table);
WriteScalar(flatbuf->data() + vec_start, newsize); // Length field.
// Set new elements to 0.. this can be overwritten by the caller.
if (delta_elem > 0) {
memset(flatbuf->data() + start, 0, delta_elem * elem_size);
}
}
return flatbuf->data() + start;
}
const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
const uint8_t *newbuf, size_t newlen) {
// Align to sizeof(uoffset_t) past sizeof(largest_scalar_t) since we're
// going to chop off the root offset.
while ((flatbuf.size() & (sizeof(uoffset_t) - 1)) ||
!(flatbuf.size() & (sizeof(largest_scalar_t) - 1))) {
flatbuf.push_back(0);
}
auto insertion_point = static_cast<uoffset_t>(flatbuf.size());
// Insert the entire FlatBuffer minus the root pointer.
flatbuf.insert(flatbuf.end(), newbuf + sizeof(uoffset_t), newbuf + newlen);
auto root_offset = ReadScalar<uoffset_t>(newbuf) - sizeof(uoffset_t);
return flatbuf.data() + insertion_point + root_offset;
}
void CopyInline(FlatBufferBuilder &fbb, const reflection::Field &fielddef,
const Table &table, size_t align, size_t size) {
fbb.Align(align);
fbb.PushBytes(table.GetStruct<const uint8_t *>(fielddef.offset()), size);
fbb.TrackField(fielddef.offset(), fbb.GetSize());
}
Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const reflection::Schema &schema,
const reflection::Object &objectdef,
const Table &table) {
// Before we can construct the table, we have to first generate any
// subobjects, and collect their offsets.
std::vector<uoffset_t> offsets;
auto fielddefs = objectdef.fields();
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
// Skip if field is not present in the source.
if (!table.CheckField(fielddef.offset())) continue;
uoffset_t offset = 0;
switch (fielddef.type()->base_type()) {
case reflection::String: {
offset = fbb.CreateString(GetFieldS(table, fielddef)).o;
break;
}
case reflection::Obj: {
auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index());
if (!subobjectdef.is_struct()) {
offset = CopyTable(fbb, schema, subobjectdef,
*GetFieldT(table, fielddef)).o;
}
break;
}
case reflection::Union: {
auto &subobjectdef = GetUnionType(schema, objectdef, fielddef, table);
offset = CopyTable(fbb, schema, subobjectdef,
*GetFieldT(table, fielddef)).o;
break;
}
case reflection::Vector: {
auto vec = table.GetPointer<const Vector<Offset<Table>> *>(
fielddef.offset());
auto element_base_type = fielddef.type()->element();
auto elemobjectdef = element_base_type == reflection::Obj
? schema.objects()->Get(fielddef.type()->index())
: nullptr;
switch (element_base_type) {
case reflection::String: {
std::vector<Offset<const String *>> elements(vec->size());
auto vec_s = reinterpret_cast<const Vector<Offset<String>> *>(vec);
for (uoffset_t i = 0; i < vec_s->size(); i++) {
elements[i] = fbb.CreateString(vec_s->Get(i)).o;
}
offset = fbb.CreateVector(elements).o;
break;
}
case reflection::Obj: {
if (!elemobjectdef->is_struct()) {
std::vector<Offset<const Table *>> elements(vec->size());
for (uoffset_t i = 0; i < vec->size(); i++) {
elements[i] =
CopyTable(fbb, schema, *elemobjectdef, *vec->Get(i));
}
offset = fbb.CreateVector(elements).o;
break;
}
// FALL-THRU:
}
default: { // Scalars and structs.
auto element_size = GetTypeSize(element_base_type);
if (elemobjectdef && elemobjectdef->is_struct())
element_size = elemobjectdef->bytesize();
fbb.StartVector(element_size, vec->size());
fbb.PushBytes(vec->Data(), element_size * vec->size());
offset = fbb.EndVector(vec->size());
break;
}
}
break;
}
default: // Scalars.
break;
}
if (offset) {
offsets.push_back(offset);
}
}
// Now we can build the actual table from either offsets or scalar data.
auto start = objectdef.is_struct()
? fbb.StartStruct(objectdef.minalign())
: fbb.StartTable();
size_t offset_idx = 0;
for (auto it = fielddefs->begin(); it != fielddefs->end(); ++it) {
auto &fielddef = **it;
if (!table.CheckField(fielddef.offset())) continue;
auto base_type = fielddef.type()->base_type();
switch (base_type) {
case reflection::Obj: {
auto &subobjectdef = *schema.objects()->Get(fielddef.type()->index());
if (subobjectdef.is_struct()) {
CopyInline(fbb, fielddef, table, subobjectdef.minalign(),
subobjectdef.bytesize());
break;
}
// else: FALL-THRU:
}
case reflection::Union:
case reflection::String:
case reflection::Vector:
fbb.AddOffset(fielddef.offset(), Offset<void>(offsets[offset_idx++]));
break;
default: { // Scalars.
auto size = GetTypeSize(base_type);
CopyInline(fbb, fielddef, table, size, size);
break;
}
}
}
assert(offset_idx == offsets.size());
if (objectdef.is_struct()) {
fbb.ClearOffsets();
return fbb.EndStruct();
} else {
return fbb.EndTable(start, static_cast<voffset_t>(fielddefs->size()));
}
}
} // namespace flatbuffers
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
<Compile Include="..\..\net\FlatBuffers\ByteBuffer.cs"> <Compile Include="..\..\net\FlatBuffers\ByteBuffer.cs">
<Link>FlatBuffers\ByteBuffer.cs</Link> <Link>FlatBuffers\ByteBuffer.cs</Link>
</Compile> </Compile>
<Compile Include="..\..\net\FlatBuffers\Offset.cs">
<Link>FlatBuffers\Offset.cs</Link>
</Compile>
<Compile Include="..\..\net\FlatBuffers\FlatBufferBuilder.cs"> <Compile Include="..\..\net\FlatBuffers\FlatBufferBuilder.cs">
<Link>FlatBuffers\FlatBufferBuilder.cs</Link> <Link>FlatBuffers\FlatBufferBuilder.cs</Link>
</Compile> </Compile>
......
...@@ -61,8 +61,8 @@ namespace FlatBuffers.Test ...@@ -61,8 +61,8 @@ namespace FlatBuffers.Test
var test4 = fbb.EndVector(); var test4 = fbb.EndVector();
Monster.StartTestarrayofstringVector(fbb, 2); Monster.StartTestarrayofstringVector(fbb, 2);
fbb.AddOffset(test2); fbb.AddOffset(test2.Value);
fbb.AddOffset(test1); fbb.AddOffset(test1.Value);
var testArrayOfString = fbb.EndVector(); var testArrayOfString = fbb.EndVector();
Monster.StartMonster(fbb); Monster.StartMonster(fbb);
...@@ -72,7 +72,7 @@ namespace FlatBuffers.Test ...@@ -72,7 +72,7 @@ namespace FlatBuffers.Test
Monster.AddName(fbb, str); Monster.AddName(fbb, str);
Monster.AddInventory(fbb, inv); Monster.AddInventory(fbb, inv);
Monster.AddTestType(fbb, Any.Monster); Monster.AddTestType(fbb, Any.Monster);
Monster.AddTest(fbb, mon2); Monster.AddTest(fbb, mon2.Value);
Monster.AddTest4(fbb, test4); Monster.AddTest4(fbb, test4);
Monster.AddTestarrayofstring(fbb, testArrayOfString); Monster.AddTestarrayofstring(fbb, testArrayOfString);
Monster.AddTestbool(fbb, false); Monster.AddTestbool(fbb, false);
...@@ -80,6 +80,7 @@ namespace FlatBuffers.Test ...@@ -80,6 +80,7 @@ namespace FlatBuffers.Test
Monster.FinishMonsterBuffer(fbb, mon); Monster.FinishMonsterBuffer(fbb, mon);
// Dump to output directory so we can inspect later, if needed // Dump to output directory so we can inspect later, if needed
using (var ms = new MemoryStream(fbb.DataBuffer.Data, fbb.DataBuffer.Position, fbb.Offset)) using (var ms = new MemoryStream(fbb.DataBuffer.Data, fbb.DataBuffer.Position, fbb.Offset))
{ {
......
...@@ -61,29 +61,29 @@ public sealed class Monster : Table { ...@@ -61,29 +61,29 @@ public sealed class Monster : Table {
public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } } public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(24); } public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(24); }
public static void AddPos(FlatBufferBuilder builder, int posOffset) { builder.AddStruct(0, posOffset, 0); } public static void AddPos(FlatBufferBuilder builder, Offset<Vec3> posOffset) { builder.AddStruct(0, posOffset.Value, 0); }
public static void AddMana(FlatBufferBuilder builder, short mana) { builder.AddShort(1, mana, 150); } public static void AddMana(FlatBufferBuilder builder, short mana) { builder.AddShort(1, mana, 150); }
public static void AddHp(FlatBufferBuilder builder, short hp) { builder.AddShort(2, hp, 100); } public static void AddHp(FlatBufferBuilder builder, short hp) { builder.AddShort(2, hp, 100); }
public static void AddName(FlatBufferBuilder builder, int nameOffset) { builder.AddOffset(3, nameOffset, 0); } public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(3, nameOffset.Value, 0); }
public static void AddInventory(FlatBufferBuilder builder, int inventoryOffset) { builder.AddOffset(5, inventoryOffset, 0); } public static void AddInventory(FlatBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(5, inventoryOffset.Value, 0); }
public static int CreateInventoryVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); } public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); }
public static void StartInventoryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } public static void StartInventoryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
public static void AddColor(FlatBufferBuilder builder, Color color) { builder.AddSbyte(6, (sbyte)(color), 8); } public static void AddColor(FlatBufferBuilder builder, Color color) { builder.AddSbyte(6, (sbyte)(color), 8); }
public static void AddTestType(FlatBufferBuilder builder, Any testType) { builder.AddByte(7, (byte)(testType), 0); } public static void AddTestType(FlatBufferBuilder builder, Any testType) { builder.AddByte(7, (byte)(testType), 0); }
public static void AddTest(FlatBufferBuilder builder, int testOffset) { builder.AddOffset(8, testOffset, 0); } public static void AddTest(FlatBufferBuilder builder, int testOffset) { builder.AddOffset(8, testOffset, 0); }
public static void AddTest4(FlatBufferBuilder builder, int test4Offset) { builder.AddOffset(9, test4Offset, 0); } public static void AddTest4(FlatBufferBuilder builder, VectorOffset test4Offset) { builder.AddOffset(9, test4Offset.Value, 0); }
public static void StartTest4Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 2); } public static void StartTest4Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 2); }
public static void AddTestarrayofstring(FlatBufferBuilder builder, int testarrayofstringOffset) { builder.AddOffset(10, testarrayofstringOffset, 0); } public static void AddTestarrayofstring(FlatBufferBuilder builder, VectorOffset testarrayofstringOffset) { builder.AddOffset(10, testarrayofstringOffset.Value, 0); }
public static int CreateTestarrayofstringVector(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); return builder.EndVector(); } public static VectorOffset CreateTestarrayofstringVector(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static void StartTestarrayofstringVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } public static void StartTestarrayofstringVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static void AddTestarrayoftables(FlatBufferBuilder builder, int testarrayoftablesOffset) { builder.AddOffset(11, testarrayoftablesOffset, 0); } public static void AddTestarrayoftables(FlatBufferBuilder builder, VectorOffset testarrayoftablesOffset) { builder.AddOffset(11, testarrayoftablesOffset.Value, 0); }
public static int CreateTestarrayoftablesVector(FlatBufferBuilder builder, int[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i]); return builder.EndVector(); } public static VectorOffset CreateTestarrayoftablesVector(FlatBufferBuilder builder, Offset<Monster>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
public static void StartTestarrayoftablesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } public static void StartTestarrayoftablesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
public static void AddEnemy(FlatBufferBuilder builder, int enemyOffset) { builder.AddOffset(12, enemyOffset, 0); } public static void AddEnemy(FlatBufferBuilder builder, Offset<Monster> enemyOffset) { builder.AddOffset(12, enemyOffset.Value, 0); }
public static void AddTestnestedflatbuffer(FlatBufferBuilder builder, int testnestedflatbufferOffset) { builder.AddOffset(13, testnestedflatbufferOffset, 0); } public static void AddTestnestedflatbuffer(FlatBufferBuilder builder, VectorOffset testnestedflatbufferOffset) { builder.AddOffset(13, testnestedflatbufferOffset.Value, 0); }
public static int CreateTestnestedflatbufferVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); } public static VectorOffset CreateTestnestedflatbufferVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); }
public static void StartTestnestedflatbufferVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } public static void StartTestnestedflatbufferVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
public static void AddTestempty(FlatBufferBuilder builder, int testemptyOffset) { builder.AddOffset(14, testemptyOffset, 0); } public static void AddTestempty(FlatBufferBuilder builder, Offset<Stat> testemptyOffset) { builder.AddOffset(14, testemptyOffset.Value, 0); }
public static void AddTestbool(FlatBufferBuilder builder, bool testbool) { builder.AddBool(15, testbool, false); } public static void AddTestbool(FlatBufferBuilder builder, bool testbool) { builder.AddBool(15, testbool, false); }
public static void AddTesthashs32Fnv1(FlatBufferBuilder builder, int testhashs32Fnv1) { builder.AddInt(16, testhashs32Fnv1, 0); } public static void AddTesthashs32Fnv1(FlatBufferBuilder builder, int testhashs32Fnv1) { builder.AddInt(16, testhashs32Fnv1, 0); }
public static void AddTesthashu32Fnv1(FlatBufferBuilder builder, uint testhashu32Fnv1) { builder.AddUint(17, testhashu32Fnv1, 0); } public static void AddTesthashu32Fnv1(FlatBufferBuilder builder, uint testhashu32Fnv1) { builder.AddUint(17, testhashu32Fnv1, 0); }
...@@ -93,12 +93,12 @@ public sealed class Monster : Table { ...@@ -93,12 +93,12 @@ public sealed class Monster : Table {
public static void AddTesthashu32Fnv1a(FlatBufferBuilder builder, uint testhashu32Fnv1a) { builder.AddUint(21, testhashu32Fnv1a, 0); } public static void AddTesthashu32Fnv1a(FlatBufferBuilder builder, uint testhashu32Fnv1a) { builder.AddUint(21, testhashu32Fnv1a, 0); }
public static void AddTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.AddLong(22, testhashs64Fnv1a, 0); } public static void AddTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.AddLong(22, testhashs64Fnv1a, 0); }
public static void AddTesthashu64Fnv1a(FlatBufferBuilder builder, ulong testhashu64Fnv1a) { builder.AddUlong(23, testhashu64Fnv1a, 0); } public static void AddTesthashu64Fnv1a(FlatBufferBuilder builder, ulong testhashu64Fnv1a) { builder.AddUlong(23, testhashu64Fnv1a, 0); }
public static int EndMonster(FlatBufferBuilder builder) { public static Offset<Monster> EndMonster(FlatBufferBuilder builder) {
int o = builder.EndObject(); int o = builder.EndObject();
builder.Required(o, 10); // name builder.Required(o, 10); // name
return o; return new Offset<Monster>(o);
} }
public static void FinishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.Finish(offset, "MONS"); } public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
}; };
......
...@@ -16,8 +16,8 @@ public sealed class Stat : Table { ...@@ -16,8 +16,8 @@ public sealed class Stat : Table {
public ushort Count { get { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; } } public ushort Count { get { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; } }
public bool MutateCount(ushort count) { int o = __offset(8); if (o != 0) { bb.PutUshort(o + bb_pos, count); return true; } else { return false; } } public bool MutateCount(ushort count) { int o = __offset(8); if (o != 0) { bb.PutUshort(o + bb_pos, count); return true; } else { return false; } }
public static int CreateStat(FlatBufferBuilder builder, public static Offset<Stat> CreateStat(FlatBufferBuilder builder,
int id = 0, StringOffset id = default(StringOffset),
long val = 0, long val = 0,
ushort count = 0) { ushort count = 0) {
builder.StartObject(3); builder.StartObject(3);
...@@ -28,12 +28,12 @@ public sealed class Stat : Table { ...@@ -28,12 +28,12 @@ public sealed class Stat : Table {
} }
public static void StartStat(FlatBufferBuilder builder) { builder.StartObject(3); } public static void StartStat(FlatBufferBuilder builder) { builder.StartObject(3); }
public static void AddId(FlatBufferBuilder builder, int idOffset) { builder.AddOffset(0, idOffset, 0); } public static void AddId(FlatBufferBuilder builder, StringOffset idOffset) { builder.AddOffset(0, idOffset.Value, 0); }
public static void AddVal(FlatBufferBuilder builder, long val) { builder.AddLong(1, val, 0); } public static void AddVal(FlatBufferBuilder builder, long val) { builder.AddLong(1, val, 0); }
public static void AddCount(FlatBufferBuilder builder, ushort count) { builder.AddUshort(2, count, 0); } public static void AddCount(FlatBufferBuilder builder, ushort count) { builder.AddUshort(2, count, 0); }
public static int EndStat(FlatBufferBuilder builder) { public static Offset<Stat> EndStat(FlatBufferBuilder builder) {
int o = builder.EndObject(); int o = builder.EndObject();
return o; return new Offset<Stat>(o);
} }
}; };
......
...@@ -13,12 +13,12 @@ public sealed class Test : Struct { ...@@ -13,12 +13,12 @@ public sealed class Test : Struct {
public sbyte B { get { return bb.GetSbyte(bb_pos + 2); } } public sbyte B { get { return bb.GetSbyte(bb_pos + 2); } }
public void MutateB(sbyte b) { bb.PutSbyte(bb_pos + 2, b); } public void MutateB(sbyte b) { bb.PutSbyte(bb_pos + 2, b); }
public static int CreateTest(FlatBufferBuilder builder, short A, sbyte B) { public static Offset<Test> CreateTest(FlatBufferBuilder builder, short A, sbyte B) {
builder.Prep(2, 4); builder.Prep(2, 4);
builder.Pad(1); builder.Pad(1);
builder.PutSbyte(B); builder.PutSbyte(B);
builder.PutShort(A); builder.PutShort(A);
return builder.Offset; return new Offset<Test>(builder.Offset);
} }
}; };
......
...@@ -21,7 +21,7 @@ public sealed class Vec3 : Struct { ...@@ -21,7 +21,7 @@ public sealed class Vec3 : Struct {
public Test Test3 { get { return GetTest3(new Test()); } } public Test Test3 { get { return GetTest3(new Test()); } }
public Test GetTest3(Test obj) { return obj.__init(bb_pos + 26, bb); } public Test GetTest3(Test obj) { return obj.__init(bb_pos + 26, bb); }
public static int CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, Color Test2, short test3_A, sbyte test3_B) { public static Offset<Vec3> CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, Color Test2, short test3_A, sbyte test3_B) {
builder.Prep(16, 32); builder.Prep(16, 32);
builder.Pad(2); builder.Pad(2);
builder.Prep(2, 4); builder.Prep(2, 4);
...@@ -35,7 +35,7 @@ public sealed class Vec3 : Struct { ...@@ -35,7 +35,7 @@ public sealed class Vec3 : Struct {
builder.PutFloat(Z); builder.PutFloat(Z);
builder.PutFloat(Y); builder.PutFloat(Y);
builder.PutFloat(X); builder.PutFloat(X);
return builder.Offset; return new Offset<Vec3>(builder.Offset);
} }
}; };
......
...@@ -324,7 +324,7 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { ...@@ -324,7 +324,7 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
TEST_EQ(hp_int64, 80); TEST_EQ(hp_int64, 80);
auto hp_double = flatbuffers::GetAnyFieldF(root, hp_field); auto hp_double = flatbuffers::GetAnyFieldF(root, hp_field);
TEST_EQ(hp_double, 80.0); TEST_EQ(hp_double, 80.0);
auto hp_string = flatbuffers::GetAnyFieldS(root, hp_field, schema); auto hp_string = flatbuffers::GetAnyFieldS(root, hp_field, &schema);
TEST_EQ_STR(hp_string.c_str(), "80"); TEST_EQ_STR(hp_string.c_str(), "80");
// We can also modify it. // We can also modify it.
...@@ -370,8 +370,44 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { ...@@ -370,8 +370,44 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
// rinventory still valid, so lets read from it. // rinventory still valid, so lets read from it.
TEST_EQ(rinventory->Get(10), 50); TEST_EQ(rinventory->Get(10), 50);
// Using reflection, we can also copy tables and other things out of // For reflection uses not covered already, there is a more powerful way:
// other FlatBuffers into a new one, either part or whole. // we can simply generate whatever object we want to add/modify in a
// FlatBuffer of its own, then add that to an existing FlatBuffer:
// As an example, let's add a string to an array of strings.
// First, find our field:
auto &testarrayofstring_field = *fields->LookupByKey("testarrayofstring");
// Find the vector value:
auto rtestarrayofstring = flatbuffers::piv(
flatbuffers::GetFieldV<flatbuffers::Offset<flatbuffers::String>>(
**rroot, testarrayofstring_field),
resizingbuf);
// It's a vector of 2 strings, to which we add one more, initialized to
// offset 0.
flatbuffers::ResizeVector<flatbuffers::Offset<flatbuffers::String>>(
schema, 3, 0, *rtestarrayofstring, &resizingbuf);
// Here we just create a buffer that contans a single string, but this
// could also be any complex set of tables and other values.
flatbuffers::FlatBufferBuilder stringfbb;
stringfbb.Finish(stringfbb.CreateString("hank"));
// Add the contents of it to our existing FlatBuffer.
// We do this last, so the pointer doesn't get invalidated (since it is
// at the end of the buffer):
auto string_ptr = flatbuffers::AddFlatBuffer(resizingbuf,
stringfbb.GetBufferPointer(),
stringfbb.GetSize());
// Finally, set the new value in the vector.
rtestarrayofstring->MutateOffset(2, string_ptr);
TEST_EQ_STR(rtestarrayofstring->Get(0)->c_str(), "bob");
TEST_EQ_STR(rtestarrayofstring->Get(2)->c_str(), "hank");
// As an additional test, also set it on the name field.
// Note: unlike the name change above, this just overwrites the offset,
// rather than changing the string in-place.
SetFieldT(*rroot, name_field, string_ptr);
TEST_EQ_STR(GetFieldS(**rroot, name_field)->c_str(), "hank");
// Using reflection, rather than mutating binary FlatBuffers, we can also copy
// tables and other things out of other FlatBuffers into a FlatBufferBuilder,
// either part or whole.
flatbuffers::FlatBufferBuilder fbb; flatbuffers::FlatBufferBuilder fbb;
auto root_offset = flatbuffers::CopyTable(fbb, schema, *root_table, auto root_offset = flatbuffers::CopyTable(fbb, schema, *root_table,
*flatbuffers::GetAnyRoot(flatbuf)); *flatbuffers::GetAnyRoot(flatbuf));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment