Cleaned up the reflection code a bit

* Renamed 'tag' variable to 'handler'
* Removed addAlias stuff, instead check for matching names with if statements
* Added after_reading function that is called by Reader after reading a complete object. This generalizes Packaged::validate, which is now also called via this mechanism.
* Removed some backwards compatibility with <0.3.0 for templates
This commit is contained in:
Twan van Laarhoven
2020-04-26 15:33:59 +02:00
parent 4bebd48786
commit 40d78edf0f
32 changed files with 248 additions and 281 deletions
+44 -47
View File
@@ -22,32 +22,24 @@
/// Declare that a class supports reflection
/** Reflection allows the member variables of a class to be inspected at runtime.
*/
#define DECLARE_REFLECTION() \
#define DECLARE_REFLECTION_PREFIX(PREFIX,SUFFIX) \
protected: \
template<class Tag> void reflect_impl(Tag& tag); \
template<class Handler> void reflect_impl(Handler&); \
friend class Reader; \
friend class Writer; \
friend class GetDefaultMember; \
friend class GetMember; \
void reflect(Reader& reader); \
void reflect(Writer& writer); \
void reflect(GetDefaultMember& gdm); \
void reflect(GetMember& gm)
PREFIX void reflect(Reader& reader) SUFFIX; \
PREFIX void reflect(Writer& writer) SUFFIX; \
PREFIX void reflect(GetDefaultMember& gdm) SUFFIX; \
PREFIX void reflect(GetMember& gm) SUFFIX
#define DECLARE_REFLECTION() DECLARE_REFLECTION_PREFIX(,)
/// Declare that a class supports reflection, which can be overridden in derived classes
#define DECLARE_REFLECTION_VIRTUAL() \
protected: \
template<class Tag> void reflect_impl(Tag& tag); \
friend class Reader; \
friend class Writer; \
friend class GetDefaultMember; \
friend class GetMember; \
/* extra level of indirection between Tag::handle \
* and reflect_impl, to allow for virtual */ \
virtual void reflect(Reader& reader); \
virtual void reflect(Writer& writer); \
virtual void reflect(GetDefaultMember& gdm); \
virtual void reflect(GetMember& gm)
#define DECLARE_REFLECTION_VIRTUAL() DECLARE_REFLECTION_PREFIX(virtual,)
#define DECLARE_REFLECTION_OVERRIDE() DECLARE_REFLECTION_PREFIX(,override)
// ----------------------------------------------------------------------------- : Implementing reflection
@@ -71,8 +63,8 @@
REFLECT_OBJECT_WRITER(Cls) \
REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) \
REFLECT_OBJECT_GET_MEMBER(Cls) \
template <class Tag> \
void Cls::reflect_impl(Tag& tag)
template <class Handler> \
void Cls::reflect_impl(Handler& handler)
/// Implement the refelection of a class type Cls that only uses REFLECT_NAMELESS
#define IMPLEMENT_REFLECTION_NAMELESS(Cls) \
@@ -80,16 +72,16 @@
REFLECT_OBJECT_WRITER(Cls) \
REFLECT_OBJECT_GET_DEFAULT_MEMBER(Cls) \
REFLECT_OBJECT_GET_MEMBER_NOT(Cls) \
template <class Tag> \
void Cls::reflect_impl(Tag& tag)
template <class Handler> \
void Cls::reflect_impl(Handler& handler)
/// Implement the refelection of a class type Cls, but only for Reader and Writer,
/** There is custom code for GetMember and GetDefaultMember */
#define IMPLEMENT_REFLECTION_NO_GET_MEMBER(Cls) \
REFLECT_OBJECT_READER(Cls) \
REFLECT_OBJECT_WRITER(Cls) \
template <class Tag> \
void Cls::reflect_impl(Tag& tag)
template <class Handler> \
void Cls::reflect_impl(Handler& handler)
/// Implement the refelection of a class type Cls, but only for Reader and Writer
/** There is no code for GetMember and GetDefaultMember */
@@ -98,18 +90,18 @@
REFLECT_OBJECT_WRITER(Cls) \
REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) \
REFLECT_OBJECT_GET_MEMBER_NOT(Cls) \
template <class Tag> \
void Cls::reflect_impl(Tag& tag)
template <class Handler> \
void Cls::reflect_impl(Handler& handler)
/// Reflect a variable
#define REFLECT(var) tag.handle(_(#var), var)
#define REFLECT(var) handler.handle(_(#var), var)
/// Reflect a variable under the given name
#define REFLECT_N(name, var) tag.handle(_(name), var)
#define REFLECT_N(name, var) handler.handle(_(name), var)
/// Reflect a variable without a name, should be used only once per class
#define REFLECT_NAMELESS(var) tag.handle(var)
#define REFLECT_NAMELESS(var) handler.handle(var)
/// Declare that the variables of a base class should also be reflected
#define REFLECT_BASE(Base) Base::reflect_impl(tag)
#define REFLECT_BASE(Base) Base::reflect_impl(handler)
/// Reflect a group of declarations only when reading
/** Usage:
@@ -119,7 +111,7 @@
* }
* @endcode
*/
#define REFLECT_IF_READING if (tag.reading())
#define REFLECT_IF_READING if (Handler::isReading)
/// Reflect a group of declarations only when *not* reading
/** Usage:
@@ -129,24 +121,29 @@
* }
* @endcode
*/
#define REFLECT_IF_NOT_READING if (!tag.reading())
#define REFLECT_IF_NOT_READING if (!Handler::isReading)
/// Add an alias for backwards compatability
/** If a key 'old' is encountered in the input file, it is interpreted as 'new' for versions < version
/// Reflect a group of declarations only when reading and when the value is a single line value
#define REFLECT_IF_READING_SINGLE_VALUE if (Handler::isReading && !handler.isCompound())
#define REFLECT_IF_READING_SINGLE_VALUE_AND(cond) if (Handler::isReading && !handler.isCompound() && cond)
/// Add an alias for backwards compatibility
/** If a key 'name' is encountered in the input file, it is interpreted as 'var' for versions < version
* Example:
* @code
* REFLECT_ALIAS(300, "style", "stylesheet") // prior to 0.3.0 style was used instead of stylesheet
* REFLECT_COMPAT(<300, "style", stylesheet) // prior to 0.3.0 style was used instead of stylesheet
* @encode
*/
#define REFLECT_ALIAS(version, old, new) tag.addAlias(version, _(old), _(new))
#define REFLECT_COMPAT(cond, name, var) if (handler.formatVersion() cond) REFLECT_N(name,var)
/// Ignore things for backwards compatability for versions < 'version'
#define REFLECT_IGNORE(version, old) tag.handleIgnore(version, _(old))
/// Ignore things for backwards compatibility for versions < 'version'
#define REFLECT_COMPAT_IGNORE(cond, name, Type) if (reflector.formatVersion() cond) {Type ignored; REFLECT_N(name,ignored);}
/// Reflect a variable, ignores the variable for scripting
#define REFLECT_NO_SCRIPT(var) tag.handleNoScript(_(#var), var)
#define REFLECT_NO_SCRIPT(var) handler.handleNoScript(_(#var), var)
/// Reflect a variable under the given name
#define REFLECT_NO_SCRIPT_N(name, var) tag.handleNoScript(_(name), var)
#define REFLECT_NO_SCRIPT_N(name, var) handler.handleNoScript(_(name), var)
/// Explicitly instantiate reflection; this is occasionally required.
#define INSTANTIATE_REFLECTION(Class) \
@@ -178,17 +175,17 @@
* - GetDefaultMember::handle(const Enum&)
*/
#define IMPLEMENT_REFLECTION_ENUM(Enum) \
template <class Tag> \
void reflect_ ## Enum (Enum& enum_, Tag& tag); \
template <class Handler> \
void reflect_ ## Enum (Enum& enum_, Handler& handler); \
REFLECT_ENUM_READER(Enum) \
REFLECT_ENUM_WRITER(Enum) \
REFLECT_ENUM_GET_MEMBER(Enum) \
template <class Tag> \
void reflect_ ## Enum (Enum& enum_, Tag& tag)
template <class Handler> \
void reflect_ ## Enum (Enum& enum_, Handler& handler)
/// Declare a possible value of an enum
#define VALUE(val) tag.handle(_(#val), val, enum_)
#define VALUE(val) handler.handle(_(#val), val, enum_)
/// Declare a possible value of an enum under the given name
#define VALUE_N(name, val) tag.handle(_(name), val, enum_)
#define VALUE_N(name, val) handler.handle(_(name), val, enum_)