55#define CF_BRIDGED_TYPE (T ) __attribute__((objc_bridge(T)))
66#define CF_BRIDGED_MUTABLE_TYPE (T ) __attribute__((objc_bridge_mutable(T)))
77typedef CF_BRIDGED_TYPE (id ) void * CFTypeRef;
8+ typedef unsigned long long CFTypeID;
89typedef signed char BOOL ;
910typedef unsigned char Boolean;
1011typedef signed long CFIndex;
@@ -21,6 +22,8 @@ typedef struct CF_BRIDGED_MUTABLE_TYPE(CFRunLoopRef) __CFRunLoop * CFRunLoopRef;
2122
2223extern const CFAllocatorRef kCFAllocatorDefault;
2324typedef struct _NSZone NSZone ;
25+ CFTypeID CFGetTypeID (CFTypeRef cf);
26+ CFTypeID CFArrayGetTypeID ();
2427CFMutableArrayRef CFArrayCreateMutable (CFAllocatorRef allocator, CFIndex capacity);
2528extern void CFArrayAppendValue (CFMutableArrayRef theArray, const void *value);
2629CFArrayRef CFArrayCreate (CFAllocatorRef allocator, const void **values, CFIndex numValues);
@@ -29,6 +32,7 @@ CFIndex CFArrayGetCount(CFArrayRef theArray);
2932typedef const struct CF_BRIDGED_TYPE (NSDictionary ) __CFDictionary * CFDictionaryRef;
3033typedef struct CF_BRIDGED_MUTABLE_TYPE (NSMutableDictionary ) __CFDictionary * CFMutableDictionaryRef;
3134
35+ CFTypeID CFDictionaryGetTypeID ();
3236CFDictionaryRef CFDictionaryCreate (CFAllocatorRef allocator, const void **keys, const void **values, CFIndex numValues);
3337CFDictionaryRef CFDictionaryCreateCopy (CFAllocatorRef allocator, CFDictionaryRef theDict);
3438CFDictionaryRef CFDictionaryCreateMutableCopy (CFAllocatorRef allocator, CFIndex capacity, CFDictionaryRef theDict);
@@ -135,6 +139,8 @@ __attribute__((objc_root_class))
135139
136140namespace WTF {
137141
142+ void WTFCrash (void );
143+
138144template<typename T> class RetainPtr;
139145template<typename T> RetainPtr<T> adoptNS (T*);
140146template<typename T> RetainPtr<T> adoptCF (T);
@@ -273,11 +279,148 @@ inline CFTypeRef bridge_cast(NSObject *object)
273279 return (__bridge CFTypeRef)object;
274280}
275281
282+ template <typename ExpectedType>
283+ struct ObjCTypeCastTraits {
284+ public:
285+ static bool isType (id object) { return [object isKindOfClass: [ExpectedType class ]]; }
286+
287+ template <typename ArgType>
288+ static bool isType (const ArgType *object) { return [object isKindOfClass: [ExpectedType class ]]; }
289+ };
290+
291+ template <typename ExpectedType, typename ArgType>
292+ inline bool is_objc (ArgType * source)
293+ {
294+ return source && ObjCTypeCastTraits<ExpectedType>::isType (source);
295+ }
296+
297+ template<typename T> inline T *checked_objc_cast (id object)
298+ {
299+ if (!object)
300+ return nullptr ;
301+
302+ if (!is_objc<T>(object))
303+ WTFCrash ();
304+
305+ return reinterpret_cast<T*>(object);
306+ }
307+
308+ template<typename T, typename U> inline T *checked_objc_cast (U *object)
309+ {
310+ if (!object)
311+ return nullptr ;
312+
313+ if (!is_objc<T>(object))
314+ WTFCrash ();
315+
316+ return static_cast<T*>(object);
317+ }
318+
319+ template<typename T, typename U> RetainPtr<T> dynamic_objc_cast (RetainPtr<U>&& object)
320+ {
321+ if (!is_objc<T>(object.get ()))
322+ return nullptr ;
323+ return adoptNS (static_cast<T*>(object.leakRef ()));
324+ }
325+
326+ template<typename T> RetainPtr<T> dynamic_objc_cast (RetainPtr<id >&& object)
327+ {
328+ if (!is_objc<T>(object.get ()))
329+ return nullptr ;
330+ return adoptNS (reinterpret_cast<T*>(object.leakRef ()));
331+ }
332+
333+ template<typename T, typename U> RetainPtr<T> dynamic_objc_cast (const RetainPtr<U>& object)
334+ {
335+ if (!is_objc<T>(object.get ()))
336+ return nullptr ;
337+ return static_cast<T*>(object.get ());
338+ }
339+
340+ template<typename T> RetainPtr<T> dynamic_objc_cast (const RetainPtr<id >& object)
341+ {
342+ if (!is_objc<T>(object.get ()))
343+ return nullptr ;
344+ return reinterpret_cast<T*>(object.get ());
345+ }
346+
347+ template<typename T> T *dynamic_objc_cast (NSObject *object)
348+ {
349+ if (!is_objc<T>(object))
350+ return nullptr ;
351+ return static_cast<T*>(object);
352+ }
353+
354+ template<typename T> T *dynamic_objc_cast (id object)
355+ {
356+ if (!is_objc<T>(object))
357+ return nullptr ;
358+ return reinterpret_cast<T*>(object);
359+ }
360+
361+ template <typename> struct CFTypeTrait;
362+
363+ template<typename T> T dynamic_cf_cast (CFTypeRef object)
364+ {
365+ if (!object)
366+ return nullptr ;
367+
368+ if (CFGetTypeID (object) != CFTypeTrait<T>::typeID ())
369+ return nullptr ;
370+
371+ return static_cast<T>(const_cast<CF_BRIDGED_TYPE (id ) void *>(object));
372+ }
373+
374+ template<typename T> T checked_cf_cast (CFTypeRef object)
375+ {
376+ if (!object)
377+ return nullptr ;
378+
379+ if (CFGetTypeID (object) != CFTypeTrait<T>::typeID ())
380+ WTFCrash ();
381+
382+ return static_cast<T>(const_cast<CF_BRIDGED_TYPE (id ) void *>(object));
383+ }
384+
385+ template<typename T, typename U> RetainPtr<T> dynamic_cf_cast (RetainPtr<U>&& object)
386+ {
387+ if (!object)
388+ return nullptr ;
389+
390+ if (CFGetTypeID (object.get ()) != CFTypeTrait<T>::typeID ())
391+ return nullptr ;
392+
393+ return adoptCF (static_cast<T>(const_cast<CF_BRIDGED_TYPE (id ) void *>(object.leakRef ())));
276394}
277395
396+ } // namespace WTF
397+
398+ #define WTF_DECLARE_CF_TYPE_TRAIT (ClassName ) \
399+ template <> \
400+ struct WTF::CFTypeTrait<ClassName##Ref> { \
401+ static inline CFTypeID typeID (void ) { return ClassName##GetTypeID (); } \
402+ };
403+
404+ WTF_DECLARE_CF_TYPE_TRAIT (CFArray);
405+ WTF_DECLARE_CF_TYPE_TRAIT (CFDictionary);
406+
407+ #define WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT (ClassName, MutableClassName ) \
408+ template <> \
409+ struct WTF::CFTypeTrait<MutableClassName##Ref> { \
410+ static inline CFTypeID typeID (void ) { return ClassName##GetTypeID (); } \
411+ };
412+
413+ WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT (CFArray, CFMutableArray);
414+ WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT (CFDictionary, CFMutableDictionary);
415+
278416using WTF::RetainPtr;
279417using WTF::adoptNS;
280418using WTF::adoptCF;
281419using WTF::retainPtr;
282420using WTF::downcast;
283421using WTF::bridge_cast;
422+ using WTF::is_objc;
423+ using WTF::checked_objc_cast;
424+ using WTF::dynamic_objc_cast;
425+ using WTF::checked_cf_cast;
426+ using WTF::dynamic_cf_cast;
0 commit comments