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