OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/values.h" | 5 #include "base/values.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <cmath> | 10 #include <cmath> |
11 #include <ostream> | 11 #include <ostream> |
12 | 12 |
13 #include "base/json/json_writer.h" | 13 #include "base/json/json_writer.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/move.h" | 15 #include "base/move.h" |
16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
17 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
18 | 18 |
19 namespace base { | 19 namespace base { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
| 23 scoped_ptr<Value> CopyWithoutEmptyChildren(const Value& node); |
| 24 |
23 // Make a deep copy of |node|, but don't include empty lists or dictionaries | 25 // Make a deep copy of |node|, but don't include empty lists or dictionaries |
24 // in the copy. It's possible for this function to return NULL and it | 26 // in the copy. It's possible for this function to return NULL and it |
25 // expects |node| to always be non-NULL. | 27 // expects |node| to always be non-NULL. |
26 Value* CopyWithoutEmptyChildren(const Value* node) { | 28 scoped_ptr<ListValue> CopyListWithoutEmptyChildren(const ListValue& list) { |
27 DCHECK(node); | 29 scoped_ptr<ListValue> copy; |
28 switch (node->GetType()) { | 30 for (ListValue::const_iterator it = list.begin(); it != list.end(); ++it) { |
29 case Value::TYPE_LIST: { | 31 scoped_ptr<Value> child_copy = CopyWithoutEmptyChildren(**it); |
30 const ListValue* list = static_cast<const ListValue*>(node); | 32 if (child_copy) { |
31 ListValue* copy = new ListValue; | 33 if (!copy) |
32 for (ListValue::const_iterator it = list->begin(); it != list->end(); | 34 copy.reset(new ListValue); |
33 ++it) { | 35 copy->Append(child_copy.Pass()); |
34 Value* child_copy = CopyWithoutEmptyChildren(*it); | 36 } |
35 if (child_copy) | 37 } |
36 copy->Append(child_copy); | 38 return copy; |
37 } | 39 } |
38 if (!copy->empty()) | |
39 return copy; | |
40 | 40 |
41 delete copy; | 41 scoped_ptr<DictionaryValue> CopyDictionaryWithoutEmptyChildren( |
42 return NULL; | 42 const DictionaryValue& dict) { |
| 43 scoped_ptr<DictionaryValue> copy; |
| 44 for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) { |
| 45 scoped_ptr<Value> child_copy = CopyWithoutEmptyChildren(it.value()); |
| 46 if (child_copy) { |
| 47 if (!copy) |
| 48 copy.reset(new DictionaryValue); |
| 49 copy->SetWithoutPathExpansion(it.key(), child_copy.Pass()); |
43 } | 50 } |
| 51 } |
| 52 return copy; |
| 53 } |
44 | 54 |
45 case Value::TYPE_DICTIONARY: { | 55 scoped_ptr<Value> CopyWithoutEmptyChildren(const Value& node) { |
46 const DictionaryValue* dict = static_cast<const DictionaryValue*>(node); | 56 switch (node.GetType()) { |
47 DictionaryValue* copy = new DictionaryValue; | 57 case Value::TYPE_LIST: |
48 for (DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { | 58 return CopyListWithoutEmptyChildren(static_cast<const ListValue&>(node)); |
49 Value* child_copy = CopyWithoutEmptyChildren(&it.value()); | |
50 if (child_copy) | |
51 copy->SetWithoutPathExpansion(it.key(), child_copy); | |
52 } | |
53 if (!copy->empty()) | |
54 return copy; | |
55 | 59 |
56 delete copy; | 60 case Value::TYPE_DICTIONARY: |
57 return NULL; | 61 return CopyDictionaryWithoutEmptyChildren( |
58 } | 62 static_cast<const DictionaryValue&>(node)); |
59 | 63 |
60 default: | 64 default: |
61 // For everything else, just make a copy. | 65 return node.CreateDeepCopy(); |
62 return node->DeepCopy(); | |
63 } | 66 } |
64 } | 67 } |
65 | 68 |
66 // A small functor for comparing Values for std::find_if and similar. | 69 // A small functor for comparing Values for std::find_if and similar. |
67 class ValueEquals { | 70 class ValueEquals { |
68 public: | 71 public: |
69 // Pass the value against which all consecutive calls of the () operator will | 72 // Pass the value against which all consecutive calls of the () operator will |
70 // compare their argument to. This Value object must not be destroyed while | 73 // compare their argument to. This Value object must not be destroyed while |
71 // the ValueEquals is in use. | 74 // the ValueEquals is in use. |
72 explicit ValueEquals(const Value* first) : first_(first) { } | 75 explicit ValueEquals(const Value* first) : first_(first) { } |
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 if (!GetDictionary(subdict_path, &subdict)) | 785 if (!GetDictionary(subdict_path, &subdict)) |
783 return false; | 786 return false; |
784 result = subdict->RemovePath(path.substr(delimiter_position + 1), | 787 result = subdict->RemovePath(path.substr(delimiter_position + 1), |
785 out_value); | 788 out_value); |
786 if (result && subdict->empty()) | 789 if (result && subdict->empty()) |
787 RemoveWithoutPathExpansion(subdict_path, NULL); | 790 RemoveWithoutPathExpansion(subdict_path, NULL); |
788 | 791 |
789 return result; | 792 return result; |
790 } | 793 } |
791 | 794 |
792 DictionaryValue* DictionaryValue::DeepCopyWithoutEmptyChildren() const { | 795 scoped_ptr<DictionaryValue> DictionaryValue::DeepCopyWithoutEmptyChildren() |
793 Value* copy = CopyWithoutEmptyChildren(this); | 796 const { |
794 return copy ? static_cast<DictionaryValue*>(copy) : new DictionaryValue; | 797 scoped_ptr<DictionaryValue> copy = CopyDictionaryWithoutEmptyChildren(*this); |
| 798 if (!copy) |
| 799 copy.reset(new DictionaryValue); |
| 800 return copy; |
795 } | 801 } |
796 | 802 |
797 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) { | 803 void DictionaryValue::MergeDictionary(const DictionaryValue* dictionary) { |
798 for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) { | 804 for (DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) { |
799 const Value* merge_value = &it.value(); | 805 const Value* merge_value = &it.value(); |
800 // Check whether we have to merge dictionaries. | 806 // Check whether we have to merge dictionaries. |
801 if (merge_value->IsType(Value::TYPE_DICTIONARY)) { | 807 if (merge_value->IsType(Value::TYPE_DICTIONARY)) { |
802 DictionaryValue* sub_dict; | 808 DictionaryValue* sub_dict; |
803 if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) { | 809 if (GetDictionaryWithoutPathExpansion(it.key(), &sub_dict)) { |
804 sub_dict->MergeDictionary( | 810 sub_dict->MergeDictionary( |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1166 ValueDeserializer::~ValueDeserializer() { | 1172 ValueDeserializer::~ValueDeserializer() { |
1167 } | 1173 } |
1168 | 1174 |
1169 std::ostream& operator<<(std::ostream& out, const Value& value) { | 1175 std::ostream& operator<<(std::ostream& out, const Value& value) { |
1170 std::string json; | 1176 std::string json; |
1171 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json); | 1177 JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json); |
1172 return out << json; | 1178 return out << json; |
1173 } | 1179 } |
1174 | 1180 |
1175 } // namespace base | 1181 } // namespace base |
OLD | NEW |