//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make Magic (tm) cards | //| Copyright: (C) 2001 - 2006 Twan van Laarhoven | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ #ifndef HEADER_UTIL_IO_GET_MEMBER #define HEADER_UTIL_IO_GET_MEMBER // ----------------------------------------------------------------------------- : Includes #include DECLARE_INTRUSIVE_POINTER_TYPE(ScriptValue); DECLARE_INTRUSIVE_POINTER_TYPE(Script); inline void intrusive_ptr_add_ref(ScriptValue* p); inline void intrusive_ptr_release(ScriptValue* p); template class Defaultable; template class Scriptable; // ----------------------------------------------------------------------------- : GetDefaultMember /// Find a member without a name using reflection /** The member is wrapped in a ScriptValue */ class GetDefaultMember { public: /// Tell the reflection code we are not reading inline bool reading() const { return false; } inline bool isComplex() const { return false; } inline void addAlias(int, const Char*, const Char*) {} inline void handleAppVersion() {} // no effect /// The result, or script_nil if the member was not found inline ScriptValueP result() { return value; } // --------------------------------------------------- : Handling objects /// Handle an object: we don't match things with a name template void handle(const Char* name, const T& object) {} /// Handle an object: investigate children, or store it if we know how template void handle(const T&); /// Handle a Defaultable: investigate children template void handle(const Defaultable&); template void handle(const Scriptable&); template void handle(const vector& c) { value = toScript(&c); } template void handle(const map& c) { value = toScript(&c); } template void handle(const IndexMap& c) { value = toScript(&c); } template void handle(const shared_ptr& p) { value = toScript(p); } void handle(const ScriptValueP&); void handle(const ScriptP&); private: ScriptValueP value; ///< The value we found (if any) }; // ----------------------------------------------------------------------------- : GetMember /// Find a member with a specific name using reflection /** The member is wrapped in a ScriptValue */ class GetMember : private GetDefaultMember { public: /// Construct a member getter that looks for the given name GetMember(const String& name); /// Tell the reflection code we are not reading inline bool reading() const { return false; } inline bool isComplex() const { return false; } inline void addAlias(int, const Char*, const Char*) {} inline void handleAppVersion() {} // no effect /// The result, or script_nil if the member was not found inline ScriptValueP result() { return gdm.result(); } // --------------------------------------------------- : Handling objects /// Handle an object: we are done if the name matches template void handle(const Char* name, const T& object) { if (!gdm.result() && cannocial_name_compare(target_name, name)) { gdm.handle(object); } } /// Handle an object: investigate children template void handle(const T&); /// Handle an index map: invistigate keys template void handle(const IndexMap& m) { if (gdm.result()) return; for (typename IndexMap::const_iterator it = m.begin() ; it != m.end() ; ++it) { if (get_key_name(*it) == target_name) { gdm.handle(*it); return; } } } private: const String& target_name; ///< The name we are looking for GetDefaultMember gdm; ///< Object to store and retrieve the value }; // ----------------------------------------------------------------------------- : Reflection /// Implement reflection as used by GetDefaultMember #define REFLECT_OBJECT_GET_DEFAULT_MEMBER(Cls) REFLECT_WRITE_YES(Cls,GetDefaultMember) #define REFLECT_OBJECT_GET_MEMBER(Cls) REFLECT_WRITE_YES(Cls,GetMember) #define REFLECT_OBJECT_GET_DEFAULT_MEMBER_NOT(Cls) REFLECT_WRITE_NO(Cls,GetDefaultMember) #define REFLECT_OBJECT_GET_MEMBER_NOT(Cls) REFLECT_WRITE_NO(Cls,GetMember) #define REFLECT_WRITE_YES(Cls, Tag) \ template<> void Tag::handle(const Cls& object) { \ const_cast(object).reflect(*this); \ } \ void Cls::reflect(Tag& tag) { \ reflect_impl(tag); \ } #define REFLECT_WRITE_NO(Cls, Tag) \ template<> void Tag::handle(const Cls& object) {} \ void Cls::reflect(Tag& tag) {} // ----------------------------------------------------------------------------- : Reflection for enumerations /// Implement enum reflection as used by GetMember #define REFLECT_ENUM_GET_MEMBER(Enum) \ template<> void GetDefaultMember::handle(const Enum& enum_) { \ EnumGetMember egm(*this); \ reflect_ ## Enum(const_cast(enum_), egm); \ } /// 'Tag' to be used when reflecting enumerations for GetMember class EnumGetMember { public: inline EnumGetMember(GetDefaultMember& gdm) : gdm(gdm) {} /// Handle a possible value for the enum, if the name matches the name in the input template inline void handle(const Char* name, Enum value, Enum enum_) { if (enum_ == value) { gdm.handle(String(name)); } } private: GetDefaultMember& gdm; ///< The object to store output in }; // ----------------------------------------------------------------------------- : EOF #endif