Index: base/values.cc |
diff --git a/base/values.cc b/base/values.cc |
index fd0bbe17a41468da40b3e55bc64c50ef3be5415d..4b362211c467b5c1af7b8b88a0ec91bef9c4fa71 100644 |
--- a/base/values.cc |
+++ b/base/values.cc |
@@ -75,9 +75,48 @@ std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) { |
} // namespace |
+Value::Value(bool in_bool) : type_(Type::BOOLEAN), bool_value_(in_bool) {} |
+ |
+Value::Value(int in_int) : type_(Type::INTEGER), int_value_(in_int) {} |
+ |
+Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { |
+ if (!std::isfinite(double_value_)) { |
+ NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " |
+ << "values cannot be represented in JSON"; |
+ double_value_ = 0.0; |
+ } |
+} |
+ |
Value::~Value() { |
} |
+void Value::InternalCopyFrom(const Value& that) { |
+ type_ = that.type_; |
+ switch (type_) { |
+ case Type::NONE: |
+ // Nothing to do |
+ return; |
+ |
+ case Type::BOOLEAN: |
+ bool_value_ = that.bool_value_; |
+ return; |
+ case Type::INTEGER: |
+ int_value_ = that.int_value_; |
+ return; |
+ case Type::DOUBLE: |
+ double_value_ = that.double_value_; |
+ return; |
+ |
+ // TODO(crbug.com/646113): Implement these once the corresponding derived |
+ // classes are removed. |
+ case Type::STRING: |
+ case Type::BINARY: |
+ case Type::LIST: |
+ case Type::DICTIONARY: |
+ return; |
+ } |
+} |
+ |
// static |
std::unique_ptr<Value> Value::CreateNullValue() { |
return WrapUnique(new Value(Type::NONE)); |
@@ -90,20 +129,55 @@ const char* Value::GetTypeName(Value::Type type) { |
return kTypeNames[static_cast<size_t>(type)]; |
} |
+bool Value::GetBool() const { |
+ CHECK(is_bool()); |
+ return bool_value_; |
+} |
+ |
+int Value::GetInt() const { |
+ CHECK(is_int()); |
+ return int_value_; |
+} |
+ |
+double Value::GetDouble() const { |
+ if (is_double()) |
+ return double_value_; |
+ if (is_int()) |
+ return int_value_; |
+ CHECK(false); |
+ return 0.0; |
+} |
+ |
bool Value::GetAsBinary(const BinaryValue** out_value) const { |
return false; |
} |
bool Value::GetAsBoolean(bool* out_value) const { |
- return false; |
+ if (out_value && is_bool()) { |
+ *out_value = bool_value_; |
+ return true; |
+ } |
+ return is_bool(); |
} |
bool Value::GetAsInteger(int* out_value) const { |
- return false; |
+ if (out_value && is_int()) { |
+ *out_value = int_value_; |
+ return true; |
+ } |
+ return is_int(); |
} |
bool Value::GetAsDouble(double* out_value) const { |
- return false; |
+ if (out_value && is_double()) { |
+ *out_value = double_value_; |
+ return true; |
+ } else if (out_value && is_int()) { |
+ // Allow promotion from int to double. |
+ *out_value = int_value_; |
+ return true; |
+ } |
+ return is_double() || is_int(); |
} |
bool Value::GetAsString(std::string* out_value) const { |
@@ -137,8 +211,24 @@ bool Value::GetAsDictionary(const DictionaryValue** out_value) const { |
Value* Value::DeepCopy() const { |
// This method should only be getting called for null Values--all subclasses |
// need to provide their own implementation;. |
- DCHECK(IsType(Type::NONE)); |
- return CreateNullValue().release(); |
+ switch (type()) { |
+ case Type::NONE: |
+ return CreateNullValue().release(); |
+ |
+ // For now, make FundamentalValues for backward-compatibility. Convert to |
+ // Value when that code is deleted. |
+ case Type::BOOLEAN: |
+ return new FundamentalValue(bool_value_); |
+ case Type::INTEGER: |
+ return new FundamentalValue(int_value_); |
+ case Type::DOUBLE: |
+ return new FundamentalValue(double_value_); |
+ |
+ default: |
+ // All other types should be handled by subclasses. |
+ NOTREACHED(); |
+ return nullptr; |
+ } |
} |
std::unique_ptr<Value> Value::CreateDeepCopy() const { |
@@ -146,10 +236,24 @@ std::unique_ptr<Value> Value::CreateDeepCopy() const { |
} |
bool Value::Equals(const Value* other) const { |
- // This method should only be getting called for null Values--all subclasses |
- // need to provide their own implementation;. |
- DCHECK(IsType(Type::NONE)); |
- return other->IsType(Type::NONE); |
+ if (other->type() != type()) |
+ return false; |
+ |
+ switch (type()) { |
+ case Type::NONE: |
+ return true; |
+ case Type::BOOLEAN: |
+ return bool_value_ == other->bool_value_; |
+ case Type::INTEGER: |
+ return int_value_ == other->int_value_; |
+ case Type::DOUBLE: |
+ return double_value_ == other->double_value_; |
+ default: |
+ // This method should only be getting called for the above types -- all |
+ // subclasses need to provide their own implementation;. |
+ NOTREACHED(); |
+ return false; |
+ } |
} |
// static |
@@ -161,92 +265,43 @@ bool Value::Equals(const Value* a, const Value* b) { |
Value::Value(Type type) : type_(type) {} |
-Value::Value(const Value& that) : type_(that.type_) {} |
- |
-Value& Value::operator=(const Value& that) { |
- type_ = that.type_; |
- return *this; |
+Value::Value(const Value& that) { |
+ InternalCopyFrom(that); |
brettw
2016/12/08 21:57:47
Thanks for finding this was missing! Seems obvious
vabr (Chromium)
2016/12/09 07:57:22
Chromium has apparently in some cases accidentally
|
} |
-///////////////////// FundamentalValue //////////////////// |
- |
-FundamentalValue::FundamentalValue(bool in_value) |
- : Value(Type::BOOLEAN), boolean_value_(in_value) {} |
- |
-FundamentalValue::FundamentalValue(int in_value) |
- : Value(Type::INTEGER), integer_value_(in_value) {} |
- |
-FundamentalValue::FundamentalValue(double in_value) |
- : Value(Type::DOUBLE), double_value_(in_value) { |
- if (!std::isfinite(double_value_)) { |
- NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " |
- << "values cannot be represented in JSON"; |
- double_value_ = 0.0; |
- } |
+Value::Value(Value&& that) { |
+ // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving |
+ // and copying differ. |
+ InternalCopyFrom(that); |
} |
-FundamentalValue::~FundamentalValue() { |
-} |
+Value& Value::operator=(const Value& that) { |
+ if (this != &that) { |
brettw
2016/12/08 21:57:47
For consistency with other code in this file, don'
vabr (Chromium)
2016/12/09 07:57:22
Done.
|
+ InternalCopyFrom(that); |
+ } |
-bool FundamentalValue::GetAsBoolean(bool* out_value) const { |
- if (out_value && IsType(Type::BOOLEAN)) |
- *out_value = boolean_value_; |
- return (IsType(Type::BOOLEAN)); |
+ return *this; |
} |
-bool FundamentalValue::GetAsInteger(int* out_value) const { |
- if (out_value && IsType(Type::INTEGER)) |
- *out_value = integer_value_; |
- return (IsType(Type::INTEGER)); |
-} |
+Value& Value::operator=(Value&& that) { |
+ if (this != &that) { |
+ // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving |
+ // and copying differ. |
+ InternalCopyFrom(that); |
+ } |
-bool FundamentalValue::GetAsDouble(double* out_value) const { |
- if (out_value && IsType(Type::DOUBLE)) |
- *out_value = double_value_; |
- else if (out_value && IsType(Type::INTEGER)) |
- *out_value = integer_value_; |
- return (IsType(Type::DOUBLE) || IsType(Type::INTEGER)); |
+ return *this; |
} |
-FundamentalValue* FundamentalValue::DeepCopy() const { |
- switch (GetType()) { |
- case Type::BOOLEAN: |
- return new FundamentalValue(boolean_value_); |
+///////////////////// FundamentalValue //////////////////// |
- case Type::INTEGER: |
- return new FundamentalValue(integer_value_); |
+FundamentalValue::FundamentalValue(bool in_value) : Value(in_value) {} |
- case Type::DOUBLE: |
- return new FundamentalValue(double_value_); |
+FundamentalValue::FundamentalValue(int in_value) : Value(in_value) {} |
- default: |
- NOTREACHED(); |
- return NULL; |
- } |
-} |
+FundamentalValue::FundamentalValue(double in_value) : Value(in_value) {} |
-bool FundamentalValue::Equals(const Value* other) const { |
- if (other->GetType() != GetType()) |
- return false; |
- |
- switch (GetType()) { |
- case Type::BOOLEAN: { |
- bool lhs, rhs; |
- return GetAsBoolean(&lhs) && other->GetAsBoolean(&rhs) && lhs == rhs; |
- } |
- case Type::INTEGER: { |
- int lhs, rhs; |
- return GetAsInteger(&lhs) && other->GetAsInteger(&rhs) && lhs == rhs; |
- } |
- case Type::DOUBLE: { |
- double lhs, rhs; |
- return GetAsDouble(&lhs) && other->GetAsDouble(&rhs) && lhs == rhs; |
- } |
- default: |
- NOTREACHED(); |
- return false; |
- } |
-} |
+FundamentalValue::~FundamentalValue() {} |
///////////////////// StringValue //////////////////// |