#ifndef BASE_MAC_BRIDGING_H_
#define BASE_MAC_BRIDGING_H_
#include <CoreText/CoreText.h>
#import <Foundation/Foundation.h>
#include "base/base_export.h"
#include "base/check.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_IOS)
#import <UIKit/UIKit.h>
#endif
#if BUILDFLAG(IS_MAC)
#import <AppKit/AppKit.h>
#endif
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "base/mac/bridging.h requires ARC."
#endif
#define CF_TO_NS_CAST_IMPL(TypeCF, TypeNS) \
namespace base::mac { \
inline BASE_EXPORT TypeNS* _Nullable CFToNSOwnershipCast( \
TypeCF##Ref CF_CONSUMED _Nullable cf_val) { \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge_transfer TypeNS*)cf_val; \
} \
inline BASE_EXPORT CF_RETURNS_RETAINED \
TypeCF##Ref _Nullable NSToCFOwnershipCast(TypeNS* _Nullable ns_val) { \
TypeCF##Ref cf_val = (__bridge_retained TypeCF##Ref)ns_val; \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
inline BASE_EXPORT TypeNS* _Nullable CFToNSPtrCast( \
TypeCF##Ref _Nullable cf_val) { \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge TypeNS*)cf_val; \
} \
inline BASE_EXPORT TypeCF##Ref _Nullable NSToCFPtrCast( \
TypeNS* _Nullable ns_val) { \
TypeCF##Ref cf_val = (__bridge TypeCF##Ref)ns_val; \
DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
}
#define CF_TO_NS_MUTABLE_CAST_IMPL(name) \
CF_TO_NS_CAST_IMPL(CF##name, NS##name) \
namespace base::mac { \
inline BASE_EXPORT NSMutable##name* _Nullable CFToNSOwnershipCast( \
CFMutable##name##Ref CF_CONSUMED _Nullable cf_val) { \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge_transfer NSMutable##name*)cf_val; \
} \
inline BASE_EXPORT CF_RETURNS_RETAINED \
CFMutable##name##Ref _Nullable NSToCFOwnershipCast( \
NSMutable##name* _Nullable ns_val) { \
CFMutable##name##Ref cf_val = \
(__bridge_retained CFMutable##name##Ref)ns_val; \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
inline BASE_EXPORT NSMutable##name* _Nullable CFToNSPtrCast( \
CFMutable##name##Ref _Nullable cf_val) { \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return (__bridge NSMutable##name*)cf_val; \
} \
inline BASE_EXPORT CFMutable##name##Ref _Nullable NSToCFPtrCast( \
NSMutable##name* _Nullable ns_val) { \
CFMutable##name##Ref cf_val = (__bridge CFMutable##name##Ref)ns_val; \
DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \
return cf_val; \
} \
}
CF_TO_NS_MUTABLE_CAST_IMPL(Array)
CF_TO_NS_MUTABLE_CAST_IMPL(AttributedString)
CF_TO_NS_CAST_IMPL(CFCalendar, NSCalendar)
CF_TO_NS_MUTABLE_CAST_IMPL(CharacterSet)
CF_TO_NS_MUTABLE_CAST_IMPL(Data)
CF_TO_NS_CAST_IMPL(CFDate, NSDate)
CF_TO_NS_MUTABLE_CAST_IMPL(Dictionary)
CF_TO_NS_CAST_IMPL(CFError, NSError)
CF_TO_NS_CAST_IMPL(CFLocale, NSLocale)
CF_TO_NS_CAST_IMPL(CFNumber, NSNumber)
CF_TO_NS_CAST_IMPL(CFRunLoopTimer, NSTimer)
CF_TO_NS_CAST_IMPL(CFTimeZone, NSTimeZone)
CF_TO_NS_MUTABLE_CAST_IMPL(Set)
CF_TO_NS_CAST_IMPL(CFReadStream, NSInputStream)
CF_TO_NS_CAST_IMPL(CFWriteStream, NSOutputStream)
CF_TO_NS_MUTABLE_CAST_IMPL(String)
CF_TO_NS_CAST_IMPL(CFURL, NSURL)
#if BUILDFLAG(IS_IOS)
CF_TO_NS_CAST_IMPL(CTFont, UIFont)
#else
extern "C" {
Boolean _CFIsObjC(CFTypeID typeID, _Nonnull CFTypeRef obj);
}
namespace base::mac {
inline BASE_EXPORT NSFont* _Nullable CFToNSOwnershipCast(
CTFontRef CF_CONSUMED _Nullable cf_val) {
NSFont* ns_val = (__bridge_transfer NSFont*)cf_val;
DCHECK(!cf_val || CTFontGetTypeID() == CFGetTypeID(cf_val) ||
(_CFIsObjC(CTFontGetTypeID(), cf_val) &&
[ns_val isKindOfClass:[NSFont class]]));
return ns_val;
}
inline BASE_EXPORT CF_RETURNS_RETAINED _Nullable CTFontRef NSToCFOwnershipCast(
NSFont* _Nullable ns_val) {
CTFontRef cf_val = (__bridge_retained CTFontRef)ns_val;
DCHECK(!cf_val || CTFontGetTypeID() == CFGetTypeID(cf_val) ||
[ns_val isKindOfClass:[NSFont class]]);
return cf_val;
}
inline BASE_EXPORT NSFont* _Nullable CFToNSPtrCast(CTFontRef _Nullable cf_val) {
NSFont* ns_val = (__bridge NSFont*)cf_val;
DCHECK(!cf_val || CTFontGetTypeID() == CFGetTypeID(cf_val) ||
(_CFIsObjC(CTFontGetTypeID(), cf_val) &&
[ns_val isKindOfClass:[NSFont class]]));
return ns_val;
}
inline BASE_EXPORT _Nullable CTFontRef NSToCFPtrCast(NSFont* _Nullable ns_val) {
CTFontRef cf_val = (__bridge CTFontRef)ns_val;
DCHECK(!cf_val || CTFontGetTypeID() == CFGetTypeID(cf_val) ||
[ns_val isKindOfClass:[NSFont class]]);
return cf_val;
}
}
#endif
#undef CF_TO_NS_CAST_IMPL
#undef CF_TO_NS_MUTABLE_CAST_IMPL
#endif