OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 | 10 |
(...skipping 856 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 static_cast<const DictionaryValue*>(merge_value)); | 867 static_cast<const DictionaryValue*>(merge_value)); |
868 continue; | 868 continue; |
869 } | 869 } |
870 } | 870 } |
871 // All other cases: Make a copy and hook it up. | 871 // All other cases: Make a copy and hook it up. |
872 SetWithoutPathExpansion(*key, merge_value->DeepCopy()); | 872 SetWithoutPathExpansion(*key, merge_value->DeepCopy()); |
873 } | 873 } |
874 } | 874 } |
875 } | 875 } |
876 | 876 |
| 877 bool DictionaryValue::GetDifferingPathsHelper( |
| 878 const std::string& path_prefix, |
| 879 const DictionaryValue* other, |
| 880 std::vector<std::string>* different_paths) const { |
| 881 bool added_path = false; |
| 882 std::map<std::string, Value*>::const_iterator current_this; |
| 883 std::map<std::string, Value*>::const_iterator end_this; |
| 884 current_this = dictionary_.begin(); |
| 885 end_this = dictionary_.end(); |
| 886 if (!other) { |
| 887 // Recursively add all paths from the |this| dictionary, since they are |
| 888 // not in |other|. |
| 889 for (; current_this != end_this; ++current_this) { |
| 890 std::string full_path_for_key(path_prefix.empty() ? current_this->first : |
| 891 path_prefix + "." + current_this->first); |
| 892 different_paths->push_back(full_path_for_key); |
| 893 added_path = true; |
| 894 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) { |
| 895 const DictionaryValue* dictionary_this = |
| 896 static_cast<const DictionaryValue*>(current_this->second); |
| 897 dictionary_this->GetDifferingPathsHelper(full_path_for_key, |
| 898 NULL, |
| 899 different_paths); |
| 900 } |
| 901 } |
| 902 } else { |
| 903 // Both the |this| and |other| dictionaries have entries. Iterate over |
| 904 // both simultaneously. Paths that are in one but not the other are |
| 905 // added to |different_paths| and DictionaryValues are processed |
| 906 // recursively. |
| 907 std::map<std::string, Value*>::const_iterator current_other = |
| 908 other->dictionary_.begin(); |
| 909 std::map<std::string, Value*>::const_iterator end_other = |
| 910 other->dictionary_.end(); |
| 911 while (current_this != end_this || current_other != end_other) { |
| 912 const Value* recursion_this = NULL; |
| 913 const Value* recursion_other = NULL; |
| 914 const std::string* key_name = NULL; |
| 915 bool current_value_known_equal = false; |
| 916 if (current_this == end_this || |
| 917 (current_other != end_other && |
| 918 (current_other->first < current_this->first))) { |
| 919 key_name = ¤t_other->first; |
| 920 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) |
| 921 recursion_this = current_other->second; |
| 922 ++current_other; |
| 923 } else { |
| 924 key_name = ¤t_this->first; |
| 925 if (current_other == end_other || |
| 926 current_this->first < current_other->first) { |
| 927 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) |
| 928 recursion_this = current_this->second; |
| 929 ++current_this; |
| 930 } else { |
| 931 DCHECK(current_this->first == current_other->first); |
| 932 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) { |
| 933 recursion_this = current_this->second; |
| 934 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) { |
| 935 recursion_other = current_other->second; |
| 936 } |
| 937 } else { |
| 938 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) { |
| 939 recursion_this = current_other->second; |
| 940 } else { |
| 941 current_value_known_equal = |
| 942 current_this->second->Equals(current_other->second); |
| 943 } |
| 944 } |
| 945 ++current_this; |
| 946 ++current_other; |
| 947 } |
| 948 } |
| 949 const std::string& full_path_for_key(path_prefix.empty() ? |
| 950 *key_name : path_prefix + "." + *key_name); |
| 951 if (!current_value_known_equal) |
| 952 different_paths->push_back(full_path_for_key); |
| 953 if (recursion_this) { |
| 954 const DictionaryValue* dictionary_this = |
| 955 static_cast<const DictionaryValue*>(recursion_this); |
| 956 bool subtree_changed = dictionary_this->GetDifferingPathsHelper( |
| 957 full_path_for_key, |
| 958 static_cast<const DictionaryValue*>(recursion_other), |
| 959 different_paths); |
| 960 if (subtree_changed) { |
| 961 added_path = true; |
| 962 } else { |
| 963 // In order to maintain lexicographical sorting order, directory |
| 964 // paths are pushed "optimistically" assuming that their subtree will |
| 965 // contain differences. If in retrospect there were no differences |
| 966 // in the subtree, the assumption was false and the dictionary path |
| 967 // must be removed. |
| 968 different_paths->pop_back(); |
| 969 } |
| 970 } else { |
| 971 added_path |= !current_value_known_equal; |
| 972 } |
| 973 } |
| 974 } |
| 975 return added_path; |
| 976 } |
| 977 |
| 978 void DictionaryValue::GetDifferingPaths( |
| 979 const DictionaryValue* other, |
| 980 std::vector<std::string>* different_paths) const { |
| 981 different_paths->clear(); |
| 982 GetDifferingPathsHelper("", other, different_paths); |
| 983 } |
| 984 |
877 ///////////////////// ListValue //////////////////// | 985 ///////////////////// ListValue //////////////////// |
878 | 986 |
879 ListValue::ListValue() : Value(TYPE_LIST) { | 987 ListValue::ListValue() : Value(TYPE_LIST) { |
880 } | 988 } |
881 | 989 |
882 ListValue::~ListValue() { | 990 ListValue::~ListValue() { |
883 Clear(); | 991 Clear(); |
884 } | 992 } |
885 | 993 |
886 void ListValue::Clear() { | 994 void ListValue::Clear() { |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1077 return false; | 1185 return false; |
1078 } | 1186 } |
1079 if (lhs_it != end() || rhs_it != other_list->end()) | 1187 if (lhs_it != end() || rhs_it != other_list->end()) |
1080 return false; | 1188 return false; |
1081 | 1189 |
1082 return true; | 1190 return true; |
1083 } | 1191 } |
1084 | 1192 |
1085 ValueSerializer::~ValueSerializer() { | 1193 ValueSerializer::~ValueSerializer() { |
1086 } | 1194 } |
OLD | NEW |