Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(49)

Side by Side Diff: base/values.cc

Issue 3035045: Add dictionary comparing functions and unit tests (Closed)
Patch Set: merge with latest Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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 = &current_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 = &current_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
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 }
OLDNEW
« no previous file with comments | « base/values.h ('k') | base/values_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698