diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-18 02:16:59 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-18 02:16:59 +0000 |
commit | 16f47e08060635631f1ad2cbb30906beb1caffc3 (patch) | |
tree | f2e07ada71f47383cb8355091b0a92e090c8656e /base | |
parent | 9fb09e0cb9a33db85884f3f81e406d12ad9f2b70 (diff) | |
download | chromium_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.cc | 20 | ||||
-rw-r--r-- | base/values.h | 23 | ||||
-rw-r--r-- | base/values_unittest.cc | 78 |
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. |