1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/prefs/pref_value_map.h"
6
7 #include <limits.h>
8 #include <map>
9 #include <memory>
10 #include <string>
11 #include <utility>
12
13 #include "base/strings/string_piece.h"
14 #include "base/values.h"
15
PrefValueMap()16 PrefValueMap::PrefValueMap() {}
17
~PrefValueMap()18 PrefValueMap::~PrefValueMap() {}
19
GetValue(base::StringPiece key,const base::Value ** value) const20 bool PrefValueMap::GetValue(base::StringPiece key,
21 const base::Value** value) const {
22 auto it = prefs_.find(key);
23 if (it == prefs_.end())
24 return false;
25
26 if (value)
27 *value = &it->second;
28
29 return true;
30 }
31
GetValue(base::StringPiece key,base::Value ** value)32 bool PrefValueMap::GetValue(base::StringPiece key, base::Value** value) {
33 auto it = prefs_.find(key);
34 if (it == prefs_.end())
35 return false;
36
37 if (value)
38 *value = &it->second;
39
40 return true;
41 }
42
SetValue(const std::string & key,base::Value value)43 bool PrefValueMap::SetValue(const std::string& key, base::Value value) {
44 base::Value& existing_value = prefs_[key];
45 if (value == existing_value)
46 return false;
47
48 existing_value = std::move(value);
49 return true;
50 }
51
RemoveValue(const std::string & key)52 bool PrefValueMap::RemoveValue(const std::string& key) {
53 return prefs_.erase(key) != 0;
54 }
55
Clear()56 void PrefValueMap::Clear() {
57 prefs_.clear();
58 }
59
ClearWithPrefix(const std::string & prefix)60 void PrefValueMap::ClearWithPrefix(const std::string& prefix) {
61 Map::iterator low = prefs_.lower_bound(prefix);
62 // Appending maximum possible character so that there will be no string with
63 // prefix |prefix| that we may miss.
64 Map::iterator high = prefs_.upper_bound(prefix + char(CHAR_MAX));
65 prefs_.erase(low, high);
66 }
67
Swap(PrefValueMap * other)68 void PrefValueMap::Swap(PrefValueMap* other) {
69 prefs_.swap(other->prefs_);
70 }
71
begin()72 PrefValueMap::iterator PrefValueMap::begin() {
73 return prefs_.begin();
74 }
75
end()76 PrefValueMap::iterator PrefValueMap::end() {
77 return prefs_.end();
78 }
79
begin() const80 PrefValueMap::const_iterator PrefValueMap::begin() const {
81 return prefs_.begin();
82 }
83
end() const84 PrefValueMap::const_iterator PrefValueMap::end() const {
85 return prefs_.end();
86 }
87
empty() const88 bool PrefValueMap::empty() const {
89 return prefs_.empty();
90 }
91
GetBoolean(const std::string & key,bool * value) const92 bool PrefValueMap::GetBoolean(const std::string& key, bool* value) const {
93 const base::Value* stored_value = nullptr;
94 if (GetValue(key, &stored_value) && stored_value->is_bool()) {
95 *value = stored_value->GetBool();
96 return true;
97 }
98 return false;
99 }
100
SetBoolean(const std::string & key,bool value)101 void PrefValueMap::SetBoolean(const std::string& key, bool value) {
102 SetValue(key, base::Value(value));
103 }
104
GetString(const std::string & key,std::string * value) const105 bool PrefValueMap::GetString(const std::string& key, std::string* value) const {
106 const base::Value* stored_value = nullptr;
107 if (GetValue(key, &stored_value) && stored_value->is_string()) {
108 *value = stored_value->GetString();
109 return true;
110 }
111 return false;
112 }
113
SetString(const std::string & key,const std::string & value)114 void PrefValueMap::SetString(const std::string& key, const std::string& value) {
115 SetValue(key, base::Value(value));
116 }
117
GetInteger(const std::string & key,int * value) const118 bool PrefValueMap::GetInteger(const std::string& key, int* value) const {
119 const base::Value* stored_value = nullptr;
120 if (GetValue(key, &stored_value) && stored_value->is_int()) {
121 *value = stored_value->GetInt();
122 return true;
123 }
124 return false;
125 }
126
SetInteger(const std::string & key,const int value)127 void PrefValueMap::SetInteger(const std::string& key, const int value) {
128 SetValue(key, base::Value(value));
129 }
130
SetDouble(const std::string & key,const double value)131 void PrefValueMap::SetDouble(const std::string& key, const double value) {
132 SetValue(key, base::Value(value));
133 }
134
GetDifferingKeys(const PrefValueMap * other,std::vector<std::string> * differing_keys) const135 void PrefValueMap::GetDifferingKeys(
136 const PrefValueMap* other,
137 std::vector<std::string>* differing_keys) const {
138 differing_keys->clear();
139
140 // Put everything into ordered maps.
141 std::map<std::string, const base::Value*> this_prefs;
142 std::map<std::string, const base::Value*> other_prefs;
143 for (const auto& pair : prefs_)
144 this_prefs.emplace(pair.first, &pair.second);
145 for (const auto& pair : other->prefs_)
146 other_prefs.emplace(pair.first, &pair.second);
147
148 // Walk over the maps in lockstep, adding everything that is different.
149 auto this_pref = this_prefs.begin();
150 auto other_pref = other_prefs.begin();
151 while (this_pref != this_prefs.end() && other_pref != other_prefs.end()) {
152 const int diff = this_pref->first.compare(other_pref->first);
153 if (diff == 0) {
154 if (*this_pref->second != *other_pref->second)
155 differing_keys->push_back(this_pref->first);
156 ++this_pref;
157 ++other_pref;
158 } else if (diff < 0) {
159 differing_keys->push_back(this_pref->first);
160 ++this_pref;
161 } else if (diff > 0) {
162 differing_keys->push_back(other_pref->first);
163 ++other_pref;
164 }
165 }
166
167 // Add the remaining entries.
168 for (; this_pref != this_prefs.end(); ++this_pref)
169 differing_keys->push_back(this_pref->first);
170 for (; other_pref != other_prefs.end(); ++other_pref)
171 differing_keys->push_back(other_pref->first);
172 }
173
AsDict() const174 base::Value::Dict PrefValueMap::AsDict() const {
175 base::Value::Dict dictionary;
176 for (const auto& value : prefs_)
177 dictionary.SetByDottedPath(value.first, value.second.Clone());
178
179 return dictionary;
180 }
181