| 1 | #ifndef SEAD_RUNTIMETYPEINFO_H_ |
| 2 | #define SEAD_RUNTIMETYPEINFO_H_ |
| 3 | |
| 4 | namespace sead |
| 5 | { |
| 6 | namespace RuntimeTypeInfo |
| 7 | { |
| 8 | class Interface |
| 9 | { |
| 10 | public: |
| 11 | Interface() {} |
| 12 | |
| 13 | virtual bool isDerived(const Interface* typeInfo) const = 0; |
| 14 | }; |
| 15 | |
| 16 | class Root : public Interface |
| 17 | { |
| 18 | public: |
| 19 | Root() {} |
| 20 | |
| 21 | bool isDerived(const Interface* typeInfo) const override { return typeInfo == this; } |
| 22 | }; |
| 23 | |
| 24 | template <typename BaseType> |
| 25 | class Derive : public Interface |
| 26 | { |
| 27 | public: |
| 28 | Derive() {} |
| 29 | |
| 30 | bool isDerived(const Interface* typeInfo) const override |
| 31 | { |
| 32 | if (this == typeInfo) |
| 33 | return true; |
| 34 | |
| 35 | const RuntimeTypeInfo::Interface* rootTypeInfo = BaseType::getRuntimeTypeInfoStatic(); |
| 36 | return rootTypeInfo->isDerived(typeInfo); |
| 37 | } |
| 38 | }; |
| 39 | |
| 40 | } // namespace RuntimeTypeInfo |
| 41 | |
| 42 | /// Tests if the object is a DerivedType or any type that derives from (i.e. inherits) DerivedType. |
| 43 | template <typename DerivedType, typename Type> |
| 44 | inline bool IsDerivedFrom(const Type* obj) |
| 45 | { |
| 46 | const RuntimeTypeInfo::Interface* typeInfo = DerivedType::getRuntimeTypeInfoStatic(); |
| 47 | return obj != nullptr && obj->checkDerivedRuntimeTypeInfo(typeInfo); |
| 48 | } |
| 49 | |
| 50 | /// If the object is a DerivedType or any type that derives from (i.e. inherits) DerivedType, |
| 51 | /// this returns obj casted to DerivedType* -- otherwise this returns nullptr. |
| 52 | /// |
| 53 | /// @note This is similar to C++'s dynamic_cast or LLVM's dyn_cast but only works with types |
| 54 | /// that use the sead RTTI mechanism. |
| 55 | template <typename DerivedType, typename Type> |
| 56 | inline DerivedType* DynamicCast(Type* obj) |
| 57 | { |
| 58 | if (IsDerivedFrom<DerivedType, Type>(obj)) |
| 59 | return static_cast<DerivedType*>(obj); |
| 60 | |
| 61 | return nullptr; |
| 62 | } |
| 63 | |
| 64 | } // namespace sead |
| 65 | |
| 66 | /// Use this macro to declare sead RTTI machinery for a base class. |
| 67 | /// You must use SEAD_RTTI_OVERRIDE in all derived classes. |
| 68 | /// @param CLASS The name of the class. |
| 69 | #define SEAD_RTTI_BASE(CLASS) \ |
| 70 | public: \ |
| 71 | static const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfoStatic() \ |
| 72 | { \ |
| 73 | static const sead::RuntimeTypeInfo::Root typeInfo; \ |
| 74 | return &typeInfo; \ |
| 75 | } \ |
| 76 | \ |
| 77 | static bool checkDerivedRuntimeTypeInfoStatic( \ |
| 78 | const sead::RuntimeTypeInfo::Interface* typeInfo) \ |
| 79 | { \ |
| 80 | const sead::RuntimeTypeInfo::Interface* clsTypeInfo = CLASS::getRuntimeTypeInfoStatic(); \ |
| 81 | return typeInfo == clsTypeInfo; \ |
| 82 | } \ |
| 83 | \ |
| 84 | virtual bool checkDerivedRuntimeTypeInfo(const sead::RuntimeTypeInfo::Interface* typeInfo) \ |
| 85 | const \ |
| 86 | { \ |
| 87 | return checkDerivedRuntimeTypeInfoStatic(typeInfo); \ |
| 88 | } \ |
| 89 | \ |
| 90 | virtual const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfo() const \ |
| 91 | { \ |
| 92 | return getRuntimeTypeInfoStatic(); \ |
| 93 | } |
| 94 | |
| 95 | /// Use this macro to declare sead RTTI machinery for a derived class. |
| 96 | /// @param CLASS The name of the class. |
| 97 | /// @param BASE The name of the base class of CLASS. |
| 98 | #define SEAD_RTTI_OVERRIDE(CLASS, BASE) \ |
| 99 | public: \ |
| 100 | static const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfoStatic() \ |
| 101 | { \ |
| 102 | static const sead::RuntimeTypeInfo::Derive<BASE> typeInfo; \ |
| 103 | return &typeInfo; \ |
| 104 | } \ |
| 105 | \ |
| 106 | static bool checkDerivedRuntimeTypeInfoStatic( \ |
| 107 | const sead::RuntimeTypeInfo::Interface* typeInfo) \ |
| 108 | \ |
| 109 | { \ |
| 110 | const sead::RuntimeTypeInfo::Interface* clsTypeInfo = CLASS::getRuntimeTypeInfoStatic(); \ |
| 111 | if (typeInfo == clsTypeInfo) \ |
| 112 | return true; \ |
| 113 | \ |
| 114 | return BASE::checkDerivedRuntimeTypeInfoStatic(typeInfo); \ |
| 115 | } \ |
| 116 | \ |
| 117 | bool checkDerivedRuntimeTypeInfo(const sead::RuntimeTypeInfo::Interface* typeInfo) \ |
| 118 | const override \ |
| 119 | { \ |
| 120 | return checkDerivedRuntimeTypeInfoStatic(typeInfo); \ |
| 121 | } \ |
| 122 | \ |
| 123 | const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfo() const override \ |
| 124 | { \ |
| 125 | return getRuntimeTypeInfoStatic(); \ |
| 126 | } |
| 127 | |
| 128 | #endif // SEAD_RUNTIMETYPEINFO_H_ |
| 129 | |