diff options
author | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-03 04:29:10 +0000 |
---|---|---|
committer | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-03 04:29:10 +0000 |
commit | 0c3bf9563dcd51310abbf9856db4aba416a664bf (patch) | |
tree | 58393ab310ebe34e458f5725b2cae410ba1396f0 /base/mac | |
parent | 408292f44ad2b7087fae088ec10b1ad92470b4bd (diff) | |
download | chromium_src-0c3bf9563dcd51310abbf9856db4aba416a664bf.zip chromium_src-0c3bf9563dcd51310abbf9856db4aba416a664bf.tar.gz chromium_src-0c3bf9563dcd51310abbf9856db4aba416a664bf.tar.bz2 |
Clean up CF To NS Casts and make them slightly safer
Also adds streaming for CFStringRefs and CFErrorRefs making it
easier to add them to LOG() type statements.
BUG=NONE
TEST=BUILD
Review URL: http://codereview.chromium.org/6594096
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76714 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/mac')
-rw-r--r-- | base/mac/mac_util.h | 99 | ||||
-rw-r--r-- | base/mac/mac_util.mm | 72 |
2 files changed, 131 insertions, 40 deletions
diff --git a/base/mac/mac_util.h b/base/mac/mac_util.h index d75fb6e..990197d 100644 --- a/base/mac/mac_util.h +++ b/base/mac/mac_util.h @@ -110,57 +110,76 @@ void RemoveFromLoginItems(); // 'Login Item' with 'hide on startup' flag. Used to suppress opening windows. bool WasLaunchedAsHiddenLoginItem(); -#if defined(__OBJC__) +} // namespace mac +} // namespace base + +#if !defined(__OBJC__) +#define OBJC_CPP_CLASS_DECL(x) class x; +#else // __OBJC__ +#define OBJC_CPP_CLASS_DECL(x) +#endif // __OBJC__ -// Convert toll-free bridged CFTypes to NSTypes. This does not autorelease -// |cf_val|. This is useful for the case where there is a CFType in a call that -// expects an NSType and the compiler is complaining about const casting -// problems. -// The call is used like this: +// Convert toll-free bridged CFTypes to NSTypes and vice-versa. This does not +// autorelease |cf_val|. This is useful for the case where there is a CFType in +// a call that expects an NSType and the compiler is complaining about const +// casting problems. +// The calls are used like this: // NSString *foo = CFToNSCast(CFSTR("Hello")); +// CFStringRef foo2 = NSToCFCast(@"Hello"); // The macro magic below is to enforce safe casting. It could possibly have // been done using template function specialization, but template function // specialization doesn't always work intuitively, // (http://www.gotw.ca/publications/mill17.htm) so the trusty combination // of macros and function overloading is used instead. -#define CF_TO_NS_CAST(TypeCF, TypeNS) \ -inline TypeNS* CFToNSCast(TypeCF cf_val) { \ - TypeNS* ns_val = \ - const_cast<TypeNS*>(reinterpret_cast<const TypeNS*>(cf_val)); \ - DCHECK(!ns_val || [ns_val isKindOfClass:[TypeNS class]]); \ - return ns_val; \ -} +#define CF_TO_NS_CAST_DECL(TypeCF, TypeNS) \ +OBJC_CPP_CLASS_DECL(TypeNS) \ +\ +namespace base { \ +namespace mac { \ +TypeNS* CFToNSCast(TypeCF##Ref cf_val); \ +TypeCF##Ref NSToCFCast(TypeNS* ns_val); \ +} \ +} \ + +#define CF_TO_NS_MUTABLE_CAST_DECL(name) \ +CF_TO_NS_CAST_DECL(CF##name, NS##name) \ +OBJC_CPP_CLASS_DECL(NSMutable##name) \ +\ +namespace base { \ +namespace mac { \ +NSMutable##name* CFToNSCast(CFMutable##name##Ref cf_val); \ +CFMutable##name##Ref NSToCFCast(NSMutable##name* ns_val); \ +} \ +} \ // List of toll-free bridged types taken from: // http://www.cocoadev.com/index.pl?TollFreeBridged -CF_TO_NS_CAST(CFArrayRef, NSArray); -CF_TO_NS_CAST(CFMutableArrayRef, NSMutableArray); -CF_TO_NS_CAST(CFAttributedStringRef, NSAttributedString); -CF_TO_NS_CAST(CFMutableAttributedStringRef, NSMutableAttributedString); -CF_TO_NS_CAST(CFCalendarRef, NSCalendar); -CF_TO_NS_CAST(CFCharacterSetRef, NSCharacterSet); -CF_TO_NS_CAST(CFMutableCharacterSetRef, NSMutableCharacterSet); -CF_TO_NS_CAST(CFDataRef, NSData); -CF_TO_NS_CAST(CFMutableDataRef, NSMutableData); -CF_TO_NS_CAST(CFDateRef, NSDate); -CF_TO_NS_CAST(CFDictionaryRef, NSDictionary); -CF_TO_NS_CAST(CFMutableDictionaryRef, NSMutableDictionary); -CF_TO_NS_CAST(CFNumberRef, NSNumber); -CF_TO_NS_CAST(CFRunLoopTimerRef, NSTimer); -CF_TO_NS_CAST(CFSetRef, NSSet); -CF_TO_NS_CAST(CFMutableSetRef, NSMutableSet); -CF_TO_NS_CAST(CFStringRef, NSString); -CF_TO_NS_CAST(CFMutableStringRef, NSMutableString); -CF_TO_NS_CAST(CFURLRef, NSURL); -CF_TO_NS_CAST(CFTimeZoneRef, NSTimeZone); -CF_TO_NS_CAST(CFReadStreamRef, NSInputStream); -CF_TO_NS_CAST(CFWriteStreamRef, NSOutputStream); - -#endif // __OBJC__ - -} // namespace mac -} // namespace base +CF_TO_NS_MUTABLE_CAST_DECL(Array); +CF_TO_NS_MUTABLE_CAST_DECL(AttributedString); +CF_TO_NS_CAST_DECL(CFCalendar, NSCalendar); +CF_TO_NS_MUTABLE_CAST_DECL(CharacterSet); +CF_TO_NS_MUTABLE_CAST_DECL(Data); +CF_TO_NS_CAST_DECL(CFDate, NSDate); +CF_TO_NS_MUTABLE_CAST_DECL(Dictionary); +CF_TO_NS_CAST_DECL(CFError, NSError); +CF_TO_NS_CAST_DECL(CFLocale, NSLocale); +CF_TO_NS_CAST_DECL(CFNumber, NSNumber); +CF_TO_NS_CAST_DECL(CFRunLoopTimer, NSTimer); +CF_TO_NS_CAST_DECL(CFTimeZone, NSTimeZone); +CF_TO_NS_MUTABLE_CAST_DECL(Set); +CF_TO_NS_CAST_DECL(CFReadStream, NSInputStream); +CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream); +CF_TO_NS_MUTABLE_CAST_DECL(String); +CF_TO_NS_CAST_DECL(CFURL, NSURL); + +// Stream operations for CFTypes. They can be used with NSTypes as well +// by using the NSToCFCast methods above. +// e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); +// Operator << can not be overloaded for ObjectiveC types as the compiler +// can not distinguish between overloads for id with overloads for void*. +extern std::ostream& operator<<(std::ostream& o, const CFErrorRef err); +extern std::ostream& operator<<(std::ostream& o, const CFStringRef str); #endif // BASE_MAC_MAC_UTIL_H_ diff --git a/base/mac/mac_util.mm b/base/mac/mac_util.mm index 7f3be18..2eddeae 100644 --- a/base/mac/mac_util.mm +++ b/base/mac/mac_util.mm @@ -480,5 +480,77 @@ bool WasLaunchedAsHiddenLoginItem() { return IsHiddenLoginItem(item); } +// Definitions for the corresponding CF_TO_NS_CAST_DECL macros in mac_util.h. +#define CF_TO_NS_CAST_DEFN(TypeCF, TypeNS) \ +\ +TypeNS* CFToNSCast(TypeCF##Ref cf_val) { \ + DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \ + TypeNS* ns_val = \ + const_cast<TypeNS*>(reinterpret_cast<const TypeNS*>(cf_val)); \ + return ns_val; \ +} \ +\ +TypeCF##Ref NSToCFCast(TypeNS* ns_val) { \ + TypeCF##Ref cf_val = reinterpret_cast<TypeCF##Ref>(ns_val); \ + DCHECK(!cf_val || TypeCF##GetTypeID() == CFGetTypeID(cf_val)); \ + return cf_val; \ +} \ + +#define CF_TO_NS_MUTABLE_CAST_DEFN(name) \ +CF_TO_NS_CAST_DEFN(CF##name, NS##name) \ +\ +NSMutable##name* CFToNSCast(CFMutable##name##Ref cf_val) { \ + DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \ + NSMutable##name* ns_val = reinterpret_cast<NSMutable##name*>(cf_val); \ + return ns_val; \ +} \ +\ +CFMutable##name##Ref NSToCFCast(NSMutable##name* ns_val) { \ + CFMutable##name##Ref cf_val = \ + reinterpret_cast<CFMutable##name##Ref>(ns_val); \ + DCHECK(!cf_val || CF##name##GetTypeID() == CFGetTypeID(cf_val)); \ + return cf_val; \ +} \ + +CF_TO_NS_MUTABLE_CAST_DEFN(Array); +CF_TO_NS_MUTABLE_CAST_DEFN(AttributedString); +CF_TO_NS_CAST_DEFN(CFCalendar, NSCalendar); +CF_TO_NS_MUTABLE_CAST_DEFN(CharacterSet); +CF_TO_NS_MUTABLE_CAST_DEFN(Data); +CF_TO_NS_CAST_DEFN(CFDate, NSDate); +CF_TO_NS_MUTABLE_CAST_DEFN(Dictionary); +CF_TO_NS_CAST_DEFN(CFError, NSError); +CF_TO_NS_CAST_DEFN(CFLocale, NSLocale); +CF_TO_NS_CAST_DEFN(CFNumber, NSNumber); +CF_TO_NS_CAST_DEFN(CFRunLoopTimer, NSTimer); +CF_TO_NS_CAST_DEFN(CFTimeZone, NSTimeZone); +CF_TO_NS_MUTABLE_CAST_DEFN(Set); +CF_TO_NS_CAST_DEFN(CFReadStream, NSInputStream); +CF_TO_NS_CAST_DEFN(CFWriteStream, NSOutputStream); +CF_TO_NS_MUTABLE_CAST_DEFN(String); +CF_TO_NS_CAST_DEFN(CFURL, NSURL); + } // namespace mac } // namespace base + +std::ostream& operator<<(std::ostream& o, const CFStringRef string) { + return o << base::SysCFStringRefToUTF8(string); +} + +std::ostream& operator<<(std::ostream& o, const CFErrorRef err) { + base::mac::ScopedCFTypeRef<CFStringRef> desc(CFErrorCopyDescription(err)); + base::mac::ScopedCFTypeRef<CFDictionaryRef> user_info( + CFErrorCopyUserInfo(err)); + CFStringRef errorDesc = NULL; + if (user_info.get()) { + errorDesc = reinterpret_cast<CFStringRef>( + CFDictionaryGetValue(user_info.get(), kCFErrorDescriptionKey)); + } + o << "Code: " << CFErrorGetCode(err) + << " Domain: " << CFErrorGetDomain(err) + << " Desc: " << desc.get(); + if(errorDesc) { + o << "(" << errorDesc << ")"; + } + return o; +} |