mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-09 22:56:27 +00:00
Add support for fixed-size arrays (#5313)
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
0d2cebccfe
commit
e635141d5b
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user