================ @@ -273,11 +279,148 @@ inline CFTypeRef bridge_cast(NSObject *object) return (__bridge CFTypeRef)object; } +template <typename ExpectedType> +struct ObjCTypeCastTraits { +public: + static bool isType(id object) { return [object isKindOfClass:[ExpectedType class]]; } + + template <typename ArgType> + static bool isType(const ArgType *object) { return [object isKindOfClass:[ExpectedType class]]; } +}; + +template <typename ExpectedType, typename ArgType> +inline bool is_objc(ArgType * source) +{ + return source && ObjCTypeCastTraits<ExpectedType>::isType(source); +} + +template<typename T> inline T *checked_objc_cast(id object) +{ + if (!object) + return nullptr; + + if (!is_objc<T>(object)) + WTFCrash(); + + return reinterpret_cast<T*>(object); +} + +template<typename T, typename U> inline T *checked_objc_cast(U *object) +{ + if (!object) + return nullptr; + + if (!is_objc<T>(object)) + WTFCrash(); + + return static_cast<T*>(object); +} + +template<typename T, typename U> RetainPtr<T> dynamic_objc_cast(RetainPtr<U>&& object) +{ + if (!is_objc<T>(object.get())) + return nullptr; + return adoptNS(static_cast<T*>(object.leakRef())); +} + +template<typename T> RetainPtr<T> dynamic_objc_cast(RetainPtr<id>&& object) +{ + if (!is_objc<T>(object.get())) + return nullptr; + return adoptNS(reinterpret_cast<T*>(object.leakRef())); +} + +template<typename T, typename U> RetainPtr<T> dynamic_objc_cast(const RetainPtr<U>& object) +{ + if (!is_objc<T>(object.get())) + return nullptr; + return static_cast<T*>(object.get()); +} + +template<typename T> RetainPtr<T> dynamic_objc_cast(const RetainPtr<id>& object) +{ + if (!is_objc<T>(object.get())) + return nullptr; + return reinterpret_cast<T*>(object.get()); +} + +template<typename T> T *dynamic_objc_cast(NSObject *object) +{ + if (!is_objc<T>(object)) + return nullptr; + return static_cast<T*>(object); +} + +template<typename T> T *dynamic_objc_cast(id object) +{ + if (!is_objc<T>(object)) + return nullptr; + return reinterpret_cast<T*>(object); +} + +template <typename> struct CFTypeTrait; + +template<typename T> T dynamic_cf_cast(CFTypeRef object) +{ + if (!object) + return nullptr; + + if (CFGetTypeID(object) != CFTypeTrait<T>::typeID()) + return nullptr; + + return static_cast<T>(const_cast<CF_BRIDGED_TYPE(id) void*>(object)); +} + +template<typename T> T checked_cf_cast(CFTypeRef object) +{ + if (!object) + return nullptr; + + if (CFGetTypeID(object) != CFTypeTrait<T>::typeID()) + WTFCrash(); + + return static_cast<T>(const_cast<CF_BRIDGED_TYPE(id) void*>(object)); +} + +template<typename T, typename U> RetainPtr<T> dynamic_cf_cast(RetainPtr<U>&& object) +{ + if (!object) + return nullptr; + + if (CFGetTypeID(object.get()) != CFTypeTrait<T>::typeID()) + return nullptr; + + return adoptCF(static_cast<T>(const_cast<CF_BRIDGED_TYPE(id) void*>(object.leakRef()))); } +} // namespace WTF + +#define WTF_DECLARE_CF_TYPE_TRAIT(ClassName) \ +template <> \ +struct WTF::CFTypeTrait<ClassName##Ref> { \ + static inline CFTypeID typeID(void) { return ClassName##GetTypeID(); } \ +}; + +WTF_DECLARE_CF_TYPE_TRAIT(CFArray); +WTF_DECLARE_CF_TYPE_TRAIT(CFDictionary); + +#define WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT(ClassName, MutableClassName) \ +template <> \ +struct WTF::CFTypeTrait<MutableClassName##Ref> { \ + static inline CFTypeID typeID(void) { return ClassName##GetTypeID(); } \ +}; + +WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT(CFArray, CFMutableArray); +WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT(CFDictionary, CFMutableDictionary); + using WTF::RetainPtr; using WTF::adoptNS; using WTF::adoptCF; using WTF::retainPtr; using WTF::downcast; using WTF::bridge_cast; +using WTF::is_objc; +using WTF::checked_objc_cast; +using WTF::dynamic_objc_cast; +using WTF::checked_cf_cast; +using WTF::dynamic_cf_cast; ---------------- rniwa wrote:
oh yeah, indeed, I'm missing `bridge_cast` and `bridge_id_cast`. https://github.com/llvm/llvm-project/pull/132784 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits