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

Unified Diff: base/values.cc

Issue 2645073002: Inline FundamentalValue into base::Value (Closed)
Patch Set: Use literals for default initialization. Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/values.cc
diff --git a/base/values.cc b/base/values.cc
index ca3692deccae32ff401b99ac35487db78dc66199..82b137a2826d101e17c80d51da81e91508814a1b 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -73,16 +73,95 @@ std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) {
}
}
-} // namespace
+// TODO(crbug.com/646113): Remove this once all types are implemented.
+bool IsAssignmentSafe(Value::Type lhs, Value::Type rhs) {
+ auto IsImplemented = [](Value::Type type) {
+ return type == Value::Type::NONE || type == Value::Type::BOOLEAN ||
+ type == Value::Type::INTEGER || type == Value::Type::DOUBLE;
+ };
-Value::~Value() {
+ return lhs == rhs || (IsImplemented(lhs) && IsImplemented(rhs));
}
+} // namespace
+
// static
std::unique_ptr<Value> Value::CreateNullValue() {
return WrapUnique(new Value(Type::NONE));
}
+Value::Value(const Value& that) {
+ InternalCopyFrom(that);
+}
+
+Value::Value(Value&& that) {
+ // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving
+ // and copying differ.
+ InternalCopyFrom(that);
+}
+
+Value::Value() : type_(Type::NONE) {}
+
+Value::Value(Type type) : type_(type) {
+ // Initialize with the default value.
+ switch (type_) {
+ case Type::NONE:
+ return;
+
+ case Type::BOOLEAN:
+ bool_value_ = false;
+ return;
+ case Type::INTEGER:
+ int_value_ = 0;
+ return;
+ case Type::DOUBLE:
+ double_value_ = 0.0;
+ 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;
+ }
+}
+
+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::operator=(const Value& that) {
+ if (this != &that) {
+ DCHECK(IsAssignmentSafe(type_, that.type_));
+ InternalCopyFrom(that);
+ }
+
+ return *this;
+}
+
+Value& Value::operator=(Value&& that) {
+ if (this != &that) {
+ // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving
+ // and copying differ.
+ DCHECK(IsAssignmentSafe(type_, that.type_));
+ InternalCopyFrom(that);
+ }
+
+ return *this;
+}
+
+Value::~Value() {}
+
// static
const char* Value::GetTypeName(Value::Type type) {
DCHECK_GE(static_cast<int>(type), 0);
@@ -90,20 +169,51 @@ const char* Value::GetTypeName(Value::Type type) {
return kTypeNames[static_cast<size_t>(type)];
}
-bool Value::GetAsBinary(const BinaryValue** out_value) const {
- return false;
+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::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 {
@@ -122,6 +232,10 @@ bool Value::GetAsString(StringPiece* out_value) const {
return false;
}
+bool Value::GetAsBinary(const BinaryValue** out_value) const {
+ return false;
+}
+
bool Value::GetAsList(ListValue** out_value) {
return false;
}
@@ -141,8 +255,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 {
@@ -150,10 +280,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
@@ -163,92 +307,30 @@ bool Value::Equals(const Value* a, const Value* b) {
return a->Equals(b);
}
-Value::Value(Type type) : type_(type) {}
-
-Value::Value(const Value& that) : type_(that.type_) {}
-
-Value& Value::operator=(const Value& that) {
+void Value::InternalCopyFrom(const Value& that) {
type_ = that.type_;
- return *this;
-}
-
-///////////////////// 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;
- }
-}
-
-FundamentalValue::~FundamentalValue() {
-}
-
-bool FundamentalValue::GetAsBoolean(bool* out_value) const {
- if (out_value && IsType(Type::BOOLEAN))
- *out_value = boolean_value_;
- return (IsType(Type::BOOLEAN));
-}
-
-bool FundamentalValue::GetAsInteger(int* out_value) const {
- if (out_value && IsType(Type::INTEGER))
- *out_value = integer_value_;
- return (IsType(Type::INTEGER));
-}
+ switch (type_) {
+ case Type::NONE:
+ // Nothing to do.
+ return;
-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));
-}
-
-FundamentalValue* FundamentalValue::DeepCopy() const {
- switch (GetType()) {
case Type::BOOLEAN:
- return new FundamentalValue(boolean_value_);
-
+ bool_value_ = that.bool_value_;
+ return;
case Type::INTEGER:
- return new FundamentalValue(integer_value_);
-
+ int_value_ = that.int_value_;
+ return;
case Type::DOUBLE:
- return new FundamentalValue(double_value_);
-
- default:
- NOTREACHED();
- return NULL;
- }
-}
-
-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;
+ 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;
}
}
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698