OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 | 7 |
8 #include <CoreFoundation/CoreFoundation.h> | 8 #include <CoreFoundation/CoreFoundation.h> |
9 | 9 |
10 #include <string> | 10 #include <string> |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 CF_TO_NS_CAST_DECL(CTFont, NSFont); | 245 CF_TO_NS_CAST_DECL(CTFont, NSFont); |
246 #endif | 246 #endif |
247 | 247 |
248 #undef CF_TO_NS_CAST_DECL | 248 #undef CF_TO_NS_CAST_DECL |
249 #undef CF_TO_NS_MUTABLE_CAST_DECL | 249 #undef CF_TO_NS_MUTABLE_CAST_DECL |
250 #undef OBJC_CPP_CLASS_DECL | 250 #undef OBJC_CPP_CLASS_DECL |
251 | 251 |
252 namespace base { | 252 namespace base { |
253 namespace mac { | 253 namespace mac { |
254 | 254 |
255 // CFCast<>() and CFCastStrict<>() cast a basic CFTypeRef to a more | 255 // CFCast<>(), CFCastStrict<>() and CFStaticCast<> cast a basic CFTypeRef to a |
256 // specific CoreFoundation type. The compatibility of the passed | 256 // more specific CoreFoundation type. The compatibility of the passed object is |
257 // object is found by comparing its opaque type against the | 257 // found by comparing its opaque type against the requested type identifier. If |
258 // requested type identifier. If the supplied object is not | 258 // the supplied object is not compatible with the requested return type: |
259 // compatible with the requested return type, CFCast<>() returns | 259 // - CFCast<>() returns null, similar to dynamic_cast<>; |
260 // NULL and CFCastStrict<>() will DCHECK. Providing a NULL pointer | 260 // - CFCastStrict<>() will DCHECK or return null in Release; and |
261 // to either variant results in NULL being returned without | 261 // - CFStaticCast<>() will DCHECK but always cast, similar to static_cast<>. |
262 // triggering any DCHECK. | 262 // Providing a null pointer to any variant results in null being returned |
| 263 // without triggering any DCHECK. |
263 // | 264 // |
264 // Example usage: | 265 // Example usage: |
265 // CFNumberRef some_number = base::mac::CFCast<CFNumberRef>( | 266 // CFNumberRef some_number = base::mac::CFCast<CFNumberRef>( |
266 // CFArrayGetValueAtIndex(array, index)); | 267 // CFArrayGetValueAtIndex(array, index)); |
267 // | 268 // |
268 // CFTypeRef hello = CFSTR("hello world"); | 269 // CFTypeRef hello = CFSTR("hello world"); |
269 // CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>(hello); | 270 // CFStringRef some_string = base::mac::CFCastStrict<CFStringRef>(hello); |
270 | |
271 template<typename T> | 271 template<typename T> |
272 T CFCast(const CFTypeRef& cf_val); | 272 T CFCast(const CFTypeRef& cf_val); |
273 | 273 |
274 template<typename T> | 274 template<typename T> |
275 T CFCastStrict(const CFTypeRef& cf_val); | 275 T CFCastStrict(const CFTypeRef& cf_val); |
276 | 276 |
| 277 template<typename T> |
| 278 T CFStaticCast(const CFTypeRef& cf_val) { |
| 279 DCHECK(!cf_val || CFCast<T>(cf_val)); |
| 280 // Note: CFTypeRef is const void*, but CGColorRef and some others are non- |
| 281 // const. So this may also cast away a const qualifier. |
| 282 return (T)(cf_val); |
| 283 } |
| 284 |
277 #define CF_CAST_DECL(TypeCF) \ | 285 #define CF_CAST_DECL(TypeCF) \ |
278 template<> BASE_EXPORT TypeCF##Ref \ | 286 template<> BASE_EXPORT TypeCF##Ref \ |
279 CFCast<TypeCF##Ref>(const CFTypeRef& cf_val);\ | 287 CFCast<TypeCF##Ref>(const CFTypeRef& cf_val);\ |
280 \ | 288 \ |
281 template<> BASE_EXPORT TypeCF##Ref \ | 289 template<> BASE_EXPORT TypeCF##Ref \ |
282 CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val); | 290 CFCastStrict<TypeCF##Ref>(const CFTypeRef& cf_val); |
283 | 291 |
284 CF_CAST_DECL(CFArray); | 292 CF_CAST_DECL(CFArray); |
285 CF_CAST_DECL(CFBag); | 293 CF_CAST_DECL(CFBag); |
286 CF_CAST_DECL(CFBoolean); | 294 CF_CAST_DECL(CFBoolean); |
(...skipping 13 matching lines...) Expand all Loading... |
300 CF_CAST_DECL(CTFontDescriptor); | 308 CF_CAST_DECL(CTFontDescriptor); |
301 CF_CAST_DECL(CTRun); | 309 CF_CAST_DECL(CTRun); |
302 | 310 |
303 CF_CAST_DECL(SecACL); | 311 CF_CAST_DECL(SecACL); |
304 CF_CAST_DECL(SecTrustedApplication); | 312 CF_CAST_DECL(SecTrustedApplication); |
305 | 313 |
306 #undef CF_CAST_DECL | 314 #undef CF_CAST_DECL |
307 | 315 |
308 #if defined(__OBJC__) | 316 #if defined(__OBJC__) |
309 | 317 |
310 // ObjCCast<>() and ObjCCastStrict<>() cast a basic id to a more | 318 // ObjCCast<>(), ObjCCastStrict<>() and ObjCStaticCast cast a basic id to a more |
311 // specific (NSObject-derived) type. The compatibility of the passed | 319 // specific (NSObject-derived) type. The compatibility of the passed object is |
312 // object is found by checking if it's a kind of the requested type | 320 // found by checking if it's a kind of the requested type identifier. If the |
313 // identifier. If the supplied object is not compatible with the | 321 // supplied object is not compatible with the requested return type: |
314 // requested return type, ObjCCast<>() returns nil and | 322 // - ObjCCast<>() returns nil, similar to dynamic_cast<>, |
315 // ObjCCastStrict<>() will DCHECK. Providing a nil pointer to either | 323 // - ObjCCastStrict<>() will DCHECK or return nil in Release; and |
316 // variant results in nil being returned without triggering any DCHECK. | 324 // - ObjCStaticCast<>() will DCHECK but always cast, similar to static_cast<>. |
| 325 // Providing a nil pointer to any variant results in nil being returned without |
| 326 // triggering any DCHECK. |
317 // | 327 // |
318 // The strict variant is useful when retrieving a value from a | 328 // The strict variant is useful when retrieving a value from a collection which |
319 // collection which only has values of a specific type, e.g. an | 329 // only has values of a specific type, e.g. an NSArray of NSStrings. The non- |
320 // NSArray of NSStrings. The non-strict variant is useful when | 330 // strict variant is useful when retrieving values from data that you can't |
321 // retrieving values from data that you can't fully control. For | 331 // fully control. For example, a plist read from disk may be beyond your |
322 // example, a plist read from disk may be beyond your exclusive | 332 // exclusive control, so you'd only want to check that the values you retrieve |
323 // control, so you'd only want to check that the values you retrieve | |
324 // from it are of the expected types, but not crash if they're not. | 333 // from it are of the expected types, but not crash if they're not. |
| 334 // ObjCStaticCast should be preferred when you have a strong contract specifying |
| 335 // the type and good test coverage. |
325 // | 336 // |
326 // Example usage: | 337 // Example usage: |
327 // NSString* version = base::mac::ObjCCast<NSString>( | 338 // NSString* version = base::mac::ObjCCast<NSString>( |
328 // [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); | 339 // [bundle objectForInfoDictionaryKey:@"CFBundleShortVersionString"]); |
329 // | 340 // |
330 // NSString* str = base::mac::ObjCCastStrict<NSString>( | 341 // NSString* str = base::mac::ObjCCastStrict<NSString>( |
331 // [ns_arr_of_ns_strs objectAtIndex:0]); | 342 // [ns_arr_of_ns_strs objectAtIndex:0]); |
332 template<typename T> | 343 template<typename T> |
333 T* ObjCCast(id objc_val) { | 344 T* ObjCCast(id objc_val) { |
334 if ([objc_val isKindOfClass:[T class]]) { | 345 if ([objc_val isKindOfClass:[T class]]) { |
335 return reinterpret_cast<T*>(objc_val); | 346 return reinterpret_cast<T*>(objc_val); |
336 } | 347 } |
337 return nil; | 348 return nil; |
338 } | 349 } |
339 | 350 |
340 template<typename T> | 351 template<typename T> |
341 T* ObjCCastStrict(id objc_val) { | 352 T* ObjCCastStrict(id objc_val) { |
342 T* rv = ObjCCast<T>(objc_val); | 353 T* rv = ObjCCast<T>(objc_val); |
343 DCHECK(objc_val == nil || rv); | 354 DCHECK(objc_val == nil || rv); |
344 return rv; | 355 return rv; |
345 } | 356 } |
346 | 357 |
| 358 template<typename T> |
| 359 T* ObjCStaticCast(id objc_val) { |
| 360 DCHECK(!objc_val || ObjCCast<T>(objc_val)); |
| 361 return reinterpret_cast<T*>(objc_val); |
| 362 } |
| 363 |
347 #endif // defined(__OBJC__) | 364 #endif // defined(__OBJC__) |
348 | 365 |
349 // Helper function for GetValueFromDictionary to create the error message | 366 // Helper function for GetValueFromDictionary to create the error message |
350 // that appears when a type mismatch is encountered. | 367 // that appears when a type mismatch is encountered. |
351 BASE_EXPORT std::string GetValueFromDictionaryErrorMessage( | 368 BASE_EXPORT std::string GetValueFromDictionaryErrorMessage( |
352 CFStringRef key, const std::string& expected_type, CFTypeRef value); | 369 CFStringRef key, const std::string& expected_type, CFTypeRef value); |
353 | 370 |
354 // Utility function to pull out a value from a dictionary, check its type, and | 371 // Utility function to pull out a value from a dictionary, check its type, and |
355 // return it. Returns NULL if the key is not present or of the wrong type. | 372 // return it. Returns NULL if the key is not present or of the wrong type. |
356 template<typename T> | 373 template<typename T> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
389 // by using the NSToCFCast methods above. | 406 // by using the NSToCFCast methods above. |
390 // e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); | 407 // e.g. LOG(INFO) << base::mac::NSToCFCast(@"foo"); |
391 // Operator << can not be overloaded for ObjectiveC types as the compiler | 408 // Operator << can not be overloaded for ObjectiveC types as the compiler |
392 // can not distinguish between overloads for id with overloads for void*. | 409 // can not distinguish between overloads for id with overloads for void*. |
393 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, | 410 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, |
394 const CFErrorRef err); | 411 const CFErrorRef err); |
395 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, | 412 BASE_EXPORT extern std::ostream& operator<<(std::ostream& o, |
396 const CFStringRef str); | 413 const CFStringRef str); |
397 | 414 |
398 #endif // BASE_MAC_FOUNDATION_UTIL_H_ | 415 #endif // BASE_MAC_FOUNDATION_UTIL_H_ |
OLD | NEW |