| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_MAC_FOUNDATION_UTIL_H_ | 5 #ifndef BASE_MAC_FOUNDATION_UTIL_H_ |
| 6 #define BASE_MAC_FOUNDATION_UTIL_H_ | 6 #define BASE_MAC_FOUNDATION_UTIL_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <CoreFoundation/CoreFoundation.h> | 9 #include <CoreFoundation/CoreFoundation.h> |
| 10 | 10 |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/base_export.h" | 14 #include "base/base_export.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/mac/scoped_cftyperef.h" |
| 16 | 17 |
| 17 #if defined(__OBJC__) | 18 #if defined(__OBJC__) |
| 18 #import <Foundation/Foundation.h> | 19 #import <Foundation/Foundation.h> |
| 19 #else // __OBJC__ | 20 #else // __OBJC__ |
| 20 class NSBundle; | 21 class NSBundle; |
| 21 class NSString; | 22 class NSString; |
| 22 #endif // __OBJC__ | 23 #endif // __OBJC__ |
| 23 | 24 |
| 24 class FilePath; | 25 class FilePath; |
| 25 | 26 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 // Returns the ~/Library directory. | 90 // Returns the ~/Library directory. |
| 90 BASE_EXPORT FilePath GetUserLibraryPath(); | 91 BASE_EXPORT FilePath GetUserLibraryPath(); |
| 91 | 92 |
| 92 // Takes a path to an (executable) binary and tries to provide the path to an | 93 // Takes a path to an (executable) binary and tries to provide the path to an |
| 93 // application bundle containing it. It takes the outermost bundle that it can | 94 // application bundle containing it. It takes the outermost bundle that it can |
| 94 // find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app"). | 95 // find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app"). |
| 95 // |exec_name| - path to the binary | 96 // |exec_name| - path to the binary |
| 96 // returns - path to the application bundle, or empty on error | 97 // returns - path to the application bundle, or empty on error |
| 97 BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name); | 98 BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name); |
| 98 | 99 |
| 100 #define TYPE_NAME_FOR_CF_TYPE_DECL(TypeCF) \ |
| 101 std::string TypeNameForCFType(TypeCF##Ref); |
| 102 |
| 103 TYPE_NAME_FOR_CF_TYPE_DECL(CFArray); |
| 104 TYPE_NAME_FOR_CF_TYPE_DECL(CFBag); |
| 105 TYPE_NAME_FOR_CF_TYPE_DECL(CFBoolean); |
| 106 TYPE_NAME_FOR_CF_TYPE_DECL(CFData); |
| 107 TYPE_NAME_FOR_CF_TYPE_DECL(CFDate); |
| 108 TYPE_NAME_FOR_CF_TYPE_DECL(CFDictionary); |
| 109 TYPE_NAME_FOR_CF_TYPE_DECL(CFNull); |
| 110 TYPE_NAME_FOR_CF_TYPE_DECL(CFNumber); |
| 111 TYPE_NAME_FOR_CF_TYPE_DECL(CFSet); |
| 112 TYPE_NAME_FOR_CF_TYPE_DECL(CFString); |
| 113 |
| 114 #undef TYPE_NAME_FOR_CF_TYPE_DECL |
| 115 |
| 116 // Helper function for GetValueFromDictionary to create the error message |
| 117 // that appears when a type mismatch is encountered. |
| 118 std::string GetValueFromDictionaryErrorMessage( |
| 119 CFStringRef key, const std::string& expected_type, CFTypeRef value); |
| 120 |
| 99 // Utility function to pull out a value from a dictionary, check its type, and | 121 // Utility function to pull out a value from a dictionary, check its type, and |
| 100 // return it. Returns NULL if the key is not present or of the wrong type. | 122 // return it. Returns NULL if the key is not present or of the wrong type. |
| 123 // This is now deprecated in favor of the two-argument form below. |
| 124 // TODO(kushi.p): Remove this function once all cases of it have been |
| 125 // replaced with the two-argument form below. See: crbug.com/104200. |
| 101 BASE_EXPORT CFTypeRef GetValueFromDictionary(CFDictionaryRef dict, | 126 BASE_EXPORT CFTypeRef GetValueFromDictionary(CFDictionaryRef dict, |
| 102 CFStringRef key, | 127 CFStringRef key, |
| 103 CFTypeID expected_type); | 128 CFTypeID expected_type); |
| 104 | 129 |
| 105 // Retain/release calls for memory management in C++. | 130 // Retain/release calls for memory management in C++. |
| 106 BASE_EXPORT void NSObjectRetain(void* obj); | 131 BASE_EXPORT void NSObjectRetain(void* obj); |
| 107 BASE_EXPORT void NSObjectRelease(void* obj); | 132 BASE_EXPORT void NSObjectRelease(void* obj); |
| 108 | 133 |
| 109 // CFTypeRefToNSObjectAutorelease transfers ownership of a Core Foundation | 134 // CFTypeRefToNSObjectAutorelease transfers ownership of a Core Foundation |
| 110 // object (one derived from CFTypeRef) to the Foundation memory management | 135 // object (one derived from CFTypeRef) to the Foundation memory management |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 CF_TO_NS_CAST_DECL(CFLocale, NSLocale); | 216 CF_TO_NS_CAST_DECL(CFLocale, NSLocale); |
| 192 CF_TO_NS_CAST_DECL(CFNumber, NSNumber); | 217 CF_TO_NS_CAST_DECL(CFNumber, NSNumber); |
| 193 CF_TO_NS_CAST_DECL(CFRunLoopTimer, NSTimer); | 218 CF_TO_NS_CAST_DECL(CFRunLoopTimer, NSTimer); |
| 194 CF_TO_NS_CAST_DECL(CFTimeZone, NSTimeZone); | 219 CF_TO_NS_CAST_DECL(CFTimeZone, NSTimeZone); |
| 195 CF_TO_NS_MUTABLE_CAST_DECL(Set); | 220 CF_TO_NS_MUTABLE_CAST_DECL(Set); |
| 196 CF_TO_NS_CAST_DECL(CFReadStream, NSInputStream); | 221 CF_TO_NS_CAST_DECL(CFReadStream, NSInputStream); |
| 197 CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream); | 222 CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream); |
| 198 CF_TO_NS_MUTABLE_CAST_DECL(String); | 223 CF_TO_NS_MUTABLE_CAST_DECL(String); |
| 199 CF_TO_NS_CAST_DECL(CFURL, NSURL); | 224 CF_TO_NS_CAST_DECL(CFURL, NSURL); |
| 200 | 225 |
| 226 #undef CF_TO_NS_CAST_DECL |
| 227 #undef CF_TO_NS_MUTABLE_CAST_DECL |
| 228 #undef OBJC_CPP_CLASS_DECL |
| 229 |
| 201 namespace base { | 230 namespace base { |
| 202 namespace mac { | 231 namespace mac { |
| 203 | 232 |
| 204 // CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more | 233 // CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more |
| 205 // specific CoreFoundation type. The compatibility of the passed | 234 // specific CoreFoundation type. The compatibility of the passed |
| 206 // object is found by comparing its opaque type against the | 235 // object is found by comparing its opaque type against the |
| 207 // requested type identifier. If the supplied object is not | 236 // requested type identifier. If the supplied object is not |
| 208 // compatible with the requested return type, CFCast<>() returns | 237 // compatible with the requested return type, CFCast<>() returns |
| 209 // NULL and CFCastStrict<>() will DCHECK. Providing a NULL pointer | 238 // NULL and CFCastStrict<>() will DCHECK. Providing a NULL pointer |
| 210 // to either variant results in NULL being returned without | 239 // to either variant results in NULL being returned without |
| 211 // triggering any DCHECK. | 240 // triggering any DCHECK. |
| 212 // | 241 // |
| 213 // Example usage: | 242 // Example usage: |
| 214 // CFNumberRef some_number = base::mac::CFCast<CFNumberRef>( | 243 // CFNumberRef some_number = base::mac::CFCast<CFNumberRef>( |
| 215 // CFArrayGetValueAtIndex(array, index)); | 244 // CFArrayGetValueAtIndex(array, index)); |
| 216 // | 245 // |
| 217 // CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>( | 246 // CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>( |
| 218 // base::mac::GetValueFromDictionary(some_dict, | 247 // base::mac::GetValueFromDictionary(some_dict, |
| 219 // CFSTR("a_key"), | 248 // CFSTR("a_key"), |
| 220 // CFStringGetTypeID())); | 249 // CFStringGetTypeID())); |
| 221 BASE_EXPORT template<class T> | 250 BASE_EXPORT template<typename T> |
| 222 T CFCast(const CFTypeRef& cf_val); | 251 T CFCast(const CFTypeRef& cf_val); |
| 223 | 252 |
| 224 BASE_EXPORT template<class T> | 253 BASE_EXPORT template<typename T> |
| 225 T CFCastStrict(const CFTypeRef& cf_val); | 254 T CFCastStrict(const CFTypeRef& cf_val); |
| 226 | 255 |
| 227 #if defined(__OBJC__) | 256 #if defined(__OBJC__) |
| 228 | 257 |
| 229 // ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more | 258 // ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more |
| 230 // specific (NSObject-derived) type. The compatibility of the passed | 259 // specific (NSObject-derived) type. The compatibility of the passed |
| 231 // object is found by checking if it's a kind of the requested type | 260 // object is found by checking if it's a kind of the requested type |
| 232 // identifier. If the supplied object is not compatible with the | 261 // identifier. If the supplied object is not compatible with the |
| 233 // requested return type, ObjCCast<>() returns nil and | 262 // requested return type, ObjCCast<>() returns nil and |
| 234 // ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either | 263 // ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either |
| 235 // variant results in nil being returned without triggering any DCHECK. | 264 // variant results in nil being returned without triggering any DCHECK. |
| 236 // | 265 // |
| 237 // The strict variant is useful when retrieving a value from a | 266 // The strict variant is useful when retrieving a value from a |
| 238 // collection which only has values of a specific type, e.g. an | 267 // collection which only has values of a specific type, e.g. an |
| 239 // NSArray of NSStrings. The non-strict variant is useful when | 268 // NSArray of NSStrings. The non-strict variant is useful when |
| 240 // retrieving values from data that you can't fully control. For | 269 // retrieving values from data that you can't fully control. For |
| 241 // example, a plist read from disk may be beyond your exclusive | 270 // example, a plist read from disk may be beyond your exclusive |
| 242 // control, so you'd only want to check that the values you retrieve | 271 // control, so you'd only want to check that the values you retrieve |
| 243 // from it are of the expected types, but not crash if they're not. | 272 // from it are of the expected types, but not crash if they're not. |
| 244 // | 273 // |
| 245 // Example usage: | 274 // Example usage: |
| 246 // NSString* version = base::mac::ObjCCast<NSString>( | 275 // NSString* version = base::mac::ObjCCast<NSString>( |
| 247 // [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); | 276 // [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); |
| 248 // | 277 // |
| 249 // NSString* str = base::mac::ObjCCastStrict<NSString>( | 278 // NSString* str = base::mac::ObjCCastStrict<NSString>( |
| 250 // [ns_arr_of_ns_strs objectAtIndex:0]); | 279 // [ns_arr_of_ns_strs objectAtIndex:0]); |
| 251 BASE_EXPORT template<class T> | 280 BASE_EXPORT template<typename T> |
| 252 T* ObjCCast(id objc_val) { | 281 T* ObjCCast(id objc_val) { |
| 253 if ([objc_val isKindOfClass:[T class]]) { | 282 if ([objc_val isKindOfClass:[T class]]) { |
| 254 return reinterpret_cast<T*>(objc_val); | 283 return reinterpret_cast<T*>(objc_val); |
| 255 } | 284 } |
| 256 return nil; | 285 return nil; |
| 257 } | 286 } |
| 258 | 287 |
| 259 BASE_EXPORT template<class T> | 288 BASE_EXPORT template<typename T> |
| 260 T* ObjCCastStrict(id objc_val) { | 289 T* ObjCCastStrict(id objc_val) { |
| 261 T* rv = ObjCCast<T>(objc_val); | 290 T* rv = ObjCCast<T>(objc_val); |
| 262 DCHECK(objc_val == nil || rv); | 291 DCHECK(objc_val == nil || rv); |
| 263 return rv; | 292 return rv; |
| 264 } | 293 } |
| 265 | 294 |
| 266 #endif // defined(__OBJC__) | 295 #endif // defined(__OBJC__) |
| 267 | 296 |
| 297 // Utility function to pull out a value from a dictionary, check its type, and |
| 298 // return it. Returns NULL if the key is not present or of the wrong type. |
| 299 BASE_EXPORT template<typename T> |
| 300 T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key) { |
| 301 CFTypeRef value = CFDictionaryGetValue(dict, key); |
| 302 T value_specific = CFCast<T>(value); |
| 303 |
| 304 if (value && !value_specific) { |
| 305 std::string expected_type = TypeNameForCFType(value_specific); |
| 306 DLOG(WARNING) << GetValueFromDictionaryErrorMessage(key, |
| 307 expected_type, |
| 308 value); |
| 309 } |
| 310 |
| 311 return value_specific; |
| 312 } |
| 313 |
| 268 } // namespace mac | 314 } // namespace mac |
| 269 } // namespace base | 315 } // namespace base |
| 270 | 316 |
| 271 // Stream operations for CFTypes. They can be used with NSTypes as well | 317 // Stream operations for CFTypes. They can be used with NSTypes as well |
| 272 // by using the NSToCFCast methods above. | 318 // by using the NSToCFCast methods above. |
| 273 // e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); | 319 // e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); |
| 274 // Operator << can not be overloaded for ObjectiveC types as the compiler | 320 // Operator << can not be overloaded for ObjectiveC types as the compiler |
| 275 // can not distinguish between overloads for id with overloads for void*. | 321 // can not distinguish between overloads for id with overloads for void*. |
| 276 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, | 322 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, |
| 277 const CFErrorRef err); | 323 const CFErrorRef err); |
| 278 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, | 324 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, |
| 279 const CFStringRef str); | 325 const CFStringRef str); |
| 280 | 326 |
| 281 #endif // BASE_MAC_FOUNDATION_UTIL_H_ | 327 #endif // BASE_MAC_FOUNDATION_UTIL_H_ |
| OLD | NEW |