summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-18 02:16:59 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-18 02:16:59 +0000
commit16f47e08060635631f1ad2cbb30906beb1caffc3 (patch)
treef2e07ada71f47383cb8355091b0a92e090c8656e /base
parent9fb09e0cb9a33db85884f3f81e406d12ad9f2b70 (diff)
downloadchromium_src-16f47e08060635631f1ad2cbb30906beb1caffc3.zip
chromium_src-16f47e08060635631f1ad2cbb30906beb1caffc3.tar.gz
chromium_src-16f47e08060635631f1ad2cbb30906beb1caffc3.tar.bz2
Made return types of various Value::DeepCopy() implementations more specific
Since C++ supports covariant return types, a subclass of Value can return its own pointer type for Value::DeepCopy(). Also made signatures of Value::Create*Value() more specific. Removed now-unnecessary casts. Added test for covariant return types. BUG=None TEST=Compile Review URL: http://codereview.chromium.org/6324004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71617 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/values.cc20
-rw-r--r--base/values.h23
-rw-r--r--base/values_unittest.cc78
3 files changed, 90 insertions, 31 deletions
diff --git a/base/values.cc b/base/values.cc
index 3522569..a4a6ff4 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -70,27 +70,27 @@ Value* Value::CreateNullValue() {
}
// static
-Value* Value::CreateBooleanValue(bool in_value) {
+FundamentalValue* Value::CreateBooleanValue(bool in_value) {
return new FundamentalValue(in_value);
}
// static
-Value* Value::CreateIntegerValue(int in_value) {
+FundamentalValue* Value::CreateIntegerValue(int in_value) {
return new FundamentalValue(in_value);
}
// static
-Value* Value::CreateRealValue(double in_value) {
+FundamentalValue* Value::CreateRealValue(double in_value) {
return new FundamentalValue(in_value);
}
// static
-Value* Value::CreateStringValue(const std::string& in_value) {
+StringValue* Value::CreateStringValue(const std::string& in_value) {
return new StringValue(in_value);
}
// static
-Value* Value::CreateStringValue(const string16& in_value) {
+StringValue* Value::CreateStringValue(const string16& in_value) {
return new StringValue(in_value);
}
@@ -182,7 +182,7 @@ bool FundamentalValue::GetAsReal(double* out_value) const {
return (IsType(TYPE_REAL));
}
-Value* FundamentalValue::DeepCopy() const {
+FundamentalValue* FundamentalValue::DeepCopy() const {
switch (GetType()) {
case TYPE_BOOLEAN:
return CreateBooleanValue(boolean_value_);
@@ -250,7 +250,7 @@ bool StringValue::GetAsString(string16* out_value) const {
return true;
}
-Value* StringValue::DeepCopy() const {
+StringValue* StringValue::DeepCopy() const {
return CreateStringValue(value_);
}
@@ -288,7 +288,7 @@ BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer,
return new BinaryValue(buffer_copy, size);
}
-Value* BinaryValue::DeepCopy() const {
+BinaryValue* BinaryValue::DeepCopy() const {
return CreateWithCopiedBuffer(buffer_, size_);
}
@@ -646,7 +646,7 @@ void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
}
}
-Value* DictionaryValue::DeepCopy() const {
+DictionaryValue* DictionaryValue::DeepCopy() const {
DictionaryValue* result = new DictionaryValue;
for (ValueMap::const_iterator current_entry(dictionary_.begin());
@@ -862,7 +862,7 @@ bool ListValue::GetAsList(ListValue** out_value) {
return true;
}
-Value* ListValue::DeepCopy() const {
+ListValue* ListValue::DeepCopy() const {
ListValue* result = new ListValue;
for (ValueVector::const_iterator i(list_.begin()); i != list_.end(); ++i)
diff --git a/base/values.h b/base/values.h
index d69a685..135a30f 100644
--- a/base/values.h
+++ b/base/values.h
@@ -63,11 +63,11 @@ class Value {
// kinds of values without thinking about which class implements them.
// These can always be expected to return a valid Value*.
static Value* CreateNullValue();
- static Value* CreateBooleanValue(bool in_value);
- static Value* CreateIntegerValue(int in_value);
- static Value* CreateRealValue(double in_value);
- static Value* CreateStringValue(const std::string& in_value);
- static Value* CreateStringValue(const string16& in_value);
+ static FundamentalValue* CreateBooleanValue(bool in_value);
+ static FundamentalValue* CreateIntegerValue(int in_value);
+ static FundamentalValue* CreateRealValue(double in_value);
+ static StringValue* CreateStringValue(const std::string& in_value);
+ static StringValue* CreateStringValue(const string16& in_value);
// This one can return NULL if the input isn't valid. If the return value
// is non-null, the new object has taken ownership of the buffer pointer.
@@ -96,6 +96,9 @@ class Value {
// This creates a deep copy of the entire Value tree, and returns a pointer
// to the copy. The caller gets ownership of the copy, of course.
+ //
+ // Subclasses return their own type directly in their overrides;
+ // this works because C++ supports covariant return types.
virtual Value* DeepCopy() const;
// Compares if two Value objects have equal contents.
@@ -130,7 +133,7 @@ class FundamentalValue : public Value {
virtual bool GetAsBoolean(bool* out_value) const;
virtual bool GetAsInteger(int* out_value) const;
virtual bool GetAsReal(double* out_value) const;
- virtual Value* DeepCopy() const;
+ virtual FundamentalValue* DeepCopy() const;
virtual bool Equals(const Value* other) const;
private:
@@ -156,7 +159,7 @@ class StringValue : public Value {
// Subclassed methods
virtual bool GetAsString(std::string* out_value) const;
virtual bool GetAsString(string16* out_value) const;
- virtual Value* DeepCopy() const;
+ virtual StringValue* DeepCopy() const;
virtual bool Equals(const Value* other) const;
private:
@@ -185,7 +188,7 @@ class BinaryValue: public Value {
const char* GetBuffer() const { return buffer_; }
// Overridden from Value:
- virtual Value* DeepCopy() const;
+ virtual BinaryValue* DeepCopy() const;
virtual bool Equals(const Value* other) const;
private:
@@ -330,7 +333,7 @@ class DictionaryValue : public Value {
key_iterator end_keys() const { return key_iterator(dictionary_.end()); }
// Overridden from Value:
- virtual Value* DeepCopy() const;
+ virtual DictionaryValue* DeepCopy() const;
virtual bool Equals(const Value* other) const;
private:
@@ -417,7 +420,7 @@ class ListValue : public Value {
// Overridden from Value:
virtual bool GetAsList(ListValue** out_value);
- virtual Value* DeepCopy() const;
+ virtual ListValue* DeepCopy() const;
virtual bool Equals(const Value* other) const;
private:
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index adcd07e..774dfca 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -323,15 +323,16 @@ TEST_F(ValuesTest, DeepCopy) {
DictionaryValue original_dict;
Value* original_null = Value::CreateNullValue();
original_dict.Set("null", original_null);
- Value* original_bool = Value::CreateBooleanValue(true);
+ FundamentalValue* original_bool = Value::CreateBooleanValue(true);
original_dict.Set("bool", original_bool);
- Value* original_int = Value::CreateIntegerValue(42);
+ FundamentalValue* original_int = Value::CreateIntegerValue(42);
original_dict.Set("int", original_int);
- Value* original_real = Value::CreateRealValue(3.14);
+ FundamentalValue* original_real = Value::CreateRealValue(3.14);
original_dict.Set("real", original_real);
- Value* original_string = Value::CreateStringValue("hello");
+ StringValue* original_string = Value::CreateStringValue("hello");
original_dict.Set("string", original_string);
- Value* original_string16 = Value::CreateStringValue(ASCIIToUTF16("hello16"));
+ StringValue* original_string16 =
+ Value::CreateStringValue(ASCIIToUTF16("hello16"));
original_dict.Set("string16", original_string16);
char* original_buffer = new char[42];
@@ -340,14 +341,13 @@ TEST_F(ValuesTest, DeepCopy) {
original_dict.Set("binary", original_binary);
ListValue* original_list = new ListValue();
- Value* original_list_element_0 = Value::CreateIntegerValue(0);
+ FundamentalValue* original_list_element_0 = Value::CreateIntegerValue(0);
original_list->Append(original_list_element_0);
- Value* original_list_element_1 = Value::CreateIntegerValue(1);
+ FundamentalValue* original_list_element_1 = Value::CreateIntegerValue(1);
original_list->Append(original_list_element_1);
original_dict.Set("list", original_list);
- scoped_ptr<DictionaryValue> copy_dict(
- static_cast<DictionaryValue*>(original_dict.DeepCopy()));
+ scoped_ptr<DictionaryValue> copy_dict(original_dict.DeepCopy());
ASSERT_TRUE(copy_dict.get());
ASSERT_NE(copy_dict.get(), &original_dict);
@@ -465,7 +465,7 @@ TEST_F(ValuesTest, Equals) {
dv.Set("e", Value::CreateNullValue());
scoped_ptr<DictionaryValue> copy;
- copy.reset(static_cast<DictionaryValue*>(dv.DeepCopy()));
+ copy.reset(dv.DeepCopy());
EXPECT_TRUE(dv.Equals(copy.get()));
ListValue* list = new ListValue;
@@ -481,7 +481,7 @@ TEST_F(ValuesTest, Equals) {
EXPECT_FALSE(dv.Equals(copy.get()));
// Check if Equals detects differences in only the keys.
- copy.reset(static_cast<DictionaryValue*>(dv.DeepCopy()));
+ copy.reset(dv.DeepCopy());
EXPECT_TRUE(dv.Equals(copy.get()));
copy->Remove("a", NULL);
copy->SetBoolean("aa", false);
@@ -511,6 +511,62 @@ TEST_F(ValuesTest, StaticEquals) {
EXPECT_FALSE(Value::Equals(NULL, null1.get()));
}
+TEST_F(ValuesTest, DeepCopyCovariantReturnTypes) {
+ DictionaryValue original_dict;
+ Value* original_null = Value::CreateNullValue();
+ original_dict.Set("null", original_null);
+ FundamentalValue* original_bool = Value::CreateBooleanValue(true);
+ original_dict.Set("bool", original_bool);
+ FundamentalValue* original_int = Value::CreateIntegerValue(42);
+ original_dict.Set("int", original_int);
+ FundamentalValue* original_real = Value::CreateRealValue(3.14);
+ original_dict.Set("real", original_real);
+ StringValue* original_string = Value::CreateStringValue("hello");
+ original_dict.Set("string", original_string);
+ StringValue* original_string16 =
+ Value::CreateStringValue(ASCIIToUTF16("hello16"));
+ original_dict.Set("string16", original_string16);
+
+ char* original_buffer = new char[42];
+ memset(original_buffer, '!', 42);
+ BinaryValue* original_binary = Value::CreateBinaryValue(original_buffer, 42);
+ original_dict.Set("binary", original_binary);
+
+ ListValue* original_list = new ListValue();
+ FundamentalValue* original_list_element_0 = Value::CreateIntegerValue(0);
+ original_list->Append(original_list_element_0);
+ FundamentalValue* original_list_element_1 = Value::CreateIntegerValue(1);
+ original_list->Append(original_list_element_1);
+ original_dict.Set("list", original_list);
+
+ Value* original_dict_value = &original_dict;
+ Value* original_bool_value = original_bool;
+ Value* original_int_value = original_int;
+ Value* original_real_value = original_real;
+ Value* original_string_value = original_string;
+ Value* original_string16_value = original_string16;
+ Value* original_binary_value = original_binary;
+ Value* original_list_value = original_list;
+
+ scoped_ptr<Value> copy_dict_value(original_dict_value->DeepCopy());
+ scoped_ptr<Value> copy_bool_value(original_bool_value->DeepCopy());
+ scoped_ptr<Value> copy_int_value(original_int_value->DeepCopy());
+ scoped_ptr<Value> copy_real_value(original_real_value->DeepCopy());
+ scoped_ptr<Value> copy_string_value(original_string_value->DeepCopy());
+ scoped_ptr<Value> copy_string16_value(original_string16_value->DeepCopy());
+ scoped_ptr<Value> copy_binary_value(original_binary_value->DeepCopy());
+ scoped_ptr<Value> copy_list_value(original_list_value->DeepCopy());
+
+ EXPECT_TRUE(original_dict_value->Equals(copy_dict_value.get()));
+ EXPECT_TRUE(original_bool_value->Equals(copy_bool_value.get()));
+ EXPECT_TRUE(original_int_value->Equals(copy_int_value.get()));
+ EXPECT_TRUE(original_real_value->Equals(copy_real_value.get()));
+ EXPECT_TRUE(original_string_value->Equals(copy_string_value.get()));
+ EXPECT_TRUE(original_string16_value->Equals(copy_string16_value.get()));
+ EXPECT_TRUE(original_binary_value->Equals(copy_binary_value.get()));
+ EXPECT_TRUE(original_list_value->Equals(copy_list_value.get()));
+}
+
TEST_F(ValuesTest, RemoveEmptyChildren) {
scoped_ptr<DictionaryValue> root(new DictionaryValue);
// Remove empty lists and dictionaries.