Commit 07406e64 authored by Wei Li's avatar Wei Li Committed by Commit Bot

Views: Check results of type conversions from strings

This CL changed the way how we handle conversion failures from strings.
Instead of using the default values, this CL returns 'false' to indicate
the conversion errors. This returned result is useful in case we need to
handle more complex type conversions such base::optional type.

Also, this CL simplify the type converter function definitions since we
only need to and from string conversions, not between arbitrary two
types.

BUG=938501

Change-Id: I1e6d8510c39a9a240161aa0b36c2141ab62ed0e8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1606772
Commit-Queue: Wei Li <weili@chromium.org>
Reviewed-by: default avatarAllen Bauer <kylixrd@chromium.org>
Cr-Commit-Position: refs/heads/master@{#659250}
parent 957a9770
...@@ -26,7 +26,7 @@ class ClassPropertyReadOnlyMetaData : public MemberMetaDataBase { ...@@ -26,7 +26,7 @@ class ClassPropertyReadOnlyMetaData : public MemberMetaDataBase {
~ClassPropertyReadOnlyMetaData() override = default; ~ClassPropertyReadOnlyMetaData() override = default;
base::string16 GetValueAsString(void* obj) const override { base::string16 GetValueAsString(void* obj) const override {
return Convert<TValue, base::string16>((static_cast<TClass*>(obj)->*Get)()); return ConvertToString<TValue>((static_cast<TClass*>(obj)->*Get)());
} }
PropertyFlags GetPropertyFlags() const override { PropertyFlags GetPropertyFlags() const override {
...@@ -53,8 +53,9 @@ class ClassPropertyMetaData ...@@ -53,8 +53,9 @@ class ClassPropertyMetaData
~ClassPropertyMetaData() override = default; ~ClassPropertyMetaData() override = default;
void SetValueAsString(void* obj, const base::string16& new_value) override { void SetValueAsString(void* obj, const base::string16& new_value) override {
(static_cast<TClass*>(obj)->*Set)(Convert<base::string16, TValue>( TValue result;
new_value, (static_cast<TClass*>(obj)->*Get)())); if (ConvertFromString<TValue>(new_value, &result))
(static_cast<TClass*>(obj)->*Set)(result);
} }
PropertyFlags GetPropertyFlags() const override { PropertyFlags GetPropertyFlags() const override {
......
...@@ -17,12 +17,6 @@ namespace metadata { ...@@ -17,12 +17,6 @@ namespace metadata {
/***** String Conversions *****/ /***** String Conversions *****/
template <>
base::string16 ConvertToString<base::string16>(
const base::string16& source_value) {
return source_value;
}
template <> template <>
base::string16 ConvertToString<int8_t>(int8_t source_value) { base::string16 ConvertToString<int8_t>(int8_t source_value) {
return base::NumberToString16(source_value); return base::NumberToString16(source_value);
...@@ -85,110 +79,131 @@ base::string16 ConvertToString<gfx::Size>(const gfx::Size& source_value) { ...@@ -85,110 +79,131 @@ base::string16 ConvertToString<gfx::Size>(const gfx::Size& source_value) {
} }
template <> template <>
int8_t ConvertFromString<int8_t>(const base::string16& source_value, base::string16 ConvertToString<base::string16>(
int8_t default_value) { const base::string16& source_value) {
int32_t ret = 0; return source_value;
return base::StringToInt(source_value, &ret) &&
base::IsValueInRangeForNumericType<int8_t>(ret)
? static_cast<int8_t>(ret)
: default_value;
} }
template <> template <>
int16_t ConvertFromString<int16_t>(const base::string16& source_value, bool ConvertFromString<int8_t>(const base::string16& source_value,
int16_t default_value) { int8_t* dst_value) {
int32_t ret = 0; int32_t ret = 0;
return base::StringToInt(source_value, &ret) && if (base::StringToInt(source_value, &ret) &&
base::IsValueInRangeForNumericType<int16_t>(ret) base::IsValueInRangeForNumericType<int8_t>(ret)) {
? static_cast<int16_t>(ret) *dst_value = static_cast<int8_t>(ret);
: default_value; return true;
}
return false;
} }
template <> template <>
int32_t ConvertFromString<int32_t>(const base::string16& source_value, bool ConvertFromString<int16_t>(const base::string16& source_value,
int32_t default_value) { int16_t* dst_value) {
int32_t ret = 0; int32_t ret = 0;
return base::StringToInt(source_value, &ret) ? static_cast<int32_t>(ret) if (base::StringToInt(source_value, &ret) &&
: default_value; base::IsValueInRangeForNumericType<int16_t>(ret)) {
*dst_value = static_cast<int16_t>(ret);
return true;
}
return false;
} }
template <> template <>
int64_t ConvertFromString<int64_t>(const base::string16& source_value, bool ConvertFromString<int32_t>(const base::string16& source_value,
int64_t default_value) { int32_t* dst_value) {
int64_t ret = 0; return base::StringToInt(source_value, dst_value);
return base::StringToInt64(source_value, &ret) ? ret : default_value;
} }
template <> template <>
uint8_t ConvertFromString<uint8_t>(const base::string16& source_value, bool ConvertFromString<int64_t>(const base::string16& source_value,
uint8_t default_value) { int64_t* dst_value) {
uint32_t ret = 0; return base::StringToInt64(source_value, dst_value);
return base::StringToUint(source_value, &ret) &&
base::IsValueInRangeForNumericType<uint8_t>(ret)
? static_cast<uint8_t>(ret)
: default_value;
} }
template <> template <>
uint16_t ConvertFromString<uint16_t>(const base::string16& source_value, bool ConvertFromString<uint8_t>(const base::string16& source_value,
uint16_t default_value) { uint8_t* dst_value) {
uint32_t ret = 0; uint32_t ret = 0;
return base::StringToUint(source_value, &ret) && if (base::StringToUint(source_value, &ret) &&
base::IsValueInRangeForNumericType<uint16_t>(ret) base::IsValueInRangeForNumericType<uint8_t>(ret)) {
? static_cast<uint16_t>(ret) *dst_value = static_cast<uint8_t>(ret);
: default_value; return true;
}
return false;
} }
template <> template <>
uint32_t ConvertFromString<uint32_t>(const base::string16& source_value, bool ConvertFromString<uint16_t>(const base::string16& source_value,
uint32_t default_value) { uint16_t* dst_value) {
uint32_t ret = 0; uint32_t ret = 0;
return base::StringToUint(source_value, &ret) ? static_cast<uint32_t>(ret) if (base::StringToUint(source_value, &ret) &&
: default_value; base::IsValueInRangeForNumericType<uint16_t>(ret)) {
*dst_value = static_cast<uint16_t>(ret);
return true;
}
return false;
} }
template <> template <>
uint64_t ConvertFromString<uint64_t>(const base::string16& source_value, bool ConvertFromString<uint32_t>(const base::string16& source_value,
uint64_t default_value) { uint32_t* dst_value) {
uint64_t ret = 0; return base::StringToUint(source_value, dst_value);
return base::StringToUint64(source_value, &ret) ? ret : default_value;
} }
template <> template <>
float ConvertFromString<float>(const base::string16& source_value, bool ConvertFromString<uint64_t>(const base::string16& source_value,
float default_value) { uint64_t* dst_value) {
return static_cast<float>( return base::StringToUint64(source_value, dst_value);
ConvertFromString<double>(source_value, default_value));
} }
template <> template <>
double ConvertFromString<double>(const base::string16& source_value, bool ConvertFromString<float>(const base::string16& source_value,
double default_value) { float* dst_value) {
double ret = 0; double temp;
return base::StringToDouble(base::UTF16ToUTF8(source_value), &ret) if (ConvertFromString<double>(source_value, &temp)) {
? ret *dst_value = static_cast<float>(temp);
: default_value; return true;
}
return false;
}
template <>
bool ConvertFromString<double>(const base::string16& source_value,
double* dst_value) {
return base::StringToDouble(base::UTF16ToUTF8(source_value), dst_value);
} }
template <> template <>
bool ConvertFromString<bool>(const base::string16& source_value, bool ConvertFromString<bool>(const base::string16& source_value,
bool default_value) { bool* dst_value) {
if (source_value == base::ASCIIToUTF16("false")) if (source_value == base::ASCIIToUTF16("true") ||
source_value == base::ASCIIToUTF16("false")) {
*dst_value = source_value == base::ASCIIToUTF16("true");
return true;
}
return false; return false;
return source_value == base::ASCIIToUTF16("true") || default_value;
} }
template <> template <>
gfx::Size ConvertFromString<gfx::Size>(const base::string16& source_value, bool ConvertFromString<gfx::Size>(const base::string16& source_value,
const gfx::Size& default_value) { gfx::Size* dst_value) {
const auto values = const auto values =
base::SplitStringPiece(source_value, base::ASCIIToUTF16("{,}"), base::SplitStringPiece(source_value, base::ASCIIToUTF16("{,}"),
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
int width, height; int width, height;
return (values.size() == 2) && base::StringToInt(values[0], &width) && if ((values.size() == 2) && base::StringToInt(values[0], &width) &&
base::StringToInt(values[1], &height) base::StringToInt(values[1], &height)) {
? gfx::Size(width, height) *dst_value = gfx::Size(width, height);
: default_value; return true;
}
return false;
}
template <>
bool ConvertFromString<base::string16>(const base::string16& source_value,
base::string16* dst_value) {
*dst_value = source_value;
return true;
} }
} // namespace metadata } // namespace metadata
......
...@@ -70,42 +70,27 @@ static const EnumStrings<T>& GetEnumStringsInstance(); ...@@ -70,42 +70,27 @@ static const EnumStrings<T>& GetEnumStringsInstance();
} \ } \
\ \
template <> \ template <> \
T views::metadata::ConvertFromString<T>(const base::string16& source_value, \ bool views::metadata::ConvertFromString<T>( \
T default_value) { \ const base::string16& source_value, T* dst_value) { \
for (const auto& pair : GetEnumStringsInstance<T>().pairs) { \ for (const auto& pair : GetEnumStringsInstance<T>().pairs) { \
if (source_value == pair.str_value) \ if (source_value == pair.str_value) { \
return pair.enum_value; \ *dst_value = pair.enum_value; \
return true; \
} \ } \
return default_value; \ } \
return false; \
} }
// TypeConverter Class -------------------------------------------------------- // Type Conversion Template Function
template <typename TSource, typename TTarget> // --------------------------------------------
class TypeConverter { template <typename TSource>
public: base::string16 ConvertToString(ArgType<TSource> source_value);
static TTarget Convert(ArgType<TSource>) = delete;
static TTarget Convert(ArgType<TSource>, ArgType<TTarget>) = delete;
private:
TypeConverter();
};
// Master Type Conversion Functions --------------------------------------------
template <typename TSource, typename TTarget>
TTarget Convert(ArgType<TSource> source_value) {
return TypeConverter<TSource, TTarget>::Convert(source_value);
}
template <typename TSource, typename TTarget> template <typename TTarget>
TTarget Convert(ArgType<TSource> source_value, ArgType<TTarget> default_value) { bool ConvertFromString(const base::string16& source_value, TTarget* dst_value);
return TypeConverter<TSource, TTarget>::Convert(source_value, default_value);
}
// String Conversions --------------------------------------------------------- // String Conversions ---------------------------------------------------------
template <typename TSource>
base::string16 ConvertToString(ArgType<TSource>) = delete;
template <> template <>
VIEWS_EXPORT base::string16 ConvertToString<base::string16>( VIEWS_EXPORT base::string16 ConvertToString<base::string16>(
const base::string16& source_value); const base::string16& source_value);
...@@ -147,97 +132,66 @@ template <> ...@@ -147,97 +132,66 @@ template <>
VIEWS_EXPORT base::string16 ConvertToString<gfx::Size>( VIEWS_EXPORT base::string16 ConvertToString<gfx::Size>(
const gfx::Size& source_value); const gfx::Size& source_value);
template <typename TSource>
class TypeConverter<TSource, base::string16> {
public:
static base::string16 Convert(ArgType<TSource> source_value) {
return ConvertToString<TSource>(source_value);
}
};
// A specialization used for string16 conversions. Since it simply passes
// the value, it is used for both converting to and from a string16 value.
template <> template <>
class TypeConverter<base::string16, base::string16> { VIEWS_EXPORT base::string16 ConvertToString<base::string16>(
public: const base::string16& source_value);
static base::string16 Convert(const base::string16& source_val) {
return ConvertToString<base::string16>(source_val);
}
static base::string16 Convert(const base::string16& source_val,
const base::string16& default_value) {
return ConvertToString<base::string16>(source_val);
}
};
template <typename TTarget>
TTarget ConvertFromString(const base::string16&, ArgType<TTarget>) = delete;
template <> template <>
VIEWS_EXPORT int8_t VIEWS_EXPORT bool ConvertFromString<int8_t>(const base::string16& source_value,
ConvertFromString<int8_t>(const base::string16& source_value, int8_t* dst_value);
int8_t default_value);
template <> template <>
VIEWS_EXPORT int16_t VIEWS_EXPORT bool ConvertFromString<int16_t>(const base::string16& source_value,
ConvertFromString<int16_t>(const base::string16& source_value, int16_t* dst_value);
int16_t default_value);
template <> template <>
VIEWS_EXPORT int32_t VIEWS_EXPORT bool ConvertFromString<int32_t>(const base::string16& source_value,
ConvertFromString<int32_t>(const base::string16& source_value, int32_t* dst_value);
int32_t default_value);
template <> template <>
VIEWS_EXPORT int64_t VIEWS_EXPORT bool ConvertFromString<int64_t>(const base::string16& source_value,
ConvertFromString<int64_t>(const base::string16& source_value, int64_t* dst_value);
int64_t default_value);
template <> template <>
VIEWS_EXPORT uint8_t VIEWS_EXPORT bool ConvertFromString<uint8_t>(const base::string16& source_value,
ConvertFromString<uint8_t>(const base::string16& source_value, uint8_t* dst_value);
uint8_t default_value);
template <> template <>
VIEWS_EXPORT uint16_t VIEWS_EXPORT bool ConvertFromString<uint16_t>(
ConvertFromString<uint16_t>(const base::string16& source_value, const base::string16& source_value,
uint16_t default_value); uint16_t* dst_value);
template <> template <>
VIEWS_EXPORT uint32_t VIEWS_EXPORT bool ConvertFromString<uint32_t>(
ConvertFromString<uint32_t>(const base::string16& source_value, const base::string16& source_value,
uint32_t default_value); uint32_t* dst_value);
template <> template <>
VIEWS_EXPORT uint64_t VIEWS_EXPORT bool ConvertFromString<uint64_t>(
ConvertFromString<uint64_t>(const base::string16& source_value, const base::string16& source_value,
uint64_t default_value); uint64_t* dst_value);
template <> template <>
VIEWS_EXPORT double ConvertFromString<double>( VIEWS_EXPORT bool ConvertFromString<double>(const base::string16& source_value,
const base::string16& source_value, double* dst_value);
double default_value);
template <> template <>
VIEWS_EXPORT float ConvertFromString<float>(const base::string16& source_value, VIEWS_EXPORT bool ConvertFromString<float>(const base::string16& source_value,
float default_value); float* dst_value);
template <> template <>
VIEWS_EXPORT bool ConvertFromString<bool>(const base::string16& source_value, VIEWS_EXPORT bool ConvertFromString<bool>(const base::string16& source_value,
bool default_value); bool* dst_value);
template <> template <>
VIEWS_EXPORT gfx::Size ConvertFromString<gfx::Size>( VIEWS_EXPORT bool ConvertFromString<gfx::Size>(
const base::string16& source_value, const base::string16& source_value,
const gfx::Size& default_value); gfx::Size* dst_value);
template <typename TTarget> template <>
class TypeConverter<base::string16, TTarget> { VIEWS_EXPORT bool ConvertFromString<base::string16>(
public: const base::string16& source_value,
static TTarget Convert(const base::string16& source_value, base::string16* dst_value);
ArgType<TTarget> default_value) {
return ConvertFromString<TTarget>(source_value, default_value);
}
};
} // namespace metadata } // namespace metadata
} // namespace views } // namespace views
......
...@@ -9,30 +9,29 @@ ...@@ -9,30 +9,29 @@
#include "testing/platform_test.h" #include "testing/platform_test.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
namespace VM = views::metadata; namespace TC = views::metadata;
using TypeConversionTest = PlatformTest; using TypeConversionTest = PlatformTest;
TEST_F(TypeConversionTest, TestConversion_IntToString) { TEST_F(TypeConversionTest, TestConversion_IntToString) {
int from_int = 5; int from_int = 5;
base::string16 to_string = VM::Convert<int, base::string16>(from_int); base::string16 to_string = TC::ConvertToString<int>(from_int);
EXPECT_EQ(to_string, base::ASCIIToUTF16("5")); EXPECT_EQ(to_string, base::ASCIIToUTF16("5"));
} }
TEST_F(TypeConversionTest, TestConversion_StringToInt) { TEST_F(TypeConversionTest, TestConversion_StringToInt) {
base::string16 from_string = base::ASCIIToUTF16("10"); base::string16 from_string = base::ASCIIToUTF16("10");
int to_int = VM::Convert<base::string16, int>(from_string, 0); int to_int = 0;
EXPECT_TRUE(TC::ConvertFromString<int>(from_string, &to_int));
EXPECT_EQ(to_int, 10); EXPECT_EQ(to_int, 10);
} }
// This tests whether the converter handles a bogus input string, in which case // This tests whether the converter handles a bogus input string, in which case
// the default value should be returned. // the return value should be false.
TEST_F(TypeConversionTest, TestConversion_StringToIntDefault) { TEST_F(TypeConversionTest, TestConversion_BogusStringToInt) {
const int default_value = 1000;
base::string16 from_string = base::ASCIIToUTF16("Foo"); base::string16 from_string = base::ASCIIToUTF16("Foo");
int to_int = VM::Convert<base::string16, int>(from_string, default_value); int to_int = 0;
EXPECT_FALSE(TC::ConvertFromString<int>(from_string, &to_int));
EXPECT_EQ(to_int, default_value);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment