129 lines
7.1 KiB
C
129 lines
7.1 KiB
C
|
#ifndef SEAD_RUNTIMETYPEINFO_H_
|
||
|
#define SEAD_RUNTIMETYPEINFO_H_
|
||
|
|
||
|
namespace sead
|
||
|
{
|
||
|
namespace RuntimeTypeInfo
|
||
|
{
|
||
|
class Interface
|
||
|
{
|
||
|
public:
|
||
|
Interface() {}
|
||
|
|
||
|
virtual bool isDerived(const Interface* typeInfo) const = 0;
|
||
|
};
|
||
|
|
||
|
class Root : public Interface
|
||
|
{
|
||
|
public:
|
||
|
Root() {}
|
||
|
|
||
|
bool isDerived(const Interface* typeInfo) const override { return typeInfo == this; }
|
||
|
};
|
||
|
|
||
|
template <typename BaseType>
|
||
|
class Derive : public Interface
|
||
|
{
|
||
|
public:
|
||
|
Derive() {}
|
||
|
|
||
|
bool isDerived(const Interface* typeInfo) const override
|
||
|
{
|
||
|
if (this == typeInfo)
|
||
|
return true;
|
||
|
|
||
|
const RuntimeTypeInfo::Interface* rootTypeInfo = BaseType::getRuntimeTypeInfoStatic();
|
||
|
return rootTypeInfo->isDerived(typeInfo);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
} // namespace RuntimeTypeInfo
|
||
|
|
||
|
/// Tests if the object is a DerivedType or any type that derives from (i.e. inherits) DerivedType.
|
||
|
template <typename DerivedType, typename Type>
|
||
|
inline bool IsDerivedFrom(const Type* obj)
|
||
|
{
|
||
|
const RuntimeTypeInfo::Interface* typeInfo = DerivedType::getRuntimeTypeInfoStatic();
|
||
|
return obj != nullptr && obj->checkDerivedRuntimeTypeInfo(typeInfo);
|
||
|
}
|
||
|
|
||
|
/// If the object is a DerivedType or any type that derives from (i.e. inherits) DerivedType,
|
||
|
/// this returns obj casted to DerivedType* -- otherwise this returns nullptr.
|
||
|
///
|
||
|
/// @note This is similar to C++'s dynamic_cast or LLVM's dyn_cast but only works with types
|
||
|
/// that use the sead RTTI mechanism.
|
||
|
template <typename DerivedType, typename Type>
|
||
|
inline DerivedType* DynamicCast(Type* obj)
|
||
|
{
|
||
|
if (IsDerivedFrom<DerivedType, Type>(obj))
|
||
|
return static_cast<DerivedType*>(obj);
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
} // namespace sead
|
||
|
|
||
|
/// Use this macro to declare sead RTTI machinery for a base class.
|
||
|
/// You must use SEAD_RTTI_OVERRIDE in all derived classes.
|
||
|
/// @param CLASS The name of the class.
|
||
|
#define SEAD_RTTI_BASE(CLASS) \
|
||
|
public: \
|
||
|
static const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfoStatic() \
|
||
|
{ \
|
||
|
static const sead::RuntimeTypeInfo::Root typeInfo; \
|
||
|
return &typeInfo; \
|
||
|
} \
|
||
|
\
|
||
|
static bool checkDerivedRuntimeTypeInfoStatic( \
|
||
|
const sead::RuntimeTypeInfo::Interface* typeInfo) \
|
||
|
{ \
|
||
|
const sead::RuntimeTypeInfo::Interface* clsTypeInfo = CLASS::getRuntimeTypeInfoStatic(); \
|
||
|
return typeInfo == clsTypeInfo; \
|
||
|
} \
|
||
|
\
|
||
|
virtual bool checkDerivedRuntimeTypeInfo(const sead::RuntimeTypeInfo::Interface* typeInfo) \
|
||
|
const \
|
||
|
{ \
|
||
|
return checkDerivedRuntimeTypeInfoStatic(typeInfo); \
|
||
|
} \
|
||
|
\
|
||
|
virtual const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfo() const \
|
||
|
{ \
|
||
|
return getRuntimeTypeInfoStatic(); \
|
||
|
}
|
||
|
|
||
|
/// Use this macro to declare sead RTTI machinery for a derived class.
|
||
|
/// @param CLASS The name of the class.
|
||
|
/// @param BASE The name of the base class of CLASS.
|
||
|
#define SEAD_RTTI_OVERRIDE(CLASS, BASE) \
|
||
|
public: \
|
||
|
static const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfoStatic() \
|
||
|
{ \
|
||
|
static const sead::RuntimeTypeInfo::Derive<BASE> typeInfo; \
|
||
|
return &typeInfo; \
|
||
|
} \
|
||
|
\
|
||
|
static bool checkDerivedRuntimeTypeInfoStatic( \
|
||
|
const sead::RuntimeTypeInfo::Interface* typeInfo) \
|
||
|
\
|
||
|
{ \
|
||
|
const sead::RuntimeTypeInfo::Interface* clsTypeInfo = CLASS::getRuntimeTypeInfoStatic(); \
|
||
|
if (typeInfo == clsTypeInfo) \
|
||
|
return true; \
|
||
|
\
|
||
|
return BASE::checkDerivedRuntimeTypeInfoStatic(typeInfo); \
|
||
|
} \
|
||
|
\
|
||
|
bool checkDerivedRuntimeTypeInfo(const sead::RuntimeTypeInfo::Interface* typeInfo) \
|
||
|
const override \
|
||
|
{ \
|
||
|
return checkDerivedRuntimeTypeInfoStatic(typeInfo); \
|
||
|
} \
|
||
|
\
|
||
|
const sead::RuntimeTypeInfo::Interface* getRuntimeTypeInfo() const override \
|
||
|
{ \
|
||
|
return getRuntimeTypeInfoStatic(); \
|
||
|
}
|
||
|
|
||
|
#endif // SEAD_RUNTIMETYPEINFO_H_
|