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,163 @@ inline CFTypeRef bridge_cast(NSObject *object)
273279 return (__bridge CFTypeRef)object;
274280}
275281
282+ inline id bridge_id_cast (CFTypeRef object)
283+ {
284+ return (__bridge id )object;
285+ }
286+
287+ inline RetainPtr<id > bridge_id_cast (RetainPtr<CFTypeRef>&& object)
288+ {
289+ #if __has_feature(objc_arc)
290+ return adoptNS ((__bridge_transfer id )object.leakRef ());
291+ #else
292+ return adoptNS ((__bridge id )object.leakRef ());
293+ #endif
294+ }
295+
296+ template <typename ExpectedType>
297+ struct ObjCTypeCastTraits {
298+ public:
299+ static bool isType (id object) { return [object isKindOfClass: [ExpectedType class ]]; }
300+
301+ template <typename ArgType>
302+ static bool isType (const ArgType *object) { return [object isKindOfClass: [ExpectedType class ]]; }
303+ };
304+
305+ template <typename ExpectedType, typename ArgType>
306+ inline bool is_objc (ArgType * source)
307+ {
308+ return source && ObjCTypeCastTraits<ExpectedType>::isType (source);
309+ }
310+
311+ template<typename T> inline T *checked_objc_cast (id object)
312+ {
313+ if (!object)
314+ return nullptr ;
315+
316+ if (!is_objc<T>(object))
317+ WTFCrash ();
318+
319+ return reinterpret_cast<T*>(object);
320+ }
321+
322+ template<typename T, typename U> inline T *checked_objc_cast (U *object)
323+ {
324+ if (!object)
325+ return nullptr ;
326+
327+ if (!is_objc<T>(object))
328+ WTFCrash ();
329+
330+ return static_cast<T*>(object);
331+ }
332+
333+ template<typename T, typename U> RetainPtr<T> dynamic_objc_cast (RetainPtr<U>&& object)
334+ {
335+ if (!is_objc<T>(object.get ()))
336+ return nullptr ;
337+ return adoptNS (static_cast<T*>(object.leakRef ()));
338+ }
339+
340+ template<typename T> RetainPtr<T> dynamic_objc_cast (RetainPtr<id >&& object)
341+ {
342+ if (!is_objc<T>(object.get ()))
343+ return nullptr ;
344+ return adoptNS (reinterpret_cast<T*>(object.leakRef ()));
345+ }
346+
347+ template<typename T, typename U> RetainPtr<T> dynamic_objc_cast (const RetainPtr<U>& object)
348+ {
349+ if (!is_objc<T>(object.get ()))
350+ return nullptr ;
351+ return static_cast<T*>(object.get ());
276352}
277353
354+ template<typename T> RetainPtr<T> dynamic_objc_cast (const RetainPtr<id >& object)
355+ {
356+ if (!is_objc<T>(object.get ()))
357+ return nullptr ;
358+ return reinterpret_cast<T*>(object.get ());
359+ }
360+
361+ template<typename T> T *dynamic_objc_cast (NSObject *object)
362+ {
363+ if (!is_objc<T>(object))
364+ return nullptr ;
365+ return static_cast<T*>(object);
366+ }
367+
368+ template<typename T> T *dynamic_objc_cast (id object)
369+ {
370+ if (!is_objc<T>(object))
371+ return nullptr ;
372+ return reinterpret_cast<T*>(object);
373+ }
374+
375+ template <typename> struct CFTypeTrait;
376+
377+ template<typename T> T dynamic_cf_cast (CFTypeRef object)
378+ {
379+ if (!object)
380+ return nullptr ;
381+
382+ if (CFGetTypeID (object) != CFTypeTrait<T>::typeID ())
383+ return nullptr ;
384+
385+ return static_cast<T>(const_cast<CF_BRIDGED_TYPE (id ) void *>(object));
386+ }
387+
388+ template<typename T> T checked_cf_cast (CFTypeRef object)
389+ {
390+ if (!object)
391+ return nullptr ;
392+
393+ if (CFGetTypeID (object) != CFTypeTrait<T>::typeID ())
394+ WTFCrash ();
395+
396+ return static_cast<T>(const_cast<CF_BRIDGED_TYPE (id ) void *>(object));
397+ }
398+
399+ template<typename T, typename U> RetainPtr<T> dynamic_cf_cast (RetainPtr<U>&& object)
400+ {
401+ if (!object)
402+ return nullptr ;
403+
404+ if (CFGetTypeID (object.get ()) != CFTypeTrait<T>::typeID ())
405+ return nullptr ;
406+
407+ return adoptCF (static_cast<T>(const_cast<CF_BRIDGED_TYPE (id ) void *>(object.leakRef ())));
408+ }
409+
410+ } // namespace WTF
411+
412+ #define WTF_DECLARE_CF_TYPE_TRAIT (ClassName ) \
413+ template <> \
414+ struct WTF::CFTypeTrait<ClassName##Ref> { \
415+ static inline CFTypeID typeID (void ) { return ClassName##GetTypeID (); } \
416+ };
417+
418+ WTF_DECLARE_CF_TYPE_TRAIT (CFArray);
419+ WTF_DECLARE_CF_TYPE_TRAIT (CFDictionary);
420+
421+ #define WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT (ClassName, MutableClassName ) \
422+ template <> \
423+ struct WTF::CFTypeTrait<MutableClassName##Ref> { \
424+ static inline CFTypeID typeID (void ) { return ClassName##GetTypeID (); } \
425+ };
426+
427+ WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT (CFArray, CFMutableArray);
428+ WTF_DECLARE_CF_MUTABLE_TYPE_TRAIT (CFDictionary, CFMutableDictionary);
429+
278430using WTF::RetainPtr;
279431using WTF::adoptNS;
280432using WTF::adoptCF;
281433using WTF::retainPtr;
282434using WTF::downcast;
283435using WTF::bridge_cast;
436+ using WTF::bridge_id_cast;
437+ using WTF::is_objc;
438+ using WTF::checked_objc_cast;
439+ using WTF::dynamic_objc_cast;
440+ using WTF::checked_cf_cast;
441+ using WTF::dynamic_cf_cast;
0 commit comments