Commit c109128a authored by jdoerrie's avatar jdoerrie Committed by Commit Bot

[base] Expose MergeDictionary on base::Value

This change moves MergeDictionary() from base::DictionaryValue to the
parent class base::Value and relaxes its interface to accept base::Value
pointers as well. Appropriate CHECKs are added.

Bug: 646133
Change-Id: Ib6dab60ea2ff4f56b320e4a54f0782905aa3c4ae
Reviewed-on: https://chromium-review.googlesource.com/1158233Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579847}
parent 8d6faa88
...@@ -443,6 +443,26 @@ bool Value::DictEmpty() const { ...@@ -443,6 +443,26 @@ bool Value::DictEmpty() const {
return dict_.empty(); return dict_.empty();
} }
void Value::MergeDictionary(const Value* dictionary) {
CHECK(is_dict());
CHECK(dictionary->is_dict());
for (const auto& pair : dictionary->dict_) {
const auto& key = pair.first;
const auto& val = pair.second;
// Check whether we have to merge dictionaries.
if (val->is_dict()) {
auto found = dict_.find(key);
if (found != dict_.end() && found->second->is_dict()) {
found->second->MergeDictionary(val.get());
continue;
}
}
// All other cases: Make a copy and hook it up.
SetKey(key, val->Clone());
}
}
bool Value::GetAsBoolean(bool* out_value) const { bool Value::GetAsBoolean(bool* out_value) const {
if (out_value && is_bool()) { if (out_value && is_bool()) {
*out_value = bool_value_; *out_value = bool_value_;
...@@ -1114,24 +1134,6 @@ std::unique_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren() ...@@ -1114,24 +1134,6 @@ std::unique_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren()
return copy; return copy;
} }
void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) {
CHECK(dictionary->is_dict());
for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) {
const Value* merge_value = &it.value();
// Check whether we have to merge dictionaries.
if (merge_value->is_dict()) {
DictionaryValue* sub_dict;
if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) {
sub_dict->MergeDictionary(
static_cast<const DictionaryValue*>(merge_value));
continue;
}
}
// All other cases: Make a copy and hook it up.
SetKey(it.key(), merge_value->Clone());
}
}
void DictionaryValue::Swap(DictionaryValue* other) { void DictionaryValue::Swap(DictionaryValue* other) {
CHECK(other->is_dict()); CHECK(other->is_dict());
dict_.swap(other->dict_); dict_.swap(other->dict_);
......
...@@ -302,6 +302,15 @@ class BASE_EXPORT Value { ...@@ -302,6 +302,15 @@ class BASE_EXPORT Value {
size_t DictSize() const; size_t DictSize() const;
bool DictEmpty() const; bool DictEmpty() const;
// Merge |dictionary| into this value. This is done recursively, i.e. any
// sub-dictionaries will be merged as well. In case of key collisions, the
// passed in dictionary takes precedence and data already present will be
// replaced. Values within |dictionary| are deep-copied, so |dictionary| may
// be freed any time after this call.
// Note: This fatally asserts if type() or dictionary->type() is not
// Type::DICTIONARY.
void MergeDictionary(const Value* dictionary);
// These methods allow the convenient retrieval of the contents of the Value. // These methods allow the convenient retrieval of the contents of the Value.
// If the current object can be converted into the given type, the value is // If the current object can be converted into the given type, the value is
// returned through the |out_value| parameter and true is returned; // returned through the |out_value| parameter and true is returned;
...@@ -542,13 +551,6 @@ class BASE_EXPORT DictionaryValue : public Value { ...@@ -542,13 +551,6 @@ class BASE_EXPORT DictionaryValue : public Value {
// the copy. This never returns NULL, even if |this| itself is empty. // the copy. This never returns NULL, even if |this| itself is empty.
std::unique_ptr<DictionaryValue> DeepCopyWithoutEmptyChildren() const; std::unique_ptr<DictionaryValue> DeepCopyWithoutEmptyChildren() const;
// Merge |dictionary| into this dictionary. This is done recursively, i.e. any
// sub-dictionaries will be merged as well. In case of key collisions, the
// passed in dictionary takes precedence and data already present will be
// replaced. Values within |dictionary| are deep-copied, so |dictionary| may
// be freed any time after this call.
void MergeDictionary(const DictionaryValue* dictionary);
// Swaps contents with the |other| dictionary. // Swaps contents with the |other| dictionary.
void Swap(DictionaryValue* other); void Swap(DictionaryValue* other);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment