mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-30 15:30:02 +00:00
Add support for fixed-size arrays (#5313)
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
0d2cebccfe
commit
e635141d5b
@@ -19,6 +19,7 @@ call generate_code.bat -b %buildtype% || goto FAIL
|
|||||||
|
|
||||||
:: TODO: Release and Debug builds produce differences here for some reason.
|
:: TODO: Release and Debug builds produce differences here for some reason.
|
||||||
git checkout HEAD -- monster_test.bfbs
|
git checkout HEAD -- monster_test.bfbs
|
||||||
|
git checkout HEAD -- arrays_test.bfbs
|
||||||
|
|
||||||
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
|
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
|
||||||
goto SUCCESS
|
goto SUCCESS
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ cd ..
|
|||||||
|
|
||||||
# TODO: Linux and macos builds produce differences here for some reason.
|
# TODO: Linux and macos builds produce differences here for some reason.
|
||||||
git checkout HEAD -- tests/monster_test.bfbs
|
git checkout HEAD -- tests/monster_test.bfbs
|
||||||
|
git checkout HEAD -- tests/arrays_test.bfbs
|
||||||
|
|
||||||
if ! git diff --quiet; then
|
if ! git diff --quiet; then
|
||||||
echo >&2
|
echo >&2
|
||||||
|
|||||||
17
BUILD
17
BUILD
@@ -164,11 +164,15 @@ cc_test(
|
|||||||
":tests/union_vector/union_vector.json",
|
":tests/union_vector/union_vector.json",
|
||||||
":tests/monster_extra.fbs",
|
":tests/monster_extra.fbs",
|
||||||
":tests/monsterdata_extra.json",
|
":tests/monsterdata_extra.json",
|
||||||
|
":tests/arrays_test.bfbs",
|
||||||
|
":tests/arrays_test.fbs",
|
||||||
|
":tests/arrays_test.golden",
|
||||||
],
|
],
|
||||||
includes = ["include/"],
|
includes = ["include/"],
|
||||||
deps = [
|
deps = [
|
||||||
":monster_extra_cc_fbs",
|
":monster_extra_cc_fbs",
|
||||||
":monster_test_cc_fbs",
|
":monster_test_cc_fbs",
|
||||||
|
":arrays_test_cc_fbs",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -188,3 +192,16 @@ flatbuffer_cc_library(
|
|||||||
name = "monster_extra_cc_fbs",
|
name = "monster_extra_cc_fbs",
|
||||||
srcs = ["tests/monster_extra.fbs"],
|
srcs = ["tests/monster_extra.fbs"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
flatbuffer_cc_library(
|
||||||
|
name = "arrays_test_cc_fbs",
|
||||||
|
srcs = ["tests/arrays_test.fbs"],
|
||||||
|
flatc_args = [
|
||||||
|
"--gen-object-api",
|
||||||
|
"--gen-compare",
|
||||||
|
"--no-includes",
|
||||||
|
"--gen-mutable",
|
||||||
|
"--reflect-names",
|
||||||
|
"--cpp-ptr-type flatbuffers::unique_ptr",
|
||||||
|
"--scoped-enums" ],
|
||||||
|
)
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ set(FlatBuffers_Tests_SRCS
|
|||||||
tests/test_builder.cpp
|
tests/test_builder.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
|
||||||
|
# file generate by running compiler on tests/arrays_test.fbs
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/tests/arrays_test_generated.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FlatBuffers_Sample_Binary_SRCS
|
set(FlatBuffers_Sample_Binary_SRCS
|
||||||
@@ -303,7 +305,7 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
|
|||||||
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
function(compile_flatbuffers_schema_to_cpp_opt SRC_FBS OPT)
|
||||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||||
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
|
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
@@ -311,12 +313,16 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
|||||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||||
--gen-object-api --gen-compare -o "${SRC_FBS_DIR}"
|
--gen-object-api --gen-compare -o "${SRC_FBS_DIR}"
|
||||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||||
--reflect-names
|
--reflect-names ${OPT}
|
||||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||||
DEPENDS flatc)
|
DEPENDS flatc)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||||
|
compile_flatbuffers_schema_to_cpp_opt(${SRC_FBS} "")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
||||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||||
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
||||||
@@ -329,6 +335,7 @@ endfunction()
|
|||||||
|
|
||||||
if(FLATBUFFERS_BUILD_TESTS)
|
if(FLATBUFFERS_BUILD_TESTS)
|
||||||
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
|
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
|
||||||
|
compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs --scoped-enums)
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
|
||||||
add_executable(flattests ${FlatBuffers_Tests_SRCS})
|
add_executable(flattests ${FlatBuffers_Tests_SRCS})
|
||||||
set_property(TARGET flattests
|
set_property(TARGET flattests
|
||||||
|
|||||||
@@ -114,6 +114,27 @@ of same-size data where a `reinterpret_cast` would give you a desirable result,
|
|||||||
e.g. you could change a `uint` to an `int` if no values in current data use the
|
e.g. you could change a `uint` to an `int` if no values in current data use the
|
||||||
high bit yet.
|
high bit yet.
|
||||||
|
|
||||||
|
### Arrays
|
||||||
|
|
||||||
|
Arrays are a convenience short-hand for a fixed-length collection of elements.
|
||||||
|
Arrays can be used to replace the following schema:
|
||||||
|
|
||||||
|
struct Vec3 {
|
||||||
|
x:float;
|
||||||
|
y:float;
|
||||||
|
z:float;
|
||||||
|
}
|
||||||
|
|
||||||
|
with the following schema:
|
||||||
|
|
||||||
|
struct Vec3 {
|
||||||
|
v:[float:3];
|
||||||
|
}
|
||||||
|
|
||||||
|
Both representations are binary equivalent.
|
||||||
|
|
||||||
|
Arrays are currently only supported in a `struct`.
|
||||||
|
|
||||||
### (Default) Values
|
### (Default) Values
|
||||||
|
|
||||||
Values are a sequence of digits. Values may be optionally followed by a decimal
|
Values are a sequence of digits. Values may be optionally followed by a decimal
|
||||||
|
|||||||
@@ -395,6 +395,83 @@ template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
|
|||||||
return v ? v->size() : 0;
|
return v ? v->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is used as a helper type for accessing arrays.
|
||||||
|
template<typename T, uint16_t length> class Array {
|
||||||
|
public:
|
||||||
|
typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
|
||||||
|
const_iterator;
|
||||||
|
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||||
|
|
||||||
|
typedef typename IndirectHelper<T>::return_type return_type;
|
||||||
|
|
||||||
|
FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
|
||||||
|
|
||||||
|
return_type Get(uoffset_t i) const {
|
||||||
|
FLATBUFFERS_ASSERT(i < size());
|
||||||
|
return IndirectHelper<T>::Read(Data(), i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return_type operator[](uoffset_t i) const { return Get(i); }
|
||||||
|
|
||||||
|
const_iterator begin() const { return const_iterator(Data(), 0); }
|
||||||
|
const_iterator end() const { return const_iterator(Data(), size()); }
|
||||||
|
|
||||||
|
const_reverse_iterator rbegin() const {
|
||||||
|
return const_reverse_iterator(end());
|
||||||
|
}
|
||||||
|
const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
|
||||||
|
|
||||||
|
const_iterator cbegin() const { return begin(); }
|
||||||
|
const_iterator cend() const { return end(); }
|
||||||
|
|
||||||
|
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||||
|
const_reverse_iterator crend() const { return rend(); }
|
||||||
|
|
||||||
|
// Change elements if you have a non-const pointer to this object.
|
||||||
|
void Mutate(uoffset_t i, const T &val) {
|
||||||
|
FLATBUFFERS_ASSERT(i < size());
|
||||||
|
WriteScalar(data() + i, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a mutable pointer to elements inside this array.
|
||||||
|
// @note This method should be only used to mutate arrays of structs followed
|
||||||
|
// by a @p Mutate operation. For primitive types use @p Mutate directly.
|
||||||
|
// @warning Assignments and reads to/from the dereferenced pointer are not
|
||||||
|
// automatically converted to the correct endianness.
|
||||||
|
T *GetMutablePointer(uoffset_t i) const {
|
||||||
|
FLATBUFFERS_ASSERT(i < size());
|
||||||
|
return const_cast<T *>(&data()[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The raw data in little endian format. Use with care.
|
||||||
|
const uint8_t *Data() const { return data_; }
|
||||||
|
|
||||||
|
uint8_t *Data() { return data_; }
|
||||||
|
|
||||||
|
// Similarly, but typed, much like std::vector::data
|
||||||
|
const T *data() const { return reinterpret_cast<const T *>(Data()); }
|
||||||
|
T *data() { return reinterpret_cast<T *>(Data()); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// This class is only used to access pre-existing data. Don't ever
|
||||||
|
// try to construct these manually.
|
||||||
|
// 'constexpr' allows us to use 'size()' at compile time.
|
||||||
|
// @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
|
||||||
|
// a constructor.
|
||||||
|
#if defined(__cpp_constexpr)
|
||||||
|
constexpr Array();
|
||||||
|
#else
|
||||||
|
Array();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t data_[length * sizeof(T)];
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This class is a pointer. Copying will therefore create an invalid object.
|
||||||
|
// Private and unimplemented copy constructor.
|
||||||
|
Array(const Array &);
|
||||||
|
};
|
||||||
|
|
||||||
// Lexicographically compare two strings (possibly containing nulls), and
|
// Lexicographically compare two strings (possibly containing nulls), and
|
||||||
// return true if the first is less than the second.
|
// return true if the first is less than the second.
|
||||||
static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
|
static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
|
||||||
|
|||||||
@@ -65,7 +65,8 @@ namespace flatbuffers {
|
|||||||
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused) \
|
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused) \
|
||||||
TD(STRUCT, "", Offset<void>, int, int, int, int, unused) \
|
TD(STRUCT, "", Offset<void>, int, int, int, int, unused) \
|
||||||
TD(UNION, "", Offset<void>, int, int, int, int, unused)
|
TD(UNION, "", Offset<void>, int, int, int, int, unused)
|
||||||
|
#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
|
||||||
|
TD(ARRAY, "", int, int, int, int, int, unused)
|
||||||
// The fields are:
|
// The fields are:
|
||||||
// - enum
|
// - enum
|
||||||
// - FlatBuffers schema type.
|
// - FlatBuffers schema type.
|
||||||
@@ -91,7 +92,8 @@ switch (type) {
|
|||||||
|
|
||||||
#define FLATBUFFERS_GEN_TYPES(TD) \
|
#define FLATBUFFERS_GEN_TYPES(TD) \
|
||||||
FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||||
FLATBUFFERS_GEN_TYPES_POINTER(TD)
|
FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
||||||
|
FLATBUFFERS_GEN_TYPE_ARRAY(TD)
|
||||||
|
|
||||||
// Create an enum for all the types above.
|
// Create an enum for all the types above.
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
@@ -145,18 +147,21 @@ class Parser;
|
|||||||
// and additional information for vectors/structs_.
|
// and additional information for vectors/structs_.
|
||||||
struct Type {
|
struct Type {
|
||||||
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
|
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
|
||||||
EnumDef *_ed = nullptr)
|
EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
|
||||||
: base_type(_base_type),
|
: base_type(_base_type),
|
||||||
element(BASE_TYPE_NONE),
|
element(BASE_TYPE_NONE),
|
||||||
struct_def(_sd),
|
struct_def(_sd),
|
||||||
enum_def(_ed) {}
|
enum_def(_ed),
|
||||||
|
fixed_length(_fixed_length) {}
|
||||||
|
|
||||||
bool operator==(const Type &o) {
|
bool operator==(const Type &o) {
|
||||||
return base_type == o.base_type && element == o.element &&
|
return base_type == o.base_type && element == o.element &&
|
||||||
struct_def == o.struct_def && enum_def == o.enum_def;
|
struct_def == o.struct_def && enum_def == o.enum_def;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type VectorType() const { return Type(element, struct_def, enum_def); }
|
Type VectorType() const {
|
||||||
|
return Type(element, struct_def, enum_def, fixed_length);
|
||||||
|
}
|
||||||
|
|
||||||
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
|
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
|
||||||
|
|
||||||
@@ -167,6 +172,7 @@ struct Type {
|
|||||||
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
||||||
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
|
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
|
||||||
// or for an integral type derived from an enum.
|
// or for an integral type derived from an enum.
|
||||||
|
uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
|
||||||
};
|
};
|
||||||
|
|
||||||
// Represents a parsed scalar value, it's type, and field offset.
|
// Represents a parsed scalar value, it's type, and field offset.
|
||||||
@@ -335,12 +341,34 @@ inline bool IsStruct(const Type &type) {
|
|||||||
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
|
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool IsVector(const Type &type) {
|
||||||
|
return type.base_type == BASE_TYPE_VECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsArray(const Type &type) {
|
||||||
|
return type.base_type == BASE_TYPE_ARRAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsSeries(const Type &type) {
|
||||||
|
return IsVector(type) || IsArray(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsEnum(const Type &type) {
|
||||||
|
return type.enum_def != nullptr && IsInteger(type.base_type);
|
||||||
|
}
|
||||||
|
|
||||||
inline size_t InlineSize(const Type &type) {
|
inline size_t InlineSize(const Type &type) {
|
||||||
return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
|
return IsStruct(type)
|
||||||
|
? type.struct_def->bytesize
|
||||||
|
: (IsArray(type)
|
||||||
|
? InlineSize(type.VectorType()) * type.fixed_length
|
||||||
|
: SizeOf(type.base_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t InlineAlignment(const Type &type) {
|
inline size_t InlineAlignment(const Type &type) {
|
||||||
return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
|
return IsStruct(type)
|
||||||
|
? type.struct_def->minalign
|
||||||
|
: (SizeOf(IsArray(type) ? type.element : type.base_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EnumDef;
|
struct EnumDef;
|
||||||
@@ -799,10 +827,13 @@ class Parser : public ParserState {
|
|||||||
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
||||||
std::string *value, uoffset_t *ovalue);
|
std::string *value, uoffset_t *ovalue);
|
||||||
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
||||||
|
void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
|
||||||
|
const Value &val);
|
||||||
template<typename F>
|
template<typename F>
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
|
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
|
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
|
||||||
FieldDef *field, size_t fieldn);
|
FieldDef *field, size_t fieldn);
|
||||||
|
FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||||
size_t fieldn,
|
size_t fieldn,
|
||||||
const StructDef *parent_struct_def);
|
const StructDef *parent_struct_def);
|
||||||
@@ -849,6 +880,7 @@ class Parser : public ParserState {
|
|||||||
BaseType baseType);
|
BaseType baseType);
|
||||||
|
|
||||||
bool SupportsAdvancedUnionFeatures() const;
|
bool SupportsAdvancedUnionFeatures() const;
|
||||||
|
bool SupportsAdvancedArrayFeatures() const;
|
||||||
Namespace *UniqueNamespace(Namespace *ns);
|
Namespace *UniqueNamespace(Namespace *ns);
|
||||||
|
|
||||||
FLATBUFFERS_CHECKED_ERROR RecurseError();
|
FLATBUFFERS_CHECKED_ERROR RecurseError();
|
||||||
|
|||||||
@@ -43,10 +43,11 @@ enum BaseType {
|
|||||||
String = 13,
|
String = 13,
|
||||||
Vector = 14,
|
Vector = 14,
|
||||||
Obj = 15,
|
Obj = 15,
|
||||||
Union = 16
|
Union = 16,
|
||||||
|
Array = 17
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const BaseType (&EnumValuesBaseType())[17] {
|
inline const BaseType (&EnumValuesBaseType())[18] {
|
||||||
static const BaseType values[] = {
|
static const BaseType values[] = {
|
||||||
None,
|
None,
|
||||||
UType,
|
UType,
|
||||||
@@ -64,13 +65,14 @@ inline const BaseType (&EnumValuesBaseType())[17] {
|
|||||||
String,
|
String,
|
||||||
Vector,
|
Vector,
|
||||||
Obj,
|
Obj,
|
||||||
Union
|
Union,
|
||||||
|
Array
|
||||||
};
|
};
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char * const *EnumNamesBaseType() {
|
inline const char * const *EnumNamesBaseType() {
|
||||||
static const char * const names[18] = {
|
static const char * const names[19] = {
|
||||||
"None",
|
"None",
|
||||||
"UType",
|
"UType",
|
||||||
"Bool",
|
"Bool",
|
||||||
@@ -88,13 +90,14 @@ inline const char * const *EnumNamesBaseType() {
|
|||||||
"Vector",
|
"Vector",
|
||||||
"Obj",
|
"Obj",
|
||||||
"Union",
|
"Union",
|
||||||
|
"Array",
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *EnumNameBaseType(BaseType e) {
|
inline const char *EnumNameBaseType(BaseType e) {
|
||||||
if (e < None || e > Union) return "";
|
if (e < None || e > Array) return "";
|
||||||
const size_t index = static_cast<size_t>(e);
|
const size_t index = static_cast<size_t>(e);
|
||||||
return EnumNamesBaseType()[index];
|
return EnumNamesBaseType()[index];
|
||||||
}
|
}
|
||||||
@@ -103,7 +106,8 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_BASE_TYPE = 4,
|
VT_BASE_TYPE = 4,
|
||||||
VT_ELEMENT = 6,
|
VT_ELEMENT = 6,
|
||||||
VT_INDEX = 8
|
VT_INDEX = 8,
|
||||||
|
VT_FIXED_LENGTH = 10
|
||||||
};
|
};
|
||||||
reflection::BaseType base_type() const {
|
reflection::BaseType base_type() const {
|
||||||
return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
|
return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
|
||||||
@@ -114,11 +118,15 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
int32_t index() const {
|
int32_t index() const {
|
||||||
return GetField<int32_t>(VT_INDEX, -1);
|
return GetField<int32_t>(VT_INDEX, -1);
|
||||||
}
|
}
|
||||||
|
uint16_t fixed_length() const {
|
||||||
|
return GetField<uint16_t>(VT_FIXED_LENGTH, 0);
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
|
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
|
||||||
VerifyField<int8_t>(verifier, VT_ELEMENT) &&
|
VerifyField<int8_t>(verifier, VT_ELEMENT) &&
|
||||||
VerifyField<int32_t>(verifier, VT_INDEX) &&
|
VerifyField<int32_t>(verifier, VT_INDEX) &&
|
||||||
|
VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -135,6 +143,9 @@ struct TypeBuilder {
|
|||||||
void add_index(int32_t index) {
|
void add_index(int32_t index) {
|
||||||
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
|
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
|
||||||
}
|
}
|
||||||
|
void add_fixed_length(uint16_t fixed_length) {
|
||||||
|
fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
|
||||||
|
}
|
||||||
explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
@@ -151,9 +162,11 @@ inline flatbuffers::Offset<Type> CreateType(
|
|||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
reflection::BaseType base_type = reflection::None,
|
reflection::BaseType base_type = reflection::None,
|
||||||
reflection::BaseType element = reflection::None,
|
reflection::BaseType element = reflection::None,
|
||||||
int32_t index = -1) {
|
int32_t index = -1,
|
||||||
|
uint16_t fixed_length = 0) {
|
||||||
TypeBuilder builder_(_fbb);
|
TypeBuilder builder_(_fbb);
|
||||||
builder_.add_index(index);
|
builder_.add_index(index);
|
||||||
|
builder_.add_fixed_length(fixed_length);
|
||||||
builder_.add_element(element);
|
builder_.add_element(element);
|
||||||
builder_.add_base_type(base_type);
|
builder_.add_base_type(base_type);
|
||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
|
|||||||
@@ -23,15 +23,18 @@ enum BaseType : byte {
|
|||||||
String,
|
String,
|
||||||
Vector,
|
Vector,
|
||||||
Obj, // Used for tables & structs.
|
Obj, // Used for tables & structs.
|
||||||
Union
|
Union,
|
||||||
|
Array
|
||||||
}
|
}
|
||||||
|
|
||||||
table Type {
|
table Type {
|
||||||
base_type:BaseType;
|
base_type:BaseType;
|
||||||
element:BaseType = None; // Only if base_type == Vector.
|
element:BaseType = None; // Only if base_type == Vector
|
||||||
|
// or base_type == Array.
|
||||||
index:int = -1; // If base_type == Object, index into "objects" below.
|
index:int = -1; // If base_type == Object, index into "objects" below.
|
||||||
// If base_type == Union, UnionType, or integral derived
|
// If base_type == Union, UnionType, or integral derived
|
||||||
// from an enum, index into "enums" below.
|
// from an enum, index into "enums" below.
|
||||||
|
fixed_length:uint16 = 0; // Only if base_type == Array.
|
||||||
}
|
}
|
||||||
|
|
||||||
table KeyValue {
|
table KeyValue {
|
||||||
|
|||||||
@@ -697,6 +697,13 @@ class CppGenerator : public BaseGenerator {
|
|||||||
bool user_facing_type) {
|
bool user_facing_type) {
|
||||||
if (IsScalar(type.base_type)) {
|
if (IsScalar(type.base_type)) {
|
||||||
return GenTypeBasic(type, user_facing_type) + afterbasic;
|
return GenTypeBasic(type, user_facing_type) + afterbasic;
|
||||||
|
} else if (IsArray(type)) {
|
||||||
|
auto element_type = type.VectorType();
|
||||||
|
return beforeptr +
|
||||||
|
(IsScalar(element_type.base_type)
|
||||||
|
? GenTypeBasic(element_type, user_facing_type)
|
||||||
|
: GenTypePointer(element_type)) +
|
||||||
|
afterptr;
|
||||||
} else {
|
} else {
|
||||||
return beforeptr + GenTypePointer(type) + afterptr;
|
return beforeptr + GenTypePointer(type) + afterptr;
|
||||||
}
|
}
|
||||||
@@ -2689,7 +2696,8 @@ class CppGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
|
static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
|
||||||
(void)bits;
|
(void)bits;
|
||||||
*code_ptr += ",\n padding" + NumToString((*id)++) + "__(0)";
|
if (*code_ptr != "") *code_ptr += ",\n ";
|
||||||
|
*code_ptr += "padding" + NumToString((*id)++) + "__(0)";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PaddingNoop(int bits, std::string *code_ptr, int *id) {
|
static void PaddingNoop(int bits, std::string *code_ptr, int *id) {
|
||||||
@@ -2717,10 +2725,14 @@ class CppGenerator : public BaseGenerator {
|
|||||||
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) {
|
||||||
const auto &field = **it;
|
const auto &field = **it;
|
||||||
code_.SetValue("FIELD_TYPE",
|
const auto &field_type = field.value.type;
|
||||||
GenTypeGet(field.value.type, " ", "", " ", false));
|
code_.SetValue("FIELD_TYPE", GenTypeGet(field_type, " ", "", " ", false));
|
||||||
code_.SetValue("FIELD_NAME", Name(field));
|
code_.SetValue("FIELD_NAME", Name(field));
|
||||||
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}_;";
|
code_.SetValue("ARRAY",
|
||||||
|
IsArray(field_type)
|
||||||
|
? "[" + NumToString(field_type.fixed_length) + "]"
|
||||||
|
: "");
|
||||||
|
code_ += (" {{FIELD_TYPE}}{{FIELD_NAME}}_{{ARRAY}};");
|
||||||
|
|
||||||
if (field.padding) {
|
if (field.padding) {
|
||||||
std::string padding;
|
std::string padding;
|
||||||
@@ -2745,33 +2757,40 @@ class CppGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Generate a default constructor.
|
// Generate a default constructor.
|
||||||
code_ += " {{STRUCT_NAME}}() {";
|
code_ += " {{STRUCT_NAME}}() {";
|
||||||
code_ += " memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));";
|
code_ +=
|
||||||
|
" memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
|
|
||||||
// Generate a constructor that takes all fields as arguments.
|
// Generate a constructor that takes all fields as arguments,
|
||||||
|
// excluding arrays
|
||||||
std::string arg_list;
|
std::string arg_list;
|
||||||
std::string init_list;
|
std::string init_list;
|
||||||
padding_id = 0;
|
padding_id = 0;
|
||||||
|
auto first = struct_def.fields.vec.begin();
|
||||||
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) {
|
||||||
const auto &field = **it;
|
const auto &field = **it;
|
||||||
|
if (IsArray(field.value.type)) {
|
||||||
|
first++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const auto member_name = Name(field) + "_";
|
const auto member_name = Name(field) + "_";
|
||||||
const auto arg_name = "_" + Name(field);
|
const auto arg_name = "_" + Name(field);
|
||||||
const auto arg_type =
|
const auto arg_type =
|
||||||
GenTypeGet(field.value.type, " ", "const ", " &", true);
|
GenTypeGet(field.value.type, " ", "const ", " &", true);
|
||||||
|
|
||||||
if (it != struct_def.fields.vec.begin()) {
|
if (it != first) { arg_list += ", "; }
|
||||||
arg_list += ", ";
|
|
||||||
init_list += ",\n ";
|
|
||||||
}
|
|
||||||
arg_list += arg_type;
|
arg_list += arg_type;
|
||||||
arg_list += arg_name;
|
arg_list += arg_name;
|
||||||
init_list += member_name;
|
if (!IsArray(field.value.type)) {
|
||||||
if (IsScalar(field.value.type.base_type)) {
|
if (it != first && init_list != "") { init_list += ",\n "; }
|
||||||
auto type = GenUnderlyingCast(field, false, arg_name);
|
init_list += member_name;
|
||||||
init_list += "(flatbuffers::EndianScalar(" + type + "))";
|
if (IsScalar(field.value.type.base_type)) {
|
||||||
} else {
|
auto type = GenUnderlyingCast(field, false, arg_name);
|
||||||
init_list += "(" + arg_name + ")";
|
init_list += "(flatbuffers::EndianScalar(" + type + "))";
|
||||||
|
} else {
|
||||||
|
init_list += "(" + arg_name + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (field.padding) {
|
if (field.padding) {
|
||||||
GenPadding(field, &init_list, &padding_id, PaddingInitializer);
|
GenPadding(field, &init_list, &padding_id, PaddingInitializer);
|
||||||
@@ -2781,12 +2800,21 @@ class CppGenerator : public BaseGenerator {
|
|||||||
if (!arg_list.empty()) {
|
if (!arg_list.empty()) {
|
||||||
code_.SetValue("ARG_LIST", arg_list);
|
code_.SetValue("ARG_LIST", arg_list);
|
||||||
code_.SetValue("INIT_LIST", init_list);
|
code_.SetValue("INIT_LIST", init_list);
|
||||||
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
|
if (!init_list.empty()) {
|
||||||
code_ += " : {{INIT_LIST}} {";
|
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
|
||||||
|
code_ += " : {{INIT_LIST}} {";
|
||||||
|
} else {
|
||||||
|
code_ += " {{STRUCT_NAME}}({{ARG_LIST}}) {";
|
||||||
|
}
|
||||||
padding_id = 0;
|
padding_id = 0;
|
||||||
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) {
|
||||||
const auto &field = **it;
|
const auto &field = **it;
|
||||||
|
if (IsArray(field.value.type)) {
|
||||||
|
const auto &member = Name(field) + "_";
|
||||||
|
code_ +=
|
||||||
|
" std::memset(" + member + ", 0, sizeof(" + member + "));";
|
||||||
|
}
|
||||||
if (field.padding) {
|
if (field.padding) {
|
||||||
std::string padding;
|
std::string padding;
|
||||||
GenPadding(field, &padding, &padding_id, PaddingNoop);
|
GenPadding(field, &padding, &padding_id, PaddingNoop);
|
||||||
@@ -2802,7 +2830,9 @@ class CppGenerator : public BaseGenerator {
|
|||||||
it != struct_def.fields.vec.end(); ++it) {
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
const auto &field = **it;
|
const auto &field = **it;
|
||||||
|
|
||||||
auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true);
|
auto field_type = GenTypeGet(field.value.type, " ",
|
||||||
|
IsArray(field.value.type) ? "" : "const ",
|
||||||
|
IsArray(field.value.type) ? "" : " &", true);
|
||||||
auto is_scalar = IsScalar(field.value.type.base_type);
|
auto is_scalar = IsScalar(field.value.type.base_type);
|
||||||
auto member = Name(field) + "_";
|
auto member = Name(field) + "_";
|
||||||
auto value =
|
auto value =
|
||||||
@@ -2813,12 +2843,29 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
|
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
|
||||||
|
|
||||||
GenComment(field.doc_comment, " ");
|
GenComment(field.doc_comment, " ");
|
||||||
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
|
|
||||||
code_ += " return {{FIELD_VALUE}};";
|
|
||||||
code_ += " }";
|
|
||||||
|
|
||||||
|
// Generate a const accessor function.
|
||||||
|
if (IsArray(field.value.type)) {
|
||||||
|
auto underlying = GenTypeGet(field.value.type, "", "", "", false);
|
||||||
|
code_ += " const flatbuffers::Array<" + field_type + ", " +
|
||||||
|
NumToString(field.value.type.fixed_length) + "> *" +
|
||||||
|
"{{FIELD_NAME}}() const {";
|
||||||
|
code_ += " return reinterpret_cast<const flatbuffers::Array<" +
|
||||||
|
field_type + ", " +
|
||||||
|
NumToString(field.value.type.fixed_length) +
|
||||||
|
"> *>({{FIELD_VALUE}});";
|
||||||
|
code_ += " }";
|
||||||
|
} else {
|
||||||
|
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
|
||||||
|
code_ += " return {{FIELD_VALUE}};";
|
||||||
|
code_ += " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a mutable accessor function.
|
||||||
if (parser_.opts.mutable_buffer) {
|
if (parser_.opts.mutable_buffer) {
|
||||||
auto mut_field_type = GenTypeGet(field.value.type, " ", "", " &", true);
|
auto mut_field_type =
|
||||||
|
GenTypeGet(field.value.type, " ", "",
|
||||||
|
IsArray(field.value.type) ? "" : " &", true);
|
||||||
code_.SetValue("FIELD_TYPE", mut_field_type);
|
code_.SetValue("FIELD_TYPE", mut_field_type);
|
||||||
if (is_scalar) {
|
if (is_scalar) {
|
||||||
code_.SetValue("ARG", GenTypeBasic(field.value.type, true));
|
code_.SetValue("ARG", GenTypeBasic(field.value.type, true));
|
||||||
@@ -2830,9 +2877,19 @@ class CppGenerator : public BaseGenerator {
|
|||||||
" flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
|
" flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
|
||||||
"{{FIELD_VALUE}});";
|
"{{FIELD_VALUE}});";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
|
} else if (IsArray(field.value.type)) {
|
||||||
|
auto underlying = GenTypeGet(field.value.type, "", "", "", false);
|
||||||
|
code_ += " flatbuffers::Array<" + mut_field_type + ", " +
|
||||||
|
NumToString(field.value.type.fixed_length) +
|
||||||
|
"> *" + "mutable_{{FIELD_NAME}}() {";
|
||||||
|
code_ += " return reinterpret_cast<flatbuffers::Array<" +
|
||||||
|
mut_field_type + ", " +
|
||||||
|
NumToString(field.value.type.fixed_length) +
|
||||||
|
"> *>({{FIELD_VALUE}});";
|
||||||
|
code_ += " }";
|
||||||
} else {
|
} else {
|
||||||
code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
|
code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
|
||||||
code_ += " return {{FIELD_NAME}}_;";
|
code_ += " return {{FIELD_VALUE}};";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,10 +254,6 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
: "";
|
: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsEnum(const Type &type) {
|
|
||||||
return type.enum_def != nullptr && IsInteger(type.base_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const {
|
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const char * const java_typename[] = {
|
static const char * const java_typename[] = {
|
||||||
@@ -312,7 +308,10 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GenTypeGet(const Type &type) const {
|
std::string GenTypeGet(const Type &type) const {
|
||||||
return IsScalar(type.base_type) ? GenTypeBasic(type) : GenTypePointer(type);
|
return IsScalar(type.base_type)
|
||||||
|
? GenTypeBasic(type)
|
||||||
|
: (IsArray(type) ? GenTypeGet(type.VectorType())
|
||||||
|
: GenTypePointer(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the destination type the user wants to receive the value in (e.g.
|
// Find the destination type the user wants to receive the value in (e.g.
|
||||||
@@ -325,6 +324,7 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT);
|
case BASE_TYPE_UCHAR: return Type(BASE_TYPE_INT);
|
||||||
case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT);
|
case BASE_TYPE_USHORT: return Type(BASE_TYPE_INT);
|
||||||
case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
|
case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
|
||||||
|
case BASE_TYPE_ARRAY:
|
||||||
case BASE_TYPE_VECTOR:
|
case BASE_TYPE_VECTOR:
|
||||||
if (vectorelem) return DestinationType(type.VectorType(), vectorelem);
|
if (vectorelem) return DestinationType(type.VectorType(), vectorelem);
|
||||||
FLATBUFFERS_FALLTHROUGH(); // else fall thru
|
FLATBUFFERS_FALLTHROUGH(); // else fall thru
|
||||||
@@ -378,7 +378,7 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Casts necessary to correctly read serialized data
|
// Casts necessary to correctly read serialized data
|
||||||
std::string DestinationCast(const Type &type) const {
|
std::string DestinationCast(const Type &type) const {
|
||||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
if (IsSeries(type)) {
|
||||||
return DestinationCast(type.VectorType());
|
return DestinationCast(type.VectorType());
|
||||||
} else {
|
} else {
|
||||||
switch (lang_.language) {
|
switch (lang_.language) {
|
||||||
@@ -405,7 +405,7 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
// directly cast an Enum to its underlying type, which is essential before
|
// directly cast an Enum to its underlying type, which is essential before
|
||||||
// putting it onto the buffer.
|
// putting it onto the buffer.
|
||||||
std::string SourceCast(const Type &type, bool castFromDest) const {
|
std::string SourceCast(const Type &type, bool castFromDest) const {
|
||||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
if (IsSeries(type)) {
|
||||||
return SourceCast(type.VectorType(), castFromDest);
|
return SourceCast(type.VectorType(), castFromDest);
|
||||||
} else {
|
} else {
|
||||||
switch (lang_.language) {
|
switch (lang_.language) {
|
||||||
@@ -602,6 +602,7 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
case BASE_TYPE_STRUCT: return lang_.accessor_prefix + "__struct";
|
case BASE_TYPE_STRUCT: return lang_.accessor_prefix + "__struct";
|
||||||
case BASE_TYPE_UNION: return lang_.accessor_prefix + "__union";
|
case BASE_TYPE_UNION: return lang_.accessor_prefix + "__union";
|
||||||
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
|
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
|
||||||
|
case BASE_TYPE_ARRAY: return GenGetter(type.VectorType());
|
||||||
default: {
|
default: {
|
||||||
std::string getter =
|
std::string getter =
|
||||||
lang_.accessor_prefix + "bb." + FunctionStart('G') + "et";
|
lang_.accessor_prefix + "bb." + FunctionStart('G') + "et";
|
||||||
@@ -656,20 +657,36 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
// Recursively generate arguments for a constructor, to deal with nested
|
// Recursively generate arguments for a constructor, to deal with nested
|
||||||
// structs.
|
// structs.
|
||||||
void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
|
void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
|
||||||
const char *nameprefix) const {
|
const char *nameprefix, size_t array_count = 0) const {
|
||||||
std::string &code = *code_ptr;
|
std::string &code = *code_ptr;
|
||||||
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) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
if (IsStruct(field.value.type)) {
|
const auto &field_type = field.value.type;
|
||||||
|
const auto array_field = IsArray(field_type);
|
||||||
|
const auto &type = array_field ? field_type.VectorType()
|
||||||
|
: DestinationType(field_type, false);
|
||||||
|
const auto array_cnt = array_field ? (array_count + 1) : array_count;
|
||||||
|
if (IsStruct(type)) {
|
||||||
// Generate arguments for a struct inside a struct. To ensure names
|
// Generate arguments for a struct inside a struct. To ensure names
|
||||||
// don't clash, and to make it obvious these arguments are constructing
|
// don't clash, and to make it obvious these arguments are constructing
|
||||||
// a nested struct, prefix the name with the field name.
|
// a nested struct, prefix the name with the field name.
|
||||||
GenStructArgs(*field.value.type.struct_def, code_ptr,
|
GenStructArgs(*field_type.struct_def, code_ptr,
|
||||||
(nameprefix + (field.name + "_")).c_str());
|
(nameprefix + (field.name + "_")).c_str(), array_cnt);
|
||||||
} else {
|
} else {
|
||||||
code += ", ";
|
code += ", ";
|
||||||
code += GenTypeBasic(DestinationType(field.value.type, false));
|
code += GenTypeBasic(type);
|
||||||
|
if (lang_.language == IDLOptions::kJava) {
|
||||||
|
for (size_t i = 0; i < array_cnt; i++) code += "[]";
|
||||||
|
} else if (lang_.language == IDLOptions::kCSharp) {
|
||||||
|
if (array_cnt > 0) {
|
||||||
|
code += "[";
|
||||||
|
for (size_t i = 1; i < array_cnt; i++) code += ",";
|
||||||
|
code += "]";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FLATBUFFERS_ASSERT(0);
|
||||||
|
}
|
||||||
code += " ";
|
code += " ";
|
||||||
code += nameprefix;
|
code += nameprefix;
|
||||||
code += MakeCamel(field.name, lang_.first_camel_upper);
|
code += MakeCamel(field.name, lang_.first_camel_upper);
|
||||||
@@ -681,29 +698,67 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
// builder.putType(name);
|
// builder.putType(name);
|
||||||
// and insert manual padding.
|
// and insert manual padding.
|
||||||
void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
|
void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
|
||||||
const char *nameprefix) const {
|
const char *nameprefix, size_t index = 0,
|
||||||
|
bool in_array = false) const {
|
||||||
std::string &code = *code_ptr;
|
std::string &code = *code_ptr;
|
||||||
code += " builder." + FunctionStart('P') + "rep(";
|
std::string indent((index + 1) * 2, ' ');
|
||||||
|
code += indent + " builder." + FunctionStart('P') + "rep(";
|
||||||
code += NumToString(struct_def.minalign) + ", ";
|
code += NumToString(struct_def.minalign) + ", ";
|
||||||
code += NumToString(struct_def.bytesize) + ");\n";
|
code += NumToString(struct_def.bytesize) + ");\n";
|
||||||
for (auto it = struct_def.fields.vec.rbegin();
|
for (auto it = struct_def.fields.vec.rbegin();
|
||||||
it != struct_def.fields.vec.rend(); ++it) {
|
it != struct_def.fields.vec.rend(); ++it) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
|
const auto &field_type = field.value.type;
|
||||||
if (field.padding) {
|
if (field.padding) {
|
||||||
code += " builder." + FunctionStart('P') + "ad(";
|
code += indent + " builder." + FunctionStart('P') + "ad(";
|
||||||
code += NumToString(field.padding) + ");\n";
|
code += NumToString(field.padding) + ");\n";
|
||||||
}
|
}
|
||||||
if (IsStruct(field.value.type)) {
|
if (IsStruct(field_type)) {
|
||||||
GenStructBody(*field.value.type.struct_def, code_ptr,
|
GenStructBody(*field_type.struct_def, code_ptr,
|
||||||
(nameprefix + (field.name + "_")).c_str());
|
(nameprefix + (field.name + "_")).c_str(), index,
|
||||||
|
in_array);
|
||||||
} else {
|
} else {
|
||||||
code += " builder." + FunctionStart('P') + "ut";
|
const auto &type =
|
||||||
code += GenMethod(field.value.type) + "(";
|
IsArray(field_type) ? field_type.VectorType() : field_type;
|
||||||
code += SourceCast(field.value.type);
|
const auto index_var = "_idx" + NumToString(index);
|
||||||
auto argname =
|
if (IsArray(field_type)) {
|
||||||
nameprefix + MakeCamel(field.name, lang_.first_camel_upper);
|
code += indent + " for (int " + index_var + " = ";
|
||||||
code += argname;
|
code += NumToString(field_type.fixed_length);
|
||||||
code += ");\n";
|
code += "; " + index_var + " > 0; " + index_var + "--) {\n";
|
||||||
|
in_array = true;
|
||||||
|
}
|
||||||
|
if (IsStruct(type)) {
|
||||||
|
GenStructBody(*field_type.struct_def, code_ptr,
|
||||||
|
(nameprefix + (field.name + "_")).c_str(), index + 1,
|
||||||
|
in_array);
|
||||||
|
} else {
|
||||||
|
code += IsArray(field_type) ? " " : "";
|
||||||
|
code += indent + " builder." + FunctionStart('P') + "ut";
|
||||||
|
code += GenMethod(type) + "(";
|
||||||
|
code += SourceCast(type);
|
||||||
|
auto argname =
|
||||||
|
nameprefix + MakeCamel(field.name, lang_.first_camel_upper);
|
||||||
|
code += argname;
|
||||||
|
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
|
||||||
|
if (lang_.language == IDLOptions::kJava) {
|
||||||
|
for (size_t i = 0; in_array && i < array_cnt; i++) {
|
||||||
|
code += "[_idx" + NumToString(i) + "-1]";
|
||||||
|
}
|
||||||
|
} else if (lang_.language == IDLOptions::kCSharp) {
|
||||||
|
if (array_cnt > 0) {
|
||||||
|
code += "[";
|
||||||
|
for (size_t i = 0; in_array && i < array_cnt; i++) {
|
||||||
|
code += "_idx" + NumToString(i) + "-1";
|
||||||
|
if (i != (array_cnt - 1)) code += ",";
|
||||||
|
}
|
||||||
|
code += "]";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FLATBUFFERS_ASSERT(0);
|
||||||
|
}
|
||||||
|
code += ");\n";
|
||||||
|
}
|
||||||
|
if (IsArray(field_type)) { code += indent + " }\n"; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -924,9 +979,11 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Most field accessors need to retrieve and test the field offset first,
|
// Most field accessors need to retrieve and test the field offset first,
|
||||||
// this is the prefix code for that:
|
// this is the prefix code for that:
|
||||||
auto offset_prefix = " { int o = " + lang_.accessor_prefix + "__offset(" +
|
auto offset_prefix =
|
||||||
NumToString(field.value.offset) +
|
IsArray(field.value.type)
|
||||||
"); return o != 0 ? ";
|
? " { return "
|
||||||
|
: (" { int o = " + lang_.accessor_prefix + "__offset(" +
|
||||||
|
NumToString(field.value.offset) + "); return o != 0 ? ");
|
||||||
// Generate the accessors that don't do object reuse.
|
// Generate the accessors that don't do object reuse.
|
||||||
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
|
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
|
||||||
// Calls the accessor that takes an accessor object with a new object.
|
// Calls the accessor that takes an accessor object with a new object.
|
||||||
@@ -1017,6 +1074,7 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
code += offset_prefix + getter + "(o + " + lang_.accessor_prefix;
|
code += offset_prefix + getter + "(o + " + lang_.accessor_prefix;
|
||||||
code += "bb_pos) : null";
|
code += "bb_pos) : null";
|
||||||
break;
|
break;
|
||||||
|
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||||
case BASE_TYPE_VECTOR: {
|
case BASE_TYPE_VECTOR: {
|
||||||
auto vectortype = field.value.type.VectorType();
|
auto vectortype = field.value.type.VectorType();
|
||||||
if (vectortype.base_type == BASE_TYPE_UNION &&
|
if (vectortype.base_type == BASE_TYPE_UNION &&
|
||||||
@@ -1043,8 +1101,13 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
} else {
|
} else {
|
||||||
code += body;
|
code += body;
|
||||||
}
|
}
|
||||||
auto index = lang_.accessor_prefix + "__vector(o) + j * " +
|
auto index = lang_.accessor_prefix;
|
||||||
NumToString(InlineSize(vectortype));
|
if (IsArray(field.value.type)) {
|
||||||
|
index += "bb_pos + " + NumToString(field.value.offset) + " + ";
|
||||||
|
} else {
|
||||||
|
index += "__vector(o) + ";
|
||||||
|
}
|
||||||
|
index += "j * " + NumToString(InlineSize(vectortype));
|
||||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||||
code += vectortype.struct_def->fixed
|
code += vectortype.struct_def->fixed
|
||||||
? index
|
? index
|
||||||
@@ -1055,13 +1118,16 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
} else {
|
} else {
|
||||||
code += index;
|
code += index;
|
||||||
}
|
}
|
||||||
code += ")" + dest_mask + " : ";
|
code += ")" + dest_mask;
|
||||||
|
if (!IsArray(field.value.type)) {
|
||||||
|
code += " : ";
|
||||||
|
code +=
|
||||||
|
field.value.type.element == BASE_TYPE_BOOL
|
||||||
|
? "false"
|
||||||
|
: (IsScalar(field.value.type.element) ? default_cast + "0"
|
||||||
|
: "null");
|
||||||
|
}
|
||||||
|
|
||||||
code +=
|
|
||||||
field.value.type.element == BASE_TYPE_BOOL
|
|
||||||
? "false"
|
|
||||||
: (IsScalar(field.value.type.element) ? default_cast + "0"
|
|
||||||
: "null");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BASE_TYPE_UNION:
|
case BASE_TYPE_UNION:
|
||||||
@@ -1215,9 +1281,9 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
// Generate mutators for scalar fields or vectors of scalars.
|
// Generate mutators for scalar fields or vectors of scalars.
|
||||||
if (parser_.opts.mutable_buffer) {
|
if (parser_.opts.mutable_buffer) {
|
||||||
auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR
|
auto is_series = (IsSeries(field.value.type));
|
||||||
? field.value.type.VectorType()
|
const auto &underlying_type =
|
||||||
: field.value.type;
|
is_series ? field.value.type.VectorType() : field.value.type;
|
||||||
// Boolean parameters have to be explicitly converted to byte
|
// Boolean parameters have to be explicitly converted to byte
|
||||||
// representation.
|
// representation.
|
||||||
auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
|
auto setter_parameter = underlying_type.base_type == BASE_TYPE_BOOL
|
||||||
@@ -1226,21 +1292,21 @@ class GeneralGenerator : public BaseGenerator {
|
|||||||
auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper);
|
auto mutator_prefix = MakeCamel("mutate", lang_.first_camel_upper);
|
||||||
// A vector mutator also needs the index of the vector element it should
|
// A vector mutator also needs the index of the vector element it should
|
||||||
// mutate.
|
// mutate.
|
||||||
auto mutator_params =
|
auto mutator_params = (is_series ? "(int j, " : "(") +
|
||||||
(field.value.type.base_type == BASE_TYPE_VECTOR ? "(int j, "
|
GenTypeNameDest(underlying_type) + " " +
|
||||||
: "(") +
|
field.name + ") { ";
|
||||||
GenTypeNameDest(underlying_type) + " " + field.name + ") { ";
|
|
||||||
auto setter_index =
|
auto setter_index =
|
||||||
field.value.type.base_type == BASE_TYPE_VECTOR
|
is_series
|
||||||
? lang_.accessor_prefix + "__vector(o) + j * " +
|
? lang_.accessor_prefix +
|
||||||
NumToString(InlineSize(underlying_type))
|
(IsArray(field.value.type)
|
||||||
|
? "bb_pos + " + NumToString(field.value.offset)
|
||||||
|
: "__vector(o)") +
|
||||||
|
+" + j * " + NumToString(InlineSize(underlying_type))
|
||||||
: (struct_def.fixed
|
: (struct_def.fixed
|
||||||
? lang_.accessor_prefix + "bb_pos + " +
|
? lang_.accessor_prefix + "bb_pos + " +
|
||||||
NumToString(field.value.offset)
|
NumToString(field.value.offset)
|
||||||
: "o + " + lang_.accessor_prefix + "bb_pos");
|
: "o + " + lang_.accessor_prefix + "bb_pos");
|
||||||
if (IsScalar(field.value.type.base_type) ||
|
if (IsScalar(underlying_type.base_type)) {
|
||||||
(field.value.type.base_type == BASE_TYPE_VECTOR &&
|
|
||||||
IsScalar(field.value.type.VectorType().base_type))) {
|
|
||||||
code += " public ";
|
code += " public ";
|
||||||
code += struct_def.fixed ? "void " : lang_.bool_type;
|
code += struct_def.fixed ? "void " : lang_.bool_type;
|
||||||
code += mutator_prefix + MakeCamel(field.name, true);
|
code += mutator_prefix + MakeCamel(field.name, true);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ std::string GenNativeType(BaseType type) {
|
|||||||
case BASE_TYPE_FLOAT:
|
case BASE_TYPE_FLOAT:
|
||||||
case BASE_TYPE_DOUBLE: return "number";
|
case BASE_TYPE_DOUBLE: return "number";
|
||||||
case BASE_TYPE_STRING: return "string";
|
case BASE_TYPE_STRING: return "string";
|
||||||
|
case BASE_TYPE_ARRAY: return "array";
|
||||||
default: return "";
|
default: return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,6 +71,7 @@ std::string GenType(const Type &type) {
|
|||||||
return GenTypeRef(type.enum_def);
|
return GenTypeRef(type.enum_def);
|
||||||
}
|
}
|
||||||
switch (type.base_type) {
|
switch (type.base_type) {
|
||||||
|
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||||
case BASE_TYPE_VECTOR: {
|
case BASE_TYPE_VECTOR: {
|
||||||
std::string typeline;
|
std::string typeline;
|
||||||
typeline.append("\"type\" : \"array\", \"items\" : { ");
|
typeline.append("\"type\" : \"array\", \"items\" : { ");
|
||||||
@@ -156,8 +158,16 @@ class JsonSchemaGenerator : public BaseGenerator {
|
|||||||
const auto &properties = structure->fields.vec;
|
const auto &properties = structure->fields.vec;
|
||||||
for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
|
for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
|
||||||
const auto &property = *prop;
|
const auto &property = *prop;
|
||||||
std::string typeLine(" \"" + property->name + "\" : { " +
|
std::string arrayInfo = "";
|
||||||
GenType(property->value.type) + " }");
|
if (IsArray(property->value.type)) {
|
||||||
|
arrayInfo = ",\n \"minItems\": " +
|
||||||
|
NumToString(property->value.type.fixed_length) +
|
||||||
|
",\n \"maxItems\": " +
|
||||||
|
NumToString(property->value.type.fixed_length);
|
||||||
|
}
|
||||||
|
std::string typeLine =
|
||||||
|
" \"" + property->name + "\" : {\n" + " " +
|
||||||
|
GenType(property->value.type) + arrayInfo + "\n }";
|
||||||
if (property != properties.back()) { typeLine.append(","); }
|
if (property != properties.back()) { typeLine.append(","); }
|
||||||
code_ += typeLine;
|
code_ += typeLine;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,6 +224,30 @@ class PythonGenerator : public BaseGenerator {
|
|||||||
code += "\n" + Indent + Indent + "return obj\n\n";
|
code += "\n" + Indent + Indent + "return obj\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the value of a fixed size array.
|
||||||
|
void GetArrayOfStruct(const StructDef &struct_def, const FieldDef &field,
|
||||||
|
std::string *code_ptr) {
|
||||||
|
std::string &code = *code_ptr;
|
||||||
|
const auto vec_type = field.value.type.VectorType();
|
||||||
|
GenReceiver(struct_def, code_ptr);
|
||||||
|
code += MakeCamel(NormalizedName(field));
|
||||||
|
if (IsStruct(vec_type)) {
|
||||||
|
code += "(self, obj, i):\n";
|
||||||
|
code += Indent + Indent + "obj.Init(self._tab.Bytes, self._tab.Pos + ";
|
||||||
|
code += NumToString(field.value.offset) + " + i * ";
|
||||||
|
code += NumToString(InlineSize(vec_type));
|
||||||
|
code += ")\n" + Indent + Indent + "return obj\n\n";
|
||||||
|
} else {
|
||||||
|
auto getter = GenGetter(vec_type);
|
||||||
|
code += "(self): return [" + getter;
|
||||||
|
code += "self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(";
|
||||||
|
code += NumToString(field.value.offset) + " + i * ";
|
||||||
|
code += NumToString(InlineSize(vec_type));
|
||||||
|
code += ")) for i in range(";
|
||||||
|
code += NumToString(field.value.type.fixed_length) + ")]\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get a struct by initializing an existing struct.
|
// Get a struct by initializing an existing struct.
|
||||||
// Specific to Table.
|
// Specific to Table.
|
||||||
void GetStructFieldOfTable(const StructDef &struct_def,
|
void GetStructFieldOfTable(const StructDef &struct_def,
|
||||||
@@ -380,12 +404,16 @@ class PythonGenerator : public BaseGenerator {
|
|||||||
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) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
if (IsStruct(field.value.type)) {
|
const auto &field_type = field.value.type;
|
||||||
|
const auto &type =
|
||||||
|
IsArray(field_type) ? field_type.VectorType() : field_type;
|
||||||
|
if (IsStruct(type)) {
|
||||||
// Generate arguments for a struct inside a struct. To ensure names
|
// Generate arguments for a struct inside a struct. To ensure names
|
||||||
// don't clash, and to make it obvious these arguments are constructing
|
// don't clash, and to make it obvious these arguments are constructing
|
||||||
// a nested struct, prefix the name with the field name.
|
// a nested struct, prefix the name with the field name.
|
||||||
StructBuilderArgs(*field.value.type.struct_def,
|
StructBuilderArgs(*field_type.struct_def,
|
||||||
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
|
(nameprefix + (NormalizedName(field) + "_")).c_str(),
|
||||||
|
code_ptr);
|
||||||
} else {
|
} else {
|
||||||
std::string &code = *code_ptr;
|
std::string &code = *code_ptr;
|
||||||
code += std::string(", ") + nameprefix;
|
code += std::string(", ") + nameprefix;
|
||||||
@@ -402,22 +430,50 @@ class PythonGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Recursively generate struct construction statements and instert manual
|
// Recursively generate struct construction statements and instert manual
|
||||||
// padding.
|
// padding.
|
||||||
void StructBuilderBody(const StructDef &struct_def,
|
void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
|
||||||
const char *nameprefix, std::string *code_ptr) {
|
std::string *code_ptr, size_t index = 0,
|
||||||
|
bool in_array = false) {
|
||||||
std::string &code = *code_ptr;
|
std::string &code = *code_ptr;
|
||||||
code += " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
|
std::string indent(index * 4, ' ');
|
||||||
|
code +=
|
||||||
|
indent + " builder.Prep(" + NumToString(struct_def.minalign) + ", ";
|
||||||
code += NumToString(struct_def.bytesize) + ")\n";
|
code += NumToString(struct_def.bytesize) + ")\n";
|
||||||
for (auto it = struct_def.fields.vec.rbegin();
|
for (auto it = struct_def.fields.vec.rbegin();
|
||||||
it != struct_def.fields.vec.rend(); ++it) {
|
it != struct_def.fields.vec.rend(); ++it) {
|
||||||
auto &field = **it;
|
auto &field = **it;
|
||||||
|
const auto &field_type = field.value.type;
|
||||||
|
const auto &type =
|
||||||
|
IsArray(field_type) ? field_type.VectorType() : field_type;
|
||||||
if (field.padding)
|
if (field.padding)
|
||||||
code += " builder.Pad(" + NumToString(field.padding) + ")\n";
|
code +=
|
||||||
if (IsStruct(field.value.type)) {
|
indent + " builder.Pad(" + NumToString(field.padding) + ")\n";
|
||||||
StructBuilderBody(*field.value.type.struct_def,
|
if (IsStruct(field_type)) {
|
||||||
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
|
StructBuilderBody(*field_type.struct_def,
|
||||||
|
(nameprefix + (NormalizedName(field) + "_")).c_str(),
|
||||||
|
code_ptr, index, in_array);
|
||||||
} else {
|
} else {
|
||||||
code += " builder.Prepend" + GenMethod(field) + "(";
|
const auto index_var = "_idx" + NumToString(index);
|
||||||
code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
|
if (IsArray(field_type)) {
|
||||||
|
code += indent + " for " + index_var + " in range(";
|
||||||
|
code += NumToString(field_type.fixed_length);
|
||||||
|
code += " , 0, -1):\n";
|
||||||
|
in_array = true;
|
||||||
|
}
|
||||||
|
if (IsStruct(type)) {
|
||||||
|
StructBuilderBody(
|
||||||
|
*field_type.struct_def,
|
||||||
|
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr,
|
||||||
|
index + 1, in_array);
|
||||||
|
} else {
|
||||||
|
code += IsArray(field_type) ? " " : "";
|
||||||
|
code += indent + " builder.Prepend" + GenMethod(field) + "(";
|
||||||
|
code += nameprefix + MakeCamel(NormalizedName(field), false);
|
||||||
|
size_t array_cnt = index + (IsArray(field_type) ? 1 : 0);
|
||||||
|
for (size_t i = 0; in_array && i < array_cnt; i++) {
|
||||||
|
code += "[_idx" + NumToString(i) + "-1]";
|
||||||
|
}
|
||||||
|
code += ")\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -505,6 +561,8 @@ class PythonGenerator : public BaseGenerator {
|
|||||||
} else {
|
} else {
|
||||||
GetScalarFieldOfTable(struct_def, field, code_ptr);
|
GetScalarFieldOfTable(struct_def, field, code_ptr);
|
||||||
}
|
}
|
||||||
|
} else if (IsArray(field.value.type)) {
|
||||||
|
GetArrayOfStruct(struct_def, field, code_ptr);
|
||||||
} else {
|
} else {
|
||||||
switch (field.value.type.base_type) {
|
switch (field.value.type.base_type) {
|
||||||
case BASE_TYPE_STRUCT:
|
case BASE_TYPE_STRUCT:
|
||||||
@@ -613,9 +671,9 @@ class PythonGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Returns the method name for use with add/put calls.
|
// Returns the method name for use with add/put calls.
|
||||||
std::string GenMethod(const FieldDef &field) {
|
std::string GenMethod(const FieldDef &field) {
|
||||||
return IsScalar(field.value.type.base_type)
|
return (IsScalar(field.value.type.base_type) || IsArray(field.value.type))
|
||||||
? MakeCamel(GenTypeBasic(field.value.type))
|
? MakeCamel(GenTypeBasic(field.value.type))
|
||||||
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
|
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenTypeBasic(const Type &type) {
|
std::string GenTypeBasic(const Type &type) {
|
||||||
@@ -628,7 +686,8 @@ class PythonGenerator : public BaseGenerator {
|
|||||||
#undef FLATBUFFERS_TD
|
#undef FLATBUFFERS_TD
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
return ctypename[type.base_type];
|
return ctypename[IsArray(type) ? type.VectorType().base_type
|
||||||
|
: type.base_type];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenTypePointer(const Type &type) {
|
std::string GenTypePointer(const Type &type) {
|
||||||
|
|||||||
@@ -69,26 +69,27 @@ bool Print(T val, Type type, int /*indent*/, Type * /*union_type*/,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print a vector a sequence of JSON values, comma separated, wrapped in "[]".
|
// Print a vector or an array of JSON values, comma seperated, wrapped in "[]".
|
||||||
template<typename T>
|
template<typename T, typename Container>
|
||||||
bool PrintVector(const Vector<T> &v, Type type, int indent,
|
bool PrintContainer(const Container &c, size_t size, Type type, int indent,
|
||||||
const IDLOptions &opts, std::string *_text) {
|
const IDLOptions &opts, std::string *_text) {
|
||||||
std::string &text = *_text;
|
std::string &text = *_text;
|
||||||
text += "[";
|
text += "[";
|
||||||
text += NewLine(opts);
|
text += NewLine(opts);
|
||||||
for (uoffset_t i = 0; i < v.size(); i++) {
|
for (uoffset_t i = 0; i < size; i++) {
|
||||||
if (i) {
|
if (i) {
|
||||||
if (!opts.protobuf_ascii_alike) text += ",";
|
if (!opts.protobuf_ascii_alike) text += ",";
|
||||||
text += NewLine(opts);
|
text += NewLine(opts);
|
||||||
}
|
}
|
||||||
text.append(indent + Indent(opts), ' ');
|
text.append(indent + Indent(opts), ' ');
|
||||||
if (IsStruct(type)) {
|
if (IsStruct(type)) {
|
||||||
if (!Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
|
if (!Print(reinterpret_cast<const void *>(c.Data() +
|
||||||
indent + Indent(opts), nullptr, opts, _text)) {
|
i * type.struct_def->bytesize),
|
||||||
|
type, indent + Indent(opts), nullptr, opts, _text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!Print(v[i], type, indent + Indent(opts), nullptr, opts, _text)) {
|
if (!Print(c[i], type, indent + Indent(opts), nullptr, opts, _text)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,6 +100,20 @@ bool PrintVector(const Vector<T> &v, Type type, int indent,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool PrintVector(const Vector<T> &v, Type type, int indent,
|
||||||
|
const IDLOptions &opts, std::string *_text) {
|
||||||
|
return PrintContainer<T, Vector<T>>(v, v.size(), type, indent, opts, _text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print an array a sequence of JSON values, comma separated, wrapped in "[]".
|
||||||
|
template<typename T>
|
||||||
|
bool PrintArray(const Array<T, 0xFFFF> &a, size_t size, Type type, int indent,
|
||||||
|
const IDLOptions &opts, std::string *_text) {
|
||||||
|
return PrintContainer<T, Array<T, 0xFFFF>>(a, size, type, indent, opts,
|
||||||
|
_text);
|
||||||
|
}
|
||||||
|
|
||||||
// Specialization of Print above for pointer types.
|
// Specialization of Print above for pointer types.
|
||||||
template<>
|
template<>
|
||||||
bool Print<const void *>(const void *val, Type type, int indent,
|
bool Print<const void *>(const void *val, Type type, int indent,
|
||||||
@@ -125,25 +140,49 @@ bool Print<const void *>(const void *val, Type type, int indent,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BASE_TYPE_VECTOR:
|
case BASE_TYPE_VECTOR: {
|
||||||
type = type.VectorType();
|
const auto vec_type = type.VectorType();
|
||||||
// Call PrintVector above specifically for each element type:
|
// Call PrintVector above specifically for each element type:
|
||||||
switch (type.base_type) {
|
// clang-format off
|
||||||
// clang-format off
|
switch (vec_type.base_type) {
|
||||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
|
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
|
||||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||||
case BASE_TYPE_ ## ENUM: \
|
case BASE_TYPE_ ## ENUM: \
|
||||||
if (!PrintVector<CTYPE>( \
|
if (!PrintVector<CTYPE>( \
|
||||||
*reinterpret_cast<const Vector<CTYPE> *>(val), \
|
*reinterpret_cast<const Vector<CTYPE> *>(val), \
|
||||||
type, indent, opts, _text)) { \
|
vec_type, indent, opts, _text)) { \
|
||||||
return false; \
|
return false; \
|
||||||
} \
|
} \
|
||||||
break;
|
break;
|
||||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||||
#undef FLATBUFFERS_TD
|
#undef FLATBUFFERS_TD
|
||||||
// clang-format on
|
|
||||||
}
|
}
|
||||||
|
// clang-format on
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
case BASE_TYPE_ARRAY: {
|
||||||
|
const auto vec_type = type.VectorType();
|
||||||
|
// Call PrintArray above specifically for each element type:
|
||||||
|
// clang-format off
|
||||||
|
switch (vec_type.base_type) {
|
||||||
|
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
|
||||||
|
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||||
|
case BASE_TYPE_ ## ENUM: \
|
||||||
|
if (!PrintArray<CTYPE>( \
|
||||||
|
*reinterpret_cast<const Array<CTYPE, 0xFFFF> *>(val), \
|
||||||
|
type.fixed_length, \
|
||||||
|
vec_type, indent, opts, _text)) { \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
break;
|
||||||
|
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
|
||||||
|
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
||||||
|
#undef FLATBUFFERS_TD
|
||||||
|
case BASE_TYPE_ARRAY: FLATBUFFERS_ASSERT(0);
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: FLATBUFFERS_ASSERT(0);
|
default: FLATBUFFERS_ASSERT(0);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -177,8 +216,8 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
|
|||||||
std::string *_text) {
|
std::string *_text) {
|
||||||
const void *val = nullptr;
|
const void *val = nullptr;
|
||||||
if (fixed) {
|
if (fixed) {
|
||||||
// The only non-scalar fields in structs are structs.
|
// The only non-scalar fields in structs are structs or arrays.
|
||||||
FLATBUFFERS_ASSERT(IsStruct(fd.value.type));
|
FLATBUFFERS_ASSERT(IsStruct(fd.value.type) || IsArray(fd.value.type));
|
||||||
val = reinterpret_cast<const Struct *>(table)->GetStruct<const void *>(
|
val = reinterpret_cast<const Struct *>(table)->GetStruct<const void *>(
|
||||||
fd.value.offset);
|
fd.value.offset);
|
||||||
} else if (fd.flexbuffer) {
|
} else if (fd.flexbuffer) {
|
||||||
@@ -241,6 +280,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
|||||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||||
case BASE_TYPE_ ## ENUM:
|
case BASE_TYPE_ ## ENUM:
|
||||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
||||||
|
FLATBUFFERS_GEN_TYPE_ARRAY(FLATBUFFERS_TD)
|
||||||
#undef FLATBUFFERS_TD
|
#undef FLATBUFFERS_TD
|
||||||
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
|
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
|
||||||
union_type, opts, _text)) {
|
union_type, opts, _text)) {
|
||||||
|
|||||||
@@ -601,12 +601,35 @@ CheckedError Parser::ParseType(Type &type) {
|
|||||||
NEXT();
|
NEXT();
|
||||||
Type subtype;
|
Type subtype;
|
||||||
ECHECK(Recurse([&]() { return ParseType(subtype); }));
|
ECHECK(Recurse([&]() { return ParseType(subtype); }));
|
||||||
if (subtype.base_type == BASE_TYPE_VECTOR) {
|
if (IsSeries(subtype)) {
|
||||||
// We could support this, but it will complicate things, and it's
|
// We could support this, but it will complicate things, and it's
|
||||||
// easier to work around with a struct around the inner vector.
|
// easier to work around with a struct around the inner vector.
|
||||||
return Error("nested vector types not supported (wrap in table first).");
|
return Error("nested vector types not supported (wrap in table first)");
|
||||||
|
}
|
||||||
|
if (token_ == ':') {
|
||||||
|
NEXT();
|
||||||
|
if (token_ != kTokenIntegerConstant) {
|
||||||
|
return Error("length of fixed-length array must be an integer value");
|
||||||
|
}
|
||||||
|
uint16_t fixed_length = 0;
|
||||||
|
bool check = StringToNumber(attribute_.c_str(), &fixed_length);
|
||||||
|
if (!check || fixed_length < 1) {
|
||||||
|
return Error(
|
||||||
|
"length of fixed-length array must be positive and fit to "
|
||||||
|
"uint16_t type");
|
||||||
|
}
|
||||||
|
// Check if enum arrays are used in C++ without specifying --scoped-enums
|
||||||
|
if ((opts.lang_to_generate & IDLOptions::kCpp) && !opts.scoped_enums &&
|
||||||
|
IsEnum(subtype)) {
|
||||||
|
return Error(
|
||||||
|
"--scoped-enums must be enabled to use enum arrays in C++\n");
|
||||||
|
}
|
||||||
|
type = Type(BASE_TYPE_ARRAY, subtype.struct_def, subtype.enum_def,
|
||||||
|
fixed_length);
|
||||||
|
NEXT();
|
||||||
|
} else {
|
||||||
|
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
|
||||||
}
|
}
|
||||||
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
|
|
||||||
type.element = subtype.base_type;
|
type.element = subtype.base_type;
|
||||||
EXPECT(']');
|
EXPECT(']');
|
||||||
} else {
|
} else {
|
||||||
@@ -651,9 +674,19 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
|||||||
Type type;
|
Type type;
|
||||||
ECHECK(ParseType(type));
|
ECHECK(ParseType(type));
|
||||||
|
|
||||||
if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type))
|
if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type) &&
|
||||||
|
!IsArray(type))
|
||||||
return Error("structs_ may contain only scalar or struct fields");
|
return Error("structs_ may contain only scalar or struct fields");
|
||||||
|
|
||||||
|
if (!struct_def.fixed && IsArray(type))
|
||||||
|
return Error("fixed-length array in table must be wrapped in struct");
|
||||||
|
|
||||||
|
if (IsArray(type) && !SupportsAdvancedArrayFeatures()) {
|
||||||
|
return Error(
|
||||||
|
"Arrays are not yet supported in all "
|
||||||
|
"the specified programming languages.");
|
||||||
|
}
|
||||||
|
|
||||||
FieldDef *typefield = nullptr;
|
FieldDef *typefield = nullptr;
|
||||||
if (type.base_type == BASE_TYPE_UNION) {
|
if (type.base_type == BASE_TYPE_UNION) {
|
||||||
// For union fields, add a second auto-generated field to hold the type,
|
// For union fields, add a second auto-generated field to hold the type,
|
||||||
@@ -703,12 +736,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type.enum_def) {
|
if (type.enum_def) {
|
||||||
// The type.base_type can only be scalar, union or vector.
|
// The type.base_type can only be scalar, union, array or vector.
|
||||||
// Table, struct or string can't have enum_def.
|
// Table, struct or string can't have enum_def.
|
||||||
// Default value of union and vector in NONE, NULL translated to "0".
|
// Default value of union and vector in NONE, NULL translated to "0".
|
||||||
FLATBUFFERS_ASSERT(IsInteger(type.base_type) ||
|
FLATBUFFERS_ASSERT(IsInteger(type.base_type) ||
|
||||||
(type.base_type == BASE_TYPE_UNION) ||
|
(type.base_type == BASE_TYPE_UNION) ||
|
||||||
(type.base_type == BASE_TYPE_VECTOR));
|
(type.base_type == BASE_TYPE_VECTOR) ||
|
||||||
|
(type.base_type == BASE_TYPE_ARRAY));
|
||||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
if (type.base_type == BASE_TYPE_VECTOR) {
|
||||||
// Vector can't use initialization list.
|
// Vector can't use initialization list.
|
||||||
FLATBUFFERS_ASSERT(field->value.constant == "0");
|
FLATBUFFERS_ASSERT(field->value.constant == "0");
|
||||||
@@ -963,6 +997,10 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
|||||||
val.constant = NumToString(off);
|
val.constant = NumToString(off);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case BASE_TYPE_ARRAY: {
|
||||||
|
ECHECK(ParseArray(val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case BASE_TYPE_INT:
|
case BASE_TYPE_INT:
|
||||||
case BASE_TYPE_UINT:
|
case BASE_TYPE_UINT:
|
||||||
case BASE_TYPE_LONG:
|
case BASE_TYPE_LONG:
|
||||||
@@ -983,11 +1021,16 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) {
|
void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) {
|
||||||
|
SerializeStruct(builder_, struct_def, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::SerializeStruct(FlatBufferBuilder &builder,
|
||||||
|
const StructDef &struct_def, const Value &val) {
|
||||||
FLATBUFFERS_ASSERT(val.constant.length() == struct_def.bytesize);
|
FLATBUFFERS_ASSERT(val.constant.length() == struct_def.bytesize);
|
||||||
builder_.Align(struct_def.minalign);
|
builder.Align(struct_def.minalign);
|
||||||
builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()),
|
builder.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()),
|
||||||
struct_def.bytesize);
|
struct_def.bytesize);
|
||||||
builder_.AddStructOffset(val.offset, builder_.GetSize());
|
builder.AddStructOffset(val.offset, builder.GetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
@@ -1161,7 +1204,13 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
|
|||||||
break;
|
break;
|
||||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD);
|
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD);
|
||||||
#undef FLATBUFFERS_TD
|
#undef FLATBUFFERS_TD
|
||||||
// clang-format on
|
case BASE_TYPE_ARRAY:
|
||||||
|
builder_.Pad(field->padding);
|
||||||
|
builder_.PushBytes(
|
||||||
|
reinterpret_cast<const uint8_t*>(field_value.constant.c_str()),
|
||||||
|
InlineSize(field_value.type));
|
||||||
|
break;
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1244,6 +1293,54 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
|
|||||||
return NoError();
|
return NoError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CheckedError Parser::ParseArray(Value &array) {
|
||||||
|
std::vector<Value> stack;
|
||||||
|
FlatBufferBuilder builder;
|
||||||
|
const auto &type = array.type.VectorType();
|
||||||
|
auto length = array.type.fixed_length;
|
||||||
|
uoffset_t count = 0;
|
||||||
|
auto err = ParseVectorDelimiters(count, [&](uoffset_t &) -> CheckedError {
|
||||||
|
vector_emplace_back(&stack, Value());
|
||||||
|
auto &val = stack.back();
|
||||||
|
val.type = type;
|
||||||
|
if (IsStruct(type)) {
|
||||||
|
ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
|
||||||
|
} else {
|
||||||
|
ECHECK(ParseSingleValue(nullptr, val, false));
|
||||||
|
}
|
||||||
|
return NoError();
|
||||||
|
});
|
||||||
|
ECHECK(err);
|
||||||
|
if (length != count) return Error("Fixed-length array size is incorrect.");
|
||||||
|
|
||||||
|
for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
|
||||||
|
auto &val = *it;
|
||||||
|
// clang-format off
|
||||||
|
switch (val.type.base_type) {
|
||||||
|
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
|
||||||
|
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||||
|
case BASE_TYPE_ ## ENUM: \
|
||||||
|
if (IsStruct(val.type)) { \
|
||||||
|
SerializeStruct(builder, *val.type.struct_def, val); \
|
||||||
|
} else { \
|
||||||
|
CTYPE elem; \
|
||||||
|
ECHECK(atot(val.constant.c_str(), *this, &elem)); \
|
||||||
|
builder.PushElement(elem); \
|
||||||
|
} \
|
||||||
|
break;
|
||||||
|
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||||
|
#undef FLATBUFFERS_TD
|
||||||
|
default: FLATBUFFERS_ASSERT(0);
|
||||||
|
}
|
||||||
|
// clang-format on
|
||||||
|
}
|
||||||
|
|
||||||
|
array.constant.assign(
|
||||||
|
reinterpret_cast<const char *>(builder.GetCurrentBufferPointer()),
|
||||||
|
InlineSize(array.type));
|
||||||
|
return NoError();
|
||||||
|
}
|
||||||
|
|
||||||
CheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
CheckedError Parser::ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||||
size_t fieldn,
|
size_t fieldn,
|
||||||
const StructDef *parent_struct_def) {
|
const StructDef *parent_struct_def) {
|
||||||
@@ -1989,6 +2086,13 @@ bool Parser::SupportsAdvancedUnionFeatures() const {
|
|||||||
IDLOptions::kBinary)) == 0;
|
IDLOptions::kBinary)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::SupportsAdvancedArrayFeatures() const {
|
||||||
|
return (opts.lang_to_generate &
|
||||||
|
~(IDLOptions::kCpp | IDLOptions::kPython | IDLOptions::kJava |
|
||||||
|
IDLOptions::kCSharp | IDLOptions::kJsonSchema | IDLOptions::kJson |
|
||||||
|
IDLOptions::kBinary)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
Namespace *Parser::UniqueNamespace(Namespace *ns) {
|
Namespace *Parser::UniqueNamespace(Namespace *ns) {
|
||||||
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
|
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
|
||||||
if (ns->components == (*it)->components) {
|
if (ns->components == (*it)->components) {
|
||||||
@@ -3171,19 +3275,22 @@ bool EnumVal::Deserialize(const Parser &parser,
|
|||||||
|
|
||||||
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
||||||
return reflection::CreateType(
|
return reflection::CreateType(
|
||||||
*builder,
|
*builder, static_cast<reflection::BaseType>(base_type),
|
||||||
static_cast<reflection::BaseType>(base_type),
|
|
||||||
static_cast<reflection::BaseType>(element),
|
static_cast<reflection::BaseType>(element),
|
||||||
struct_def ? struct_def->index : (enum_def ? enum_def->index : -1));
|
struct_def ? struct_def->index : (enum_def ? enum_def->index : -1),
|
||||||
|
fixed_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
|
bool Type::Deserialize(const Parser &parser, const reflection::Type *type) {
|
||||||
if (type == nullptr) return true;
|
if (type == nullptr) return true;
|
||||||
base_type = static_cast<BaseType>(type->base_type());
|
base_type = static_cast<BaseType>(type->base_type());
|
||||||
element = static_cast<BaseType>(type->element());
|
element = static_cast<BaseType>(type->element());
|
||||||
|
fixed_length = type->fixed_length();
|
||||||
if (type->index() >= 0) {
|
if (type->index() >= 0) {
|
||||||
|
bool is_series = type->base_type() == reflection::Vector ||
|
||||||
|
type->base_type() == reflection::Array;
|
||||||
if (type->base_type() == reflection::Obj ||
|
if (type->base_type() == reflection::Obj ||
|
||||||
(type->base_type() == reflection::Vector &&
|
(is_series &&
|
||||||
type->element() == reflection::Obj)) {
|
type->element() == reflection::Obj)) {
|
||||||
if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) {
|
if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) {
|
||||||
struct_def = parser.structs_.vec[type->index()];
|
struct_def = parser.structs_.vec[type->index()];
|
||||||
|
|||||||
@@ -99,6 +99,18 @@
|
|||||||
<Compile Include="..\MyGame\Example\Ability.cs">
|
<Compile Include="..\MyGame\Example\Ability.cs">
|
||||||
<Link>MyGame\Example\Ability.cs</Link>
|
<Link>MyGame\Example\Ability.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\MyGame\Example\ArrayTable.cs">
|
||||||
|
<Link>MyGame\Example\ArrayTable.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\MyGame\Example\ArrayStruct.cs">
|
||||||
|
<Link>MyGame\Example\ArrayStruct.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\MyGame\Example\NestedStruct.cs">
|
||||||
|
<Link>MyGame\Example\NestedStruct.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\MyGame\Example\TestEnum.cs">
|
||||||
|
<Link>MyGame\Example\TestEnum.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\MyGame\InParentNamespace.cs">
|
<Compile Include="..\MyGame\InParentNamespace.cs">
|
||||||
<Link>MyGame\InParentNamespace.cs</Link>
|
<Link>MyGame\InParentNamespace.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|||||||
@@ -330,5 +330,58 @@ namespace FlatBuffers.Test
|
|||||||
Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
|
Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
|
||||||
Assert.AreEqual(nestedMonsterName, nestedMonster.Name);
|
Assert.AreEqual(nestedMonsterName, nestedMonster.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[FlatBuffersTestMethod]
|
||||||
|
public void TestFixedLenghtArrays()
|
||||||
|
{
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder(100);
|
||||||
|
|
||||||
|
float a;
|
||||||
|
int[] b = new int[15];
|
||||||
|
sbyte c;
|
||||||
|
int[,] d_a = new int[2, 2];
|
||||||
|
TestEnum[] d_b = new TestEnum[2];
|
||||||
|
TestEnum[,] d_c = new TestEnum[2, 2];
|
||||||
|
|
||||||
|
a = 0.5f;
|
||||||
|
for (int i = 0; i < 15; i++) b[i] = i;
|
||||||
|
c = 1;
|
||||||
|
d_a[0, 0] = 1;
|
||||||
|
d_a[0, 1] = 2;
|
||||||
|
d_a[1, 0] = 3;
|
||||||
|
d_a[1, 1] = 4;
|
||||||
|
d_b[0] = TestEnum.B;
|
||||||
|
d_b[1] = TestEnum.C;
|
||||||
|
d_c[0, 0] = TestEnum.A;
|
||||||
|
d_c[0, 1] = TestEnum.B;
|
||||||
|
d_c[1, 0] = TestEnum.C;
|
||||||
|
d_c[1, 1] = TestEnum.B;
|
||||||
|
|
||||||
|
Offset<ArrayStruct> arrayOffset = ArrayStruct.CreateArrayStruct(
|
||||||
|
builder, a, b, c, d_a, d_b, d_c);
|
||||||
|
|
||||||
|
// Create a table with the ArrayStruct.
|
||||||
|
ArrayTable.StartArrayTable(builder);
|
||||||
|
ArrayTable.AddA(builder, arrayOffset);
|
||||||
|
Offset<ArrayTable> tableOffset = ArrayTable.EndArrayTable(builder);
|
||||||
|
|
||||||
|
ArrayTable.FinishArrayTableBuffer(builder, tableOffset);
|
||||||
|
|
||||||
|
ArrayTable table = ArrayTable.GetRootAsArrayTable(builder.DataBuffer);
|
||||||
|
|
||||||
|
Assert.AreEqual(table.A?.A, 0.5f);
|
||||||
|
for (int i = 0; i < 15; i++) Assert.AreEqual(table.A?.B(i), i);
|
||||||
|
Assert.AreEqual(table.A?.C, (sbyte)1);
|
||||||
|
Assert.AreEqual(table.A?.D(0).A(0), 1);
|
||||||
|
Assert.AreEqual(table.A?.D(0).A(1), 2);
|
||||||
|
Assert.AreEqual(table.A?.D(1).A(0), 3);
|
||||||
|
Assert.AreEqual(table.A?.D(1).A(1), 4);
|
||||||
|
Assert.AreEqual(table.A?.D(0).B, TestEnum.B);
|
||||||
|
Assert.AreEqual(table.A?.D(1).B, TestEnum.C);
|
||||||
|
Assert.AreEqual(table.A?.D(0).C(0), TestEnum.A);
|
||||||
|
Assert.AreEqual(table.A?.D(0).C(1), TestEnum.B);
|
||||||
|
Assert.AreEqual(table.A?.D(1).C(0), TestEnum.C);
|
||||||
|
Assert.AreEqual(table.A?.D(1).C(1), TestEnum.B);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ class JavaTest {
|
|||||||
|
|
||||||
TestVectorOfUnions();
|
TestVectorOfUnions();
|
||||||
|
|
||||||
|
TestFixedLengthArrays();
|
||||||
|
|
||||||
System.out.println("FlatBuffers test: completed successfully");
|
System.out.println("FlatBuffers test: completed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,6 +454,58 @@ class JavaTest {
|
|||||||
TestEq(((Attacker)movie.characters(new Attacker(), 0)).swordAttackDamage(), swordAttackDamage);
|
TestEq(((Attacker)movie.characters(new Attacker(), 0)).swordAttackDamage(), swordAttackDamage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestFixedLengthArrays() {
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder(0);
|
||||||
|
|
||||||
|
float a;
|
||||||
|
int[] b = new int[15];
|
||||||
|
byte c;
|
||||||
|
int[][] d_a = new int[2][2];
|
||||||
|
byte[] d_b = new byte[2];
|
||||||
|
byte[][] d_c = new byte[2][2];
|
||||||
|
|
||||||
|
a = 0.5f;
|
||||||
|
for (int i = 0; i < 15; i++) b[i] = i;
|
||||||
|
c = 1;
|
||||||
|
d_a[0][0] = 1;
|
||||||
|
d_a[0][1] = 2;
|
||||||
|
d_a[1][0] = 3;
|
||||||
|
d_a[1][1] = 4;
|
||||||
|
d_b[0] = TestEnum.B;
|
||||||
|
d_b[1] = TestEnum.C;
|
||||||
|
d_c[0][0] = TestEnum.A;
|
||||||
|
d_c[0][1] = TestEnum.B;
|
||||||
|
d_c[1][0] = TestEnum.C;
|
||||||
|
d_c[1][1] = TestEnum.B;
|
||||||
|
|
||||||
|
int arrayOffset = ArrayStruct.createArrayStruct(builder,
|
||||||
|
a, b, c, d_a, d_b, d_c);
|
||||||
|
|
||||||
|
// Create a table with the ArrayStruct.
|
||||||
|
ArrayTable.startArrayTable(builder);
|
||||||
|
ArrayTable.addA(builder, arrayOffset);
|
||||||
|
int tableOffset = ArrayTable.endArrayTable(builder);
|
||||||
|
|
||||||
|
ArrayTable.finishArrayTableBuffer(builder, tableOffset);
|
||||||
|
|
||||||
|
ArrayTable table = ArrayTable.getRootAsArrayTable(builder.dataBuffer());
|
||||||
|
NestedStruct nested = new NestedStruct();
|
||||||
|
|
||||||
|
TestEq(table.a().a(), 0.5f);
|
||||||
|
for (int i = 0; i < 15; i++) TestEq(table.a().b(i), i);
|
||||||
|
TestEq(table.a().c(), (byte)1);
|
||||||
|
TestEq(table.a().d(nested, 0).a(0), 1);
|
||||||
|
TestEq(table.a().d(nested, 0).a(1), 2);
|
||||||
|
TestEq(table.a().d(nested, 1).a(0), 3);
|
||||||
|
TestEq(table.a().d(nested, 1).a(1), 4);
|
||||||
|
TestEq(table.a().d(nested, 0).b(), TestEnum.B);
|
||||||
|
TestEq(table.a().d(nested, 1).b(), TestEnum.C);
|
||||||
|
TestEq(table.a().d(nested, 0).c(0), TestEnum.A);
|
||||||
|
TestEq(table.a().d(nested, 0).c(1), TestEnum.B);
|
||||||
|
TestEq(table.a().d(nested, 1).c(0), TestEnum.C);
|
||||||
|
TestEq(table.a().d(nested, 1).c(1), TestEnum.B);
|
||||||
|
}
|
||||||
|
|
||||||
static <T> void TestEq(T a, T b) {
|
static <T> void TestEq(T a, T b) {
|
||||||
if (!a.equals(b)) {
|
if (!a.equals(b)) {
|
||||||
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
|
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
|
||||||
|
|||||||
50
tests/MyGame/Example/ArrayStruct.cs
Normal file
50
tests/MyGame/Example/ArrayStruct.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// <auto-generated>
|
||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
// </auto-generated>
|
||||||
|
|
||||||
|
namespace MyGame.Example
|
||||||
|
{
|
||||||
|
|
||||||
|
using global::System;
|
||||||
|
using global::FlatBuffers;
|
||||||
|
|
||||||
|
public struct ArrayStruct : IFlatbufferObject
|
||||||
|
{
|
||||||
|
private Struct __p;
|
||||||
|
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
||||||
|
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
|
||||||
|
public ArrayStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||||
|
|
||||||
|
public float A { get { return __p.bb.GetFloat(__p.bb_pos + 0); } }
|
||||||
|
public void MutateA(float a) { __p.bb.PutFloat(__p.bb_pos + 0, a); }
|
||||||
|
public int B(int j) { return __p.bb.GetInt(__p.bb_pos + 4 + j * 4); }
|
||||||
|
public void MutateB(int j, int b) { __p.bb.PutInt(__p.bb_pos + 4 + j * 4, b); }
|
||||||
|
public sbyte C { get { return __p.bb.GetSbyte(__p.bb_pos + 64); } }
|
||||||
|
public void MutateC(sbyte c) { __p.bb.PutSbyte(__p.bb_pos + 64, c); }
|
||||||
|
public MyGame.Example.NestedStruct D(int j) { return (new MyGame.Example.NestedStruct()).__assign(__p.bb_pos + 68 + j * 12, __p.bb); }
|
||||||
|
|
||||||
|
public static Offset<MyGame.Example.ArrayStruct> CreateArrayStruct(FlatBufferBuilder builder, float A, int[] B, sbyte C, int[,] d_A, MyGame.Example.TestEnum[] d_B, MyGame.Example.TestEnum[,] d_C) {
|
||||||
|
builder.Prep(4, 92);
|
||||||
|
for (int _idx0 = 2; _idx0 > 0; _idx0--) {
|
||||||
|
builder.Prep(4, 12);
|
||||||
|
builder.Pad(1);
|
||||||
|
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
|
||||||
|
builder.PutSbyte((sbyte)d_C[_idx0-1,_idx1-1]);
|
||||||
|
}
|
||||||
|
builder.PutSbyte((sbyte)d_B[_idx0-1]);
|
||||||
|
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
|
||||||
|
builder.PutInt(d_A[_idx0-1,_idx1-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.Pad(3);
|
||||||
|
builder.PutSbyte(C);
|
||||||
|
for (int _idx0 = 15; _idx0 > 0; _idx0--) {
|
||||||
|
builder.PutInt(B[_idx0-1]);
|
||||||
|
}
|
||||||
|
builder.PutFloat(A);
|
||||||
|
return new Offset<MyGame.Example.ArrayStruct>(builder.Offset);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
45
tests/MyGame/Example/ArrayStruct.java
Normal file
45
tests/MyGame/Example/ArrayStruct.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
package MyGame.Example;
|
||||||
|
|
||||||
|
import java.nio.*;
|
||||||
|
import java.lang.*;
|
||||||
|
import java.util.*;
|
||||||
|
import com.google.flatbuffers.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class ArrayStruct extends Struct {
|
||||||
|
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
|
||||||
|
public ArrayStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||||
|
|
||||||
|
public float a() { return bb.getFloat(bb_pos + 0); }
|
||||||
|
public void mutateA(float a) { bb.putFloat(bb_pos + 0, a); }
|
||||||
|
public int b(int j) { return bb.getInt(bb_pos + 4 + j * 4); }
|
||||||
|
public void mutateB(int j, int b) { bb.putInt(bb_pos + 4 + j * 4, b); }
|
||||||
|
public byte c() { return bb.get(bb_pos + 64); }
|
||||||
|
public void mutateC(byte c) { bb.put(bb_pos + 64, c); }
|
||||||
|
public MyGame.Example.NestedStruct d(MyGame.Example.NestedStruct obj, int j) { return obj.__assign(bb_pos + 68 + j * 12, bb); }
|
||||||
|
|
||||||
|
public static int createArrayStruct(FlatBufferBuilder builder, float a, int[] b, byte c, int[][] d_a, byte[] d_b, byte[][] d_c) {
|
||||||
|
builder.prep(4, 92);
|
||||||
|
for (int _idx0 = 2; _idx0 > 0; _idx0--) {
|
||||||
|
builder.prep(4, 12);
|
||||||
|
builder.pad(1);
|
||||||
|
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
|
||||||
|
builder.putByte(d_c[_idx0-1][_idx1-1]);
|
||||||
|
}
|
||||||
|
builder.putByte(d_b[_idx0-1]);
|
||||||
|
for (int _idx1 = 2; _idx1 > 0; _idx1--) {
|
||||||
|
builder.putInt(d_a[_idx0-1][_idx1-1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.pad(3);
|
||||||
|
builder.putByte(c);
|
||||||
|
for (int _idx0 = 15; _idx0 > 0; _idx0--) {
|
||||||
|
builder.putInt(b[_idx0-1]);
|
||||||
|
}
|
||||||
|
builder.putFloat(a);
|
||||||
|
return builder.offset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
41
tests/MyGame/Example/ArrayStruct.py
Normal file
41
tests/MyGame/Example/ArrayStruct.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
# namespace: Example
|
||||||
|
|
||||||
|
import flatbuffers
|
||||||
|
|
||||||
|
class ArrayStruct(object):
|
||||||
|
__slots__ = ['_tab']
|
||||||
|
|
||||||
|
# ArrayStruct
|
||||||
|
def Init(self, buf, pos):
|
||||||
|
self._tab = flatbuffers.table.Table(buf, pos)
|
||||||
|
|
||||||
|
# ArrayStruct
|
||||||
|
def A(self): return self._tab.Get(flatbuffers.number_types.Float32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(0))
|
||||||
|
# ArrayStruct
|
||||||
|
def B(self): return [self._tab.Get(flatbuffers.number_types.Int32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(4 + i * 4)) for i in range(15)]
|
||||||
|
# ArrayStruct
|
||||||
|
def C(self): return self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(64))
|
||||||
|
# ArrayStruct
|
||||||
|
def D(self, obj, i):
|
||||||
|
obj.Init(self._tab.Bytes, self._tab.Pos + 68 + i * 12)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def CreateArrayStruct(builder, a, b, c, d_a, d_b, d_c):
|
||||||
|
builder.Prep(4, 92)
|
||||||
|
for _idx0 in range(2 , 0, -1):
|
||||||
|
builder.Prep(4, 12)
|
||||||
|
builder.Pad(1)
|
||||||
|
for _idx1 in range(2 , 0, -1):
|
||||||
|
builder.PrependInt8(d_c[_idx0-1][_idx1-1])
|
||||||
|
builder.PrependInt8(d_b[_idx0-1])
|
||||||
|
for _idx1 in range(2 , 0, -1):
|
||||||
|
builder.PrependInt32(d_a[_idx0-1][_idx1-1])
|
||||||
|
builder.Pad(3)
|
||||||
|
builder.PrependInt8(c)
|
||||||
|
for _idx0 in range(15 , 0, -1):
|
||||||
|
builder.PrependInt32(b[_idx0-1])
|
||||||
|
builder.PrependFloat32(a)
|
||||||
|
return builder.Offset()
|
||||||
34
tests/MyGame/Example/ArrayTable.cs
Normal file
34
tests/MyGame/Example/ArrayTable.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// <auto-generated>
|
||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
// </auto-generated>
|
||||||
|
|
||||||
|
namespace MyGame.Example
|
||||||
|
{
|
||||||
|
|
||||||
|
using global::System;
|
||||||
|
using global::FlatBuffers;
|
||||||
|
|
||||||
|
public struct ArrayTable : IFlatbufferObject
|
||||||
|
{
|
||||||
|
private Table __p;
|
||||||
|
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
||||||
|
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb) { return GetRootAsArrayTable(_bb, new ArrayTable()); }
|
||||||
|
public static ArrayTable GetRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { FlatBufferConstants.FLATBUFFERS_1_11_1(); return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
|
||||||
|
public static bool ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "ARRT"); }
|
||||||
|
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
|
||||||
|
public ArrayTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||||
|
|
||||||
|
public MyGame.Example.ArrayStruct? A { get { int o = __p.__offset(4); return o != 0 ? (MyGame.Example.ArrayStruct?)(new MyGame.Example.ArrayStruct()).__assign(o + __p.bb_pos, __p.bb) : null; } }
|
||||||
|
|
||||||
|
public static void StartArrayTable(FlatBufferBuilder builder) { builder.StartTable(1); }
|
||||||
|
public static void AddA(FlatBufferBuilder builder, Offset<MyGame.Example.ArrayStruct> aOffset) { builder.AddStruct(0, aOffset.Value, 0); }
|
||||||
|
public static Offset<MyGame.Example.ArrayTable> EndArrayTable(FlatBufferBuilder builder) {
|
||||||
|
int o = builder.EndTable();
|
||||||
|
return new Offset<MyGame.Example.ArrayTable>(o);
|
||||||
|
}
|
||||||
|
public static void FinishArrayTableBuffer(FlatBufferBuilder builder, Offset<MyGame.Example.ArrayTable> offset) { builder.Finish(offset.Value, "ARRT"); }
|
||||||
|
public static void FinishSizePrefixedArrayTableBuffer(FlatBufferBuilder builder, Offset<MyGame.Example.ArrayTable> offset) { builder.FinishSizePrefixed(offset.Value, "ARRT"); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
30
tests/MyGame/Example/ArrayTable.java
Normal file
30
tests/MyGame/Example/ArrayTable.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
package MyGame.Example;
|
||||||
|
|
||||||
|
import java.nio.*;
|
||||||
|
import java.lang.*;
|
||||||
|
import java.util.*;
|
||||||
|
import com.google.flatbuffers.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class ArrayTable extends Table {
|
||||||
|
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb) { return getRootAsArrayTable(_bb, new ArrayTable()); }
|
||||||
|
public static ArrayTable getRootAsArrayTable(ByteBuffer _bb, ArrayTable obj) { Constants.FLATBUFFERS_1_11_1(); _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
|
||||||
|
public static boolean ArrayTableBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "ARRT"); }
|
||||||
|
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); }
|
||||||
|
public ArrayTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||||
|
|
||||||
|
public MyGame.Example.ArrayStruct a() { return a(new MyGame.Example.ArrayStruct()); }
|
||||||
|
public MyGame.Example.ArrayStruct a(MyGame.Example.ArrayStruct obj) { int o = __offset(4); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; }
|
||||||
|
|
||||||
|
public static void startArrayTable(FlatBufferBuilder builder) { builder.startTable(1); }
|
||||||
|
public static void addA(FlatBufferBuilder builder, int aOffset) { builder.addStruct(0, aOffset, 0); }
|
||||||
|
public static int endArrayTable(FlatBufferBuilder builder) {
|
||||||
|
int o = builder.endTable();
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
public static void finishArrayTableBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "ARRT"); }
|
||||||
|
public static void finishSizePrefixedArrayTableBuffer(FlatBufferBuilder builder, int offset) { builder.finishSizePrefixed(offset, "ARRT"); }
|
||||||
|
}
|
||||||
|
|
||||||
34
tests/MyGame/Example/ArrayTable.py
Normal file
34
tests/MyGame/Example/ArrayTable.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
# namespace: Example
|
||||||
|
|
||||||
|
import flatbuffers
|
||||||
|
|
||||||
|
class ArrayTable(object):
|
||||||
|
__slots__ = ['_tab']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def GetRootAsArrayTable(cls, buf, offset):
|
||||||
|
n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
|
||||||
|
x = ArrayTable()
|
||||||
|
x.Init(buf, n + offset)
|
||||||
|
return x
|
||||||
|
|
||||||
|
# ArrayTable
|
||||||
|
def Init(self, buf, pos):
|
||||||
|
self._tab = flatbuffers.table.Table(buf, pos)
|
||||||
|
|
||||||
|
# ArrayTable
|
||||||
|
def A(self):
|
||||||
|
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4))
|
||||||
|
if o != 0:
|
||||||
|
x = o + self._tab.Pos
|
||||||
|
from .ArrayStruct import ArrayStruct
|
||||||
|
obj = ArrayStruct()
|
||||||
|
obj.Init(self._tab.Bytes, x)
|
||||||
|
return obj
|
||||||
|
return None
|
||||||
|
|
||||||
|
def ArrayTableStart(builder): builder.StartObject(1)
|
||||||
|
def ArrayTableAddA(builder, a): builder.PrependStructSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(a), 0)
|
||||||
|
def ArrayTableEnd(builder): return builder.EndObject()
|
||||||
40
tests/MyGame/Example/NestedStruct.cs
Normal file
40
tests/MyGame/Example/NestedStruct.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// <auto-generated>
|
||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
// </auto-generated>
|
||||||
|
|
||||||
|
namespace MyGame.Example
|
||||||
|
{
|
||||||
|
|
||||||
|
using global::System;
|
||||||
|
using global::FlatBuffers;
|
||||||
|
|
||||||
|
public struct NestedStruct : IFlatbufferObject
|
||||||
|
{
|
||||||
|
private Struct __p;
|
||||||
|
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
||||||
|
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
|
||||||
|
public NestedStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||||
|
|
||||||
|
public int A(int j) { return __p.bb.GetInt(__p.bb_pos + 0 + j * 4); }
|
||||||
|
public void MutateA(int j, int a) { __p.bb.PutInt(__p.bb_pos + 0 + j * 4, a); }
|
||||||
|
public MyGame.Example.TestEnum B { get { return (MyGame.Example.TestEnum)__p.bb.GetSbyte(__p.bb_pos + 8); } }
|
||||||
|
public void MutateB(MyGame.Example.TestEnum b) { __p.bb.PutSbyte(__p.bb_pos + 8, (sbyte)b); }
|
||||||
|
public MyGame.Example.TestEnum C(int j) { return (MyGame.Example.TestEnum)__p.bb.GetSbyte(__p.bb_pos + 9 + j * 1); }
|
||||||
|
public void MutateC(int j, MyGame.Example.TestEnum c) { __p.bb.PutSbyte(__p.bb_pos + 9 + j * 1, (sbyte)c); }
|
||||||
|
|
||||||
|
public static Offset<MyGame.Example.NestedStruct> CreateNestedStruct(FlatBufferBuilder builder, int[] A, MyGame.Example.TestEnum B, MyGame.Example.TestEnum[] C) {
|
||||||
|
builder.Prep(4, 12);
|
||||||
|
builder.Pad(1);
|
||||||
|
for (int _idx0 = 2; _idx0 > 0; _idx0--) {
|
||||||
|
builder.PutSbyte((sbyte)C[_idx0-1]);
|
||||||
|
}
|
||||||
|
builder.PutSbyte((sbyte)B);
|
||||||
|
for (int _idx0 = 2; _idx0 > 0; _idx0--) {
|
||||||
|
builder.PutInt(A[_idx0-1]);
|
||||||
|
}
|
||||||
|
return new Offset<MyGame.Example.NestedStruct>(builder.Offset);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
35
tests/MyGame/Example/NestedStruct.java
Normal file
35
tests/MyGame/Example/NestedStruct.java
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
package MyGame.Example;
|
||||||
|
|
||||||
|
import java.nio.*;
|
||||||
|
import java.lang.*;
|
||||||
|
import java.util.*;
|
||||||
|
import com.google.flatbuffers.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public final class NestedStruct extends Struct {
|
||||||
|
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
|
||||||
|
public NestedStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||||
|
|
||||||
|
public int a(int j) { return bb.getInt(bb_pos + 0 + j * 4); }
|
||||||
|
public void mutateA(int j, int a) { bb.putInt(bb_pos + 0 + j * 4, a); }
|
||||||
|
public byte b() { return bb.get(bb_pos + 8); }
|
||||||
|
public void mutateB(byte b) { bb.put(bb_pos + 8, b); }
|
||||||
|
public byte c(int j) { return bb.get(bb_pos + 9 + j * 1); }
|
||||||
|
public void mutateC(int j, byte c) { bb.put(bb_pos + 9 + j * 1, c); }
|
||||||
|
|
||||||
|
public static int createNestedStruct(FlatBufferBuilder builder, int[] a, byte b, byte[] c) {
|
||||||
|
builder.prep(4, 12);
|
||||||
|
builder.pad(1);
|
||||||
|
for (int _idx0 = 2; _idx0 > 0; _idx0--) {
|
||||||
|
builder.putByte(c[_idx0-1]);
|
||||||
|
}
|
||||||
|
builder.putByte(b);
|
||||||
|
for (int _idx0 = 2; _idx0 > 0; _idx0--) {
|
||||||
|
builder.putInt(a[_idx0-1]);
|
||||||
|
}
|
||||||
|
return builder.offset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
29
tests/MyGame/Example/NestedStruct.py
Normal file
29
tests/MyGame/Example/NestedStruct.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
# namespace: Example
|
||||||
|
|
||||||
|
import flatbuffers
|
||||||
|
|
||||||
|
class NestedStruct(object):
|
||||||
|
__slots__ = ['_tab']
|
||||||
|
|
||||||
|
# NestedStruct
|
||||||
|
def Init(self, buf, pos):
|
||||||
|
self._tab = flatbuffers.table.Table(buf, pos)
|
||||||
|
|
||||||
|
# NestedStruct
|
||||||
|
def A(self): return [self._tab.Get(flatbuffers.number_types.Int32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(0 + i * 4)) for i in range(2)]
|
||||||
|
# NestedStruct
|
||||||
|
def B(self): return self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(8))
|
||||||
|
# NestedStruct
|
||||||
|
def C(self): return [self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(9 + i * 1)) for i in range(2)]
|
||||||
|
|
||||||
|
def CreateNestedStruct(builder, a, b, c):
|
||||||
|
builder.Prep(4, 12)
|
||||||
|
builder.Pad(1)
|
||||||
|
for _idx0 in range(2 , 0, -1):
|
||||||
|
builder.PrependInt8(c[_idx0-1])
|
||||||
|
builder.PrependInt8(b)
|
||||||
|
for _idx0 in range(2 , 0, -1):
|
||||||
|
builder.PrependInt32(a[_idx0-1])
|
||||||
|
return builder.Offset()
|
||||||
16
tests/MyGame/Example/TestEnum.cs
Normal file
16
tests/MyGame/Example/TestEnum.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// <auto-generated>
|
||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
// </auto-generated>
|
||||||
|
|
||||||
|
namespace MyGame.Example
|
||||||
|
{
|
||||||
|
|
||||||
|
public enum TestEnum : sbyte
|
||||||
|
{
|
||||||
|
A = 0,
|
||||||
|
B = 1,
|
||||||
|
C = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
15
tests/MyGame/Example/TestEnum.java
Normal file
15
tests/MyGame/Example/TestEnum.java
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
package MyGame.Example;
|
||||||
|
|
||||||
|
public final class TestEnum {
|
||||||
|
private TestEnum() { }
|
||||||
|
public static final byte A = 0;
|
||||||
|
public static final byte B = 1;
|
||||||
|
public static final byte C = 2;
|
||||||
|
|
||||||
|
public static final String[] names = { "A", "B", "C", };
|
||||||
|
|
||||||
|
public static String name(int e) { return names[e]; }
|
||||||
|
}
|
||||||
|
|
||||||
9
tests/MyGame/Example/TestEnum.py
Normal file
9
tests/MyGame/Example/TestEnum.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
# namespace: Example
|
||||||
|
|
||||||
|
class TestEnum(object):
|
||||||
|
A = 0
|
||||||
|
B = 1
|
||||||
|
C = 2
|
||||||
|
|
||||||
BIN
tests/arrays_test.bfbs
Normal file
BIN
tests/arrays_test.bfbs
Normal file
Binary file not shown.
24
tests/arrays_test.fbs
Normal file
24
tests/arrays_test.fbs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace MyGame.Example;
|
||||||
|
|
||||||
|
enum TestEnum : byte { A, B, C }
|
||||||
|
|
||||||
|
struct NestedStruct{
|
||||||
|
a:[int:2];
|
||||||
|
b:TestEnum;
|
||||||
|
c:[TestEnum:2];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ArrayStruct{
|
||||||
|
a:float;
|
||||||
|
b:[int:0xF];
|
||||||
|
c:byte;
|
||||||
|
d:[NestedStruct:2];
|
||||||
|
}
|
||||||
|
|
||||||
|
table ArrayTable{
|
||||||
|
a:ArrayStruct;
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type ArrayTable;
|
||||||
|
file_identifier "ARRT";
|
||||||
|
file_extension "mon";
|
||||||
19
tests/arrays_test.golden
Normal file
19
tests/arrays_test.golden
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
a : {
|
||||||
|
a: 12.34,
|
||||||
|
b: [1,2,3,4,5,6,7,8,9,0xA,0xB,0xC,0xD,0xE,0xF],
|
||||||
|
c: -127,
|
||||||
|
d: [
|
||||||
|
{
|
||||||
|
a : [-1,2],
|
||||||
|
b : A,
|
||||||
|
c : [C, B]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
a : [3,-4],
|
||||||
|
b : B,
|
||||||
|
c : [B, A]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
60
tests/arrays_test.schema.json
Normal file
60
tests/arrays_test.schema.json
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||||
|
"definitions": {
|
||||||
|
"MyGame_Example_TestEnum" : {
|
||||||
|
"type" : "string",
|
||||||
|
"enum": ["A", "B", "C"]
|
||||||
|
},
|
||||||
|
"MyGame_Example_NestedStruct" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"a" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" },
|
||||||
|
"minItems": 2,
|
||||||
|
"maxItems": 2
|
||||||
|
},
|
||||||
|
"b" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_TestEnum"
|
||||||
|
},
|
||||||
|
"c" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_TestEnum",
|
||||||
|
"minItems": 2,
|
||||||
|
"maxItems": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
},
|
||||||
|
"MyGame_Example_ArrayStruct" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"a" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"b" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" },
|
||||||
|
"minItems": 15,
|
||||||
|
"maxItems": 15
|
||||||
|
},
|
||||||
|
"c" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"d" : {
|
||||||
|
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_NestedStruct" },
|
||||||
|
"minItems": 2,
|
||||||
|
"maxItems": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
},
|
||||||
|
"MyGame_Example_ArrayTable" : {
|
||||||
|
"type" : "object",
|
||||||
|
"properties" : {
|
||||||
|
"a" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_ArrayStruct"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_ArrayTable"
|
||||||
|
}
|
||||||
419
tests/arrays_test_generated.h
Normal file
419
tests/arrays_test_generated.h
Normal file
@@ -0,0 +1,419 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_GENERATED_ARRAYSTEST_MYGAME_EXAMPLE_H_
|
||||||
|
#define FLATBUFFERS_GENERATED_ARRAYSTEST_MYGAME_EXAMPLE_H_
|
||||||
|
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
|
||||||
|
namespace MyGame {
|
||||||
|
namespace Example {
|
||||||
|
|
||||||
|
struct NestedStruct;
|
||||||
|
|
||||||
|
struct ArrayStruct;
|
||||||
|
|
||||||
|
struct ArrayTable;
|
||||||
|
struct ArrayTableT;
|
||||||
|
|
||||||
|
bool operator==(const NestedStruct &lhs, const NestedStruct &rhs);
|
||||||
|
bool operator!=(const NestedStruct &lhs, const NestedStruct &rhs);
|
||||||
|
bool operator==(const ArrayStruct &lhs, const ArrayStruct &rhs);
|
||||||
|
bool operator!=(const ArrayStruct &lhs, const ArrayStruct &rhs);
|
||||||
|
bool operator==(const ArrayTableT &lhs, const ArrayTableT &rhs);
|
||||||
|
bool operator!=(const ArrayTableT &lhs, const ArrayTableT &rhs);
|
||||||
|
|
||||||
|
inline const flatbuffers::TypeTable *NestedStructTypeTable();
|
||||||
|
|
||||||
|
inline const flatbuffers::TypeTable *ArrayStructTypeTable();
|
||||||
|
|
||||||
|
inline const flatbuffers::TypeTable *ArrayTableTypeTable();
|
||||||
|
|
||||||
|
enum class TestEnum : int8_t {
|
||||||
|
A = 0,
|
||||||
|
B = 1,
|
||||||
|
C = 2,
|
||||||
|
MIN = A,
|
||||||
|
MAX = C
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const TestEnum (&EnumValuesTestEnum())[3] {
|
||||||
|
static const TestEnum values[] = {
|
||||||
|
TestEnum::A,
|
||||||
|
TestEnum::B,
|
||||||
|
TestEnum::C
|
||||||
|
};
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char * const *EnumNamesTestEnum() {
|
||||||
|
static const char * const names[4] = {
|
||||||
|
"A",
|
||||||
|
"B",
|
||||||
|
"C",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *EnumNameTestEnum(TestEnum e) {
|
||||||
|
if (e < TestEnum::A || e > TestEnum::C) return "";
|
||||||
|
const size_t index = static_cast<size_t>(e);
|
||||||
|
return EnumNamesTestEnum()[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) NestedStruct FLATBUFFERS_FINAL_CLASS {
|
||||||
|
private:
|
||||||
|
int32_t a_[2];
|
||||||
|
int8_t b_;
|
||||||
|
int8_t c_[2];
|
||||||
|
int8_t padding0__;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
|
return NestedStructTypeTable();
|
||||||
|
}
|
||||||
|
NestedStruct() {
|
||||||
|
memset(static_cast<void *>(this), 0, sizeof(NestedStruct));
|
||||||
|
}
|
||||||
|
NestedStruct(MyGame::Example::TestEnum _b)
|
||||||
|
: b_(flatbuffers::EndianScalar(static_cast<int8_t>(_b))) {
|
||||||
|
std::memset(a_, 0, sizeof(a_));
|
||||||
|
std::memset(c_, 0, sizeof(c_));
|
||||||
|
(void)padding0__;
|
||||||
|
}
|
||||||
|
const flatbuffers::Array<int32_t, 2> *a() const {
|
||||||
|
return reinterpret_cast<const flatbuffers::Array<int32_t, 2> *>(a_);
|
||||||
|
}
|
||||||
|
flatbuffers::Array<int32_t, 2> *mutable_a() {
|
||||||
|
return reinterpret_cast<flatbuffers::Array<int32_t, 2> *>(a_);
|
||||||
|
}
|
||||||
|
MyGame::Example::TestEnum b() const {
|
||||||
|
return static_cast<MyGame::Example::TestEnum>(flatbuffers::EndianScalar(b_));
|
||||||
|
}
|
||||||
|
void mutate_b(MyGame::Example::TestEnum _b) {
|
||||||
|
flatbuffers::WriteScalar(&b_, static_cast<int8_t>(_b));
|
||||||
|
}
|
||||||
|
const flatbuffers::Array<MyGame::Example::TestEnum, 2> *c() const {
|
||||||
|
return reinterpret_cast<const flatbuffers::Array<MyGame::Example::TestEnum, 2> *>(c_);
|
||||||
|
}
|
||||||
|
flatbuffers::Array<MyGame::Example::TestEnum, 2> *mutable_c() {
|
||||||
|
return reinterpret_cast<flatbuffers::Array<MyGame::Example::TestEnum, 2> *>(c_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FLATBUFFERS_STRUCT_END(NestedStruct, 12);
|
||||||
|
|
||||||
|
inline bool operator==(const NestedStruct &lhs, const NestedStruct &rhs) {
|
||||||
|
return
|
||||||
|
(lhs.a() == rhs.a()) &&
|
||||||
|
(lhs.b() == rhs.b()) &&
|
||||||
|
(lhs.c() == rhs.c());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const NestedStruct &lhs, const NestedStruct &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) ArrayStruct FLATBUFFERS_FINAL_CLASS {
|
||||||
|
private:
|
||||||
|
float a_;
|
||||||
|
int32_t b_[15];
|
||||||
|
int8_t c_;
|
||||||
|
int8_t padding0__; int16_t padding1__;
|
||||||
|
MyGame::Example::NestedStruct d_[2];
|
||||||
|
|
||||||
|
public:
|
||||||
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
|
return ArrayStructTypeTable();
|
||||||
|
}
|
||||||
|
ArrayStruct() {
|
||||||
|
memset(static_cast<void *>(this), 0, sizeof(ArrayStruct));
|
||||||
|
}
|
||||||
|
ArrayStruct(float _a, int8_t _c)
|
||||||
|
: a_(flatbuffers::EndianScalar(_a)),
|
||||||
|
c_(flatbuffers::EndianScalar(_c)),
|
||||||
|
padding0__(0),
|
||||||
|
padding1__(0) {
|
||||||
|
std::memset(b_, 0, sizeof(b_));
|
||||||
|
(void)padding0__; (void)padding1__;
|
||||||
|
std::memset(d_, 0, sizeof(d_));
|
||||||
|
}
|
||||||
|
float a() const {
|
||||||
|
return flatbuffers::EndianScalar(a_);
|
||||||
|
}
|
||||||
|
void mutate_a(float _a) {
|
||||||
|
flatbuffers::WriteScalar(&a_, _a);
|
||||||
|
}
|
||||||
|
const flatbuffers::Array<int32_t, 15> *b() const {
|
||||||
|
return reinterpret_cast<const flatbuffers::Array<int32_t, 15> *>(b_);
|
||||||
|
}
|
||||||
|
flatbuffers::Array<int32_t, 15> *mutable_b() {
|
||||||
|
return reinterpret_cast<flatbuffers::Array<int32_t, 15> *>(b_);
|
||||||
|
}
|
||||||
|
int8_t c() const {
|
||||||
|
return flatbuffers::EndianScalar(c_);
|
||||||
|
}
|
||||||
|
void mutate_c(int8_t _c) {
|
||||||
|
flatbuffers::WriteScalar(&c_, _c);
|
||||||
|
}
|
||||||
|
const flatbuffers::Array<MyGame::Example::NestedStruct, 2> *d() const {
|
||||||
|
return reinterpret_cast<const flatbuffers::Array<MyGame::Example::NestedStruct, 2> *>(d_);
|
||||||
|
}
|
||||||
|
flatbuffers::Array<MyGame::Example::NestedStruct, 2> *mutable_d() {
|
||||||
|
return reinterpret_cast<flatbuffers::Array<MyGame::Example::NestedStruct, 2> *>(d_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
FLATBUFFERS_STRUCT_END(ArrayStruct, 92);
|
||||||
|
|
||||||
|
inline bool operator==(const ArrayStruct &lhs, const ArrayStruct &rhs) {
|
||||||
|
return
|
||||||
|
(lhs.a() == rhs.a()) &&
|
||||||
|
(lhs.b() == rhs.b()) &&
|
||||||
|
(lhs.c() == rhs.c()) &&
|
||||||
|
(lhs.d() == rhs.d());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const ArrayStruct &lhs, const ArrayStruct &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ArrayTableT : public flatbuffers::NativeTable {
|
||||||
|
typedef ArrayTable TableType;
|
||||||
|
flatbuffers::unique_ptr<MyGame::Example::ArrayStruct> a;
|
||||||
|
ArrayTableT() {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator==(const ArrayTableT &lhs, const ArrayTableT &rhs) {
|
||||||
|
return
|
||||||
|
(lhs.a == rhs.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const ArrayTableT &lhs, const ArrayTableT &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ArrayTable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
|
typedef ArrayTableT NativeTableType;
|
||||||
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
|
return ArrayTableTypeTable();
|
||||||
|
}
|
||||||
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
|
VT_A = 4
|
||||||
|
};
|
||||||
|
const MyGame::Example::ArrayStruct *a() const {
|
||||||
|
return GetStruct<const MyGame::Example::ArrayStruct *>(VT_A);
|
||||||
|
}
|
||||||
|
MyGame::Example::ArrayStruct *mutable_a() {
|
||||||
|
return GetStruct<MyGame::Example::ArrayStruct *>(VT_A);
|
||||||
|
}
|
||||||
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
|
return VerifyTableStart(verifier) &&
|
||||||
|
VerifyField<MyGame::Example::ArrayStruct>(verifier, VT_A) &&
|
||||||
|
verifier.EndTable();
|
||||||
|
}
|
||||||
|
ArrayTableT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||||
|
void UnPackTo(ArrayTableT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||||
|
static flatbuffers::Offset<ArrayTable> Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArrayTableT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ArrayTableBuilder {
|
||||||
|
flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
|
flatbuffers::uoffset_t start_;
|
||||||
|
void add_a(const MyGame::Example::ArrayStruct *a) {
|
||||||
|
fbb_.AddStruct(ArrayTable::VT_A, a);
|
||||||
|
}
|
||||||
|
explicit ArrayTableBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
|
: fbb_(_fbb) {
|
||||||
|
start_ = fbb_.StartTable();
|
||||||
|
}
|
||||||
|
ArrayTableBuilder &operator=(const ArrayTableBuilder &);
|
||||||
|
flatbuffers::Offset<ArrayTable> Finish() {
|
||||||
|
const auto end = fbb_.EndTable(start_);
|
||||||
|
auto o = flatbuffers::Offset<ArrayTable>(end);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline flatbuffers::Offset<ArrayTable> CreateArrayTable(
|
||||||
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
const MyGame::Example::ArrayStruct *a = 0) {
|
||||||
|
ArrayTableBuilder builder_(_fbb);
|
||||||
|
builder_.add_a(a);
|
||||||
|
return builder_.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
flatbuffers::Offset<ArrayTable> CreateArrayTable(flatbuffers::FlatBufferBuilder &_fbb, const ArrayTableT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
|
||||||
|
inline ArrayTableT *ArrayTable::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
|
||||||
|
auto _o = new ArrayTableT();
|
||||||
|
UnPackTo(_o, _resolver);
|
||||||
|
return _o;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ArrayTable::UnPackTo(ArrayTableT *_o, const flatbuffers::resolver_function_t *_resolver) const {
|
||||||
|
(void)_o;
|
||||||
|
(void)_resolver;
|
||||||
|
{ auto _e = a(); if (_e) _o->a = flatbuffers::unique_ptr<MyGame::Example::ArrayStruct>(new MyGame::Example::ArrayStruct(*_e)); };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline flatbuffers::Offset<ArrayTable> ArrayTable::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ArrayTableT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||||
|
return CreateArrayTable(_fbb, _o, _rehasher);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline flatbuffers::Offset<ArrayTable> CreateArrayTable(flatbuffers::FlatBufferBuilder &_fbb, const ArrayTableT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||||
|
(void)_rehasher;
|
||||||
|
(void)_o;
|
||||||
|
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ArrayTableT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||||
|
auto _a = _o->a ? _o->a.get() : 0;
|
||||||
|
return MyGame::Example::CreateArrayTable(
|
||||||
|
_fbb,
|
||||||
|
_a);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const flatbuffers::TypeTable *TestEnumTypeTable() {
|
||||||
|
static const flatbuffers::TypeCode type_codes[] = {
|
||||||
|
{ flatbuffers::ET_CHAR, 0, 0 },
|
||||||
|
{ flatbuffers::ET_CHAR, 0, 0 },
|
||||||
|
{ flatbuffers::ET_CHAR, 0, 0 }
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeFunction type_refs[] = {
|
||||||
|
MyGame::Example::TestEnumTypeTable
|
||||||
|
};
|
||||||
|
static const char * const names[] = {
|
||||||
|
"A",
|
||||||
|
"B",
|
||||||
|
"C"
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeTable tt = {
|
||||||
|
flatbuffers::ST_ENUM, 3, type_codes, type_refs, nullptr, names
|
||||||
|
};
|
||||||
|
return &tt;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const flatbuffers::TypeTable *NestedStructTypeTable() {
|
||||||
|
static const flatbuffers::TypeCode type_codes[] = {
|
||||||
|
{ flatbuffers::ET_SEQUENCE, 0, -1 },
|
||||||
|
{ flatbuffers::ET_CHAR, 0, 0 },
|
||||||
|
{ flatbuffers::ET_SEQUENCE, 0, 0 }
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeFunction type_refs[] = {
|
||||||
|
MyGame::Example::TestEnumTypeTable
|
||||||
|
};
|
||||||
|
static const int64_t values[] = { 0, 8, 9, 12 };
|
||||||
|
static const char * const names[] = {
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
"c"
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeTable tt = {
|
||||||
|
flatbuffers::ST_STRUCT, 3, type_codes, type_refs, values, names
|
||||||
|
};
|
||||||
|
return &tt;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const flatbuffers::TypeTable *ArrayStructTypeTable() {
|
||||||
|
static const flatbuffers::TypeCode type_codes[] = {
|
||||||
|
{ flatbuffers::ET_FLOAT, 0, -1 },
|
||||||
|
{ flatbuffers::ET_SEQUENCE, 0, -1 },
|
||||||
|
{ flatbuffers::ET_CHAR, 0, -1 },
|
||||||
|
{ flatbuffers::ET_SEQUENCE, 0, 0 }
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeFunction type_refs[] = {
|
||||||
|
MyGame::Example::NestedStructTypeTable
|
||||||
|
};
|
||||||
|
static const int64_t values[] = { 0, 4, 64, 68, 92 };
|
||||||
|
static const char * const names[] = {
|
||||||
|
"a",
|
||||||
|
"b",
|
||||||
|
"c",
|
||||||
|
"d"
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeTable tt = {
|
||||||
|
flatbuffers::ST_STRUCT, 4, type_codes, type_refs, values, names
|
||||||
|
};
|
||||||
|
return &tt;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const flatbuffers::TypeTable *ArrayTableTypeTable() {
|
||||||
|
static const flatbuffers::TypeCode type_codes[] = {
|
||||||
|
{ flatbuffers::ET_SEQUENCE, 0, 0 }
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeFunction type_refs[] = {
|
||||||
|
MyGame::Example::ArrayStructTypeTable
|
||||||
|
};
|
||||||
|
static const char * const names[] = {
|
||||||
|
"a"
|
||||||
|
};
|
||||||
|
static const flatbuffers::TypeTable tt = {
|
||||||
|
flatbuffers::ST_TABLE, 1, type_codes, type_refs, nullptr, names
|
||||||
|
};
|
||||||
|
return &tt;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const MyGame::Example::ArrayTable *GetArrayTable(const void *buf) {
|
||||||
|
return flatbuffers::GetRoot<MyGame::Example::ArrayTable>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const MyGame::Example::ArrayTable *GetSizePrefixedArrayTable(const void *buf) {
|
||||||
|
return flatbuffers::GetSizePrefixedRoot<MyGame::Example::ArrayTable>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ArrayTable *GetMutableArrayTable(void *buf) {
|
||||||
|
return flatbuffers::GetMutableRoot<ArrayTable>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *ArrayTableIdentifier() {
|
||||||
|
return "ARRT";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ArrayTableBufferHasIdentifier(const void *buf) {
|
||||||
|
return flatbuffers::BufferHasIdentifier(
|
||||||
|
buf, ArrayTableIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool VerifyArrayTableBuffer(
|
||||||
|
flatbuffers::Verifier &verifier) {
|
||||||
|
return verifier.VerifyBuffer<MyGame::Example::ArrayTable>(ArrayTableIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool VerifySizePrefixedArrayTableBuffer(
|
||||||
|
flatbuffers::Verifier &verifier) {
|
||||||
|
return verifier.VerifySizePrefixedBuffer<MyGame::Example::ArrayTable>(ArrayTableIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char *ArrayTableExtension() {
|
||||||
|
return "mon";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FinishArrayTableBuffer(
|
||||||
|
flatbuffers::FlatBufferBuilder &fbb,
|
||||||
|
flatbuffers::Offset<MyGame::Example::ArrayTable> root) {
|
||||||
|
fbb.Finish(root, ArrayTableIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FinishSizePrefixedArrayTableBuffer(
|
||||||
|
flatbuffers::FlatBufferBuilder &fbb,
|
||||||
|
flatbuffers::Offset<MyGame::Example::ArrayTable> root) {
|
||||||
|
fbb.FinishSizePrefixed(root, ArrayTableIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline flatbuffers::unique_ptr<MyGame::Example::ArrayTableT> UnPackArrayTable(
|
||||||
|
const void *buf,
|
||||||
|
const flatbuffers::resolver_function_t *res = nullptr) {
|
||||||
|
return flatbuffers::unique_ptr<MyGame::Example::ArrayTableT>(GetArrayTable(buf)->UnPack(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline flatbuffers::unique_ptr<MyGame::Example::ArrayTableT> UnPackSizePrefixedArrayTable(
|
||||||
|
const void *buf,
|
||||||
|
const flatbuffers::resolver_function_t *res = nullptr) {
|
||||||
|
return flatbuffers::unique_ptr<MyGame::Example::ArrayTableT>(GetSizePrefixedArrayTable(buf)->UnPack(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Example
|
||||||
|
} // namespace MyGame
|
||||||
|
|
||||||
|
#endif // FLATBUFFERS_GENERATED_ARRAYSTEST_MYGAME_EXAMPLE_H_
|
||||||
@@ -19,7 +19,9 @@ if "%1"=="-b" set buildtype=%2
|
|||||||
..\%buildtype%\flatc.exe --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs || goto FAIL
|
..\%buildtype%\flatc.exe --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs || goto FAIL
|
||||||
..\%buildtype%\flatc.exe --cpp --java --csharp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs || goto FAIL
|
..\%buildtype%\flatc.exe --cpp --java --csharp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs || goto FAIL
|
||||||
..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs || goto FAIL
|
..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs || goto FAIL
|
||||||
|
..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs || goto FAIL
|
||||||
..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs || goto FAIL
|
..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs || goto FAIL
|
||||||
|
..\%buildtype%\flatc.exe --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --scoped-enums --jsonschema --cpp-ptr-type flatbuffers::unique_ptr arrays_test.fbs || goto FAIL
|
||||||
|
|
||||||
IF NOT "%MONSTER_EXTRA%"=="skip" (
|
IF NOT "%MONSTER_EXTRA%"=="skip" (
|
||||||
@echo Generate MosterExtra
|
@echo Generate MosterExtra
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ set -e
|
|||||||
../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
|
../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
|
||||||
../flatc --cpp --java --csharp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs
|
../flatc --cpp --java --csharp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs
|
||||||
../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs
|
../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test monster_test.fbs
|
||||||
|
../flatc -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs
|
||||||
../flatc --jsonschema --schema -I include_test monster_test.fbs
|
../flatc --jsonschema --schema -I include_test monster_test.fbs
|
||||||
../flatc --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs monsterdata_extra.json || goto FAIL
|
../flatc --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes monster_extra.fbs monsterdata_extra.json
|
||||||
|
../flatc --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --scoped-enums --jsonschema --cpp-ptr-type flatbuffers::unique_ptr arrays_test.fbs
|
||||||
cd ../samples
|
cd ../samples
|
||||||
../flatc --cpp --lobster --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr monster.fbs
|
../flatc --cpp --lobster --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr monster.fbs
|
||||||
../flatc -b --schema --bfbs-comments --bfbs-builtins monster.fbs
|
../flatc -b --schema --bfbs-comments --bfbs-builtins monster.fbs
|
||||||
|
|||||||
@@ -24,21 +24,27 @@
|
|||||||
"MyGame_OtherNameSpace_Unused" : {
|
"MyGame_OtherNameSpace_Unused" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : { "type" : "number" }
|
"a" : {
|
||||||
|
"type" : "number"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
"MyGame_OtherNameSpace_TableB" : {
|
"MyGame_OtherNameSpace_TableB" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : { "$ref" : "#/definitions/TableA" }
|
"a" : {
|
||||||
|
"$ref" : "#/definitions/TableA"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
"TableA" : {
|
"TableA" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"b" : { "$ref" : "#/definitions/MyGame_OtherNameSpace_TableB" }
|
"b" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_OtherNameSpace_TableB"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
@@ -57,51 +63,81 @@
|
|||||||
"MyGame_Example_Test" : {
|
"MyGame_Example_Test" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"a" : { "type" : "number" },
|
"a" : {
|
||||||
"b" : { "type" : "number" }
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"b" : {
|
||||||
|
"type" : "number"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
"MyGame_Example_TestSimpleTableWithEnum" : {
|
"MyGame_Example_TestSimpleTableWithEnum" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"color" : { "$ref" : "#/definitions/MyGame_Example_Color" }
|
"color" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_Color"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
"MyGame_Example_Vec3" : {
|
"MyGame_Example_Vec3" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"x" : { "type" : "number" },
|
"x" : {
|
||||||
"y" : { "type" : "number" },
|
"type" : "number"
|
||||||
"z" : { "type" : "number" },
|
},
|
||||||
"test1" : { "type" : "number" },
|
"y" : {
|
||||||
"test2" : { "$ref" : "#/definitions/MyGame_Example_Color" },
|
"type" : "number"
|
||||||
"test3" : { "$ref" : "#/definitions/MyGame_Example_Test" }
|
},
|
||||||
|
"z" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"test1" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"test2" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_Color"
|
||||||
|
},
|
||||||
|
"test3" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_Test"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
"MyGame_Example_Ability" : {
|
"MyGame_Example_Ability" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"id" : { "type" : "number" },
|
"id" : {
|
||||||
"distance" : { "type" : "number" }
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"distance" : {
|
||||||
|
"type" : "number"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
"MyGame_Example_Stat" : {
|
"MyGame_Example_Stat" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"id" : { "type" : "string" },
|
"id" : {
|
||||||
"val" : { "type" : "number" },
|
"type" : "string"
|
||||||
"count" : { "type" : "number" }
|
},
|
||||||
|
"val" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"count" : {
|
||||||
|
"type" : "number"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
"MyGame_Example_Referrable" : {
|
"MyGame_Example_Referrable" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"id" : { "type" : "number" }
|
"id" : {
|
||||||
|
"type" : "number"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
},
|
},
|
||||||
@@ -109,54 +145,150 @@
|
|||||||
"type" : "object",
|
"type" : "object",
|
||||||
"description" : " an example documentation comment: monster object",
|
"description" : " an example documentation comment: monster object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"pos" : { "$ref" : "#/definitions/MyGame_Example_Vec3" },
|
"pos" : {
|
||||||
"mana" : { "type" : "number" },
|
"$ref" : "#/definitions/MyGame_Example_Vec3"
|
||||||
"hp" : { "type" : "number" },
|
},
|
||||||
"name" : { "type" : "string" },
|
"mana" : {
|
||||||
"friendly" : { "type" : "boolean" },
|
"type" : "number"
|
||||||
"inventory" : { "type" : "array", "items" : { "type" : "number" } },
|
},
|
||||||
"color" : { "$ref" : "#/definitions/MyGame_Example_Color" },
|
"hp" : {
|
||||||
"test_type" : { "$ref" : "#/definitions/MyGame_Example_Any" },
|
"type" : "number"
|
||||||
"test" : { "anyOf": [{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_TestSimpleTableWithEnum" },{ "$ref" : "#/definitions/MyGame_Example2_Monster" }] },
|
},
|
||||||
"test4" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Test" } },
|
"name" : {
|
||||||
"testarrayofstring" : { "type" : "array", "items" : { "type" : "string" } },
|
"type" : "string"
|
||||||
"testarrayoftables" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Monster" } },
|
},
|
||||||
"enemy" : { "$ref" : "#/definitions/MyGame_Example_Monster" },
|
"friendly" : {
|
||||||
"testnestedflatbuffer" : { "type" : "array", "items" : { "type" : "number" } },
|
"type" : "boolean"
|
||||||
"testempty" : { "$ref" : "#/definitions/MyGame_Example_Stat" },
|
},
|
||||||
"testbool" : { "type" : "boolean" },
|
"inventory" : {
|
||||||
"testhashs32_fnv1" : { "type" : "number" },
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
"testhashu32_fnv1" : { "type" : "number" },
|
},
|
||||||
"testhashs64_fnv1" : { "type" : "number" },
|
"color" : {
|
||||||
"testhashu64_fnv1" : { "type" : "number" },
|
"$ref" : "#/definitions/MyGame_Example_Color"
|
||||||
"testhashs32_fnv1a" : { "type" : "number" },
|
},
|
||||||
"testhashu32_fnv1a" : { "type" : "number" },
|
"test_type" : {
|
||||||
"testhashs64_fnv1a" : { "type" : "number" },
|
"$ref" : "#/definitions/MyGame_Example_Any"
|
||||||
"testhashu64_fnv1a" : { "type" : "number" },
|
},
|
||||||
"testarrayofbools" : { "type" : "array", "items" : { "type" : "boolean" } },
|
"test" : {
|
||||||
"testf" : { "type" : "number" },
|
"anyOf": [{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_TestSimpleTableWithEnum" },{ "$ref" : "#/definitions/MyGame_Example2_Monster" }]
|
||||||
"testf2" : { "type" : "number" },
|
},
|
||||||
"testf3" : { "type" : "number" },
|
"test4" : {
|
||||||
"testarrayofstring2" : { "type" : "array", "items" : { "type" : "string" } },
|
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Test" }
|
||||||
"testarrayofsortedstruct" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Ability" } },
|
},
|
||||||
"flex" : { "type" : "array", "items" : { "type" : "number" } },
|
"testarrayofstring" : {
|
||||||
"test5" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Test" } },
|
"type" : "array", "items" : { "type" : "string" }
|
||||||
"vector_of_longs" : { "type" : "array", "items" : { "type" : "number" } },
|
},
|
||||||
"vector_of_doubles" : { "type" : "array", "items" : { "type" : "number" } },
|
"testarrayoftables" : {
|
||||||
"parent_namespace_test" : { "$ref" : "#/definitions/MyGame_InParentNamespace" },
|
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Monster" }
|
||||||
"vector_of_referrables" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Referrable" } },
|
},
|
||||||
"single_weak_reference" : { "type" : "number" },
|
"enemy" : {
|
||||||
"vector_of_weak_references" : { "type" : "array", "items" : { "type" : "number" } },
|
"$ref" : "#/definitions/MyGame_Example_Monster"
|
||||||
"vector_of_strong_referrables" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Referrable" } },
|
},
|
||||||
"co_owning_reference" : { "type" : "number" },
|
"testnestedflatbuffer" : {
|
||||||
"vector_of_co_owning_references" : { "type" : "array", "items" : { "type" : "number" } },
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
"non_owning_reference" : { "type" : "number" },
|
},
|
||||||
"vector_of_non_owning_references" : { "type" : "array", "items" : { "type" : "number" } },
|
"testempty" : {
|
||||||
"any_unique_type" : { "$ref" : "#/definitions/MyGame_Example_AnyUniqueAliases" },
|
"$ref" : "#/definitions/MyGame_Example_Stat"
|
||||||
"any_unique" : { "anyOf": [{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_TestSimpleTableWithEnum" },{ "$ref" : "#/definitions/MyGame_Example2_Monster" }] },
|
},
|
||||||
"any_ambiguous_type" : { "$ref" : "#/definitions/MyGame_Example_AnyAmbiguousAliases" },
|
"testbool" : {
|
||||||
"any_ambiguous" : { "anyOf": [{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_Monster" }] },
|
"type" : "boolean"
|
||||||
"vector_of_enums" : { "$ref" : "#/definitions/MyGame_Example_Color" }
|
},
|
||||||
|
"testhashs32_fnv1" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testhashu32_fnv1" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testhashs64_fnv1" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testhashu64_fnv1" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testhashs32_fnv1a" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testhashu32_fnv1a" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testhashs64_fnv1a" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testhashu64_fnv1a" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testarrayofbools" : {
|
||||||
|
"type" : "array", "items" : { "type" : "boolean" }
|
||||||
|
},
|
||||||
|
"testf" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testf2" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testf3" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"testarrayofstring2" : {
|
||||||
|
"type" : "array", "items" : { "type" : "string" }
|
||||||
|
},
|
||||||
|
"testarrayofsortedstruct" : {
|
||||||
|
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Ability" }
|
||||||
|
},
|
||||||
|
"flex" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
},
|
||||||
|
"test5" : {
|
||||||
|
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Test" }
|
||||||
|
},
|
||||||
|
"vector_of_longs" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
},
|
||||||
|
"vector_of_doubles" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
},
|
||||||
|
"parent_namespace_test" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_InParentNamespace"
|
||||||
|
},
|
||||||
|
"vector_of_referrables" : {
|
||||||
|
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Referrable" }
|
||||||
|
},
|
||||||
|
"single_weak_reference" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"vector_of_weak_references" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
},
|
||||||
|
"vector_of_strong_referrables" : {
|
||||||
|
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Referrable" }
|
||||||
|
},
|
||||||
|
"co_owning_reference" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"vector_of_co_owning_references" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
},
|
||||||
|
"non_owning_reference" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"vector_of_non_owning_references" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
},
|
||||||
|
"any_unique_type" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_AnyUniqueAliases"
|
||||||
|
},
|
||||||
|
"any_unique" : {
|
||||||
|
"anyOf": [{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_TestSimpleTableWithEnum" },{ "$ref" : "#/definitions/MyGame_Example2_Monster" }]
|
||||||
|
},
|
||||||
|
"any_ambiguous_type" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_AnyAmbiguousAliases"
|
||||||
|
},
|
||||||
|
"any_ambiguous" : {
|
||||||
|
"anyOf": [{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_Monster" },{ "$ref" : "#/definitions/MyGame_Example_Monster" }]
|
||||||
|
},
|
||||||
|
"vector_of_enums" : {
|
||||||
|
"$ref" : "#/definitions/MyGame_Example_Color"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"required" : ["name"],
|
"required" : ["name"],
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
@@ -164,18 +296,42 @@
|
|||||||
"MyGame_Example_TypeAliases" : {
|
"MyGame_Example_TypeAliases" : {
|
||||||
"type" : "object",
|
"type" : "object",
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"i8" : { "type" : "number" },
|
"i8" : {
|
||||||
"u8" : { "type" : "number" },
|
"type" : "number"
|
||||||
"i16" : { "type" : "number" },
|
},
|
||||||
"u16" : { "type" : "number" },
|
"u8" : {
|
||||||
"i32" : { "type" : "number" },
|
"type" : "number"
|
||||||
"u32" : { "type" : "number" },
|
},
|
||||||
"i64" : { "type" : "number" },
|
"i16" : {
|
||||||
"u64" : { "type" : "number" },
|
"type" : "number"
|
||||||
"f32" : { "type" : "number" },
|
},
|
||||||
"f64" : { "type" : "number" },
|
"u16" : {
|
||||||
"v8" : { "type" : "array", "items" : { "type" : "number" } },
|
"type" : "number"
|
||||||
"vf64" : { "type" : "array", "items" : { "type" : "number" } }
|
},
|
||||||
|
"i32" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"u32" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"i64" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"u64" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"f32" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"f64" : {
|
||||||
|
"type" : "number"
|
||||||
|
},
|
||||||
|
"v8" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
},
|
||||||
|
"vf64" : {
|
||||||
|
"type" : "array", "items" : { "type" : "number" }
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : false
|
"additionalProperties" : false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,10 @@ import MyGame.Example.Test # refers to generated code
|
|||||||
import MyGame.Example.Stat # refers to generated code
|
import MyGame.Example.Stat # refers to generated code
|
||||||
import MyGame.Example.Vec3 # refers to generated code
|
import MyGame.Example.Vec3 # refers to generated code
|
||||||
import MyGame.MonsterExtra # refers to generated code
|
import MyGame.MonsterExtra # refers to generated code
|
||||||
|
import MyGame.Example.ArrayTable # refers to generated code
|
||||||
|
import MyGame.Example.ArrayStruct # refers to generated code
|
||||||
|
import MyGame.Example.NestedStruct # refers to generated code
|
||||||
|
import MyGame.Example.TestEnum # refers to generated code
|
||||||
|
|
||||||
def assertRaises(test_case, fn, exception_class):
|
def assertRaises(test_case, fn, exception_class):
|
||||||
''' Backwards-compatible assertion for exceptions raised. '''
|
''' Backwards-compatible assertion for exceptions raised. '''
|
||||||
@@ -1544,6 +1547,55 @@ class TestExceptions(unittest.TestCase):
|
|||||||
flatbuffers.builder.BuilderNotFinishedError)
|
flatbuffers.builder.BuilderNotFinishedError)
|
||||||
|
|
||||||
|
|
||||||
|
class TestFixedLengthArrays(unittest.TestCase):
|
||||||
|
def test_fixed_length_array(self):
|
||||||
|
builder = flatbuffers.Builder(0)
|
||||||
|
|
||||||
|
a = 0.5
|
||||||
|
b = range(0, 15)
|
||||||
|
c = 1
|
||||||
|
d_a = [[1, 2], [3, 4]]
|
||||||
|
d_b = [MyGame.Example.TestEnum.TestEnum.B, \
|
||||||
|
MyGame.Example.TestEnum.TestEnum.C]
|
||||||
|
d_c = [[MyGame.Example.TestEnum.TestEnum.A, \
|
||||||
|
MyGame.Example.TestEnum.TestEnum.B], \
|
||||||
|
[MyGame.Example.TestEnum.TestEnum.C, \
|
||||||
|
MyGame.Example.TestEnum.TestEnum.B]]
|
||||||
|
|
||||||
|
arrayOffset = MyGame.Example.ArrayStruct.CreateArrayStruct(builder, \
|
||||||
|
a, b, c, d_a, d_b, d_c)
|
||||||
|
|
||||||
|
# Create a table with the ArrayStruct.
|
||||||
|
MyGame.Example.ArrayTable.ArrayTableStart(builder)
|
||||||
|
MyGame.Example.ArrayTable.ArrayTableAddA(builder, arrayOffset)
|
||||||
|
tableOffset = MyGame.Example.ArrayTable.ArrayTableEnd(builder)
|
||||||
|
|
||||||
|
builder.Finish(tableOffset)
|
||||||
|
|
||||||
|
buf = builder.Output()
|
||||||
|
|
||||||
|
table = MyGame.Example.ArrayTable.ArrayTable.GetRootAsArrayTable(buf, 0)
|
||||||
|
|
||||||
|
# Verify structure.
|
||||||
|
nested = MyGame.Example.NestedStruct.NestedStruct()
|
||||||
|
self.assertEqual(table.A().A(), 0.5)
|
||||||
|
self.assertEqual(table.A().B(), \
|
||||||
|
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
|
||||||
|
self.assertEqual(table.A().C(), 1)
|
||||||
|
self.assertEqual(table.A().D(nested, 0).A(), [1, 2])
|
||||||
|
self.assertEqual(table.A().D(nested, 1).A(), [3, 4])
|
||||||
|
self.assertEqual(table.A().D(nested, 0).B(), \
|
||||||
|
MyGame.Example.TestEnum.TestEnum.B)
|
||||||
|
self.assertEqual(table.A().D(nested, 1).B(), \
|
||||||
|
MyGame.Example.TestEnum.TestEnum.C)
|
||||||
|
self.assertEqual(table.A().D(nested, 0).C(), \
|
||||||
|
[MyGame.Example.TestEnum.TestEnum.A, \
|
||||||
|
MyGame.Example.TestEnum.TestEnum.B])
|
||||||
|
self.assertEqual(table.A().D(nested, 1).C(), \
|
||||||
|
[MyGame.Example.TestEnum.TestEnum.C, \
|
||||||
|
MyGame.Example.TestEnum.TestEnum.B])
|
||||||
|
|
||||||
|
|
||||||
def CheckAgainstGoldDataGo():
|
def CheckAgainstGoldDataGo():
|
||||||
try:
|
try:
|
||||||
gen_buf, gen_off = make_monster_from_generated_code()
|
gen_buf, gen_off = make_monster_from_generated_code()
|
||||||
|
|||||||
151
tests/test.cpp
151
tests/test.cpp
@@ -34,6 +34,9 @@
|
|||||||
#include "namespace_test/namespace_test2_generated.h"
|
#include "namespace_test/namespace_test2_generated.h"
|
||||||
#include "union_vector/union_vector_generated.h"
|
#include "union_vector/union_vector_generated.h"
|
||||||
#include "monster_extra_generated.h"
|
#include "monster_extra_generated.h"
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
# include "arrays_test_generated.h"
|
||||||
|
#endif
|
||||||
#include "test_assert.h"
|
#include "test_assert.h"
|
||||||
|
|
||||||
#include "flatbuffers/flexbuffers.h"
|
#include "flatbuffers/flexbuffers.h"
|
||||||
@@ -1203,6 +1206,15 @@ void FuzzTest2() {
|
|||||||
AddToSchemaAndInstances(
|
AddToSchemaAndInstances(
|
||||||
"bool", deprecated ? "" : (lcg_rand() % 2 ? "true" : "false"));
|
"bool", deprecated ? "" : (lcg_rand() % 2 ? "true" : "false"));
|
||||||
break;
|
break;
|
||||||
|
case flatbuffers::BASE_TYPE_ARRAY:
|
||||||
|
if (!is_struct) {
|
||||||
|
AddToSchemaAndInstances(
|
||||||
|
"ubyte",
|
||||||
|
deprecated ? "" : "255"); // No fixed-length arrays in tables.
|
||||||
|
} else {
|
||||||
|
AddToSchemaAndInstances("[int:3]", deprecated ? "" : "[\n,\n,\n]");
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
// All the scalar types.
|
// All the scalar types.
|
||||||
schema += flatbuffers::kTypeNames[base_type];
|
schema += flatbuffers::kTypeNames[base_type];
|
||||||
@@ -2671,6 +2683,142 @@ void CreateSharedStringTest() {
|
|||||||
TEST_EQ((*a[6]) < (*a[5]), true);
|
TEST_EQ((*a[6]) < (*a[5]), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FixedLengthArrayTest() {
|
||||||
|
// VS10 does not support typed enums, exclude from tests
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
// Generate an ArrayTable containing one ArrayStruct.
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
MyGame::Example::NestedStruct nStruct0(MyGame::Example::TestEnum::B);
|
||||||
|
TEST_NOTNULL(nStruct0.mutable_a());
|
||||||
|
nStruct0.mutable_a()->Mutate(0, 1);
|
||||||
|
nStruct0.mutable_a()->Mutate(1, 2);
|
||||||
|
TEST_NOTNULL(nStruct0.mutable_c());
|
||||||
|
nStruct0.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
|
||||||
|
nStruct0.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
|
||||||
|
MyGame::Example::NestedStruct nStruct1(MyGame::Example::TestEnum::C);
|
||||||
|
TEST_NOTNULL(nStruct1.mutable_a());
|
||||||
|
nStruct1.mutable_a()->Mutate(0, 3);
|
||||||
|
nStruct1.mutable_a()->Mutate(1, 4);
|
||||||
|
TEST_NOTNULL(nStruct1.mutable_c());
|
||||||
|
nStruct1.mutable_c()->Mutate(0, MyGame::Example::TestEnum::C);
|
||||||
|
nStruct1.mutable_c()->Mutate(1, MyGame::Example::TestEnum::A);
|
||||||
|
MyGame::Example::ArrayStruct aStruct(2, 12);
|
||||||
|
TEST_NOTNULL(aStruct.b());
|
||||||
|
TEST_NOTNULL(aStruct.mutable_b());
|
||||||
|
TEST_NOTNULL(aStruct.mutable_d());
|
||||||
|
for (int i = 0; i < aStruct.b()->size(); i++)
|
||||||
|
aStruct.mutable_b()->Mutate(i, i + 1);
|
||||||
|
aStruct.mutable_d()->Mutate(0, nStruct0);
|
||||||
|
aStruct.mutable_d()->Mutate(1, nStruct1);
|
||||||
|
auto aTable = MyGame::Example::CreateArrayTable(fbb, &aStruct);
|
||||||
|
fbb.Finish(aTable);
|
||||||
|
|
||||||
|
// Verify correctness of the ArrayTable.
|
||||||
|
flatbuffers::Verifier verifier(fbb.GetBufferPointer(), fbb.GetSize());
|
||||||
|
MyGame::Example::VerifyArrayTableBuffer(verifier);
|
||||||
|
auto p = MyGame::Example::GetMutableArrayTable(fbb.GetBufferPointer());
|
||||||
|
auto mArStruct = p->mutable_a();
|
||||||
|
TEST_NOTNULL(mArStruct);
|
||||||
|
TEST_NOTNULL(mArStruct->b());
|
||||||
|
TEST_NOTNULL(mArStruct->d());
|
||||||
|
TEST_NOTNULL(mArStruct->mutable_b());
|
||||||
|
TEST_NOTNULL(mArStruct->mutable_d());
|
||||||
|
mArStruct->mutable_b()->Mutate(14, -14);
|
||||||
|
TEST_EQ(mArStruct->a(), 2);
|
||||||
|
TEST_EQ(mArStruct->b()->size(), 15);
|
||||||
|
TEST_EQ(mArStruct->b()->Get(aStruct.b()->size() - 1), -14);
|
||||||
|
TEST_EQ(mArStruct->c(), 12);
|
||||||
|
TEST_NOTNULL(mArStruct->d()->Get(0).a());
|
||||||
|
TEST_EQ(mArStruct->d()->Get(0).a()->Get(0), 1);
|
||||||
|
TEST_EQ(mArStruct->d()->Get(0).a()->Get(1), 2);
|
||||||
|
TEST_NOTNULL(mArStruct->d()->Get(1).a());
|
||||||
|
TEST_EQ(mArStruct->d()->Get(1).a()->Get(0), 3);
|
||||||
|
TEST_EQ(mArStruct->d()->Get(1).a()->Get(1), 4);
|
||||||
|
TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1));
|
||||||
|
TEST_NOTNULL(mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a());
|
||||||
|
mArStruct->mutable_d()->GetMutablePointer(1)->mutable_a()->Mutate(1, 5);
|
||||||
|
TEST_EQ(mArStruct->d()->Get(1).a()->Get(1), 5);
|
||||||
|
TEST_EQ(mArStruct->d()->Get(0).b() == MyGame::Example::TestEnum::B, true);
|
||||||
|
TEST_NOTNULL(mArStruct->d()->Get(0).c());
|
||||||
|
TEST_EQ(mArStruct->d()->Get(0).c()->Get(0) == MyGame::Example::TestEnum::C,
|
||||||
|
true);
|
||||||
|
TEST_EQ(mArStruct->d()->Get(0).c()->Get(1) == MyGame::Example::TestEnum::A,
|
||||||
|
true);
|
||||||
|
TEST_EQ(mArStruct->d()->Get(1).b() == MyGame::Example::TestEnum::C, true);
|
||||||
|
TEST_NOTNULL(mArStruct->d()->Get(1).c());
|
||||||
|
TEST_EQ(mArStruct->d()->Get(1).c()->Get(0) == MyGame::Example::TestEnum::C,
|
||||||
|
true);
|
||||||
|
TEST_EQ(mArStruct->d()->Get(1).c()->Get(1) == MyGame::Example::TestEnum::A,
|
||||||
|
true);
|
||||||
|
for (int i = 0; i < mArStruct->b()->size() - 1; i++)
|
||||||
|
TEST_EQ(mArStruct->b()->Get(i), i + 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedLengthArrayJsonTest(bool binary) {
|
||||||
|
// VS10 does not support typed enums, exclude from tests
|
||||||
|
#if !defined(_MSC_VER) || _MSC_VER >= 1700
|
||||||
|
// load FlatBuffer schema (.fbs) and JSON from disk
|
||||||
|
std::string schemafile;
|
||||||
|
std::string jsonfile;
|
||||||
|
TEST_EQ(
|
||||||
|
flatbuffers::LoadFile(
|
||||||
|
(test_data_path + "arrays_test." + (binary ? "bfbs" : "fbs")).c_str(),
|
||||||
|
binary, &schemafile),
|
||||||
|
true);
|
||||||
|
TEST_EQ(flatbuffers::LoadFile((test_data_path + "arrays_test.golden").c_str(),
|
||||||
|
false, &jsonfile),
|
||||||
|
true);
|
||||||
|
|
||||||
|
// parse schema first, so we can use it to parse the data after
|
||||||
|
flatbuffers::Parser parserOrg, parserGen;
|
||||||
|
if (binary) {
|
||||||
|
flatbuffers::Verifier verifier(
|
||||||
|
reinterpret_cast<const uint8_t *>(schemafile.c_str()),
|
||||||
|
schemafile.size());
|
||||||
|
TEST_EQ(reflection::VerifySchemaBuffer(verifier), true);
|
||||||
|
TEST_EQ(parserOrg.Deserialize((const uint8_t *)schemafile.c_str(),
|
||||||
|
schemafile.size()),
|
||||||
|
true);
|
||||||
|
TEST_EQ(parserGen.Deserialize((const uint8_t *)schemafile.c_str(),
|
||||||
|
schemafile.size()),
|
||||||
|
true);
|
||||||
|
} else {
|
||||||
|
TEST_EQ(parserOrg.Parse(schemafile.c_str()), true);
|
||||||
|
TEST_EQ(parserGen.Parse(schemafile.c_str()), true);
|
||||||
|
}
|
||||||
|
TEST_EQ(parserOrg.Parse(jsonfile.c_str()), true);
|
||||||
|
|
||||||
|
// First, verify it, just in case:
|
||||||
|
flatbuffers::Verifier verifierOrg(parserOrg.builder_.GetBufferPointer(),
|
||||||
|
parserOrg.builder_.GetSize());
|
||||||
|
TEST_EQ(VerifyArrayTableBuffer(verifierOrg), true);
|
||||||
|
|
||||||
|
// Export to JSON
|
||||||
|
std::string jsonGen;
|
||||||
|
TEST_EQ(
|
||||||
|
GenerateText(parserOrg, parserOrg.builder_.GetBufferPointer(), &jsonGen),
|
||||||
|
true);
|
||||||
|
|
||||||
|
// Import from JSON
|
||||||
|
TEST_EQ(parserGen.Parse(jsonGen.c_str()), true);
|
||||||
|
|
||||||
|
// Verify buffer from generated JSON
|
||||||
|
flatbuffers::Verifier verifierGen(parserGen.builder_.GetBufferPointer(),
|
||||||
|
parserGen.builder_.GetSize());
|
||||||
|
TEST_EQ(VerifyArrayTableBuffer(verifierGen), true);
|
||||||
|
|
||||||
|
// Compare generated buffer to original
|
||||||
|
TEST_EQ(parserOrg.builder_.GetSize(), parserGen.builder_.GetSize());
|
||||||
|
TEST_EQ(std::memcmp(parserOrg.builder_.GetBufferPointer(),
|
||||||
|
parserGen.builder_.GetBufferPointer(),
|
||||||
|
parserOrg.builder_.GetSize()),
|
||||||
|
0);
|
||||||
|
#else
|
||||||
|
(void)binary;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int FlatBufferTests() {
|
int FlatBufferTests() {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
@@ -2705,6 +2853,8 @@ int FlatBufferTests() {
|
|||||||
#endif
|
#endif
|
||||||
ParseAndGenerateTextTest(false);
|
ParseAndGenerateTextTest(false);
|
||||||
ParseAndGenerateTextTest(true);
|
ParseAndGenerateTextTest(true);
|
||||||
|
FixedLengthArrayJsonTest(false);
|
||||||
|
FixedLengthArrayJsonTest(true);
|
||||||
ReflectionTest(flatbuf.data(), flatbuf.size());
|
ReflectionTest(flatbuf.data(), flatbuf.size());
|
||||||
ParseProtoTest();
|
ParseProtoTest();
|
||||||
UnionVectorTest();
|
UnionVectorTest();
|
||||||
@@ -2747,6 +2897,7 @@ int FlatBufferTests() {
|
|||||||
ValidFloatTest();
|
ValidFloatTest();
|
||||||
InvalidFloatTest();
|
InvalidFloatTest();
|
||||||
TestMonsterExtraFloats();
|
TestMonsterExtraFloats();
|
||||||
|
FixedLengthArrayTest();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user