mirror of
https://github.com/google/flatbuffers.git
synced 2025-04-08 09:12:14 +08:00
Add support for fixed-size arrays (#5313)
This commit is contained in:
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.
|
||||
git checkout HEAD -- monster_test.bfbs
|
||||
git checkout HEAD -- arrays_test.bfbs
|
||||
|
||||
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
|
||||
goto SUCCESS
|
||||
|
@ -21,6 +21,7 @@ cd ..
|
||||
|
||||
# TODO: Linux and macos builds produce differences here for some reason.
|
||||
git checkout HEAD -- tests/monster_test.bfbs
|
||||
git checkout HEAD -- tests/arrays_test.bfbs
|
||||
|
||||
if ! git diff --quiet; then
|
||||
echo >&2
|
||||
|
17
BUILD
17
BUILD
@ -164,11 +164,15 @@ cc_test(
|
||||
":tests/union_vector/union_vector.json",
|
||||
":tests/monster_extra.fbs",
|
||||
":tests/monsterdata_extra.json",
|
||||
":tests/arrays_test.bfbs",
|
||||
":tests/arrays_test.fbs",
|
||||
":tests/arrays_test.golden",
|
||||
],
|
||||
includes = ["include/"],
|
||||
deps = [
|
||||
":monster_extra_cc_fbs",
|
||||
":monster_test_cc_fbs",
|
||||
":arrays_test_cc_fbs",
|
||||
],
|
||||
)
|
||||
|
||||
@ -188,3 +192,16 @@ flatbuffer_cc_library(
|
||||
name = "monster_extra_cc_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
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${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
|
||||
@ -303,7 +305,7 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||
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)
|
||||
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
|
||||
add_custom_command(
|
||||
@ -311,12 +313,16 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||
--gen-object-api --gen-compare -o "${SRC_FBS_DIR}"
|
||||
--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"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
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)
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
||||
@ -329,6 +335,7 @@ endfunction()
|
||||
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
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)
|
||||
add_executable(flattests ${FlatBuffers_Tests_SRCS})
|
||||
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
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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
|
||||
// return true if the first is less than the second.
|
||||
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(STRUCT, "", 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:
|
||||
// - enum
|
||||
// - FlatBuffers schema type.
|
||||
@ -91,7 +92,8 @@ switch (type) {
|
||||
|
||||
#define FLATBUFFERS_GEN_TYPES(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.
|
||||
#ifdef __GNUC__
|
||||
@ -145,18 +147,21 @@ class Parser;
|
||||
// and additional information for vectors/structs_.
|
||||
struct Type {
|
||||
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),
|
||||
element(BASE_TYPE_NONE),
|
||||
struct_def(_sd),
|
||||
enum_def(_ed) {}
|
||||
enum_def(_ed),
|
||||
fixed_length(_fixed_length) {}
|
||||
|
||||
bool operator==(const Type &o) {
|
||||
return base_type == o.base_type && element == o.element &&
|
||||
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;
|
||||
|
||||
@ -167,6 +172,7 @@ struct Type {
|
||||
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
||||
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
|
||||
// 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.
|
||||
@ -335,12 +341,34 @@ inline bool IsStruct(const Type &type) {
|
||||
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) {
|
||||
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) {
|
||||
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;
|
||||
@ -799,10 +827,13 @@ class Parser : public ParserState {
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
||||
std::string *value, uoffset_t *ovalue);
|
||||
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
||||
void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
|
||||
const Value &val);
|
||||
template<typename F>
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
|
||||
FieldDef *field, size_t fieldn);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||
size_t fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
@ -849,6 +880,7 @@ class Parser : public ParserState {
|
||||
BaseType baseType);
|
||||
|
||||
bool SupportsAdvancedUnionFeatures() const;
|
||||
bool SupportsAdvancedArrayFeatures() const;
|
||||
Namespace *UniqueNamespace(Namespace *ns);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR RecurseError();
|
||||
|
@ -43,10 +43,11 @@ enum BaseType {
|
||||
String = 13,
|
||||
Vector = 14,
|
||||
Obj = 15,
|
||||
Union = 16
|
||||
Union = 16,
|
||||
Array = 17
|
||||
};
|
||||
|
||||
inline const BaseType (&EnumValuesBaseType())[17] {
|
||||
inline const BaseType (&EnumValuesBaseType())[18] {
|
||||
static const BaseType values[] = {
|
||||
None,
|
||||
UType,
|
||||
@ -64,13 +65,14 @@ inline const BaseType (&EnumValuesBaseType())[17] {
|
||||
String,
|
||||
Vector,
|
||||
Obj,
|
||||
Union
|
||||
Union,
|
||||
Array
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char * const *EnumNamesBaseType() {
|
||||
static const char * const names[18] = {
|
||||
static const char * const names[19] = {
|
||||
"None",
|
||||
"UType",
|
||||
"Bool",
|
||||
@ -88,13 +90,14 @@ inline const char * const *EnumNamesBaseType() {
|
||||
"Vector",
|
||||
"Obj",
|
||||
"Union",
|
||||
"Array",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
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);
|
||||
return EnumNamesBaseType()[index];
|
||||
}
|
||||
@ -103,7 +106,8 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_BASE_TYPE = 4,
|
||||
VT_ELEMENT = 6,
|
||||
VT_INDEX = 8
|
||||
VT_INDEX = 8,
|
||||
VT_FIXED_LENGTH = 10
|
||||
};
|
||||
reflection::BaseType base_type() const {
|
||||
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 {
|
||||
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 {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
|
||||
VerifyField<int8_t>(verifier, VT_ELEMENT) &&
|
||||
VerifyField<int32_t>(verifier, VT_INDEX) &&
|
||||
VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
@ -135,6 +143,9 @@ struct TypeBuilder {
|
||||
void add_index(int32_t index) {
|
||||
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)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
@ -151,9 +162,11 @@ inline flatbuffers::Offset<Type> CreateType(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
reflection::BaseType base_type = reflection::None,
|
||||
reflection::BaseType element = reflection::None,
|
||||
int32_t index = -1) {
|
||||
int32_t index = -1,
|
||||
uint16_t fixed_length = 0) {
|
||||
TypeBuilder builder_(_fbb);
|
||||
builder_.add_index(index);
|
||||
builder_.add_fixed_length(fixed_length);
|
||||
builder_.add_element(element);
|
||||
builder_.add_base_type(base_type);
|
||||
return builder_.Finish();
|
||||
|
@ -23,15 +23,18 @@ enum BaseType : byte {
|
||||
String,
|
||||
Vector,
|
||||
Obj, // Used for tables & structs.
|
||||
Union
|
||||
Union,
|
||||
Array
|
||||
}
|
||||
|
||||
table Type {
|
||||
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.
|
||||
// If base_type == Union, UnionType, or integral derived
|
||||
// from an enum, index into "enums" below.
|
||||
fixed_length:uint16 = 0; // Only if base_type == Array.
|
||||
}
|
||||
|
||||
table KeyValue {
|
||||
|
@ -697,6 +697,13 @@ class CppGenerator : public BaseGenerator {
|
||||
bool user_facing_type) {
|
||||
if (IsScalar(type.base_type)) {
|
||||
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 {
|
||||
return beforeptr + GenTypePointer(type) + afterptr;
|
||||
}
|
||||
@ -2689,7 +2696,8 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
static void PaddingInitializer(int bits, std::string *code_ptr, int *id) {
|
||||
(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) {
|
||||
@ -2717,10 +2725,14 @@ class CppGenerator : public BaseGenerator {
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto &field = **it;
|
||||
code_.SetValue("FIELD_TYPE",
|
||||
GenTypeGet(field.value.type, " ", "", " ", false));
|
||||
const auto &field_type = field.value.type;
|
||||
code_.SetValue("FIELD_TYPE", GenTypeGet(field_type, " ", "", " ", false));
|
||||
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) {
|
||||
std::string padding;
|
||||
@ -2745,33 +2757,40 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
// Generate a default constructor.
|
||||
code_ += " {{STRUCT_NAME}}() {";
|
||||
code_ += " memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));";
|
||||
code_ +=
|
||||
" memset(static_cast<void *>(this), 0, sizeof({{STRUCT_NAME}}));";
|
||||
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 init_list;
|
||||
padding_id = 0;
|
||||
auto first = struct_def.fields.vec.begin();
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto &field = **it;
|
||||
if (IsArray(field.value.type)) {
|
||||
first++;
|
||||
continue;
|
||||
}
|
||||
const auto member_name = Name(field) + "_";
|
||||
const auto arg_name = "_" + Name(field);
|
||||
const auto arg_type =
|
||||
GenTypeGet(field.value.type, " ", "const ", " &", true);
|
||||
|
||||
if (it != struct_def.fields.vec.begin()) {
|
||||
arg_list += ", ";
|
||||
init_list += ",\n ";
|
||||
}
|
||||
if (it != first) { arg_list += ", "; }
|
||||
arg_list += arg_type;
|
||||
arg_list += arg_name;
|
||||
init_list += member_name;
|
||||
if (IsScalar(field.value.type.base_type)) {
|
||||
auto type = GenUnderlyingCast(field, false, arg_name);
|
||||
init_list += "(flatbuffers::EndianScalar(" + type + "))";
|
||||
} else {
|
||||
init_list += "(" + arg_name + ")";
|
||||
if (!IsArray(field.value.type)) {
|
||||
if (it != first && init_list != "") { init_list += ",\n "; }
|
||||
init_list += member_name;
|
||||
if (IsScalar(field.value.type.base_type)) {
|
||||
auto type = GenUnderlyingCast(field, false, arg_name);
|
||||
init_list += "(flatbuffers::EndianScalar(" + type + "))";
|
||||
} else {
|
||||
init_list += "(" + arg_name + ")";
|
||||
}
|
||||
}
|
||||
if (field.padding) {
|
||||
GenPadding(field, &init_list, &padding_id, PaddingInitializer);
|
||||
@ -2781,12 +2800,21 @@ class CppGenerator : public BaseGenerator {
|
||||
if (!arg_list.empty()) {
|
||||
code_.SetValue("ARG_LIST", arg_list);
|
||||
code_.SetValue("INIT_LIST", init_list);
|
||||
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
|
||||
code_ += " : {{INIT_LIST}} {";
|
||||
if (!init_list.empty()) {
|
||||
code_ += " {{STRUCT_NAME}}({{ARG_LIST}})";
|
||||
code_ += " : {{INIT_LIST}} {";
|
||||
} else {
|
||||
code_ += " {{STRUCT_NAME}}({{ARG_LIST}}) {";
|
||||
}
|
||||
padding_id = 0;
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++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) {
|
||||
std::string padding;
|
||||
GenPadding(field, &padding, &padding_id, PaddingNoop);
|
||||
@ -2802,7 +2830,9 @@ class CppGenerator : public BaseGenerator {
|
||||
it != struct_def.fields.vec.end(); ++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 member = Name(field) + "_";
|
||||
auto value =
|
||||
@ -2813,12 +2843,29 @@ class CppGenerator : public BaseGenerator {
|
||||
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
|
||||
|
||||
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) {
|
||||
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);
|
||||
if (is_scalar) {
|
||||
code_.SetValue("ARG", GenTypeBasic(field.value.type, true));
|
||||
@ -2830,9 +2877,19 @@ class CppGenerator : public BaseGenerator {
|
||||
" flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "
|
||||
"{{FIELD_VALUE}});";
|
||||
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 {
|
||||
code_ += " {{FIELD_TYPE}}mutable_{{FIELD_NAME}}() {";
|
||||
code_ += " return {{FIELD_NAME}}_;";
|
||||
code_ += " return {{FIELD_VALUE}};";
|
||||
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 {
|
||||
// clang-format off
|
||||
static const char * const java_typename[] = {
|
||||
@ -312,7 +308,10 @@ class GeneralGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
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.
|
||||
@ -325,6 +324,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
case BASE_TYPE_UCHAR: 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_ARRAY:
|
||||
case BASE_TYPE_VECTOR:
|
||||
if (vectorelem) return DestinationType(type.VectorType(), vectorelem);
|
||||
FLATBUFFERS_FALLTHROUGH(); // else fall thru
|
||||
@ -378,7 +378,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
|
||||
// Casts necessary to correctly read serialized data
|
||||
std::string DestinationCast(const Type &type) const {
|
||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
||||
if (IsSeries(type)) {
|
||||
return DestinationCast(type.VectorType());
|
||||
} else {
|
||||
switch (lang_.language) {
|
||||
@ -405,7 +405,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
// directly cast an Enum to its underlying type, which is essential before
|
||||
// putting it onto the buffer.
|
||||
std::string SourceCast(const Type &type, bool castFromDest) const {
|
||||
if (type.base_type == BASE_TYPE_VECTOR) {
|
||||
if (IsSeries(type)) {
|
||||
return SourceCast(type.VectorType(), castFromDest);
|
||||
} else {
|
||||
switch (lang_.language) {
|
||||
@ -602,6 +602,7 @@ class GeneralGenerator : public BaseGenerator {
|
||||
case BASE_TYPE_STRUCT: return lang_.accessor_prefix + "__struct";
|
||||
case BASE_TYPE_UNION: return lang_.accessor_prefix + "__union";
|
||||
case BASE_TYPE_VECTOR: return GenGetter(type.VectorType());
|
||||
case BASE_TYPE_ARRAY: return GenGetter(type.VectorType());
|
||||
default: {
|
||||
std::string getter =
|
||||
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
|
||||
// structs.
|
||||
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;
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++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
|
||||
// don't clash, and to make it obvious these arguments are constructing
|
||||
// a nested struct, prefix the name with the field name.
|
||||
GenStructArgs(*field.value.type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str());
|
||||
GenStructArgs(*field_type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str(), array_cnt);
|
||||
} else {
|
||||
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 += nameprefix;
|
||||
code += MakeCamel(field.name, lang_.first_camel_upper);
|
||||
@ -681,29 +698,67 @@ class GeneralGenerator : public BaseGenerator {
|
||||
// builder.putType(name);
|
||||
// and insert manual padding.
|
||||
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;
|
||||
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.bytesize) + ");\n";
|
||||
for (auto it = struct_def.fields.vec.rbegin();
|
||||
it != struct_def.fields.vec.rend(); ++it) {
|
||||
auto &field = **it;
|
||||
const auto &field_type = field.value.type;
|
||||
if (field.padding) {
|
||||
code += " builder." + FunctionStart('P') + "ad(";
|
||||
code += indent + " builder." + FunctionStart('P') + "ad(";
|
||||
code += NumToString(field.padding) + ");\n";
|
||||
}
|
||||
if (IsStruct(field.value.type)) {
|
||||
GenStructBody(*field.value.type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str());
|
||||
if (IsStruct(field_type)) {
|
||||
GenStructBody(*field_type.struct_def, code_ptr,
|
||||
(nameprefix + (field.name + "_")).c_str(), index,
|
||||
in_array);
|
||||
} else {
|
||||
code += " builder." + FunctionStart('P') + "ut";
|
||||
code += GenMethod(field.value.type) + "(";
|
||||
code += SourceCast(field.value.type);
|
||||
auto argname =
|
||||
nameprefix + MakeCamel(field.name, lang_.first_camel_upper);
|
||||
code += argname;
|
||||
code += ");\n";
|
||||
const auto &type =
|
||||
IsArray(field_type) ? field_type.VectorType() : field_type;
|
||||
const auto index_var = "_idx" + NumToString(index);
|
||||
if (IsArray(field_type)) {
|
||||
code += indent + " for (int " + index_var + " = ";
|
||||
code += NumToString(field_type.fixed_length);
|
||||
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,
|
||||
// this is the prefix code for that:
|
||||
auto offset_prefix = " { int o = " + lang_.accessor_prefix + "__offset(" +
|
||||
NumToString(field.value.offset) +
|
||||
"); return o != 0 ? ";
|
||||
auto offset_prefix =
|
||||
IsArray(field.value.type)
|
||||
? " { return "
|
||||
: (" { int o = " + lang_.accessor_prefix + "__offset(" +
|
||||
NumToString(field.value.offset) + "); return o != 0 ? ");
|
||||
// Generate the accessors that don't do object reuse.
|
||||
if (field.value.type.base_type == BASE_TYPE_STRUCT) {
|
||||
// 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 += "bb_pos) : null";
|
||||
break;
|
||||
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case BASE_TYPE_VECTOR: {
|
||||
auto vectortype = field.value.type.VectorType();
|
||||
if (vectortype.base_type == BASE_TYPE_UNION &&
|
||||
@ -1043,8 +1101,13 @@ class GeneralGenerator : public BaseGenerator {
|
||||
} else {
|
||||
code += body;
|
||||
}
|
||||
auto index = lang_.accessor_prefix + "__vector(o) + j * " +
|
||||
NumToString(InlineSize(vectortype));
|
||||
auto index = lang_.accessor_prefix;
|
||||
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) {
|
||||
code += vectortype.struct_def->fixed
|
||||
? index
|
||||
@ -1055,13 +1118,16 @@ class GeneralGenerator : public BaseGenerator {
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
@ -1215,9 +1281,9 @@ class GeneralGenerator : public BaseGenerator {
|
||||
}
|
||||
// Generate mutators for scalar fields or vectors of scalars.
|
||||
if (parser_.opts.mutable_buffer) {
|
||||
auto underlying_type = field.value.type.base_type == BASE_TYPE_VECTOR
|
||||
? field.value.type.VectorType()
|
||||
: field.value.type;
|
||||
auto is_series = (IsSeries(field.value.type));
|
||||
const auto &underlying_type =
|
||||
is_series ? field.value.type.VectorType() : field.value.type;
|
||||
// Boolean parameters have to be explicitly converted to byte
|
||||
// representation.
|
||||
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);
|
||||
// A vector mutator also needs the index of the vector element it should
|
||||
// mutate.
|
||||
auto mutator_params =
|
||||
(field.value.type.base_type == BASE_TYPE_VECTOR ? "(int j, "
|
||||
: "(") +
|
||||
GenTypeNameDest(underlying_type) + " " + field.name + ") { ";
|
||||
auto mutator_params = (is_series ? "(int j, " : "(") +
|
||||
GenTypeNameDest(underlying_type) + " " +
|
||||
field.name + ") { ";
|
||||
auto setter_index =
|
||||
field.value.type.base_type == BASE_TYPE_VECTOR
|
||||
? lang_.accessor_prefix + "__vector(o) + j * " +
|
||||
NumToString(InlineSize(underlying_type))
|
||||
is_series
|
||||
? lang_.accessor_prefix +
|
||||
(IsArray(field.value.type)
|
||||
? "bb_pos + " + NumToString(field.value.offset)
|
||||
: "__vector(o)") +
|
||||
+" + j * " + NumToString(InlineSize(underlying_type))
|
||||
: (struct_def.fixed
|
||||
? lang_.accessor_prefix + "bb_pos + " +
|
||||
NumToString(field.value.offset)
|
||||
: "o + " + lang_.accessor_prefix + "bb_pos");
|
||||
if (IsScalar(field.value.type.base_type) ||
|
||||
(field.value.type.base_type == BASE_TYPE_VECTOR &&
|
||||
IsScalar(field.value.type.VectorType().base_type))) {
|
||||
if (IsScalar(underlying_type.base_type)) {
|
||||
code += " public ";
|
||||
code += struct_def.fixed ? "void " : lang_.bool_type;
|
||||
code += mutator_prefix + MakeCamel(field.name, true);
|
||||
|
@ -42,6 +42,7 @@ std::string GenNativeType(BaseType type) {
|
||||
case BASE_TYPE_FLOAT:
|
||||
case BASE_TYPE_DOUBLE: return "number";
|
||||
case BASE_TYPE_STRING: return "string";
|
||||
case BASE_TYPE_ARRAY: return "array";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
@ -70,6 +71,7 @@ std::string GenType(const Type &type) {
|
||||
return GenTypeRef(type.enum_def);
|
||||
}
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case BASE_TYPE_VECTOR: {
|
||||
std::string typeline;
|
||||
typeline.append("\"type\" : \"array\", \"items\" : { ");
|
||||
@ -156,8 +158,16 @@ class JsonSchemaGenerator : public BaseGenerator {
|
||||
const auto &properties = structure->fields.vec;
|
||||
for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
|
||||
const auto &property = *prop;
|
||||
std::string typeLine(" \"" + property->name + "\" : { " +
|
||||
GenType(property->value.type) + " }");
|
||||
std::string arrayInfo = "";
|
||||
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(","); }
|
||||
code_ += typeLine;
|
||||
}
|
||||
|
@ -224,6 +224,30 @@ class PythonGenerator : public BaseGenerator {
|
||||
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.
|
||||
// Specific to Table.
|
||||
void GetStructFieldOfTable(const StructDef &struct_def,
|
||||
@ -380,12 +404,16 @@ class PythonGenerator : public BaseGenerator {
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++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
|
||||
// don't clash, and to make it obvious these arguments are constructing
|
||||
// a nested struct, prefix the name with the field name.
|
||||
StructBuilderArgs(*field.value.type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
|
||||
StructBuilderArgs(*field_type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(),
|
||||
code_ptr);
|
||||
} else {
|
||||
std::string &code = *code_ptr;
|
||||
code += std::string(", ") + nameprefix;
|
||||
@ -402,22 +430,50 @@ class PythonGenerator : public BaseGenerator {
|
||||
|
||||
// Recursively generate struct construction statements and instert manual
|
||||
// padding.
|
||||
void StructBuilderBody(const StructDef &struct_def,
|
||||
const char *nameprefix, std::string *code_ptr) {
|
||||
void StructBuilderBody(const StructDef &struct_def, const char *nameprefix,
|
||||
std::string *code_ptr, size_t index = 0,
|
||||
bool in_array = false) {
|
||||
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";
|
||||
for (auto it = struct_def.fields.vec.rbegin();
|
||||
it != struct_def.fields.vec.rend(); ++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)
|
||||
code += " builder.Pad(" + NumToString(field.padding) + ")\n";
|
||||
if (IsStruct(field.value.type)) {
|
||||
StructBuilderBody(*field.value.type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(), code_ptr);
|
||||
code +=
|
||||
indent + " builder.Pad(" + NumToString(field.padding) + ")\n";
|
||||
if (IsStruct(field_type)) {
|
||||
StructBuilderBody(*field_type.struct_def,
|
||||
(nameprefix + (NormalizedName(field) + "_")).c_str(),
|
||||
code_ptr, index, in_array);
|
||||
} else {
|
||||
code += " builder.Prepend" + GenMethod(field) + "(";
|
||||
code += nameprefix + MakeCamel(NormalizedName(field), false) + ")\n";
|
||||
const auto index_var = "_idx" + NumToString(index);
|
||||
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 {
|
||||
GetScalarFieldOfTable(struct_def, field, code_ptr);
|
||||
}
|
||||
} else if (IsArray(field.value.type)) {
|
||||
GetArrayOfStruct(struct_def, field, code_ptr);
|
||||
} else {
|
||||
switch (field.value.type.base_type) {
|
||||
case BASE_TYPE_STRUCT:
|
||||
@ -613,9 +671,9 @@ class PythonGenerator : public BaseGenerator {
|
||||
|
||||
// Returns the method name for use with add/put calls.
|
||||
std::string GenMethod(const FieldDef &field) {
|
||||
return IsScalar(field.value.type.base_type)
|
||||
? MakeCamel(GenTypeBasic(field.value.type))
|
||||
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
|
||||
return (IsScalar(field.value.type.base_type) || IsArray(field.value.type))
|
||||
? MakeCamel(GenTypeBasic(field.value.type))
|
||||
: (IsStruct(field.value.type) ? "Struct" : "UOffsetTRelative");
|
||||
}
|
||||
|
||||
std::string GenTypeBasic(const Type &type) {
|
||||
@ -628,7 +686,8 @@ class PythonGenerator : public BaseGenerator {
|
||||
#undef FLATBUFFERS_TD
|
||||
// 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) {
|
||||
|
@ -69,26 +69,27 @@ bool Print(T val, Type type, int /*indent*/, Type * /*union_type*/,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Print a vector a sequence of JSON values, comma separated, wrapped in "[]".
|
||||
template<typename T>
|
||||
bool PrintVector(const Vector<T> &v, Type type, int indent,
|
||||
const IDLOptions &opts, std::string *_text) {
|
||||
// Print a vector or an array of JSON values, comma seperated, wrapped in "[]".
|
||||
template<typename T, typename Container>
|
||||
bool PrintContainer(const Container &c, size_t size, Type type, int indent,
|
||||
const IDLOptions &opts, std::string *_text) {
|
||||
std::string &text = *_text;
|
||||
text += "[";
|
||||
text += NewLine(opts);
|
||||
for (uoffset_t i = 0; i < v.size(); i++) {
|
||||
for (uoffset_t i = 0; i < size; i++) {
|
||||
if (i) {
|
||||
if (!opts.protobuf_ascii_alike) text += ",";
|
||||
text += NewLine(opts);
|
||||
}
|
||||
text.append(indent + Indent(opts), ' ');
|
||||
if (IsStruct(type)) {
|
||||
if (!Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
|
||||
indent + Indent(opts), nullptr, opts, _text)) {
|
||||
if (!Print(reinterpret_cast<const void *>(c.Data() +
|
||||
i * type.struct_def->bytesize),
|
||||
type, indent + Indent(opts), nullptr, opts, _text)) {
|
||||
return false;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -99,6 +100,20 @@ bool PrintVector(const Vector<T> &v, Type type, int indent,
|
||||
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.
|
||||
template<>
|
||||
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;
|
||||
}
|
||||
case BASE_TYPE_VECTOR:
|
||||
type = type.VectorType();
|
||||
case BASE_TYPE_VECTOR: {
|
||||
const auto vec_type = type.VectorType();
|
||||
// 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, \
|
||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
if (!PrintVector<CTYPE>( \
|
||||
*reinterpret_cast<const Vector<CTYPE> *>(val), \
|
||||
type, indent, opts, _text)) { \
|
||||
vec_type, indent, opts, _text)) { \
|
||||
return false; \
|
||||
} \
|
||||
break;
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
// clang-format on
|
||||
}
|
||||
// clang-format on
|
||||
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);
|
||||
}
|
||||
return true;
|
||||
@ -177,8 +216,8 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
|
||||
std::string *_text) {
|
||||
const void *val = nullptr;
|
||||
if (fixed) {
|
||||
// The only non-scalar fields in structs are structs.
|
||||
FLATBUFFERS_ASSERT(IsStruct(fd.value.type));
|
||||
// The only non-scalar fields in structs are structs or arrays.
|
||||
FLATBUFFERS_ASSERT(IsStruct(fd.value.type) || IsArray(fd.value.type));
|
||||
val = reinterpret_cast<const Struct *>(table)->GetStruct<const void *>(
|
||||
fd.value.offset);
|
||||
} else if (fd.flexbuffer) {
|
||||
@ -241,6 +280,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \
|
||||
case BASE_TYPE_ ## ENUM:
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
||||
FLATBUFFERS_GEN_TYPE_ARRAY(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
|
||||
union_type, opts, _text)) {
|
||||
|
@ -601,12 +601,35 @@ CheckedError Parser::ParseType(Type &type) {
|
||||
NEXT();
|
||||
Type 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
|
||||
// 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;
|
||||
EXPECT(']');
|
||||
} else {
|
||||
@ -651,9 +674,19 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
Type 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");
|
||||
|
||||
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;
|
||||
if (type.base_type == BASE_TYPE_UNION) {
|
||||
// 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) {
|
||||
// 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.
|
||||
// Default value of union and vector in NONE, NULL translated to "0".
|
||||
FLATBUFFERS_ASSERT(IsInteger(type.base_type) ||
|
||||
(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) {
|
||||
// Vector can't use initialization list.
|
||||
FLATBUFFERS_ASSERT(field->value.constant == "0");
|
||||
@ -963,6 +997,10 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
val.constant = NumToString(off);
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_ARRAY: {
|
||||
ECHECK(ParseArray(val));
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_INT:
|
||||
case BASE_TYPE_UINT:
|
||||
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) {
|
||||
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);
|
||||
builder_.Align(struct_def.minalign);
|
||||
builder_.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()),
|
||||
struct_def.bytesize);
|
||||
builder_.AddStructOffset(val.offset, builder_.GetSize());
|
||||
builder.Align(struct_def.minalign);
|
||||
builder.PushBytes(reinterpret_cast<const uint8_t *>(val.constant.c_str()),
|
||||
struct_def.bytesize);
|
||||
builder.AddStructOffset(val.offset, builder.GetSize());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
@ -1161,7 +1204,13 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
|
||||
break;
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(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();
|
||||
}
|
||||
|
||||
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,
|
||||
size_t fieldn,
|
||||
const StructDef *parent_struct_def) {
|
||||
@ -1989,6 +2086,13 @@ bool Parser::SupportsAdvancedUnionFeatures() const {
|
||||
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) {
|
||||
for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) {
|
||||
if (ns->components == (*it)->components) {
|
||||
@ -3171,19 +3275,22 @@ bool EnumVal::Deserialize(const Parser &parser,
|
||||
|
||||
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
||||
return reflection::CreateType(
|
||||
*builder,
|
||||
static_cast<reflection::BaseType>(base_type),
|
||||
*builder, static_cast<reflection::BaseType>(base_type),
|
||||
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) {
|
||||
if (type == nullptr) return true;
|
||||
base_type = static_cast<BaseType>(type->base_type());
|
||||
element = static_cast<BaseType>(type->element());
|
||||
fixed_length = type->fixed_length();
|
||||
if (type->index() >= 0) {
|
||||
bool is_series = type->base_type() == reflection::Vector ||
|
||||
type->base_type() == reflection::Array;
|
||||
if (type->base_type() == reflection::Obj ||
|
||||
(type->base_type() == reflection::Vector &&
|
||||
(is_series &&
|
||||
type->element() == reflection::Obj)) {
|
||||
if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) {
|
||||
struct_def = parser.structs_.vec[type->index()];
|
||||
|
@ -99,6 +99,18 @@
|
||||
<Compile Include="..\MyGame\Example\Ability.cs">
|
||||
<Link>MyGame\Example\Ability.cs</Link>
|
||||
</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">
|
||||
<Link>MyGame\InParentNamespace.cs</Link>
|
||||
</Compile>
|
||||
|
@ -330,5 +330,58 @@ namespace FlatBuffers.Test
|
||||
Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);
|
||||
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();
|
||||
|
||||
TestFixedLengthArrays();
|
||||
|
||||
System.out.println("FlatBuffers test: completed successfully");
|
||||
}
|
||||
|
||||
@ -452,6 +454,58 @@ class JavaTest {
|
||||
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) {
|
||||
if (!a.equals(b)) {
|
||||
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 --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 arrays_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" (
|
||||
@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 --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 arrays_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
|
||||
../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
|
||||
|
@ -24,21 +24,27 @@
|
||||
"MyGame_OtherNameSpace_Unused" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"a" : { "type" : "number" }
|
||||
"a" : {
|
||||
"type" : "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"MyGame_OtherNameSpace_TableB" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"a" : { "$ref" : "#/definitions/TableA" }
|
||||
"a" : {
|
||||
"$ref" : "#/definitions/TableA"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"TableA" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"b" : { "$ref" : "#/definitions/MyGame_OtherNameSpace_TableB" }
|
||||
"b" : {
|
||||
"$ref" : "#/definitions/MyGame_OtherNameSpace_TableB"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
@ -57,51 +63,81 @@
|
||||
"MyGame_Example_Test" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"a" : { "type" : "number" },
|
||||
"b" : { "type" : "number" }
|
||||
"a" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"b" : {
|
||||
"type" : "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"MyGame_Example_TestSimpleTableWithEnum" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"color" : { "$ref" : "#/definitions/MyGame_Example_Color" }
|
||||
"color" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Color"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"MyGame_Example_Vec3" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"x" : { "type" : "number" },
|
||||
"y" : { "type" : "number" },
|
||||
"z" : { "type" : "number" },
|
||||
"test1" : { "type" : "number" },
|
||||
"test2" : { "$ref" : "#/definitions/MyGame_Example_Color" },
|
||||
"test3" : { "$ref" : "#/definitions/MyGame_Example_Test" }
|
||||
"x" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"y" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"z" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"test1" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"test2" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Color"
|
||||
},
|
||||
"test3" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Test"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"MyGame_Example_Ability" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"id" : { "type" : "number" },
|
||||
"distance" : { "type" : "number" }
|
||||
"id" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"distance" : {
|
||||
"type" : "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"MyGame_Example_Stat" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"id" : { "type" : "string" },
|
||||
"val" : { "type" : "number" },
|
||||
"count" : { "type" : "number" }
|
||||
"id" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"val" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"count" : {
|
||||
"type" : "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
"MyGame_Example_Referrable" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"id" : { "type" : "number" }
|
||||
"id" : {
|
||||
"type" : "number"
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
},
|
||||
@ -109,54 +145,150 @@
|
||||
"type" : "object",
|
||||
"description" : " an example documentation comment: monster object",
|
||||
"properties" : {
|
||||
"pos" : { "$ref" : "#/definitions/MyGame_Example_Vec3" },
|
||||
"mana" : { "type" : "number" },
|
||||
"hp" : { "type" : "number" },
|
||||
"name" : { "type" : "string" },
|
||||
"friendly" : { "type" : "boolean" },
|
||||
"inventory" : { "type" : "array", "items" : { "type" : "number" } },
|
||||
"color" : { "$ref" : "#/definitions/MyGame_Example_Color" },
|
||||
"test_type" : { "$ref" : "#/definitions/MyGame_Example_Any" },
|
||||
"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" } },
|
||||
"testarrayofstring" : { "type" : "array", "items" : { "type" : "string" } },
|
||||
"testarrayoftables" : { "type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Monster" } },
|
||||
"enemy" : { "$ref" : "#/definitions/MyGame_Example_Monster" },
|
||||
"testnestedflatbuffer" : { "type" : "array", "items" : { "type" : "number" } },
|
||||
"testempty" : { "$ref" : "#/definitions/MyGame_Example_Stat" },
|
||||
"testbool" : { "type" : "boolean" },
|
||||
"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" }
|
||||
"pos" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Vec3"
|
||||
},
|
||||
"mana" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"hp" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"name" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"friendly" : {
|
||||
"type" : "boolean"
|
||||
},
|
||||
"inventory" : {
|
||||
"type" : "array", "items" : { "type" : "number" }
|
||||
},
|
||||
"color" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Color"
|
||||
},
|
||||
"test_type" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Any"
|
||||
},
|
||||
"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" }
|
||||
},
|
||||
"testarrayofstring" : {
|
||||
"type" : "array", "items" : { "type" : "string" }
|
||||
},
|
||||
"testarrayoftables" : {
|
||||
"type" : "array", "items" : { "$ref" : "#/definitions/MyGame_Example_Monster" }
|
||||
},
|
||||
"enemy" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Monster"
|
||||
},
|
||||
"testnestedflatbuffer" : {
|
||||
"type" : "array", "items" : { "type" : "number" }
|
||||
},
|
||||
"testempty" : {
|
||||
"$ref" : "#/definitions/MyGame_Example_Stat"
|
||||
},
|
||||
"testbool" : {
|
||||
"type" : "boolean"
|
||||
},
|
||||
"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"],
|
||||
"additionalProperties" : false
|
||||
@ -164,18 +296,42 @@
|
||||
"MyGame_Example_TypeAliases" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"i8" : { "type" : "number" },
|
||||
"u8" : { "type" : "number" },
|
||||
"i16" : { "type" : "number" },
|
||||
"u16" : { "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" } }
|
||||
"i8" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"u8" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"i16" : {
|
||||
"type" : "number"
|
||||
},
|
||||
"u16" : {
|
||||
"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
|
||||
}
|
||||
|
@ -42,7 +42,10 @@ import MyGame.Example.Test # refers to generated code
|
||||
import MyGame.Example.Stat # refers to generated code
|
||||
import MyGame.Example.Vec3 # 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):
|
||||
''' Backwards-compatible assertion for exceptions raised. '''
|
||||
@ -1544,6 +1547,55 @@ class TestExceptions(unittest.TestCase):
|
||||
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():
|
||||
try:
|
||||
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 "union_vector/union_vector_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 "flatbuffers/flexbuffers.h"
|
||||
@ -1203,6 +1206,15 @@ void FuzzTest2() {
|
||||
AddToSchemaAndInstances(
|
||||
"bool", deprecated ? "" : (lcg_rand() % 2 ? "true" : "false"));
|
||||
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:
|
||||
// All the scalar types.
|
||||
schema += flatbuffers::kTypeNames[base_type];
|
||||
@ -2671,6 +2683,142 @@ void CreateSharedStringTest() {
|
||||
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() {
|
||||
// clang-format off
|
||||
|
||||
@ -2705,6 +2853,8 @@ int FlatBufferTests() {
|
||||
#endif
|
||||
ParseAndGenerateTextTest(false);
|
||||
ParseAndGenerateTextTest(true);
|
||||
FixedLengthArrayJsonTest(false);
|
||||
FixedLengthArrayJsonTest(true);
|
||||
ReflectionTest(flatbuf.data(), flatbuf.size());
|
||||
ParseProtoTest();
|
||||
UnionVectorTest();
|
||||
@ -2747,6 +2897,7 @@ int FlatBufferTests() {
|
||||
ValidFloatTest();
|
||||
InvalidFloatTest();
|
||||
TestMonsterExtraFloats();
|
||||
FixedLengthArrayTest();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user