summaryrefslogtreecommitdiffstats
path: root/base/mac
diff options
context:
space:
mode:
authordmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-03 04:29:10 +0000
committerdmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-03 04:29:10 +0000
commit0c3bf9563dcd51310abbf9856db4aba416a664bf (patch)
tree58393ab310ebe34e458f5725b2cae410ba1396f0 /base/mac
parent408292f44ad2b7087fae088ec10b1ad92470b4bd (diff)
downloadchromium_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.h99
-rw-r--r--base/mac/mac_util.mm72
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;
+}