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 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
678 static_cast<const DictionaryValue*>(merge_value)); | 678 static_cast<const DictionaryValue*>(merge_value)); |
679 continue; | 679 continue; |
680 } | 680 } |
681 } | 681 } |
682 // All other cases: Make a copy and hook it up. | 682 // All other cases: Make a copy and hook it up. |
683 SetWithoutPathExpansion(*key, merge_value->DeepCopy()); | 683 SetWithoutPathExpansion(*key, merge_value->DeepCopy()); |
684 } | 684 } |
685 } | 685 } |
686 } | 686 } |
687 | 687 |
688 bool DictionaryValue::GetDifferingPathsHelper( | |
689 const std::string& path_prefix, | |
690 const DictionaryValue* other, | |
691 std::vector<std::string>* different_paths) const { | |
692 bool added_path = false; | |
693 std::map<std::string, Value*>::const_iterator current_this; | |
694 std::map<std::string, Value*>::const_iterator end_this; | |
695 current_this = dictionary_.begin(); | |
696 end_this = dictionary_.end(); | |
697 if (!other) { | |
698 // Recursively add all paths from the |this| dictionary, since they are | |
699 // not in |other|. | |
700 for (; current_this != end_this; ++current_this) { | |
701 std::string full_path_for_key(path_prefix.empty() ? current_this->first : | |
702 path_prefix + "." + current_this->first); | |
703 different_paths->push_back(full_path_for_key); | |
704 added_path = true; | |
705 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) { | |
706 const DictionaryValue* dictionary_this = | |
707 static_cast<const DictionaryValue*>(current_this->second); | |
708 dictionary_this->GetDifferingPathsHelper(full_path_for_key, | |
709 NULL, | |
710 different_paths); | |
711 } | |
712 } | |
713 } else { | |
714 // Both the |this| and |other| dictionaries have entries. Iterate over | |
715 // both simultaneously. Paths that are in one but not the other are | |
716 // added to |different_paths| and DictionaryValues are processed | |
717 // recursively. | |
718 std::map<std::string, Value*>::const_iterator current_other = | |
719 other->dictionary_.begin(); | |
720 std::map<std::string, Value*>::const_iterator end_other = | |
721 other->dictionary_.end(); | |
722 while (current_this != end_this || current_other != end_other) { | |
723 const Value* recursion_this = NULL; | |
724 const Value* recursion_other = NULL; | |
725 const std::string* key_name = NULL; | |
726 bool current_value_known_equal = false; | |
727 if (current_this == end_this || | |
728 (current_other != end_other && | |
729 (current_other->first < current_this->first))) { | |
730 key_name = ¤t_other->first; | |
731 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) | |
732 recursion_this = current_other->second; | |
733 ++current_other; | |
734 } else { | |
735 key_name = ¤t_this->first; | |
736 if (current_other == end_other || | |
737 current_this->first < current_other->first) { | |
738 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) | |
739 recursion_this = current_this->second; | |
740 ++current_this; | |
741 } else { | |
742 DCHECK(current_this->first == current_other->first); | |
743 if (current_this->second->IsType(Value::TYPE_DICTIONARY)) { | |
744 recursion_this = current_this->second; | |
745 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) { | |
746 recursion_other = current_other->second; | |
747 } | |
748 } else { | |
749 if (current_other->second->IsType(Value::TYPE_DICTIONARY)) { | |
750 recursion_this = current_other->second; | |
751 } else { | |
752 current_value_known_equal = | |
753 current_this->second->Equals(current_other->second); | |
754 } | |
755 } | |
756 ++current_this; | |
757 ++current_other; | |
758 } | |
759 } | |
760 const std::string& full_path_for_key(path_prefix.empty() ? | |
761 *key_name : path_prefix + "." + *key_name); | |
762 if (!current_value_known_equal) | |
763 different_paths->push_back(full_path_for_key); | |
764 if (recursion_this) { | |
765 const DictionaryValue* dictionary_this = | |
766 static_cast<const DictionaryValue*>(recursion_this); | |
767 bool subtree_changed = dictionary_this->GetDifferingPathsHelper( | |
768 full_path_for_key, | |
769 static_cast<const DictionaryValue*>(recursion_other), | |
770 different_paths); | |
771 if (subtree_changed) { | |
772 added_path = true; | |
773 } else { | |
774 // In order to maintain lexicographical sorting order, directory | |
775 // paths are pushed "optimistically" assuming that their subtree will | |
776 // contain differences. If in retrospect there were no differences | |
777 // in the subtree, the assumption was false and the dictionary path | |
778 // must be removed. | |
779 different_paths->pop_back(); | |
780 } | |
781 } else { | |
782 added_path |= !current_value_known_equal; | |
783 } | |
784 } | |
785 } | |
786 return added_path; | |
787 } | |
788 | |
789 void DictionaryValue::GetDifferingPaths( | |
790 const DictionaryValue* other, | |
791 std::vector<std::string>* different_paths) const { | |
792 different_paths->clear(); | |
793 GetDifferingPathsHelper("", other, different_paths); | |
794 } | |
795 | |
796 ///////////////////// ListValue //////////////////// | 688 ///////////////////// ListValue //////////////////// |
797 | 689 |
798 ListValue::ListValue() : Value(TYPE_LIST) { | 690 ListValue::ListValue() : Value(TYPE_LIST) { |
799 } | 691 } |
800 | 692 |
801 ListValue::~ListValue() { | 693 ListValue::~ListValue() { |
802 Clear(); | 694 Clear(); |
803 } | 695 } |
804 | 696 |
805 void ListValue::Clear() { | 697 void ListValue::Clear() { |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 return false; | 886 return false; |
995 } | 887 } |
996 if (lhs_it != end() || rhs_it != other_list->end()) | 888 if (lhs_it != end() || rhs_it != other_list->end()) |
997 return false; | 889 return false; |
998 | 890 |
999 return true; | 891 return true; |
1000 } | 892 } |
1001 | 893 |
1002 ValueSerializer::~ValueSerializer() { | 894 ValueSerializer::~ValueSerializer() { |
1003 } | 895 } |
OLD | NEW |