From 72fc45aa6acbc11052c6baa462fac26c5075392a Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 11 Apr 2016 17:36:56 -0700 Subject: [PATCH] Made user-defined attributes available in the reflection data. Tested: on Linux. Bug: 27923233 Change-Id: Ic16675650e4a8e138c163f1e2131a3aad7008ada --- include/flatbuffers/idl.h | 49 +-- include/flatbuffers/reflection_generated.h | 341 ++++++++++++------ reflection/reflection.fbs | 8 + src/idl_parser.cpp | 49 ++- tests/monster_test.bfbs | Bin 2744 -> 2840 bytes .../namespace_test2_generated.h | 10 - tests/test.cpp | 4 + 7 files changed, 305 insertions(+), 156 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index fbc696f55..e671c01e7 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -18,7 +18,6 @@ #define FLATBUFFERS_IDL_H_ #include -#include #include #include #include @@ -113,6 +112,7 @@ inline size_t SizeOf(BaseType t) { struct StructDef; struct EnumDef; +struct Parser; // Represents any type in the IDL, which is a combination of the BaseType // and additional information for vectors/structs_. @@ -184,10 +184,8 @@ template class SymbolTable { return it == dict.end() ? nullptr : it->second; } - private: - std::map dict; // quick lookup - public: + std::map dict; // quick lookup std::vector vec; // Used to iterate in order of insertion }; @@ -208,6 +206,11 @@ struct Definition { Definition() : generated(false), defined_namespace(nullptr), serialized_location(0), index(-1) {} + flatbuffers::Offset>> + SerializeAttributes(FlatBufferBuilder *builder, + const Parser &parser) const; + std::string name; std::string file; std::vector doc_comment; @@ -223,8 +226,8 @@ struct Definition { struct FieldDef : public Definition { FieldDef() : deprecated(false), required(false), key(false), padding(0) {} - Offset Serialize(FlatBufferBuilder *builder, uint16_t id) - const; + Offset Serialize(FlatBufferBuilder *builder, uint16_t id, + const Parser &parser) const; Value value; bool deprecated; // Field is allowed to be present in old data, but can't be @@ -250,7 +253,8 @@ struct StructDef : public Definition { if (fields.vec.size()) fields.vec.back()->padding = padding; } - Offset Serialize(FlatBufferBuilder *builder) const; + Offset Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; SymbolTable fields; bool fixed; // If it's struct, not a table. @@ -299,7 +303,8 @@ struct EnumDef : public Definition { return nullptr; } - Offset Serialize(FlatBufferBuilder *builder) const; + Offset Serialize(FlatBufferBuilder *builder, + const Parser &parser) const; SymbolTable vals; bool is_union; @@ -406,18 +411,18 @@ class Parser { anonymous_counter(0) { // Just in case none are declared: namespaces_.push_back(new Namespace()); - known_attributes_.insert("deprecated"); - known_attributes_.insert("required"); - known_attributes_.insert("key"); - known_attributes_.insert("hash"); - known_attributes_.insert("id"); - known_attributes_.insert("force_align"); - known_attributes_.insert("bit_flags"); - known_attributes_.insert("original_order"); - known_attributes_.insert("nested_flatbuffer"); - known_attributes_.insert("csharp_partial"); - known_attributes_.insert("stream"); - known_attributes_.insert("idempotent"); + known_attributes_["deprecated"] = true; + known_attributes_["required"] = true; + known_attributes_["key"] = true; + known_attributes_["hash"] = true; + known_attributes_["id"] = true; + known_attributes_["force_align"] = true; + known_attributes_["bit_flags"] = true; + known_attributes_["original_order"] = true; + known_attributes_["nested_flatbuffer"] = true; + known_attributes_["csharp_partial"] = true; + known_attributes_["stream"] = true; + known_attributes_["idempotent"] = true; } ~Parser() { @@ -528,6 +533,8 @@ private: std::map included_files_; std::map> files_included_per_file_; + std::map known_attributes_; + IDLOptions opts; private: @@ -541,8 +548,6 @@ private: std::vector> field_stack_; - std::set known_attributes_; - int anonymous_counter; }; diff --git a/include/flatbuffers/reflection_generated.h b/include/flatbuffers/reflection_generated.h index 86023df9d..da1124939 100644 --- a/include/flatbuffers/reflection_generated.h +++ b/include/flatbuffers/reflection_generated.h @@ -5,14 +5,20 @@ #include "flatbuffers/flatbuffers.h" - namespace reflection { struct Type; + +struct KeyValue; + struct EnumVal; + struct Enum; + struct Field; + struct Object; + struct Schema; enum BaseType { @@ -32,7 +38,9 @@ enum BaseType { String = 13, Vector = 14, Obj = 15, - Union = 16 + Union = 16, + MIN = None, + MAX = Union }; inline const char **EnumNamesBaseType() { @@ -40,17 +48,22 @@ inline const char **EnumNamesBaseType() { return names; } -inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[e]; } +inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[static_cast(e)]; } struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - BaseType base_type() const { return static_cast(GetField(4, 0)); } - BaseType element() const { return static_cast(GetField(6, 0)); } - int32_t index() const { return GetField(8, -1); } + enum { + VT_BASE_TYPE = 4, + VT_ELEMENT = 6, + VT_INDEX = 8 + }; + BaseType base_type() const { return static_cast(GetField(VT_BASE_TYPE, 0)); } + BaseType element() const { return static_cast(GetField(VT_ELEMENT, 0)); } + int32_t index() const { return GetField(VT_INDEX, -1); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyField(verifier, 4 /* base_type */) && - VerifyField(verifier, 6 /* element */) && - VerifyField(verifier, 8 /* index */) && + VerifyField(verifier, VT_BASE_TYPE) && + VerifyField(verifier, VT_ELEMENT) && + VerifyField(verifier, VT_INDEX) && verifier.EndTable(); } }; @@ -58,9 +71,9 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct TypeBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_base_type(BaseType base_type) { fbb_.AddElement(4, static_cast(base_type), 0); } - void add_element(BaseType element) { fbb_.AddElement(6, static_cast(element), 0); } - void add_index(int32_t index) { fbb_.AddElement(8, index, -1); } + void add_base_type(BaseType base_type) { fbb_.AddElement(Type::VT_BASE_TYPE, static_cast(base_type), 0); } + void add_element(BaseType element) { fbb_.AddElement(Type::VT_ELEMENT, static_cast(element), 0); } + void add_index(int32_t index) { fbb_.AddElement(Type::VT_INDEX, index, -1); } TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } TypeBuilder &operator=(const TypeBuilder &); flatbuffers::Offset Finish() { @@ -80,18 +93,65 @@ inline flatbuffers::Offset CreateType(flatbuffers::FlatBufferBuilder &_fbb return builder_.Finish(); } -struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const flatbuffers::String *name() const { return GetPointer(4); } - int64_t value() const { return GetField(6, 0); } - bool KeyCompareLessThan(const EnumVal *o) const { return value() < o->value(); } - int KeyCompareWithValue(int64_t val) const { return value() < val ? -1 : value() > val; } - const Object *object() const { return GetPointer(8); } +struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_KEY = 4, + VT_VALUE = 6 + }; + const flatbuffers::String *key() const { return GetPointer(VT_KEY); } + bool KeyCompareLessThan(const KeyValue *o) const { return *key() < *o->key(); } + int KeyCompareWithValue(const char *val) const { return strcmp(key()->c_str(), val); } + const flatbuffers::String *value() const { return GetPointer(VT_VALUE); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyFieldRequired(verifier, 4 /* name */) && + VerifyFieldRequired(verifier, VT_KEY) && + verifier.Verify(key()) && + VerifyField(verifier, VT_VALUE) && + verifier.Verify(value()) && + verifier.EndTable(); + } +}; + +struct KeyValueBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_key(flatbuffers::Offset key) { fbb_.AddOffset(KeyValue::VT_KEY, key); } + void add_value(flatbuffers::Offset value) { fbb_.AddOffset(KeyValue::VT_VALUE, value); } + KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + KeyValueBuilder &operator=(const KeyValueBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + fbb_.Required(o, KeyValue::VT_KEY); // key + return o; + } +}; + +inline flatbuffers::Offset CreateKeyValue(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset key = 0, + flatbuffers::Offset value = 0) { + KeyValueBuilder builder_(_fbb); + builder_.add_value(value); + builder_.add_key(key); + return builder_.Finish(); +} + +struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_NAME = 4, + VT_VALUE = 6, + VT_OBJECT = 8 + }; + const flatbuffers::String *name() const { return GetPointer(VT_NAME); } + int64_t value() const { return GetField(VT_VALUE, 0); } + bool KeyCompareLessThan(const EnumVal *o) const { return value() < o->value(); } + int KeyCompareWithValue(int64_t val) const { return value() < val ? -1 : value() > val; } + const Object *object() const { return GetPointer(VT_OBJECT); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyFieldRequired(verifier, VT_NAME) && verifier.Verify(name()) && - VerifyField(verifier, 6 /* value */) && - VerifyField(verifier, 8 /* object */) && + VerifyField(verifier, VT_VALUE) && + VerifyField(verifier, VT_OBJECT) && verifier.VerifyTable(object()) && verifier.EndTable(); } @@ -100,14 +160,14 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct EnumValBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_name(flatbuffers::Offset name) { fbb_.AddOffset(4, name); } - void add_value(int64_t value) { fbb_.AddElement(6, value, 0); } - void add_object(flatbuffers::Offset object) { fbb_.AddOffset(8, object); } + void add_name(flatbuffers::Offset name) { fbb_.AddOffset(EnumVal::VT_NAME, name); } + void add_value(int64_t value) { fbb_.AddElement(EnumVal::VT_VALUE, value, 0); } + void add_object(flatbuffers::Offset object) { fbb_.AddOffset(EnumVal::VT_OBJECT, object); } EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } EnumValBuilder &operator=(const EnumValBuilder &); flatbuffers::Offset Finish() { auto o = flatbuffers::Offset(fbb_.EndTable(start_, 3)); - fbb_.Required(o, 4); // name + fbb_.Required(o, EnumVal::VT_NAME); // name return o; } }; @@ -124,22 +184,33 @@ inline flatbuffers::Offset CreateEnumVal(flatbuffers::FlatBufferBuilder } struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const flatbuffers::String *name() const { return GetPointer(4); } + enum { + VT_NAME = 4, + VT_VALUES = 6, + VT_IS_UNION = 8, + VT_UNDERLYING_TYPE = 10, + VT_ATTRIBUTES = 12 + }; + const flatbuffers::String *name() const { return GetPointer(VT_NAME); } bool KeyCompareLessThan(const Enum *o) const { return *name() < *o->name(); } int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); } - const flatbuffers::Vector> *values() const { return GetPointer> *>(6); } - uint8_t is_union() const { return GetField(8, 0); } - const Type *underlying_type() const { return GetPointer(10); } + const flatbuffers::Vector> *values() const { return GetPointer> *>(VT_VALUES); } + bool is_union() const { return GetField(VT_IS_UNION, 0) != 0; } + const Type *underlying_type() const { return GetPointer(VT_UNDERLYING_TYPE); } + const flatbuffers::Vector> *attributes() const { return GetPointer> *>(VT_ATTRIBUTES); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyFieldRequired(verifier, 4 /* name */) && + VerifyFieldRequired(verifier, VT_NAME) && verifier.Verify(name()) && - VerifyFieldRequired(verifier, 6 /* values */) && + VerifyFieldRequired(verifier, VT_VALUES) && verifier.Verify(values()) && verifier.VerifyVectorOfTables(values()) && - VerifyField(verifier, 8 /* is_union */) && - VerifyFieldRequired(verifier, 10 /* underlying_type */) && + VerifyField(verifier, VT_IS_UNION) && + VerifyFieldRequired(verifier, VT_UNDERLYING_TYPE) && verifier.VerifyTable(underlying_type()) && + VerifyField(verifier, VT_ATTRIBUTES) && + verifier.Verify(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && verifier.EndTable(); } }; @@ -147,17 +218,18 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct EnumBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_name(flatbuffers::Offset name) { fbb_.AddOffset(4, name); } - void add_values(flatbuffers::Offset>> values) { fbb_.AddOffset(6, values); } - void add_is_union(uint8_t is_union) { fbb_.AddElement(8, is_union, 0); } - void add_underlying_type(flatbuffers::Offset underlying_type) { fbb_.AddOffset(10, underlying_type); } + void add_name(flatbuffers::Offset name) { fbb_.AddOffset(Enum::VT_NAME, name); } + void add_values(flatbuffers::Offset>> values) { fbb_.AddOffset(Enum::VT_VALUES, values); } + void add_is_union(bool is_union) { fbb_.AddElement(Enum::VT_IS_UNION, static_cast(is_union), 0); } + void add_underlying_type(flatbuffers::Offset underlying_type) { fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type); } + void add_attributes(flatbuffers::Offset>> attributes) { fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes); } EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } EnumBuilder &operator=(const EnumBuilder &); flatbuffers::Offset Finish() { - auto o = flatbuffers::Offset(fbb_.EndTable(start_, 4)); - fbb_.Required(o, 4); // name - fbb_.Required(o, 6); // values - fbb_.Required(o, 10); // underlying_type + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 5)); + fbb_.Required(o, Enum::VT_NAME); // name + fbb_.Required(o, Enum::VT_VALUES); // values + fbb_.Required(o, Enum::VT_UNDERLYING_TYPE); // underlying_type return o; } }; @@ -165,9 +237,11 @@ struct EnumBuilder { inline flatbuffers::Offset CreateEnum(flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset name = 0, flatbuffers::Offset>> values = 0, - uint8_t is_union = 0, - flatbuffers::Offset underlying_type = 0) { + bool is_union = false, + flatbuffers::Offset underlying_type = 0, + flatbuffers::Offset>> attributes = 0) { EnumBuilder builder_(_fbb); + builder_.add_attributes(attributes); builder_.add_underlying_type(underlying_type); builder_.add_values(values); builder_.add_name(name); @@ -176,30 +250,46 @@ inline flatbuffers::Offset CreateEnum(flatbuffers::FlatBufferBuilder &_fbb } struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const flatbuffers::String *name() const { return GetPointer(4); } + enum { + VT_NAME = 4, + VT_TYPE = 6, + VT_ID = 8, + VT_OFFSET = 10, + VT_DEFAULT_INTEGER = 12, + VT_DEFAULT_REAL = 14, + VT_DEPRECATED = 16, + VT_REQUIRED = 18, + VT_KEY = 20, + VT_ATTRIBUTES = 22 + }; + const flatbuffers::String *name() const { return GetPointer(VT_NAME); } bool KeyCompareLessThan(const Field *o) const { return *name() < *o->name(); } int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); } - const Type *type() const { return GetPointer(6); } - uint16_t id() const { return GetField(8, 0); } - uint16_t offset() const { return GetField(10, 0); } - int64_t default_integer() const { return GetField(12, 0); } - double default_real() const { return GetField(14, 0.0); } - uint8_t deprecated() const { return GetField(16, 0); } - uint8_t required() const { return GetField(18, 0); } - uint8_t key() const { return GetField(20, 0); } + const Type *type() const { return GetPointer(VT_TYPE); } + uint16_t id() const { return GetField(VT_ID, 0); } + uint16_t offset() const { return GetField(VT_OFFSET, 0); } + int64_t default_integer() const { return GetField(VT_DEFAULT_INTEGER, 0); } + double default_real() const { return GetField(VT_DEFAULT_REAL, 0.0); } + bool deprecated() const { return GetField(VT_DEPRECATED, 0) != 0; } + bool required() const { return GetField(VT_REQUIRED, 0) != 0; } + bool key() const { return GetField(VT_KEY, 0) != 0; } + const flatbuffers::Vector> *attributes() const { return GetPointer> *>(VT_ATTRIBUTES); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyFieldRequired(verifier, 4 /* name */) && + VerifyFieldRequired(verifier, VT_NAME) && verifier.Verify(name()) && - VerifyFieldRequired(verifier, 6 /* type */) && + VerifyFieldRequired(verifier, VT_TYPE) && verifier.VerifyTable(type()) && - VerifyField(verifier, 8 /* id */) && - VerifyField(verifier, 10 /* offset */) && - VerifyField(verifier, 12 /* default_integer */) && - VerifyField(verifier, 14 /* default_real */) && - VerifyField(verifier, 16 /* deprecated */) && - VerifyField(verifier, 18 /* required */) && - VerifyField(verifier, 20 /* key */) && + VerifyField(verifier, VT_ID) && + VerifyField(verifier, VT_OFFSET) && + VerifyField(verifier, VT_DEFAULT_INTEGER) && + VerifyField(verifier, VT_DEFAULT_REAL) && + VerifyField(verifier, VT_DEPRECATED) && + VerifyField(verifier, VT_REQUIRED) && + VerifyField(verifier, VT_KEY) && + VerifyField(verifier, VT_ATTRIBUTES) && + verifier.Verify(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && verifier.EndTable(); } }; @@ -207,21 +297,22 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct FieldBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_name(flatbuffers::Offset name) { fbb_.AddOffset(4, name); } - void add_type(flatbuffers::Offset type) { fbb_.AddOffset(6, type); } - void add_id(uint16_t id) { fbb_.AddElement(8, id, 0); } - void add_offset(uint16_t offset) { fbb_.AddElement(10, offset, 0); } - void add_default_integer(int64_t default_integer) { fbb_.AddElement(12, default_integer, 0); } - void add_default_real(double default_real) { fbb_.AddElement(14, default_real, 0.0); } - void add_deprecated(uint8_t deprecated) { fbb_.AddElement(16, deprecated, 0); } - void add_required(uint8_t required) { fbb_.AddElement(18, required, 0); } - void add_key(uint8_t key) { fbb_.AddElement(20, key, 0); } + void add_name(flatbuffers::Offset name) { fbb_.AddOffset(Field::VT_NAME, name); } + void add_type(flatbuffers::Offset type) { fbb_.AddOffset(Field::VT_TYPE, type); } + void add_id(uint16_t id) { fbb_.AddElement(Field::VT_ID, id, 0); } + void add_offset(uint16_t offset) { fbb_.AddElement(Field::VT_OFFSET, offset, 0); } + void add_default_integer(int64_t default_integer) { fbb_.AddElement(Field::VT_DEFAULT_INTEGER, default_integer, 0); } + void add_default_real(double default_real) { fbb_.AddElement(Field::VT_DEFAULT_REAL, default_real, 0.0); } + void add_deprecated(bool deprecated) { fbb_.AddElement(Field::VT_DEPRECATED, static_cast(deprecated), 0); } + void add_required(bool required) { fbb_.AddElement(Field::VT_REQUIRED, static_cast(required), 0); } + void add_key(bool key) { fbb_.AddElement(Field::VT_KEY, static_cast(key), 0); } + void add_attributes(flatbuffers::Offset>> attributes) { fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes); } FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } FieldBuilder &operator=(const FieldBuilder &); flatbuffers::Offset Finish() { - auto o = flatbuffers::Offset(fbb_.EndTable(start_, 9)); - fbb_.Required(o, 4); // name - fbb_.Required(o, 6); // type + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 10)); + fbb_.Required(o, Field::VT_NAME); // name + fbb_.Required(o, Field::VT_TYPE); // type return o; } }; @@ -233,12 +324,14 @@ inline flatbuffers::Offset CreateField(flatbuffers::FlatBufferBuilder &_f uint16_t offset = 0, int64_t default_integer = 0, double default_real = 0.0, - uint8_t deprecated = 0, - uint8_t required = 0, - uint8_t key = 0) { + bool deprecated = false, + bool required = false, + bool key = false, + flatbuffers::Offset>> attributes = 0) { FieldBuilder builder_(_fbb); builder_.add_default_real(default_real); builder_.add_default_integer(default_integer); + builder_.add_attributes(attributes); builder_.add_type(type); builder_.add_name(name); builder_.add_offset(offset); @@ -250,23 +343,35 @@ inline flatbuffers::Offset CreateField(flatbuffers::FlatBufferBuilder &_f } struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const flatbuffers::String *name() const { return GetPointer(4); } + enum { + VT_NAME = 4, + VT_FIELDS = 6, + VT_IS_STRUCT = 8, + VT_MINALIGN = 10, + VT_BYTESIZE = 12, + VT_ATTRIBUTES = 14 + }; + const flatbuffers::String *name() const { return GetPointer(VT_NAME); } bool KeyCompareLessThan(const Object *o) const { return *name() < *o->name(); } int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); } - const flatbuffers::Vector> *fields() const { return GetPointer> *>(6); } - uint8_t is_struct() const { return GetField(8, 0); } - int32_t minalign() const { return GetField(10, 0); } - int32_t bytesize() const { return GetField(12, 0); } + const flatbuffers::Vector> *fields() const { return GetPointer> *>(VT_FIELDS); } + bool is_struct() const { return GetField(VT_IS_STRUCT, 0) != 0; } + int32_t minalign() const { return GetField(VT_MINALIGN, 0); } + int32_t bytesize() const { return GetField(VT_BYTESIZE, 0); } + const flatbuffers::Vector> *attributes() const { return GetPointer> *>(VT_ATTRIBUTES); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyFieldRequired(verifier, 4 /* name */) && + VerifyFieldRequired(verifier, VT_NAME) && verifier.Verify(name()) && - VerifyFieldRequired(verifier, 6 /* fields */) && + VerifyFieldRequired(verifier, VT_FIELDS) && verifier.Verify(fields()) && verifier.VerifyVectorOfTables(fields()) && - VerifyField(verifier, 8 /* is_struct */) && - VerifyField(verifier, 10 /* minalign */) && - VerifyField(verifier, 12 /* bytesize */) && + VerifyField(verifier, VT_IS_STRUCT) && + VerifyField(verifier, VT_MINALIGN) && + VerifyField(verifier, VT_BYTESIZE) && + VerifyField(verifier, VT_ATTRIBUTES) && + verifier.Verify(attributes()) && + verifier.VerifyVectorOfTables(attributes()) && verifier.EndTable(); } }; @@ -274,17 +379,18 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct ObjectBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_name(flatbuffers::Offset name) { fbb_.AddOffset(4, name); } - void add_fields(flatbuffers::Offset>> fields) { fbb_.AddOffset(6, fields); } - void add_is_struct(uint8_t is_struct) { fbb_.AddElement(8, is_struct, 0); } - void add_minalign(int32_t minalign) { fbb_.AddElement(10, minalign, 0); } - void add_bytesize(int32_t bytesize) { fbb_.AddElement(12, bytesize, 0); } + void add_name(flatbuffers::Offset name) { fbb_.AddOffset(Object::VT_NAME, name); } + void add_fields(flatbuffers::Offset>> fields) { fbb_.AddOffset(Object::VT_FIELDS, fields); } + void add_is_struct(bool is_struct) { fbb_.AddElement(Object::VT_IS_STRUCT, static_cast(is_struct), 0); } + void add_minalign(int32_t minalign) { fbb_.AddElement(Object::VT_MINALIGN, minalign, 0); } + void add_bytesize(int32_t bytesize) { fbb_.AddElement(Object::VT_BYTESIZE, bytesize, 0); } + void add_attributes(flatbuffers::Offset>> attributes) { fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes); } ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } ObjectBuilder &operator=(const ObjectBuilder &); flatbuffers::Offset Finish() { - auto o = flatbuffers::Offset(fbb_.EndTable(start_, 5)); - fbb_.Required(o, 4); // name - fbb_.Required(o, 6); // fields + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 6)); + fbb_.Required(o, Object::VT_NAME); // name + fbb_.Required(o, Object::VT_FIELDS); // fields return o; } }; @@ -292,10 +398,12 @@ struct ObjectBuilder { inline flatbuffers::Offset CreateObject(flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset name = 0, flatbuffers::Offset>> fields = 0, - uint8_t is_struct = 0, + bool is_struct = false, int32_t minalign = 0, - int32_t bytesize = 0) { + int32_t bytesize = 0, + flatbuffers::Offset>> attributes = 0) { ObjectBuilder builder_(_fbb); + builder_.add_attributes(attributes); builder_.add_bytesize(bytesize); builder_.add_minalign(minalign); builder_.add_fields(fields); @@ -305,24 +413,31 @@ inline flatbuffers::Offset CreateObject(flatbuffers::FlatBufferBuilder & } struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - const flatbuffers::Vector> *objects() const { return GetPointer> *>(4); } - const flatbuffers::Vector> *enums() const { return GetPointer> *>(6); } - const flatbuffers::String *file_ident() const { return GetPointer(8); } - const flatbuffers::String *file_ext() const { return GetPointer(10); } - const Object *root_table() const { return GetPointer(12); } + enum { + VT_OBJECTS = 4, + VT_ENUMS = 6, + VT_FILE_IDENT = 8, + VT_FILE_EXT = 10, + VT_ROOT_TABLE = 12 + }; + const flatbuffers::Vector> *objects() const { return GetPointer> *>(VT_OBJECTS); } + const flatbuffers::Vector> *enums() const { return GetPointer> *>(VT_ENUMS); } + const flatbuffers::String *file_ident() const { return GetPointer(VT_FILE_IDENT); } + const flatbuffers::String *file_ext() const { return GetPointer(VT_FILE_EXT); } + const Object *root_table() const { return GetPointer(VT_ROOT_TABLE); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && - VerifyFieldRequired(verifier, 4 /* objects */) && + VerifyFieldRequired(verifier, VT_OBJECTS) && verifier.Verify(objects()) && verifier.VerifyVectorOfTables(objects()) && - VerifyFieldRequired(verifier, 6 /* enums */) && + VerifyFieldRequired(verifier, VT_ENUMS) && verifier.Verify(enums()) && verifier.VerifyVectorOfTables(enums()) && - VerifyField(verifier, 8 /* file_ident */) && + VerifyField(verifier, VT_FILE_IDENT) && verifier.Verify(file_ident()) && - VerifyField(verifier, 10 /* file_ext */) && + VerifyField(verifier, VT_FILE_EXT) && verifier.Verify(file_ext()) && - VerifyField(verifier, 12 /* root_table */) && + VerifyField(verifier, VT_ROOT_TABLE) && verifier.VerifyTable(root_table()) && verifier.EndTable(); } @@ -331,17 +446,17 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct SchemaBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_; - void add_objects(flatbuffers::Offset>> objects) { fbb_.AddOffset(4, objects); } - void add_enums(flatbuffers::Offset>> enums) { fbb_.AddOffset(6, enums); } - void add_file_ident(flatbuffers::Offset file_ident) { fbb_.AddOffset(8, file_ident); } - void add_file_ext(flatbuffers::Offset file_ext) { fbb_.AddOffset(10, file_ext); } - void add_root_table(flatbuffers::Offset root_table) { fbb_.AddOffset(12, root_table); } + void add_objects(flatbuffers::Offset>> objects) { fbb_.AddOffset(Schema::VT_OBJECTS, objects); } + void add_enums(flatbuffers::Offset>> enums) { fbb_.AddOffset(Schema::VT_ENUMS, enums); } + void add_file_ident(flatbuffers::Offset file_ident) { fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident); } + void add_file_ext(flatbuffers::Offset file_ext) { fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext); } + void add_root_table(flatbuffers::Offset root_table) { fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table); } SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } SchemaBuilder &operator=(const SchemaBuilder &); flatbuffers::Offset Finish() { auto o = flatbuffers::Offset(fbb_.EndTable(start_, 5)); - fbb_.Required(o, 4); // objects - fbb_.Required(o, 6); // enums + fbb_.Required(o, Schema::VT_OBJECTS); // objects + fbb_.Required(o, Schema::VT_ENUMS); // enums return o; } }; diff --git a/reflection/reflection.fbs b/reflection/reflection.fbs index 77305f69f..57f234c6a 100644 --- a/reflection/reflection.fbs +++ b/reflection/reflection.fbs @@ -34,6 +34,11 @@ table Type { // from an enum, index into "enums" below. } +table KeyValue { + key:string (required, key); + value:string; +} + table EnumVal { name:string (required); value:long (key); @@ -45,6 +50,7 @@ table Enum { values:[EnumVal] (required); // In order of their values. is_union:bool = false; underlying_type:Type (required); + attributes:[KeyValue]; } table Field { @@ -57,6 +63,7 @@ table Field { deprecated:bool = false; required:bool = false; key:bool = false; + attributes:[KeyValue]; } table Object { // Used for both tables and structs. @@ -65,6 +72,7 @@ table Object { // Used for both tables and structs. is_struct:bool = false; minalign:int; bytesize:int; // For structs. + attributes:[KeyValue]; } table Schema { diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 1df44add1..e0eaa5d6a 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1784,7 +1784,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, auto name = attribute_; EXPECT(kTokenStringConstant); EXPECT(';'); - known_attributes_.insert(name); + known_attributes_[name] = false; } else if (token_ == kTokenService) { ECHECK(ParseService()); } else { @@ -1853,13 +1853,13 @@ void Parser::Serialize() { AssignIndices(enums_.vec); std::vector> object_offsets; for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { - auto offset = (*it)->Serialize(&builder_); + auto offset = (*it)->Serialize(&builder_, *this); object_offsets.push_back(offset); (*it)->serialized_location = offset.o; } std::vector> enum_offsets; for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { - auto offset = (*it)->Serialize(&builder_); + auto offset = (*it)->Serialize(&builder_, *this); enum_offsets.push_back(offset); (*it)->serialized_location = offset.o; } @@ -1875,13 +1875,13 @@ void Parser::Serialize() { builder_.Finish(schema_offset, reflection::SchemaIdentifier()); } -Offset StructDef::Serialize(FlatBufferBuilder *builder) - const { +Offset StructDef::Serialize(FlatBufferBuilder *builder, + const Parser &parser) const { std::vector> field_offsets; for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { field_offsets.push_back( (*it)->Serialize(builder, - static_cast(it - fields.vec.begin()))); + static_cast(it - fields.vec.begin()), parser)); } return reflection::CreateObject(*builder, builder->CreateString(name), @@ -1889,11 +1889,13 @@ Offset StructDef::Serialize(FlatBufferBuilder *builder) &field_offsets), fixed, static_cast(minalign), - static_cast(bytesize)); + static_cast(bytesize), + SerializeAttributes(builder, parser)); } Offset FieldDef::Serialize(FlatBufferBuilder *builder, - uint16_t id) const { + uint16_t id, + const Parser &parser) const { return reflection::CreateField(*builder, builder->CreateString(name), value.type.Serialize(builder), @@ -1907,12 +1909,14 @@ Offset FieldDef::Serialize(FlatBufferBuilder *builder, : 0.0, deprecated, required, - key); + key, + SerializeAttributes(builder, parser)); // TODO: value.constant is almost always "0", we could save quite a bit of // space by sharing it. Same for common values of value.type. } -Offset EnumDef::Serialize(FlatBufferBuilder *builder) const { +Offset EnumDef::Serialize(FlatBufferBuilder *builder, + const Parser &parser) const { std::vector> enumval_offsets; for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { enumval_offsets.push_back((*it)->Serialize(builder)); @@ -1921,7 +1925,8 @@ Offset EnumDef::Serialize(FlatBufferBuilder *builder) const { builder->CreateString(name), builder->CreateVector(enumval_offsets), is_union, - underlying_type.Serialize(builder)); + underlying_type.Serialize(builder), + SerializeAttributes(builder, parser)); } Offset EnumVal::Serialize(FlatBufferBuilder *builder) const @@ -1942,4 +1947,26 @@ Offset Type::Serialize(FlatBufferBuilder *builder) const { (enum_def ? enum_def->index : -1)); } +flatbuffers::Offset>> + Definition::SerializeAttributes(FlatBufferBuilder *builder, + const Parser &parser) const { + std::vector> attrs; + for (auto kv : attributes.dict) { + auto it = parser.known_attributes_.find(kv.first); + assert(it != parser.known_attributes_.end()); + if (!it->second) { // Custom attribute. + attrs.push_back( + reflection::CreateKeyValue(*builder, builder->CreateString(kv.first), + builder->CreateString( + kv.second->constant))); + } + } + if (attrs.size()) { + return builder->CreateVectorOfSortedTables(&attrs); + } else { + return 0; + } +} + } // namespace flatbuffers diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index e5f51face696a1ee9b3aa64b70bba83df1c4645a..db1232821257da777a2adf0e6a8bf34226613243 100644 GIT binary patch literal 2840 zcmaJ@O=w(I6h8Bl%ugnhX|3rfB0~wKh=@&tWRXRUHvWLAn3xukwlA4C&cK`ZhBt3Q zr?_xYx)RB%6cNcnx{x5ng-Zz{;wp66MHfLz7p{s()mk0D@1A#Oo*2Av=G^zrch3Fp zx#!$BRS{WST3it+OI5Oxmy%TE2%ZGLBF{tSA*Ug=w8%Jg6?!Kpk}ZmO1(93OujWNE zu)PSm2iZ!&4*k~IWyDrnJMb|pBQ96TVI4l1kt#v)`56e~yzKXlzKZ!J2;YDD_h0~p z$Q(t(w}e<&-f-Oq2T&W1qnNF_-DsuN?s)F1v+lX)T2b?i-)qBCgijVc)SqjgM&vj+ z*nxZCcOy5HM_8A8p)8+WJ_98e27>`PGe(yQ3&-aX2HoMon;6*_>6v3HHbxqF5G4@|`Jk-JOqnwaWGKWv$c?aZfAXp8~ zcObX%T*0P3#(W-n9?x0Gc?fInM_{)gcNq-&3+R1J7oaag*P*weA47=G19J%+sxoKt z%bH;hBh-KshE6|dtOtSD#Vh&bG0&u&-U9xp%ntE~Vtmu-HhVA4U2OQ9Cmp<70}iUV z3q6f0=NU1665mbWuPMIp0QyOJ;Xr)v)a)?+H;T{K{um67pz98dpTOT&eC}=FpOEK< zc)Q;uf6$a^;Gl{hK_5m1*!W4jaFn~KlxLsw+xKzujmPy9{A z=PHi|gDE*?@a!e>;(76)h}%rJ5e9=uV9CoLPW21H{A8!0QYPaIpNpF?uPdTPm6oT zNbz>Icb4VQ2wSdS_joMwv+_-oFme2<@C(NEDdbMw30pzfGG$`!xs!NTg*CZ0zieDz z*G{D}hOgEF^XWTnrbsU6ekaLY*JGAOgZ^n)_>Sw>V-wG**%A3%{l}`N*2wq2{wch( zdA}a}Q;|p8@g2_Z$8kJUGu*Z209U7Ug06h~m)0!L>UEqY^TU|T72~W#P6TDXRkV@k z3CK45$e;1J2R-YaPw;yhbNqW~a!jtdi4VXPwHK=9Oc|B`7DhvJJL1Zmw6O5k>Nokm z=|xF#U1F(g5b|AfH%>vBh)w7P2<^L&&mfl}^dF0R({g7Y&~Z;=n|`^9dDfiYXph9r z0{2jHrk-~&&zQaZ8^`)-D6VuH+UAQpW`3_guBmP@0|q>Pd2=pW~ZGjnPESgG&&y{`G|g!w-^gWWO! delta 1254 zcmZuxOGs2<6h8OPef@W4u7=JvF`Yu2sgxc@(fb8OMNRaeMT;;~q0p(U2HHgK+!PFl zqIE=6P>X00Eh1aA5Q++lh=>Y;5DHo(S?2Ve{~sZu3+Mj#yub7K@8$SjCN+zQHf`Co z7YCJtw%sY4$iugTbE{8uT@lrSc7#N4!6%^W0KEqdTd>2qb5}w8i*Ddpky2Do0p32< zQmQ=EZjX(ZZ?{;(L zzlmnz6u3#ymce5K+lq(#Pxtf^P-yw~AC(HvwmYnG-f3s&-vyk@sGNw7GoP5~wONR+^KY5RnQw78N`+3O8s*>UCvwXwJ zrlU!1S|b(S;UwEy*& zCG{!h8Gg3;sY#xGh0<;KOBC6a9&zVGe*H{0#)8O3I&hQv%oB6j&#QG)y2);lNBoBL zQ^VB=^mY8nZ&h9Rng_bXGlHhIcZ}YPs{^B zgYxu*C|%(5LB8=glxskO>KW)N=p3lPPmt}6v8}-xQwf=!>NKT1K`1loL`&taN$bp1 zNzdULH>)P~$V5nu@c_str(), "hp"); TEST_EQ(hp_field.id(), 2); TEST_EQ(hp_field.type()->base_type(), reflection::Short); + auto friendly_field_ptr = fields->LookupByKey("friendly"); + TEST_NOTNULL(friendly_field_ptr); + TEST_NOTNULL(friendly_field_ptr->attributes()); + TEST_NOTNULL(friendly_field_ptr->attributes()->LookupByKey("priority")); // Now use it to dynamically access a buffer. auto &root = *flatbuffers::GetAnyRoot(flatbuf);