Index: base/values.cc |
diff --git a/base/values.cc b/base/values.cc |
index e835e0088ec5a0191d5c44ffcee824e230c1a6d6..1e60096c315081d58f1074633cff21b7027e8611 100644 |
--- a/base/values.cc |
+++ b/base/values.cc |
@@ -73,17 +73,6 @@ std::unique_ptr<Value> CopyWithoutEmptyChildren(const Value& node) { |
} |
} |
-// 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 || |
- type == Value::Type::STRING || type == Value::Type::BINARY; |
- }; |
- |
- return lhs == rhs || (IsImplemented(lhs) && IsImplemented(rhs)); |
-} |
- |
} // namespace |
// static |
@@ -129,11 +118,11 @@ Value::Value(Type type) : type_(type) { |
case Type::BINARY: |
binary_value_.Init(); |
return; |
- |
- // TODO(crbug.com/646113): Implement these once the corresponding derived |
- // classes are removed. |
- case Type::LIST: |
case Type::DICTIONARY: |
+ dictionary_.Init(); |
+ return; |
+ case Type::LIST: |
+ list_.Init(); |
return; |
} |
} |
@@ -185,7 +174,6 @@ Value::Value(std::vector<char>&& in_blob) : type_(Type::BINARY) { |
Value& Value::operator=(const Value& that) { |
if (this != &that) { |
- DCHECK(IsAssignmentSafe(type_, that.type_)); |
if (type_ == that.type_) { |
InternalCopyAssignFrom(that); |
} else { |
@@ -199,7 +187,6 @@ Value& Value::operator=(const Value& that) { |
Value& Value::operator=(Value&& that) { |
if (this != &that) { |
- DCHECK(IsAssignmentSafe(type_, that.type_)); |
if (type_ == that.type_) { |
InternalMoveAssignFrom(std::move(that)); |
} else { |
@@ -328,19 +315,35 @@ bool Value::GetAsBinary(const BinaryValue** out_value) const { |
} |
bool Value::GetAsList(ListValue** out_value) { |
- return false; |
+ if (out_value && is_list()) { |
+ *out_value = static_cast<ListValue*>(this); |
+ return true; |
+ } |
+ return is_list(); |
} |
bool Value::GetAsList(const ListValue** out_value) const { |
- return false; |
+ if (out_value && is_list()) { |
+ *out_value = static_cast<const ListValue*>(this); |
+ return true; |
+ } |
+ return is_list(); |
} |
bool Value::GetAsDictionary(DictionaryValue** out_value) { |
- return false; |
+ if (out_value && is_dict()) { |
+ *out_value = static_cast<DictionaryValue*>(this); |
+ return true; |
+ } |
+ return is_dict(); |
} |
bool Value::GetAsDictionary(const DictionaryValue** out_value) const { |
- return false; |
+ if (out_value && is_dict()) { |
+ *out_value = static_cast<const DictionaryValue*>(this); |
+ return true; |
+ } |
+ return is_dict(); |
} |
Value* Value::DeepCopy() const { |
@@ -367,8 +370,29 @@ Value* Value::DeepCopy() const { |
case Type::BINARY: |
return new BinaryValue(*binary_value_); |
+ // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue |
+ // are completely inlined. |
+ case Type::DICTIONARY: { |
+ DictionaryValue* result = new DictionaryValue; |
+ |
+ for (const auto& current_entry : *dictionary_) { |
+ result->SetWithoutPathExpansion(current_entry.first, |
+ current_entry.second->CreateDeepCopy()); |
+ } |
+ |
+ return result; |
+ } |
+ |
+ case Type::LIST: { |
+ ListValue* result = new ListValue; |
+ |
+ for (const auto& entry : *list_) |
+ result->Append(entry->CreateDeepCopy()); |
+ |
+ return result; |
+ } |
+ |
default: |
- // All other types should be handled by subclasses. |
NOTREACHED(); |
return nullptr; |
} |
@@ -395,12 +419,37 @@ bool Value::Equals(const Value* other) const { |
return *string_value_ == *(other->string_value_); |
case Type::BINARY: |
return *binary_value_ == *(other->binary_value_); |
- default: |
- // This method should only be getting called for the above types -- all |
- // subclasses need to provide their own implementation;. |
- NOTREACHED(); |
- return false; |
+ // TODO(crbug.com/646113): Clean this up when DictionaryValue and ListValue |
+ // are completely inlined. |
+ case Type::DICTIONARY: { |
+ if (dictionary_->size() != other->dictionary_->size()) |
+ return false; |
+ |
+ return std::equal(std::begin(*dictionary_), std::end(*dictionary_), |
+ std::begin(*(other->dictionary_)), |
+ [](const DictStorage::value_type& lhs, |
+ const DictStorage::value_type& rhs) { |
+ if (lhs.first != rhs.first) |
+ return false; |
+ |
+ return lhs.second->Equals(rhs.second.get()); |
+ }); |
+ } |
+ case Type::LIST: { |
+ if (list_->size() != other->list_->size()) |
+ return false; |
+ |
+ return std::equal(std::begin(*list_), std::end(*list_), |
+ std::begin(*(other->list_)), |
+ [](const ListStorage::value_type& lhs, |
+ const ListStorage::value_type& rhs) { |
+ return lhs->Equals(rhs.get()); |
+ }); |
+ } |
} |
+ |
+ NOTREACHED(); |
+ return false; |
} |
// static |
@@ -448,11 +497,17 @@ void Value::InternalCopyConstructFrom(const Value& that) { |
case Type::BINARY: |
binary_value_.Init(*that.binary_value_); |
return; |
- |
- // TODO(crbug.com/646113): Implement these once the corresponding derived |
- // classes are removed. |
- case Type::LIST: |
case Type::DICTIONARY: |
+ // Currently not implementable due to the presence of unique_ptrs in |
+ // DictStorage. |
+ // TODO(crbug.com/646113): Implement this when DictionaryValues are |
+ // completely inlined. |
+ return; |
+ case Type::LIST: |
+ // Currently not implementable due to the presence of unique_ptrs in |
+ // ListStorage. |
+ // TODO(crbug.com/646113): Implement this when ListValues are completely |
+ // inlined. |
return; |
} |
} |
@@ -474,11 +529,11 @@ void Value::InternalMoveConstructFrom(Value&& that) { |
case Type::BINARY: |
binary_value_.InitFromMove(std::move(that.binary_value_)); |
return; |
- |
- // TODO(crbug.com/646113): Implement these once the corresponding derived |
- // classes are removed. |
- case Type::LIST: |
case Type::DICTIONARY: |
+ dictionary_.InitFromMove(std::move(that.dictionary_)); |
+ return; |
+ case Type::LIST: |
+ list_.InitFromMove(std::move(that.list_)); |
return; |
} |
} |
@@ -500,11 +555,17 @@ void Value::InternalCopyAssignFrom(const Value& that) { |
case Type::BINARY: |
*binary_value_ = *that.binary_value_; |
return; |
- |
- // TODO(crbug.com/646113): Implement these once the corresponding derived |
- // classes are removed. |
- case Type::LIST: |
case Type::DICTIONARY: |
+ // Currently not implementable due to the presence of unique_ptrs in |
+ // DictStorage. |
+ // TODO(crbug.com/646113): Implement this when DictionaryValues are |
+ // completely inlined. |
+ return; |
+ case Type::LIST: |
+ // Currently not implementable due to the presence of unique_ptrs in |
+ // ListStorage. |
+ // TODO(crbug.com/646113): Implement this when ListValues are completely |
+ // inlined. |
return; |
} |
} |
@@ -526,11 +587,11 @@ void Value::InternalMoveAssignFrom(Value&& that) { |
case Type::BINARY: |
*binary_value_ = std::move(*that.binary_value_); |
return; |
- |
- // TODO(crbug.com/646113): Implement these once the corresponding derived |
- // classes are removed. |
- case Type::LIST: |
case Type::DICTIONARY: |
+ *dictionary_ = std::move(*that.dictionary_); |
+ return; |
+ case Type::LIST: |
+ *list_ = std::move(*that.list_); |
return; |
} |
} |
@@ -550,11 +611,11 @@ void Value::InternalCleanup() { |
case Type::BINARY: |
binary_value_.Destroy(); |
return; |
- |
- // TODO(crbug.com/646113): Implement these once the corresponding derived |
- // classes are removed. |
- case Type::LIST: |
case Type::DICTIONARY: |
+ dictionary_.Destroy(); |
+ return; |
+ case Type::LIST: |
+ list_.Destroy(); |
return; |
} |
} |
@@ -574,31 +635,17 @@ std::unique_ptr<DictionaryValue> DictionaryValue::From( |
DictionaryValue::DictionaryValue() : Value(Type::DICTIONARY) {} |
-DictionaryValue::~DictionaryValue() { |
- Clear(); |
-} |
- |
-bool DictionaryValue::GetAsDictionary(DictionaryValue** out_value) { |
- if (out_value) |
- *out_value = this; |
- return true; |
-} |
- |
-bool DictionaryValue::GetAsDictionary(const DictionaryValue** out_value) const { |
- if (out_value) |
- *out_value = this; |
- return true; |
-} |
+DictionaryValue::~DictionaryValue() = default; |
bool DictionaryValue::HasKey(StringPiece key) const { |
DCHECK(IsStringUTF8(key)); |
- auto current_entry = dictionary_.find(key.as_string()); |
- DCHECK((current_entry == dictionary_.end()) || current_entry->second); |
- return current_entry != dictionary_.end(); |
+ auto current_entry = dictionary_->find(key.as_string()); |
+ DCHECK((current_entry == dictionary_->end()) || current_entry->second); |
+ return current_entry != dictionary_->end(); |
} |
void DictionaryValue::Clear() { |
- dictionary_.clear(); |
+ dictionary_->clear(); |
} |
void DictionaryValue::Set(StringPiece path, std::unique_ptr<Value> in_value) { |
@@ -653,7 +700,7 @@ void DictionaryValue::SetString(StringPiece path, const string16& in_value) { |
void DictionaryValue::SetWithoutPathExpansion(StringPiece key, |
std::unique_ptr<Value> in_value) { |
- dictionary_[key.as_string()] = std::move(in_value); |
+ (*dictionary_)[key.as_string()] = std::move(in_value); |
} |
void DictionaryValue::SetWithoutPathExpansion(StringPiece key, |
@@ -833,8 +880,8 @@ bool DictionaryValue::GetList(StringPiece path, ListValue** out_value) { |
bool DictionaryValue::GetWithoutPathExpansion(StringPiece key, |
const Value** out_value) const { |
DCHECK(IsStringUTF8(key)); |
- auto entry_iterator = dictionary_.find(key.as_string()); |
- if (entry_iterator == dictionary_.end()) |
+ auto entry_iterator = dictionary_->find(key.as_string()); |
+ if (entry_iterator == dictionary_->end()) |
return false; |
if (out_value) |
@@ -962,13 +1009,13 @@ bool DictionaryValue::RemoveWithoutPathExpansion( |
StringPiece key, |
std::unique_ptr<Value>* out_value) { |
DCHECK(IsStringUTF8(key)); |
- auto entry_iterator = dictionary_.find(key.as_string()); |
- if (entry_iterator == dictionary_.end()) |
+ auto entry_iterator = dictionary_->find(key.as_string()); |
+ if (entry_iterator == dictionary_->end()) |
return false; |
if (out_value) |
*out_value = std::move(entry_iterator->second); |
- dictionary_.erase(entry_iterator); |
+ dictionary_->erase(entry_iterator); |
return true; |
} |
@@ -1020,54 +1067,24 @@ void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) { |
} |
void DictionaryValue::Swap(DictionaryValue* other) { |
- dictionary_.swap(other->dictionary_); |
+ dictionary_->swap(*(other->dictionary_)); |
} |
DictionaryValue::Iterator::Iterator(const DictionaryValue& target) |
- : target_(target), |
- it_(target.dictionary_.begin()) {} |
+ : target_(target), it_(target.dictionary_->begin()) {} |
DictionaryValue::Iterator::Iterator(const Iterator& other) = default; |
DictionaryValue::Iterator::~Iterator() {} |
DictionaryValue* DictionaryValue::DeepCopy() const { |
- DictionaryValue* result = new DictionaryValue; |
- |
- for (const auto& current_entry : dictionary_) { |
- result->SetWithoutPathExpansion(current_entry.first, |
- current_entry.second->CreateDeepCopy()); |
- } |
- |
- return result; |
+ return static_cast<DictionaryValue*>(Value::DeepCopy()); |
} |
std::unique_ptr<DictionaryValue> DictionaryValue::CreateDeepCopy() const { |
return WrapUnique(DeepCopy()); |
} |
-bool DictionaryValue::Equals(const Value* other) const { |
- if (other->GetType() != GetType()) |
- return false; |
- |
- const DictionaryValue* other_dict = |
- static_cast<const DictionaryValue*>(other); |
- Iterator lhs_it(*this); |
- Iterator rhs_it(*other_dict); |
- while (!lhs_it.IsAtEnd() && !rhs_it.IsAtEnd()) { |
- if (lhs_it.key() != rhs_it.key() || |
- !lhs_it.value().Equals(&rhs_it.value())) { |
- return false; |
- } |
- lhs_it.Advance(); |
- rhs_it.Advance(); |
- } |
- if (!lhs_it.IsAtEnd() || !rhs_it.IsAtEnd()) |
- return false; |
- |
- return true; |
-} |
- |
///////////////////// ListValue //////////////////// |
// static |
@@ -1082,12 +1099,10 @@ std::unique_ptr<ListValue> ListValue::From(std::unique_ptr<Value> value) { |
ListValue::ListValue() : Value(Type::LIST) {} |
-ListValue::~ListValue() { |
- Clear(); |
-} |
+ListValue::~ListValue() = default; |
void ListValue::Clear() { |
- list_.clear(); |
+ list_->clear(); |
} |
bool ListValue::Set(size_t index, Value* in_value) { |
@@ -1098,25 +1113,25 @@ bool ListValue::Set(size_t index, std::unique_ptr<Value> in_value) { |
if (!in_value) |
return false; |
- if (index >= list_.size()) { |
+ if (index >= list_->size()) { |
// Pad out any intermediate indexes with null settings |
- while (index > list_.size()) |
+ while (index > list_->size()) |
Append(CreateNullValue()); |
Append(std::move(in_value)); |
} else { |
// TODO(dcheng): remove this DCHECK once the raw pointer version is removed? |
- DCHECK(list_[index] != in_value); |
- list_[index] = std::move(in_value); |
+ DCHECK((*list_)[index] != in_value); |
+ (*list_)[index] = std::move(in_value); |
} |
return true; |
} |
bool ListValue::Get(size_t index, const Value** out_value) const { |
- if (index >= list_.size()) |
+ if (index >= list_->size()) |
return false; |
if (out_value) |
- *out_value = list_[index].get(); |
+ *out_value = (*list_)[index].get(); |
return true; |
} |
@@ -1223,21 +1238,21 @@ bool ListValue::GetList(size_t index, ListValue** out_value) { |
} |
bool ListValue::Remove(size_t index, std::unique_ptr<Value>* out_value) { |
- if (index >= list_.size()) |
+ if (index >= list_->size()) |
return false; |
if (out_value) |
- *out_value = std::move(list_[index]); |
+ *out_value = std::move((*list_)[index]); |
- list_.erase(list_.begin() + index); |
+ list_->erase(list_->begin() + index); |
return true; |
} |
bool ListValue::Remove(const Value& value, size_t* index) { |
- for (auto it = list_.begin(); it != list_.end(); ++it) { |
+ for (auto it = list_->begin(); it != list_->end(); ++it) { |
if ((*it)->Equals(&value)) { |
- size_t previous_index = it - list_.begin(); |
- list_.erase(it); |
+ size_t previous_index = it - list_->begin(); |
+ list_->erase(it); |
if (index) |
*index = previous_index; |
@@ -1250,13 +1265,13 @@ bool ListValue::Remove(const Value& value, size_t* index) { |
ListValue::iterator ListValue::Erase(iterator iter, |
std::unique_ptr<Value>* out_value) { |
if (out_value) |
- *out_value = std::move(*Storage::iterator(iter)); |
+ *out_value = std::move(*ListStorage::iterator(iter)); |
- return list_.erase(iter); |
+ return list_->erase(iter); |
} |
void ListValue::Append(std::unique_ptr<Value> in_value) { |
- list_.push_back(std::move(in_value)); |
+ list_->push_back(std::move(in_value)); |
} |
#if !defined(OS_LINUX) |
@@ -1302,79 +1317,43 @@ void ListValue::AppendStrings(const std::vector<string16>& in_values) { |
bool ListValue::AppendIfNotPresent(std::unique_ptr<Value> in_value) { |
DCHECK(in_value); |
- for (const auto& entry : list_) { |
+ for (const auto& entry : *list_) { |
if (entry->Equals(in_value.get())) { |
return false; |
} |
} |
- list_.push_back(std::move(in_value)); |
+ list_->push_back(std::move(in_value)); |
return true; |
} |
bool ListValue::Insert(size_t index, std::unique_ptr<Value> in_value) { |
DCHECK(in_value); |
- if (index > list_.size()) |
+ if (index > list_->size()) |
return false; |
- list_.insert(list_.begin() + index, std::move(in_value)); |
+ list_->insert(list_->begin() + index, std::move(in_value)); |
return true; |
} |
ListValue::const_iterator ListValue::Find(const Value& value) const { |
- return std::find_if(list_.begin(), list_.end(), |
+ return std::find_if(list_->begin(), list_->end(), |
[&value](const std::unique_ptr<Value>& entry) { |
return entry->Equals(&value); |
}); |
} |
void ListValue::Swap(ListValue* other) { |
- list_.swap(other->list_); |
-} |
- |
-bool ListValue::GetAsList(ListValue** out_value) { |
- if (out_value) |
- *out_value = this; |
- return true; |
-} |
- |
-bool ListValue::GetAsList(const ListValue** out_value) const { |
- if (out_value) |
- *out_value = this; |
- return true; |
+ list_->swap(*(other->list_)); |
} |
ListValue* ListValue::DeepCopy() const { |
- ListValue* result = new ListValue; |
- |
- for (const auto& entry : list_) |
- result->Append(entry->CreateDeepCopy()); |
- |
- return result; |
+ return static_cast<ListValue*>(Value::DeepCopy()); |
} |
std::unique_ptr<ListValue> ListValue::CreateDeepCopy() const { |
return WrapUnique(DeepCopy()); |
} |
-bool ListValue::Equals(const Value* other) const { |
- if (other->GetType() != GetType()) |
- return false; |
- |
- const ListValue* other_list = |
- static_cast<const ListValue*>(other); |
- Storage::const_iterator lhs_it, rhs_it; |
- for (lhs_it = begin(), rhs_it = other_list->begin(); |
- lhs_it != end() && rhs_it != other_list->end(); |
- ++lhs_it, ++rhs_it) { |
- if (!(*lhs_it)->Equals(rhs_it->get())) |
- return false; |
- } |
- if (lhs_it != end() || rhs_it != other_list->end()) |
- return false; |
- |
- return true; |
-} |
- |
ValueSerializer::~ValueSerializer() { |
} |