Chromium Code Reviews| 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" | |
| 17 | |
| 16 | 18 |
| 17 #if defined(__OBJC__) | 19 #if defined(__OBJC__) |
| 18 #import <Foundation/Foundation.h> | 20 #import <Foundation/Foundation.h> |
| 19 #else // __OBJC__ | 21 #else // __OBJC__ |
| 20 class NSBundle; | 22 class NSBundle; |
| 21 class NSString; | 23 class NSString; |
| 22 #endif // __OBJC__ | 24 #endif // __OBJC__ |
| 23 | 25 |
| 24 class FilePath; | 26 class FilePath; |
| 25 | 27 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 // Returns the ~/Library directory. | 91 // Returns the ~/Library directory. |
| 90 BASE_EXPORT FilePath GetUserLibraryPath(); | 92 BASE_EXPORT FilePath GetUserLibraryPath(); |
| 91 | 93 |
| 92 // Takes a path to an (executable) binary and tries to provide the path to an | 94 // 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 | 95 // 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"). | 96 // find (so for "/Foo/Bar.app/.../Baz.app/..." it produces "/Foo/Bar.app"). |
| 95 // |exec_name| - path to the binary | 97 // |exec_name| - path to the binary |
| 96 // returns - path to the application bundle, or empty on error | 98 // returns - path to the application bundle, or empty on error |
| 97 BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name); | 99 BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name); |
| 98 | 100 |
| 101 // Helper function for GetValueFromDictionary to create the error message | |
| 102 // that appears when a type mismatch is encountered. | |
| 103 std::string GetValueFromDictionaryErrorMessage(CFStringRef key, | |
| 104 CFStringRef expected_type_ref, | |
|
Mark Mentovai
2011/11/13 01:28:22
Bad alignment on the indent.
| |
| 105 CFTypeRef value); | |
| 106 | |
| 99 // Utility function to pull out a value from a dictionary, check its type, and | 107 // 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. | 108 // return it. Returns NULL if the key is not present or of the wrong type. |
| 101 BASE_EXPORT CFTypeRef GetValueFromDictionary(CFDictionaryRef dict, | 109 BASE_EXPORT CFTypeRef GetValueFromDictionary(CFDictionaryRef dict, |
| 102 CFStringRef key, | 110 CFStringRef key, |
| 103 CFTypeID expected_type); | 111 CFTypeID expected_type); |
| 104 | 112 |
| 113 // Utility function to pull out a value from a dictionary, check its type, and | |
| 114 // return it. Returns NULL if the key is not present or of the wrong type. | |
| 115 BASE_EXPORT template<class T> | |
|
Mark Mentovai
2011/11/13 01:28:22
Remember what I said? typename sounds better than
| |
| 116 T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key); | |
|
Mark Mentovai
2011/11/13 01:28:22
Why did you declare this here? You can just have t
KushalP
2011/11/13 12:30:27
Thought I'd killed this with the patch set.
| |
| 117 | |
| 105 // Retain/release calls for memory management in C++. | 118 // Retain/release calls for memory management in C++. |
| 106 BASE_EXPORT void NSObjectRetain(void* obj); | 119 BASE_EXPORT void NSObjectRetain(void* obj); |
| 107 BASE_EXPORT void NSObjectRelease(void* obj); | 120 BASE_EXPORT void NSObjectRelease(void* obj); |
| 108 | 121 |
| 109 // CFTypeRefToNSObjectAutorelease transfers ownership of a Core Foundation | 122 // CFTypeRefToNSObjectAutorelease transfers ownership of a Core Foundation |
| 110 // object (one derived from CFTypeRef) to the Foundation memory management | 123 // object (one derived from CFTypeRef) to the Foundation memory management |
| 111 // system. In a traditional managed-memory environment, cf_object is | 124 // system. In a traditional managed-memory environment, cf_object is |
| 112 // autoreleased and returned as an NSObject. In a garbage-collected | 125 // autoreleased and returned as an NSObject. In a garbage-collected |
| 113 // environment, cf_object is marked as eligible for garbage collection. | 126 // environment, cf_object is marked as eligible for garbage collection. |
| 114 // | 127 // |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 // triggering any DCHECK. | 224 // triggering any DCHECK. |
| 212 // | 225 // |
| 213 // Example usage: | 226 // Example usage: |
| 214 // CFNumberRef some_number = base::mac::CFCast<CFNumberRef>( | 227 // CFNumberRef some_number = base::mac::CFCast<CFNumberRef>( |
| 215 // CFArrayGetValueAtIndex(array, index)); | 228 // CFArrayGetValueAtIndex(array, index)); |
| 216 // | 229 // |
| 217 // CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>( | 230 // CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>( |
| 218 // base::mac::GetValueFromDictionary(some_dict, | 231 // base::mac::GetValueFromDictionary(some_dict, |
| 219 // CFSTR("a_key"), | 232 // CFSTR("a_key"), |
| 220 // CFStringGetTypeID())); | 233 // CFStringGetTypeID())); |
| 221 BASE_EXPORT template<class T> | 234 BASE_EXPORT template<typename T> |
| 222 T CFCast(const CFTypeRef& cf_val); | 235 T CFCast(const CFTypeRef& cf_val); |
| 223 | 236 |
| 224 BASE_EXPORT template<class T> | 237 BASE_EXPORT template<typename T> |
| 225 T CFCastStrict(const CFTypeRef& cf_val); | 238 T CFCastStrict(const CFTypeRef& cf_val); |
| 226 | 239 |
| 227 #if defined(__OBJC__) | 240 #if defined(__OBJC__) |
| 228 | 241 |
| 229 // ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more | 242 // ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more |
| 230 // specific (NSObject-derived) type. The compatibility of the passed | 243 // specific (NSObject-derived) type. The compatibility of the passed |
| 231 // object is found by checking if it's a kind of the requested type | 244 // 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 | 245 // identifier. If the supplied object is not compatible with the |
| 233 // requested return type, ObjCCast<>() returns nil and | 246 // requested return type, ObjCCast<>() returns nil and |
| 234 // ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either | 247 // ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either |
| 235 // variant results in nil being returned without triggering any DCHECK. | 248 // variant results in nil being returned without triggering any DCHECK. |
| 236 // | 249 // |
| 237 // The strict variant is useful when retrieving a value from a | 250 // The strict variant is useful when retrieving a value from a |
| 238 // collection which only has values of a specific type, e.g. an | 251 // collection which only has values of a specific type, e.g. an |
| 239 // NSArray of NSStrings. The non-strict variant is useful when | 252 // NSArray of NSStrings. The non-strict variant is useful when |
| 240 // retrieving values from data that you can't fully control. For | 253 // retrieving values from data that you can't fully control. For |
| 241 // example, a plist read from disk may be beyond your exclusive | 254 // 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 | 255 // 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. | 256 // from it are of the expected types, but not crash if they're not. |
| 244 // | 257 // |
| 245 // Example usage: | 258 // Example usage: |
| 246 // NSString* version = base::mac::ObjCCast<NSString>( | 259 // NSString* version = base::mac::ObjCCast<NSString>( |
| 247 // [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); | 260 // [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); |
| 248 // | 261 // |
| 249 // NSString* str = base::mac::ObjCCastStrict<NSString>( | 262 // NSString* str = base::mac::ObjCCastStrict<NSString>( |
| 250 // [ns_arr_of_ns_strs objectAtIndex:0]); | 263 // [ns_arr_of_ns_strs objectAtIndex:0]); |
| 251 BASE_EXPORT template<class T> | 264 BASE_EXPORT template<typename T> |
| 252 T* ObjCCast(id objc_val) { | 265 T* ObjCCast(id objc_val) { |
| 253 if ([objc_val isKindOfClass:[T class]]) { | 266 if ([objc_val isKindOfClass:[T class]]) { |
| 254 return reinterpret_cast<T*>(objc_val); | 267 return reinterpret_cast<T*>(objc_val); |
| 255 } | 268 } |
| 256 return nil; | 269 return nil; |
| 257 } | 270 } |
| 258 | 271 |
| 259 BASE_EXPORT template<class T> | 272 BASE_EXPORT template<typename T> |
| 260 T* ObjCCastStrict(id objc_val) { | 273 T* ObjCCastStrict(id objc_val) { |
| 261 T* rv = ObjCCast<T>(objc_val); | 274 T* rv = ObjCCast<T>(objc_val); |
| 262 DCHECK(objc_val == nil || rv); | 275 DCHECK(objc_val == nil || rv); |
| 263 return rv; | 276 return rv; |
| 264 } | 277 } |
| 265 | 278 |
| 266 #endif // defined(__OBJC__) | 279 #endif // defined(__OBJC__) |
| 267 | 280 |
| 281 // Utility function to pull out a value from a dictionary, check its type, and | |
| 282 // return it. Returns NULL if the key is not present or of the wrong type. | |
| 283 // Is a cleaner implementation of base::mac::GetValueFromDictionary() above. | |
| 284 BASE_EXPORT template<typename T> | |
| 285 T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key) { | |
| 286 CFTypeRef value = CFDictionaryGetValue(dict, key); | |
| 287 T value_specific = CFCast<T>(value); | |
| 288 | |
| 289 if (!value) | |
|
Mark Mentovai
2011/11/13 01:28:22
Rid this entire function of early returns. Everyth
| |
| 290 // Can't return 'value' as it's a CFTypeRef. Provide a type T return. | |
| 291 return value_specific; | |
| 292 | |
| 293 if (!value_specific) { | |
| 294 // TODO: Get the string value of the type name T. | |
|
Mark Mentovai
2011/11/13 01:28:22
Can you think of a good way to do this?
KushalP
2011/11/13 12:30:27
If I'm honest I don't know "what" I'm looking for.
Mark Mentovai
2011/11/14 14:12:05
KushalP wrote:
| |
| 295 std::string type_name = "INSERT TYPE NAME"; | |
| 296 ScopedCFTypeRef<CFStringRef> expected_type_ref(CFStringCreateWithCString( | |
| 297 kCFAllocatorDefault, | |
| 298 type_name.c_str(), | |
| 299 kCFStringEncodingUTF8)); | |
| 300 DLOG(WARNING) << GetValueFromDictionaryErrorMessage(key, | |
| 301 expected_type_ref, | |
| 302 value); | |
| 303 return NULL; | |
| 304 } | |
| 305 return value_specific; | |
| 306 } | |
| 307 | |
| 268 } // namespace mac | 308 } // namespace mac |
| 269 } // namespace base | 309 } // namespace base |
| 270 | 310 |
| 271 // Stream operations for CFTypes. They can be used with NSTypes as well | 311 // Stream operations for CFTypes. They can be used with NSTypes as well |
| 272 // by using the NSToCFCast methods above. | 312 // by using the NSToCFCast methods above. |
| 273 // e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); | 313 // e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); |
| 274 // Operator << can not be overloaded for ObjectiveC types as the compiler | 314 // Operator << can not be overloaded for ObjectiveC types as the compiler |
| 275 // can not distinguish between overloads for id with overloads for void*. | 315 // can not distinguish between overloads for id with overloads for void*. |
| 276 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, | 316 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, |
| 277 const CFErrorRef err); | 317 const CFErrorRef err); |
| 278 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, | 318 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, |
| 279 const CFStringRef str); | 319 const CFStringRef str); |
| 280 | 320 |
| 281 #endif // BASE_MAC_FOUNDATION_UTIL_H_ | 321 #endif // BASE_MAC_FOUNDATION_UTIL_H_ |
| OLD | NEW |