Made user-defined attributes available in the reflection data.

Tested: on Linux.

Bug: 27923233
Change-Id: Ic16675650e4a8e138c163f1e2131a3aad7008ada
parent 9f2b05df
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#define FLATBUFFERS_IDL_H_ #define FLATBUFFERS_IDL_H_
#include <map> #include <map>
#include <set>
#include <stack> #include <stack>
#include <memory> #include <memory>
#include <functional> #include <functional>
...@@ -113,6 +112,7 @@ inline size_t SizeOf(BaseType t) { ...@@ -113,6 +112,7 @@ inline size_t SizeOf(BaseType t) {
struct StructDef; struct StructDef;
struct EnumDef; struct EnumDef;
struct Parser;
// Represents any type in the IDL, which is a combination of the BaseType // Represents any type in the IDL, which is a combination of the BaseType
// and additional information for vectors/structs_. // and additional information for vectors/structs_.
...@@ -184,10 +184,8 @@ template<typename T> class SymbolTable { ...@@ -184,10 +184,8 @@ template<typename T> class SymbolTable {
return it == dict.end() ? nullptr : it->second; return it == dict.end() ? nullptr : it->second;
} }
private:
std::map<std::string, T *> dict; // quick lookup
public: public:
std::map<std::string, T *> dict; // quick lookup
std::vector<T *> vec; // Used to iterate in order of insertion std::vector<T *> vec; // Used to iterate in order of insertion
}; };
...@@ -208,6 +206,11 @@ struct Definition { ...@@ -208,6 +206,11 @@ struct Definition {
Definition() : generated(false), defined_namespace(nullptr), Definition() : generated(false), defined_namespace(nullptr),
serialized_location(0), index(-1) {} serialized_location(0), index(-1) {}
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
reflection::KeyValue>>>
SerializeAttributes(FlatBufferBuilder *builder,
const Parser &parser) const;
std::string name; std::string name;
std::string file; std::string file;
std::vector<std::string> doc_comment; std::vector<std::string> doc_comment;
...@@ -223,8 +226,8 @@ struct Definition { ...@@ -223,8 +226,8 @@ struct Definition {
struct FieldDef : public Definition { struct FieldDef : public Definition {
FieldDef() : deprecated(false), required(false), key(false), padding(0) {} FieldDef() : deprecated(false), required(false), key(false), padding(0) {}
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id) Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
const; const Parser &parser) const;
Value value; Value value;
bool deprecated; // Field is allowed to be present in old data, but can't be bool deprecated; // Field is allowed to be present in old data, but can't be
...@@ -250,7 +253,8 @@ struct StructDef : public Definition { ...@@ -250,7 +253,8 @@ struct StructDef : public Definition {
if (fields.vec.size()) fields.vec.back()->padding = padding; if (fields.vec.size()) fields.vec.back()->padding = padding;
} }
Offset<reflection::Object> Serialize(FlatBufferBuilder *builder) const; Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
const Parser &parser) const;
SymbolTable<FieldDef> fields; SymbolTable<FieldDef> fields;
bool fixed; // If it's struct, not a table. bool fixed; // If it's struct, not a table.
...@@ -299,7 +303,8 @@ struct EnumDef : public Definition { ...@@ -299,7 +303,8 @@ struct EnumDef : public Definition {
return nullptr; return nullptr;
} }
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder) const; Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
const Parser &parser) const;
SymbolTable<EnumVal> vals; SymbolTable<EnumVal> vals;
bool is_union; bool is_union;
...@@ -406,18 +411,18 @@ class Parser { ...@@ -406,18 +411,18 @@ class Parser {
anonymous_counter(0) { anonymous_counter(0) {
// Just in case none are declared: // Just in case none are declared:
namespaces_.push_back(new Namespace()); namespaces_.push_back(new Namespace());
known_attributes_.insert("deprecated"); known_attributes_["deprecated"] = true;
known_attributes_.insert("required"); known_attributes_["required"] = true;
known_attributes_.insert("key"); known_attributes_["key"] = true;
known_attributes_.insert("hash"); known_attributes_["hash"] = true;
known_attributes_.insert("id"); known_attributes_["id"] = true;
known_attributes_.insert("force_align"); known_attributes_["force_align"] = true;
known_attributes_.insert("bit_flags"); known_attributes_["bit_flags"] = true;
known_attributes_.insert("original_order"); known_attributes_["original_order"] = true;
known_attributes_.insert("nested_flatbuffer"); known_attributes_["nested_flatbuffer"] = true;
known_attributes_.insert("csharp_partial"); known_attributes_["csharp_partial"] = true;
known_attributes_.insert("stream"); known_attributes_["stream"] = true;
known_attributes_.insert("idempotent"); known_attributes_["idempotent"] = true;
} }
~Parser() { ~Parser() {
...@@ -528,6 +533,8 @@ private: ...@@ -528,6 +533,8 @@ private:
std::map<std::string, bool> included_files_; std::map<std::string, bool> included_files_;
std::map<std::string, std::set<std::string>> files_included_per_file_; std::map<std::string, std::set<std::string>> files_included_per_file_;
std::map<std::string, bool> known_attributes_;
IDLOptions opts; IDLOptions opts;
private: private:
...@@ -541,8 +548,6 @@ private: ...@@ -541,8 +548,6 @@ private:
std::vector<std::pair<Value, FieldDef *>> field_stack_; std::vector<std::pair<Value, FieldDef *>> field_stack_;
std::set<std::string> known_attributes_;
int anonymous_counter; int anonymous_counter;
}; };
......
This diff is collapsed.
...@@ -34,6 +34,11 @@ table Type { ...@@ -34,6 +34,11 @@ table Type {
// from an enum, index into "enums" below. // from an enum, index into "enums" below.
} }
table KeyValue {
key:string (required, key);
value:string;
}
table EnumVal { table EnumVal {
name:string (required); name:string (required);
value:long (key); value:long (key);
...@@ -45,6 +50,7 @@ table Enum { ...@@ -45,6 +50,7 @@ table Enum {
values:[EnumVal] (required); // In order of their values. values:[EnumVal] (required); // In order of their values.
is_union:bool = false; is_union:bool = false;
underlying_type:Type (required); underlying_type:Type (required);
attributes:[KeyValue];
} }
table Field { table Field {
...@@ -57,6 +63,7 @@ table Field { ...@@ -57,6 +63,7 @@ table Field {
deprecated:bool = false; deprecated:bool = false;
required:bool = false; required:bool = false;
key:bool = false; key:bool = false;
attributes:[KeyValue];
} }
table Object { // Used for both tables and structs. table Object { // Used for both tables and structs.
...@@ -65,6 +72,7 @@ table Object { // Used for both tables and structs. ...@@ -65,6 +72,7 @@ table Object { // Used for both tables and structs.
is_struct:bool = false; is_struct:bool = false;
minalign:int; minalign:int;
bytesize:int; // For structs. bytesize:int; // For structs.
attributes:[KeyValue];
} }
table Schema { table Schema {
......
...@@ -1784,7 +1784,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, ...@@ -1784,7 +1784,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
auto name = attribute_; auto name = attribute_;
EXPECT(kTokenStringConstant); EXPECT(kTokenStringConstant);
EXPECT(';'); EXPECT(';');
known_attributes_.insert(name); known_attributes_[name] = false;
} else if (token_ == kTokenService) { } else if (token_ == kTokenService) {
ECHECK(ParseService()); ECHECK(ParseService());
} else { } else {
...@@ -1853,13 +1853,13 @@ void Parser::Serialize() { ...@@ -1853,13 +1853,13 @@ void Parser::Serialize() {
AssignIndices(enums_.vec); AssignIndices(enums_.vec);
std::vector<Offset<reflection::Object>> object_offsets; std::vector<Offset<reflection::Object>> object_offsets;
for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { 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); object_offsets.push_back(offset);
(*it)->serialized_location = offset.o; (*it)->serialized_location = offset.o;
} }
std::vector<Offset<reflection::Enum>> enum_offsets; std::vector<Offset<reflection::Enum>> enum_offsets;
for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { 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); enum_offsets.push_back(offset);
(*it)->serialized_location = offset.o; (*it)->serialized_location = offset.o;
} }
...@@ -1875,13 +1875,13 @@ void Parser::Serialize() { ...@@ -1875,13 +1875,13 @@ void Parser::Serialize() {
builder_.Finish(schema_offset, reflection::SchemaIdentifier()); builder_.Finish(schema_offset, reflection::SchemaIdentifier());
} }
Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder) Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,
const { const Parser &parser) const {
std::vector<Offset<reflection::Field>> field_offsets; std::vector<Offset<reflection::Field>> field_offsets;
for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) { for (auto it = fields.vec.begin(); it != fields.vec.end(); ++it) {
field_offsets.push_back( field_offsets.push_back(
(*it)->Serialize(builder, (*it)->Serialize(builder,
static_cast<uint16_t>(it - fields.vec.begin()))); static_cast<uint16_t>(it - fields.vec.begin()), parser));
} }
return reflection::CreateObject(*builder, return reflection::CreateObject(*builder,
builder->CreateString(name), builder->CreateString(name),
...@@ -1889,11 +1889,13 @@ Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder) ...@@ -1889,11 +1889,13 @@ Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder)
&field_offsets), &field_offsets),
fixed, fixed,
static_cast<int>(minalign), static_cast<int>(minalign),
static_cast<int>(bytesize)); static_cast<int>(bytesize),
SerializeAttributes(builder, parser));
} }
Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
uint16_t id) const { uint16_t id,
const Parser &parser) const {
return reflection::CreateField(*builder, return reflection::CreateField(*builder,
builder->CreateString(name), builder->CreateString(name),
value.type.Serialize(builder), value.type.Serialize(builder),
...@@ -1907,12 +1909,14 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder, ...@@ -1907,12 +1909,14 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
: 0.0, : 0.0,
deprecated, deprecated,
required, required,
key); key,
SerializeAttributes(builder, parser));
// TODO: value.constant is almost always "0", we could save quite a bit of // 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. // space by sharing it. Same for common values of value.type.
} }
Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder) const { Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder,
const Parser &parser) const {
std::vector<Offset<reflection::EnumVal>> enumval_offsets; std::vector<Offset<reflection::EnumVal>> enumval_offsets;
for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) {
enumval_offsets.push_back((*it)->Serialize(builder)); enumval_offsets.push_back((*it)->Serialize(builder));
...@@ -1921,7 +1925,8 @@ Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder) const { ...@@ -1921,7 +1925,8 @@ Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder) const {
builder->CreateString(name), builder->CreateString(name),
builder->CreateVector(enumval_offsets), builder->CreateVector(enumval_offsets),
is_union, is_union,
underlying_type.Serialize(builder)); underlying_type.Serialize(builder),
SerializeAttributes(builder, parser));
} }
Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const
...@@ -1942,4 +1947,26 @@ Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { ...@@ -1942,4 +1947,26 @@ Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
(enum_def ? enum_def->index : -1)); (enum_def ? enum_def->index : -1));
} }
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
reflection::KeyValue>>>
Definition::SerializeAttributes(FlatBufferBuilder *builder,
const Parser &parser) const {
std::vector<flatbuffers::Offset<reflection::KeyValue>> 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 } // namespace flatbuffers
No preview for this file type
...@@ -7,16 +7,6 @@ ...@@ -7,16 +7,6 @@
#include "namespace_test1_generated.h" #include "namespace_test1_generated.h"
namespace NamespaceA {
namespace NamespaceB {
struct TableInNestedNS;
struct StructInNestedNS;
} // namespace NamespaceB
} // namespace NamespaceA
namespace NamespaceA { namespace NamespaceA {
struct TableInFirstNS; struct TableInFirstNS;
......
...@@ -322,6 +322,10 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { ...@@ -322,6 +322,10 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) {
TEST_EQ_STR(hp_field.name()->c_str(), "hp"); TEST_EQ_STR(hp_field.name()->c_str(), "hp");
TEST_EQ(hp_field.id(), 2); TEST_EQ(hp_field.id(), 2);
TEST_EQ(hp_field.type()->base_type(), reflection::Short); 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. // Now use it to dynamically access a buffer.
auto &root = *flatbuffers::GetAnyRoot(flatbuf); auto &root = *flatbuffers::GetAnyRoot(flatbuf);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment