summaryrefslogtreecommitdiffstats
path: root/base/mac
diff options
context:
space:
mode:
Diffstat (limited to 'base/mac')
-rw-r--r--base/mac/foundation_util.h54
-rw-r--r--base/mac/foundation_util.mm51
-rw-r--r--base/mac/foundation_util_unittest.mm44
3 files changed, 134 insertions, 15 deletions
diff --git a/base/mac/foundation_util.h b/base/mac/foundation_util.h
index f7821de..a36ad75 100644
--- a/base/mac/foundation_util.h
+++ b/base/mac/foundation_util.h
@@ -13,6 +13,7 @@
#include "base/base_export.h"
#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
#if defined(__OBJC__)
#import <Foundation/Foundation.h>
@@ -96,8 +97,32 @@ BASE_EXPORT FilePath GetUserLibraryPath();
// returns - path to the application bundle, or empty on error
BASE_EXPORT FilePath GetAppBundlePath(const FilePath& exec_name);
+#define TYPE_NAME_FOR_CF_TYPE_DECL(TypeCF) \
+std::string TypeNameForCFType(TypeCF##Ref);
+
+TYPE_NAME_FOR_CF_TYPE_DECL(CFArray);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFBag);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFBoolean);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFData);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFDate);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFDictionary);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFNull);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFNumber);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFSet);
+TYPE_NAME_FOR_CF_TYPE_DECL(CFString);
+
+#undef TYPE_NAME_FOR_CF_TYPE_DECL
+
+// Helper function for GetValueFromDictionary to create the error message
+// that appears when a type mismatch is encountered.
+std::string GetValueFromDictionaryErrorMessage(
+ CFStringRef key, const std::string& expected_type, CFTypeRef value);
+
// Utility function to pull out a value from a dictionary, check its type, and
// return it. Returns NULL if the key is not present or of the wrong type.
+// This is now deprecated in favor of the two-argument form below.
+// TODO(kushi.p): Remove this function once all cases of it have been
+// replaced with the two-argument form below. See: crbug.com/104200.
BASE_EXPORT CFTypeRef GetValueFromDictionary(CFDictionaryRef dict,
CFStringRef key,
CFTypeID expected_type);
@@ -198,6 +223,10 @@ CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream);
CF_TO_NS_MUTABLE_CAST_DECL(String);
CF_TO_NS_CAST_DECL(CFURL, NSURL);
+#undef CF_TO_NS_CAST_DECL
+#undef CF_TO_NS_MUTABLE_CAST_DECL
+#undef OBJC_CPP_CLASS_DECL
+
namespace base {
namespace mac {
@@ -218,10 +247,10 @@ namespace mac {
// base::mac::GetValueFromDictionary(some_dict,
// CFSTR("a_key"),
// CFStringGetTypeID()));
-BASE_EXPORT template<class T>
+BASE_EXPORT template<typename T>
T CFCast(const CFTypeRef& cf_val);
-BASE_EXPORT template<class T>
+BASE_EXPORT template<typename T>
T CFCastStrict(const CFTypeRef& cf_val);
#if defined(__OBJC__)
@@ -248,7 +277,7 @@ T CFCastStrict(const CFTypeRef& cf_val);
//
// NSString* str = base::mac::ObjCCastStrict<NSString>(
// [ns_arr_of_ns_strs objectAtIndex:0]);
-BASE_EXPORT template<class T>
+BASE_EXPORT template<typename T>
T* ObjCCast(id objc_val) {
if ([objc_val isKindOfClass:[T class]]) {
return reinterpret_cast<T*>(objc_val);
@@ -256,7 +285,7 @@ T* ObjCCast(id objc_val) {
return nil;
}
-BASE_EXPORT template<class T>
+BASE_EXPORT template<typename T>
T* ObjCCastStrict(id objc_val) {
T* rv = ObjCCast<T>(objc_val);
DCHECK(objc_val == nil || rv);
@@ -265,6 +294,23 @@ T* ObjCCastStrict(id objc_val) {
#endif // defined(__OBJC__)
+// Utility function to pull out a value from a dictionary, check its type, and
+// return it. Returns NULL if the key is not present or of the wrong type.
+BASE_EXPORT template<typename T>
+T GetValueFromDictionary(CFDictionaryRef dict, CFStringRef key) {
+ CFTypeRef value = CFDictionaryGetValue(dict, key);
+ T value_specific = CFCast<T>(value);
+
+ if (value && !value_specific) {
+ std::string expected_type = TypeNameForCFType(value_specific);
+ DLOG(WARNING) << GetValueFromDictionaryErrorMessage(key,
+ expected_type,
+ value);
+ }
+
+ return value_specific;
+}
+
} // namespace mac
} // namespace base
diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm
index 8a4ce47..44b81d3 100644
--- a/base/mac/foundation_util.mm
+++ b/base/mac/foundation_util.mm
@@ -9,7 +9,6 @@
#include "base/file_path.h"
#include "base/logging.h"
-#include "base/mac/scoped_cftyperef.h"
#include "base/sys_string_conversions.h"
namespace base {
@@ -200,6 +199,37 @@ FilePath GetAppBundlePath(const FilePath& exec_name) {
return FilePath();
}
+#define TYPE_NAME_FOR_CF_TYPE_DEFN(TypeCF) \
+std::string TypeNameForCFType(TypeCF##Ref) { \
+ return #TypeCF; \
+}
+
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFArray);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFBag);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFBoolean);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFData);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFDate);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFDictionary);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFNull);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFNumber);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFSet);
+TYPE_NAME_FOR_CF_TYPE_DEFN(CFString);
+
+#undef TYPE_NAME_FOR_CF_TYPE_DEFN
+
+std::string GetValueFromDictionaryErrorMessage(
+ CFStringRef key, const std::string& expected_type, CFTypeRef value) {
+ ScopedCFTypeRef<CFStringRef> actual_type_ref(
+ CFCopyTypeIDDescription(CFGetTypeID(value)));
+ return "Expected value for key " +
+ base::SysCFStringRefToUTF8(key) +
+ " to be " +
+ expected_type +
+ " but it was " +
+ base::SysCFStringRefToUTF8(actual_type_ref) +
+ " instead";
+}
+
CFTypeRef GetValueFromDictionary(CFDictionaryRef dict,
CFStringRef key,
CFTypeID expected_type) {
@@ -208,17 +238,11 @@ CFTypeRef GetValueFromDictionary(CFDictionaryRef dict,
return value;
if (CFGetTypeID(value) != expected_type) {
- ScopedCFTypeRef<CFStringRef> expected_type_ref(
+ std::string expected_type_name = base::SysCFStringRefToUTF8(
CFCopyTypeIDDescription(expected_type));
- ScopedCFTypeRef<CFStringRef> actual_type_ref(
- CFCopyTypeIDDescription(CFGetTypeID(value)));
- DLOG(WARNING) << "Expected value for key "
- << base::SysCFStringRefToUTF8(key)
- << " to be "
- << base::SysCFStringRefToUTF8(expected_type_ref)
- << " but it was "
- << base::SysCFStringRefToUTF8(actual_type_ref)
- << " instead";
+ DLOG(WARNING) << GetValueFromDictionaryErrorMessage(key,
+ expected_type_name,
+ value);
return NULL;
}
@@ -318,6 +342,9 @@ CF_TO_NS_CAST_DEFN(CFWriteStream, NSOutputStream);
CF_TO_NS_MUTABLE_CAST_DEFN(String);
CF_TO_NS_CAST_DEFN(CFURL, NSURL);
+#undef CF_TO_NS_CAST_DEFN
+#undef CF_TO_NS_MUTABLE_CAST_DEFN
+
#define CF_CAST_DEFN(TypeCF) \
template<> TypeCF##Ref \
CFCast<TypeCF##Ref>(const CFTypeRef& cf_val) { \
@@ -348,6 +375,8 @@ CF_CAST_DEFN(CFNumber);
CF_CAST_DEFN(CFSet);
CF_CAST_DEFN(CFString);
+#undef CF_CAST_DEFN
+
} // namespace mac
} // namespace base
diff --git a/base/mac/foundation_util_unittest.mm b/base/mac/foundation_util_unittest.mm
index 9c5daac..7405691 100644
--- a/base/mac/foundation_util_unittest.mm
+++ b/base/mac/foundation_util_unittest.mm
@@ -4,6 +4,7 @@
#include "base/mac/foundation_util.h"
+#include "base/basictypes.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -275,3 +276,46 @@ TEST(FoundationUtilTest, ObjCCast) {
EXPECT_FALSE(base::mac::ObjCCastStrict<NSSet>(nil));
EXPECT_FALSE(base::mac::ObjCCastStrict<NSString>(nil));
}
+
+TEST(FoundationUtilTest, GetValueFromDictionary) {
+ int one = 1, two = 2, three = 3;
+
+ base::mac::ScopedCFTypeRef<CFNumberRef> cf_one(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &one));
+ base::mac::ScopedCFTypeRef<CFNumberRef> cf_two(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &two));
+ base::mac::ScopedCFTypeRef<CFNumberRef> cf_three(
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &three));
+
+ CFStringRef keys[] = { CFSTR("one"), CFSTR("two"), CFSTR("three") };
+ CFNumberRef values[] = { cf_one, cf_two, cf_three };
+
+ COMPILE_ASSERT(arraysize(keys) == arraysize(values),
+ keys_and_values_arraysizes_are_different);
+
+ base::mac::ScopedCFTypeRef<CFDictionaryRef> test_dict(
+ CFDictionaryCreate(kCFAllocatorDefault,
+ reinterpret_cast<const void**>(keys),
+ reinterpret_cast<const void**>(values),
+ arraysize(values),
+ &kCFCopyStringDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks));
+
+ // base::mac::GetValueFromDictionary<>(_, _) should produce the correct
+ // expected output.
+ EXPECT_EQ(values[0],
+ base::mac::GetValueFromDictionary<CFNumberRef>(test_dict,
+ CFSTR("one")));
+ EXPECT_EQ(values[1],
+ base::mac::GetValueFromDictionary<CFNumberRef>(test_dict,
+ CFSTR("two")));
+ EXPECT_EQ(values[2],
+ base::mac::GetValueFromDictionary<CFNumberRef>(test_dict,
+ CFSTR("three")));
+
+ // Bad input should produce bad output.
+ EXPECT_FALSE(base::mac::GetValueFromDictionary<CFNumberRef>(test_dict,
+ CFSTR("four")));
+ EXPECT_FALSE(base::mac::GetValueFromDictionary<CFStringRef>(test_dict,
+ CFSTR("one")));
+}