================
@@ -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:

Added a new test case for this.

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

Reply via email to