Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: base/mac/foundation_util.h

Issue 1927003004: Mac: Introduce "StaticCast" variants of base::mac::FooCastStrict, which do not typecheck in Release (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add StaticCast variants Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ui/gfx/render_text_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/render_text_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698