Index: base/values.cc |
diff --git a/base/values.cc b/base/values.cc |
index 82b137a2826d101e17c80d51da81e91508814a1b..145c0c11914be03e22ed9d1457e177ffd0efcda0 100644 |
--- a/base/values.cc |
+++ b/base/values.cc |
@@ -77,7 +77,8 @@ std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) { |
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; |
+ type == Value::Type::INTEGER || type == Value::Type::DOUBLE || |
+ type == Value::Type::STRING; |
}; |
return lhs == rhs || (IsImplemented(lhs) && IsImplemented(rhs)); |
@@ -91,13 +92,11 @@ std::unique_ptr<Value> Value::CreateNullValue() { |
} |
Value::Value(const Value& that) { |
- InternalCopyFrom(that); |
+ InternalCopyConstructFrom(that); |
} |
Value::Value(Value&& that) { |
- // TODO(crbug.com/646113): Implement InternalMoveFrom for types where moving |
- // and copying differ. |
- InternalCopyFrom(that); |
+ InternalMoveConstructFrom(std::move(that)); |
} |
Value::Value() : type_(Type::NONE) {} |
@@ -117,10 +116,12 @@ Value::Value(Type type) : type_(type) { |
case Type::DOUBLE: |
double_value_ = 0.0; |
return; |
+ case Type::STRING: |
+ string_value_.Init(); |
+ 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: |
@@ -140,10 +141,40 @@ Value::Value(double in_double) : type_(Type::DOUBLE), double_value_(in_double) { |
} |
} |
+Value::Value(const char* in_string) : type_(Type::STRING) { |
+ string_value_.Init(in_string); |
+ DCHECK(IsStringUTF8(*string_value_)); |
+} |
+ |
+Value::Value(const std::string& in_string) : type_(Type::STRING) { |
+ string_value_.Init(in_string); |
+ DCHECK(IsStringUTF8(*string_value_)); |
+} |
+ |
+Value::Value(std::string&& in_string) : type_(Type::STRING) { |
+ string_value_.Init(std::move(in_string)); |
+ DCHECK(IsStringUTF8(*string_value_)); |
+} |
+ |
+Value::Value(const char16* in_string) : type_(Type::STRING) { |
+ string_value_.Init(UTF16ToUTF8(in_string)); |
+} |
+ |
+Value::Value(const string16& in_string) : type_(Type::STRING) { |
+ string_value_.Init(UTF16ToUTF8(in_string)); |
+} |
+ |
+Value::Value(StringPiece in_string) : Value(in_string.as_string()) {} |
+ |
Value& Value::operator=(const Value& that) { |
if (this != &that) { |
DCHECK(IsAssignmentSafe(type_, that.type_)); |
- InternalCopyFrom(that); |
+ if (type_ == that.type_) { |
+ InternalCopyAssignFrom(that); |
+ } else { |
+ InternalCleanup(); |
+ InternalCopyConstructFrom(that); |
+ } |
} |
return *this; |
@@ -151,16 +182,21 @@ Value& Value::operator=(const Value& that) { |
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); |
+ if (type_ == that.type_) { |
+ InternalMoveAssignFrom(std::move(that)); |
+ } else { |
+ InternalCleanup(); |
+ InternalMoveConstructFrom(std::move(that)); |
+ } |
} |
return *this; |
} |
-Value::~Value() {} |
+Value::~Value() { |
+ InternalCleanup(); |
+} |
// static |
const char* Value::GetTypeName(Value::Type type) { |
@@ -188,6 +224,11 @@ double Value::GetDouble() const { |
return 0.0; |
} |
+const std::string& Value::GetString() const { |
+ CHECK(is_string()); |
+ return *string_value_; |
+} |
+ |
bool Value::GetAsBoolean(bool* out_value) const { |
if (out_value && is_bool()) { |
*out_value = bool_value_; |
@@ -217,19 +258,35 @@ bool Value::GetAsDouble(double* out_value) const { |
} |
bool Value::GetAsString(std::string* out_value) const { |
- return false; |
+ if (out_value && is_string()) { |
+ *out_value = *string_value_; |
+ return true; |
+ } |
+ return is_string(); |
} |
bool Value::GetAsString(string16* out_value) const { |
- return false; |
+ if (out_value && is_string()) { |
+ *out_value = UTF8ToUTF16(*string_value_); |
+ return true; |
+ } |
+ return is_string(); |
} |
bool Value::GetAsString(const StringValue** out_value) const { |
- return false; |
+ if (out_value && is_string()) { |
+ *out_value = static_cast<const StringValue*>(this); |
+ return true; |
+ } |
+ return is_string(); |
} |
bool Value::GetAsString(StringPiece* out_value) const { |
- return false; |
+ if (out_value && is_string()) { |
+ *out_value = *string_value_; |
+ return true; |
+ } |
+ return is_string(); |
} |
bool Value::GetAsBinary(const BinaryValue** out_value) const { |
@@ -267,6 +324,10 @@ Value* Value::DeepCopy() const { |
return new FundamentalValue(int_value_); |
case Type::DOUBLE: |
return new FundamentalValue(double_value_); |
+ // For now, make StringValues for backward-compatibility. Convert to |
+ // Value when that code is deleted. |
+ case Type::STRING: |
+ return new StringValue(*string_value_); |
default: |
// All other types should be handled by subclasses. |
@@ -292,6 +353,11 @@ bool Value::Equals(const Value* other) const { |
return int_value_ == other->int_value_; |
case Type::DOUBLE: |
return double_value_ == other->double_value_; |
+ // TODO(crbug.com/646113): Simplify this once JSONStringValue is removed. |
+ case Type::STRING: { |
+ std::string lhs, rhs; |
+ return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs; |
+ } |
default: |
// This method should only be getting called for the above types -- all |
// subclasses need to provide their own implementation;. |
@@ -307,8 +373,7 @@ bool Value::Equals(const Value* a, const Value* b) { |
return a->Equals(b); |
} |
-void Value::InternalCopyFrom(const Value& that) { |
- type_ = that.type_; |
+void Value::InternalCopyFundamentalValue(const Value& that) { |
switch (type_) { |
case Type::NONE: |
// Nothing to do. |
@@ -324,9 +389,28 @@ void Value::InternalCopyFrom(const Value& that) { |
double_value_ = that.double_value_; |
return; |
+ default: |
+ NOTREACHED(); |
+ } |
+} |
+ |
+void Value::InternalCopyConstructFrom(const Value& that) { |
+ type_ = that.type_; |
+ |
+ switch (type_) { |
+ case Type::NONE: |
+ case Type::BOOLEAN: |
+ case Type::INTEGER: |
+ case Type::DOUBLE: |
+ InternalCopyFundamentalValue(that); |
+ return; |
+ |
+ case Type::STRING: |
+ string_value_.Init(*that.string_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: |
@@ -334,60 +418,98 @@ void Value::InternalCopyFrom(const Value& that) { |
} |
} |
-///////////////////// StringValue //////////////////// |
+void Value::InternalMoveConstructFrom(Value&& that) { |
+ type_ = that.type_; |
-StringValue::StringValue(StringPiece in_value) |
- : Value(Type::STRING), value_(in_value.as_string()) { |
- DCHECK(IsStringUTF8(in_value)); |
-} |
+ switch (type_) { |
+ case Type::NONE: |
+ case Type::BOOLEAN: |
+ case Type::INTEGER: |
+ case Type::DOUBLE: |
+ InternalCopyFundamentalValue(that); |
+ return; |
-StringValue::StringValue(const string16& in_value) |
- : Value(Type::STRING), value_(UTF16ToUTF8(in_value)) {} |
+ case Type::STRING: |
+ string_value_.InitFromMove(std::move(that.string_value_)); |
+ return; |
-StringValue::~StringValue() { |
+ // TODO(crbug.com/646113): Implement these once the corresponding derived |
+ // classes are removed. |
+ case Type::BINARY: |
+ case Type::LIST: |
+ case Type::DICTIONARY: |
+ return; |
+ } |
} |
-std::string* StringValue::GetString() { |
- return &value_; |
-} |
+void Value::InternalCopyAssignFrom(const Value& that) { |
+ type_ = that.type_; |
-const std::string& StringValue::GetString() const { |
- return value_; |
-} |
+ switch (type_) { |
+ case Type::NONE: |
+ case Type::BOOLEAN: |
+ case Type::INTEGER: |
+ case Type::DOUBLE: |
+ InternalCopyFundamentalValue(that); |
+ return; |
-bool StringValue::GetAsString(std::string* out_value) const { |
- if (out_value) |
- *out_value = value_; |
- return true; |
-} |
+ case Type::STRING: |
+ *string_value_ = *that.string_value_; |
+ return; |
-bool StringValue::GetAsString(string16* out_value) const { |
- if (out_value) |
- *out_value = UTF8ToUTF16(value_); |
- return true; |
+ // TODO(crbug.com/646113): Implement these once the corresponding derived |
+ // classes are removed. |
+ case Type::BINARY: |
+ case Type::LIST: |
+ case Type::DICTIONARY: |
+ return; |
+ } |
} |
-bool StringValue::GetAsString(const StringValue** out_value) const { |
- if (out_value) |
- *out_value = this; |
- return true; |
-} |
+void Value::InternalMoveAssignFrom(Value&& that) { |
+ type_ = that.type_; |
-bool StringValue::GetAsString(StringPiece* out_value) const { |
- if (out_value) |
- *out_value = value_; |
- return true; |
-} |
+ switch (type_) { |
+ case Type::NONE: |
+ case Type::BOOLEAN: |
+ case Type::INTEGER: |
+ case Type::DOUBLE: |
+ InternalCopyFundamentalValue(that); |
+ return; |
-StringValue* StringValue::DeepCopy() const { |
- return new StringValue(value_); |
+ case Type::STRING: |
+ *string_value_ = std::move(*that.string_value_); |
+ return; |
+ |
+ // TODO(crbug.com/646113): Implement these once the corresponding derived |
+ // classes are removed. |
+ case Type::BINARY: |
+ case Type::LIST: |
+ case Type::DICTIONARY: |
+ return; |
+ } |
} |
-bool StringValue::Equals(const Value* other) const { |
- if (other->GetType() != GetType()) |
- return false; |
- std::string lhs, rhs; |
- return GetAsString(&lhs) && other->GetAsString(&rhs) && lhs == rhs; |
+void Value::InternalCleanup() { |
+ switch (type_) { |
+ case Type::NONE: |
+ case Type::BOOLEAN: |
+ case Type::INTEGER: |
+ case Type::DOUBLE: |
+ // Nothing to do |
+ return; |
+ |
+ case Type::STRING: |
+ string_value_.Destroy(); |
+ return; |
+ |
+ // TODO(crbug.com/646113): Implement these once the corresponding derived |
+ // classes are removed. |
+ case Type::BINARY: |
+ case Type::LIST: |
+ case Type::DICTIONARY: |
+ return; |
+ } |
} |
///////////////////// BinaryValue //////////////////// |