• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include <map>
10 #include <memory>
11 #include <string>
12 #include <string_view>
13 #include <utility>
14 
15 #include "base/values.h"
16 
17 PrefValueMap::PrefValueMap() = default;
18 
19 PrefValueMap::~PrefValueMap() = default;
20 
GetValue(std::string_view key,const base::Value ** value) const21 bool PrefValueMap::GetValue(std::string_view key,
22                             const base::Value** value) const {
23   auto it = prefs_.find(key);
24   if (it == prefs_.end())
25     return false;
26 
27   if (value)
28     *value = &it->second;
29 
30   return true;
31 }
32 
GetValue(std::string_view key,base::Value ** value)33 bool PrefValueMap::GetValue(std::string_view key, base::Value** value) {
34   auto it = prefs_.find(key);
35   if (it == prefs_.end())
36     return false;
37 
38   if (value)
39     *value = &it->second;
40 
41   return true;
42 }
43 
SetValue(std::string_view key,base::Value value)44 bool PrefValueMap::SetValue(std::string_view key, base::Value value) {
45   // Once C++26 is supported, just do `base::Value& existing_value =
46   // prefs_[key]`.
47   auto it = prefs_.find(key);
48   if (it == prefs_.end()) {
49     it = prefs_.insert({std::string(key), base::Value()}).first;
50   }
51   base::Value& existing_value = it->second;
52   if (value == existing_value)
53     return false;
54 
55   existing_value = std::move(value);
56   return true;
57 }
58 
RemoveValue(std::string_view key)59 bool PrefValueMap::RemoveValue(std::string_view key) {
60   // Once C++23 is supported, just do `return prefs_.erase(key)`;
61   auto it = prefs_.find(key);
62   if (it == prefs_.end()) {
63     return false;
64   }
65   prefs_.erase(it);
66   return true;
67 }
68 
Clear()69 void PrefValueMap::Clear() {
70   prefs_.clear();
71 }
72 
ClearWithPrefix(std::string_view prefix)73 void PrefValueMap::ClearWithPrefix(std::string_view prefix) {
74   Map::iterator low = prefs_.lower_bound(prefix);
75   // Appending maximum possible character so that there will be no string with
76   // prefix |prefix| that we may miss.
77   Map::iterator high = prefs_.upper_bound(std::string(prefix) + char(CHAR_MAX));
78   prefs_.erase(low, high);
79 }
80 
Swap(PrefValueMap * other)81 void PrefValueMap::Swap(PrefValueMap* other) {
82   prefs_.swap(other->prefs_);
83 }
84 
begin()85 PrefValueMap::iterator PrefValueMap::begin() {
86   return prefs_.begin();
87 }
88 
end()89 PrefValueMap::iterator PrefValueMap::end() {
90   return prefs_.end();
91 }
92 
begin() const93 PrefValueMap::const_iterator PrefValueMap::begin() const {
94   return prefs_.begin();
95 }
96 
end() const97 PrefValueMap::const_iterator PrefValueMap::end() const {
98   return prefs_.end();
99 }
100 
empty() const101 bool PrefValueMap::empty() const {
102   return prefs_.empty();
103 }
104 
GetBoolean(std::string_view key,bool * value) const105 bool PrefValueMap::GetBoolean(std::string_view key, bool* value) const {
106   const base::Value* stored_value = nullptr;
107   if (GetValue(key, &stored_value) && stored_value->is_bool()) {
108     *value = stored_value->GetBool();
109     return true;
110   }
111   return false;
112 }
113 
SetBoolean(std::string_view key,bool value)114 void PrefValueMap::SetBoolean(std::string_view key, bool value) {
115   SetValue(key, base::Value(value));
116 }
117 
GetString(std::string_view key,std::string * value) const118 bool PrefValueMap::GetString(std::string_view key, std::string* value) const {
119   const base::Value* stored_value = nullptr;
120   if (GetValue(key, &stored_value) && stored_value->is_string()) {
121     *value = stored_value->GetString();
122     return true;
123   }
124   return false;
125 }
126 
SetString(std::string_view key,std::string_view value)127 void PrefValueMap::SetString(std::string_view key, std::string_view value) {
128   SetValue(key, base::Value(value));
129 }
130 
GetInteger(std::string_view key,int * value) const131 bool PrefValueMap::GetInteger(std::string_view key, int* value) const {
132   const base::Value* stored_value = nullptr;
133   if (GetValue(key, &stored_value) && stored_value->is_int()) {
134     *value = stored_value->GetInt();
135     return true;
136   }
137   return false;
138 }
139 
SetInteger(std::string_view key,const int value)140 void PrefValueMap::SetInteger(std::string_view key, const int value) {
141   SetValue(key, base::Value(value));
142 }
143 
SetDouble(std::string_view key,const double value)144 void PrefValueMap::SetDouble(std::string_view key, const double value) {
145   SetValue(key, base::Value(value));
146 }
147 
GetDifferingKeys(const PrefValueMap * other,std::vector<std::string> * differing_keys) const148 void PrefValueMap::GetDifferingKeys(
149     const PrefValueMap* other,
150     std::vector<std::string>* differing_keys) const {
151   differing_keys->clear();
152 
153   // Put everything into ordered maps.
154   std::map<std::string, const base::Value*> this_prefs;
155   std::map<std::string, const base::Value*> other_prefs;
156   for (const auto& pair : prefs_)
157     this_prefs.emplace(pair.first, &pair.second);
158   for (const auto& pair : other->prefs_)
159     other_prefs.emplace(pair.first, &pair.second);
160 
161   // Walk over the maps in lockstep, adding everything that is different.
162   auto this_pref = this_prefs.begin();
163   auto other_pref = other_prefs.begin();
164   while (this_pref != this_prefs.end() && other_pref != other_prefs.end()) {
165     const int diff = this_pref->first.compare(other_pref->first);
166     if (diff == 0) {
167       if (*this_pref->second != *other_pref->second)
168         differing_keys->push_back(this_pref->first);
169       ++this_pref;
170       ++other_pref;
171     } else if (diff < 0) {
172       differing_keys->push_back(this_pref->first);
173       ++this_pref;
174     } else if (diff > 0) {
175       differing_keys->push_back(other_pref->first);
176       ++other_pref;
177     }
178   }
179 
180   // Add the remaining entries.
181   for (; this_pref != this_prefs.end(); ++this_pref)
182     differing_keys->push_back(this_pref->first);
183   for (; other_pref != other_prefs.end(); ++other_pref)
184     differing_keys->push_back(other_pref->first);
185 }
186 
AsDict() const187 base::Value::Dict PrefValueMap::AsDict() const {
188   base::Value::Dict dictionary;
189   for (const auto& value : prefs_)
190     dictionary.SetByDottedPath(value.first, value.second.Clone());
191 
192   return dictionary;
193 }
194