xref: /aosp_15_r20/external/cronet/base/values.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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 "base/values.h"
6 
7 #include <cmath>
8 #include <memory>
9 #include <optional>
10 #include <ostream>
11 #include <tuple>
12 #include <utility>
13 
14 #include "base/bit_cast.h"
15 #include "base/check.h"
16 #include "base/check_op.h"
17 #include "base/containers/checked_iterators.h"
18 #include "base/containers/map_util.h"
19 #include "base/json/json_writer.h"
20 #include "base/logging.h"
21 #include "base/memory/ptr_util.h"
22 #include "base/notreached.h"
23 #include "base/ranges/algorithm.h"
24 #include "base/strings/string_util.h"
25 #include "base/strings/utf_string_conversions.h"
26 #include "base/trace_event/base_tracing.h"
27 #include "base/tracing_buildflags.h"
28 #include "base/types/to_address.h"
29 #include "third_party/abseil-cpp/absl/types/variant.h"
30 
31 #if BUILDFLAG(ENABLE_BASE_TRACING)
32 #include "base/trace_event/memory_usage_estimator.h"  // no-presubmit-check
33 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
34 
35 namespace base {
36 
37 namespace {
38 
39 const char* const kTypeNames[] = {"null",   "boolean", "integer",    "double",
40                                   "string", "binary",  "dictionary", "list"};
41 static_assert(std::size(kTypeNames) ==
42                   static_cast<size_t>(Value::Type::LIST) + 1,
43               "kTypeNames Has Wrong Size");
44 
45 // Helper class to enumerate the path components from a StringPiece
46 // without performing heap allocations. Components are simply separated
47 // by single dots (e.g. "foo.bar.baz"  -> ["foo", "bar", "baz"]).
48 //
49 // Usage example:
50 //    PathSplitter splitter(some_path);
51 //    while (splitter.HasNext()) {
52 //       StringPiece component = splitter.Next();
53 //       ...
54 //    }
55 //
56 class PathSplitter {
57  public:
PathSplitter(StringPiece path)58   explicit PathSplitter(StringPiece path) : path_(path) {}
59 
HasNext() const60   bool HasNext() const { return pos_ < path_.size(); }
61 
Next()62   StringPiece Next() {
63     DCHECK(HasNext());
64     size_t start = pos_;
65     size_t pos = path_.find('.', start);
66     size_t end;
67     if (pos == path_.npos) {
68       end = path_.size();
69       pos_ = end;
70     } else {
71       end = pos;
72       pos_ = pos + 1;
73     }
74     return path_.substr(start, end - start);
75   }
76 
77  private:
78   StringPiece path_;
79   size_t pos_ = 0;
80 };
81 
DebugStringImpl(ValueView value)82 std::string DebugStringImpl(ValueView value) {
83   std::string json;
84   JSONWriter::WriteWithOptions(value, JSONWriter::OPTIONS_PRETTY_PRINT, &json);
85   return json;
86 }
87 
88 }  // namespace
89 
90 // A helper used to provide templated functions for cloning to Value, and
91 // ValueView. This private class is used so the cloning method may have access
92 // to the special private constructors in Value, created specifically for
93 // cloning.
94 class Value::CloningHelper {
95  public:
96   // This set of overloads are used to unwrap the reference wrappers, which are
97   // presented when cloning a ValueView.
98   template <typename T>
UnwrapReference(std::reference_wrapper<const T> value)99   static const T& UnwrapReference(std::reference_wrapper<const T> value) {
100     return value.get();
101   }
102 
103   template <typename T>
UnwrapReference(const T & value)104   static const T& UnwrapReference(const T& value) {
105     return value;
106   }
107 
108   // Returns a new Value object using the contents of the |storage| variant.
109   template <typename Storage>
Clone(const Storage & storage)110   static Value Clone(const Storage& storage) {
111     return absl::visit(
112         [](const auto& member) {
113           const auto& value = UnwrapReference(member);
114           using T = std::decay_t<decltype(value)>;
115           if constexpr (std::is_same_v<T, Value::Dict> ||
116                         std::is_same_v<T, Value::List>) {
117             return Value(value.Clone());
118           } else {
119             return Value(value);
120           }
121         },
122         storage);
123   }
124 };
125 
126 // static
FromUniquePtrValue(std::unique_ptr<Value> val)127 Value Value::FromUniquePtrValue(std::unique_ptr<Value> val) {
128   return std::move(*val);
129 }
130 
131 // static
ToUniquePtrValue(Value val)132 std::unique_ptr<Value> Value::ToUniquePtrValue(Value val) {
133   return std::make_unique<Value>(std::move(val));
134 }
135 
136 Value::Value() noexcept = default;
137 
138 Value::Value(Value&&) noexcept = default;
139 
140 Value& Value::operator=(Value&&) noexcept = default;
141 
Value(Type type)142 Value::Value(Type type) {
143   // Initialize with the default value.
144   switch (type) {
145     case Type::NONE:
146       return;
147 
148     case Type::BOOLEAN:
149       data_.emplace<bool>(false);
150       return;
151     case Type::INTEGER:
152       data_.emplace<int>(0);
153       return;
154     case Type::DOUBLE:
155       data_.emplace<DoubleStorage>(0.0);
156       return;
157     case Type::STRING:
158       data_.emplace<std::string>();
159       return;
160     case Type::BINARY:
161       data_.emplace<BlobStorage>();
162       return;
163     case Type::DICT:
164       data_.emplace<Dict>();
165       return;
166     case Type::LIST:
167       data_.emplace<List>();
168       return;
169   }
170 
171   CHECK(false);
172 }
173 
Value(bool value)174 Value::Value(bool value) : data_(value) {}
175 
Value(int value)176 Value::Value(int value) : data_(value) {}
177 
Value(double value)178 Value::Value(double value)
179     : data_(absl::in_place_type_t<DoubleStorage>(), value) {}
180 
Value(StringPiece value)181 Value::Value(StringPiece value) : Value(std::string(value)) {}
182 
Value(StringPiece16 value)183 Value::Value(StringPiece16 value) : Value(UTF16ToUTF8(value)) {}
184 
Value(const char * value)185 Value::Value(const char* value) : Value(std::string(value)) {}
186 
Value(const char16_t * value)187 Value::Value(const char16_t* value) : Value(UTF16ToUTF8(value)) {}
188 
Value(std::string && value)189 Value::Value(std::string&& value) noexcept : data_(std::move(value)) {
190   DCHECK(IsStringUTF8AllowingNoncharacters(GetString()));
191 }
192 
Value(const std::vector<char> & value)193 Value::Value(const std::vector<char>& value)
194     : data_(absl::in_place_type_t<BlobStorage>(), value.begin(), value.end()) {}
195 
Value(base::span<const uint8_t> value)196 Value::Value(base::span<const uint8_t> value)
197     : data_(absl::in_place_type_t<BlobStorage>(), value.size()) {
198   // This is 100x faster than using the "range" constructor for a 512k blob:
199   // crbug.com/1343636
200   ranges::copy(value, absl::get<BlobStorage>(data_).data());
201 }
202 
Value(BlobStorage && value)203 Value::Value(BlobStorage&& value) noexcept : data_(std::move(value)) {}
204 
Value(Dict && value)205 Value::Value(Dict&& value) noexcept : data_(std::move(value)) {}
206 
Value(List && value)207 Value::Value(List&& value) noexcept : data_(std::move(value)) {}
208 
Value(absl::monostate)209 Value::Value(absl::monostate) {}
210 
Value(DoubleStorage storage)211 Value::Value(DoubleStorage storage) : data_(std::move(storage)) {}
212 
DoubleStorage(double v)213 Value::DoubleStorage::DoubleStorage(double v) : v_(bit_cast<decltype(v_)>(v)) {
214   if (!std::isfinite(v)) {
215     NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) "
216                  << "values cannot be represented in JSON";
217     v_ = bit_cast<decltype(v_)>(0.0);
218   }
219 }
220 
Clone() const221 Value Value::Clone() const {
222   return CloningHelper::Clone(data_);
223 }
224 
225 Value::~Value() = default;
226 
227 // static
GetTypeName(Value::Type type)228 const char* Value::GetTypeName(Value::Type type) {
229   DCHECK_GE(static_cast<int>(type), 0);
230   DCHECK_LT(static_cast<size_t>(type), std::size(kTypeNames));
231   return kTypeNames[static_cast<size_t>(type)];
232 }
233 
GetIfBool() const234 std::optional<bool> Value::GetIfBool() const {
235   return is_bool() ? std::make_optional(GetBool()) : std::nullopt;
236 }
237 
GetIfInt() const238 std::optional<int> Value::GetIfInt() const {
239   return is_int() ? std::make_optional(GetInt()) : std::nullopt;
240 }
241 
GetIfDouble() const242 std::optional<double> Value::GetIfDouble() const {
243   return (is_int() || is_double()) ? std::make_optional(GetDouble())
244                                    : std::nullopt;
245 }
246 
GetIfString() const247 const std::string* Value::GetIfString() const {
248   return absl::get_if<std::string>(&data_);
249 }
250 
GetIfString()251 std::string* Value::GetIfString() {
252   return absl::get_if<std::string>(&data_);
253 }
254 
GetIfBlob() const255 const Value::BlobStorage* Value::GetIfBlob() const {
256   return absl::get_if<BlobStorage>(&data_);
257 }
258 
GetIfDict() const259 const Value::Dict* Value::GetIfDict() const {
260   return absl::get_if<Dict>(&data_);
261 }
262 
GetIfDict()263 Value::Dict* Value::GetIfDict() {
264   return absl::get_if<Dict>(&data_);
265 }
266 
GetIfList() const267 const Value::List* Value::GetIfList() const {
268   return absl::get_if<List>(&data_);
269 }
270 
GetIfList()271 Value::List* Value::GetIfList() {
272   return absl::get_if<List>(&data_);
273 }
274 
GetBool() const275 bool Value::GetBool() const {
276   DCHECK(is_bool());
277   return absl::get<bool>(data_);
278 }
279 
GetInt() const280 int Value::GetInt() const {
281   DCHECK(is_int());
282   return absl::get<int>(data_);
283 }
284 
GetDouble() const285 double Value::GetDouble() const {
286   if (is_double()) {
287     return absl::get<DoubleStorage>(data_);
288   }
289   if (is_int()) {
290     return GetInt();
291   }
292   CHECK(false);
293   return 0.0;
294 }
295 
GetString() const296 const std::string& Value::GetString() const {
297   DCHECK(is_string());
298   return absl::get<std::string>(data_);
299 }
300 
GetString()301 std::string& Value::GetString() {
302   DCHECK(is_string());
303   return absl::get<std::string>(data_);
304 }
305 
GetBlob() const306 const Value::BlobStorage& Value::GetBlob() const {
307   DCHECK(is_blob());
308   return absl::get<BlobStorage>(data_);
309 }
310 
GetDict() const311 const Value::Dict& Value::GetDict() const {
312   DCHECK(is_dict());
313   return absl::get<Dict>(data_);
314 }
315 
GetDict()316 Value::Dict& Value::GetDict() {
317   DCHECK(is_dict());
318   return absl::get<Dict>(data_);
319 }
320 
GetList() const321 const Value::List& Value::GetList() const {
322   DCHECK(is_list());
323   return absl::get<List>(data_);
324 }
325 
GetList()326 Value::List& Value::GetList() {
327   DCHECK(is_list());
328   return absl::get<List>(data_);
329 }
330 
TakeString()331 std::string Value::TakeString() && {
332   return std::move(GetString());
333 }
334 
TakeDict()335 Value::Dict Value::TakeDict() && {
336   return std::move(GetDict());
337 }
338 
TakeList()339 Value::List Value::TakeList() && {
340   return std::move(GetList());
341 }
342 
343 Value::Dict::Dict() = default;
344 
345 Value::Dict::Dict(Dict&&) noexcept = default;
346 
347 Value::Dict& Value::Dict::operator=(Dict&&) noexcept = default;
348 
349 Value::Dict::~Dict() = default;
350 
empty() const351 bool Value::Dict::empty() const {
352   return storage_.empty();
353 }
354 
size() const355 size_t Value::Dict::size() const {
356   return storage_.size();
357 }
358 
begin()359 Value::Dict::iterator Value::Dict::begin() {
360   return iterator(storage_.begin());
361 }
362 
begin() const363 Value::Dict::const_iterator Value::Dict::begin() const {
364   return const_iterator(storage_.begin());
365 }
366 
cbegin() const367 Value::Dict::const_iterator Value::Dict::cbegin() const {
368   return const_iterator(storage_.cbegin());
369 }
370 
end()371 Value::Dict::iterator Value::Dict::end() {
372   return iterator(storage_.end());
373 }
374 
end() const375 Value::Dict::const_iterator Value::Dict::end() const {
376   return const_iterator(storage_.end());
377 }
378 
cend() const379 Value::Dict::const_iterator Value::Dict::cend() const {
380   return const_iterator(storage_.cend());
381 }
382 
contains(base::StringPiece key) const383 bool Value::Dict::contains(base::StringPiece key) const {
384   DCHECK(IsStringUTF8AllowingNoncharacters(key));
385 
386   return storage_.contains(key);
387 }
388 
clear()389 void Value::Dict::clear() {
390   return storage_.clear();
391 }
392 
erase(iterator pos)393 Value::Dict::iterator Value::Dict::erase(iterator pos) {
394   return iterator(storage_.erase(pos.GetUnderlyingIteratorDoNotUse()));
395 }
396 
erase(const_iterator pos)397 Value::Dict::iterator Value::Dict::erase(const_iterator pos) {
398   return iterator(storage_.erase(pos.GetUnderlyingIteratorDoNotUse()));
399 }
400 
Clone() const401 Value::Dict Value::Dict::Clone() const {
402   return Dict(storage_);
403 }
404 
Merge(Dict dict)405 void Value::Dict::Merge(Dict dict) {
406   for (const auto [key, value] : dict) {
407     if (Dict* nested_dict = value.GetIfDict()) {
408       if (Dict* current_dict = FindDict(key)) {
409         // If `key` is a nested dictionary in this dictionary and the dictionary
410         // being merged, recursively merge the two dictionaries.
411         current_dict->Merge(std::move(*nested_dict));
412         continue;
413       }
414     }
415 
416     // Otherwise, unconditionally set the value, overwriting any value that may
417     // already be associated with the key.
418     Set(key, std::move(value));
419   }
420 }
421 
Find(StringPiece key) const422 const Value* Value::Dict::Find(StringPiece key) const {
423   DCHECK(IsStringUTF8AllowingNoncharacters(key));
424   return FindPtrOrNull(storage_, key);
425 }
426 
Find(StringPiece key)427 Value* Value::Dict::Find(StringPiece key) {
428   return FindPtrOrNull(storage_, key);
429 }
430 
FindBool(StringPiece key) const431 std::optional<bool> Value::Dict::FindBool(StringPiece key) const {
432   const Value* v = Find(key);
433   return v ? v->GetIfBool() : std::nullopt;
434 }
435 
FindInt(StringPiece key) const436 std::optional<int> Value::Dict::FindInt(StringPiece key) const {
437   const Value* v = Find(key);
438   return v ? v->GetIfInt() : std::nullopt;
439 }
440 
FindDouble(StringPiece key) const441 std::optional<double> Value::Dict::FindDouble(StringPiece key) const {
442   const Value* v = Find(key);
443   return v ? v->GetIfDouble() : std::nullopt;
444 }
445 
FindString(StringPiece key) const446 const std::string* Value::Dict::FindString(StringPiece key) const {
447   const Value* v = Find(key);
448   return v ? v->GetIfString() : nullptr;
449 }
450 
FindString(StringPiece key)451 std::string* Value::Dict::FindString(StringPiece key) {
452   Value* v = Find(key);
453   return v ? v->GetIfString() : nullptr;
454 }
455 
FindBlob(StringPiece key) const456 const Value::BlobStorage* Value::Dict::FindBlob(StringPiece key) const {
457   const Value* v = Find(key);
458   return v ? v->GetIfBlob() : nullptr;
459 }
460 
FindDict(StringPiece key) const461 const Value::Dict* Value::Dict::FindDict(StringPiece key) const {
462   const Value* v = Find(key);
463   return v ? v->GetIfDict() : nullptr;
464 }
465 
FindDict(StringPiece key)466 Value::Dict* Value::Dict::FindDict(StringPiece key) {
467   Value* v = Find(key);
468   return v ? v->GetIfDict() : nullptr;
469 }
470 
FindList(StringPiece key) const471 const Value::List* Value::Dict::FindList(StringPiece key) const {
472   const Value* v = Find(key);
473   return v ? v->GetIfList() : nullptr;
474 }
475 
FindList(StringPiece key)476 Value::List* Value::Dict::FindList(StringPiece key) {
477   Value* v = Find(key);
478   return v ? v->GetIfList() : nullptr;
479 }
480 
EnsureDict(StringPiece key)481 Value::Dict* Value::Dict::EnsureDict(StringPiece key) {
482   Value::Dict* dict = FindDict(key);
483   if (dict) {
484     return dict;
485   }
486   return &Set(key, base::Value::Dict())->GetDict();
487 }
488 
EnsureList(StringPiece key)489 Value::List* Value::Dict::EnsureList(StringPiece key) {
490   Value::List* list = FindList(key);
491   if (list) {
492     return list;
493   }
494   return &Set(key, base::Value::List())->GetList();
495 }
496 
Set(StringPiece key,Value && value)497 Value* Value::Dict::Set(StringPiece key, Value&& value) & {
498   DCHECK(IsStringUTF8AllowingNoncharacters(key));
499 
500   auto wrapped_value = std::make_unique<Value>(std::move(value));
501   auto* raw_value = wrapped_value.get();
502   storage_.insert_or_assign(key, std::move(wrapped_value));
503   return raw_value;
504 }
505 
Set(StringPiece key,bool value)506 Value* Value::Dict::Set(StringPiece key, bool value) & {
507   return Set(key, Value(value));
508 }
509 
Set(StringPiece key,int value)510 Value* Value::Dict::Set(StringPiece key, int value) & {
511   return Set(key, Value(value));
512 }
513 
Set(StringPiece key,double value)514 Value* Value::Dict::Set(StringPiece key, double value) & {
515   return Set(key, Value(value));
516 }
517 
Set(StringPiece key,StringPiece value)518 Value* Value::Dict::Set(StringPiece key, StringPiece value) & {
519   return Set(key, Value(value));
520 }
521 
Set(StringPiece key,StringPiece16 value)522 Value* Value::Dict::Set(StringPiece key, StringPiece16 value) & {
523   return Set(key, Value(value));
524 }
525 
Set(StringPiece key,const char * value)526 Value* Value::Dict::Set(StringPiece key, const char* value) & {
527   return Set(key, Value(value));
528 }
529 
Set(StringPiece key,const char16_t * value)530 Value* Value::Dict::Set(StringPiece key, const char16_t* value) & {
531   return Set(key, Value(value));
532 }
533 
Set(StringPiece key,std::string && value)534 Value* Value::Dict::Set(StringPiece key, std::string&& value) & {
535   return Set(key, Value(std::move(value)));
536 }
537 
Set(StringPiece key,BlobStorage && value)538 Value* Value::Dict::Set(StringPiece key, BlobStorage&& value) & {
539   return Set(key, Value(std::move(value)));
540 }
541 
Set(StringPiece key,Dict && value)542 Value* Value::Dict::Set(StringPiece key, Dict&& value) & {
543   return Set(key, Value(std::move(value)));
544 }
545 
Set(StringPiece key,List && value)546 Value* Value::Dict::Set(StringPiece key, List&& value) & {
547   return Set(key, Value(std::move(value)));
548 }
549 
Set(StringPiece key,Value && value)550 Value::Dict&& Value::Dict::Set(StringPiece key, Value&& value) && {
551   DCHECK(IsStringUTF8AllowingNoncharacters(key));
552   storage_.insert_or_assign(key, std::make_unique<Value>(std::move(value)));
553   return std::move(*this);
554 }
555 
Set(StringPiece key,bool value)556 Value::Dict&& Value::Dict::Set(StringPiece key, bool value) && {
557   return std::move(*this).Set(key, Value(value));
558 }
559 
Set(StringPiece key,int value)560 Value::Dict&& Value::Dict::Set(StringPiece key, int value) && {
561   return std::move(*this).Set(key, Value(value));
562 }
563 
Set(StringPiece key,double value)564 Value::Dict&& Value::Dict::Set(StringPiece key, double value) && {
565   return std::move(*this).Set(key, Value(value));
566 }
567 
Set(StringPiece key,StringPiece value)568 Value::Dict&& Value::Dict::Set(StringPiece key, StringPiece value) && {
569   return std::move(*this).Set(key, Value(value));
570 }
571 
Set(StringPiece key,StringPiece16 value)572 Value::Dict&& Value::Dict::Set(StringPiece key, StringPiece16 value) && {
573   return std::move(*this).Set(key, Value(value));
574 }
575 
Set(StringPiece key,const char * value)576 Value::Dict&& Value::Dict::Set(StringPiece key, const char* value) && {
577   return std::move(*this).Set(key, Value(value));
578 }
579 
Set(StringPiece key,const char16_t * value)580 Value::Dict&& Value::Dict::Set(StringPiece key, const char16_t* value) && {
581   return std::move(*this).Set(key, Value(value));
582 }
583 
Set(StringPiece key,std::string && value)584 Value::Dict&& Value::Dict::Set(StringPiece key, std::string&& value) && {
585   return std::move(*this).Set(key, Value(std::move(value)));
586 }
587 
Set(StringPiece key,BlobStorage && value)588 Value::Dict&& Value::Dict::Set(StringPiece key, BlobStorage&& value) && {
589   return std::move(*this).Set(key, Value(std::move(value)));
590 }
591 
Set(StringPiece key,Dict && value)592 Value::Dict&& Value::Dict::Set(StringPiece key, Dict&& value) && {
593   return std::move(*this).Set(key, Value(std::move(value)));
594 }
595 
Set(StringPiece key,List && value)596 Value::Dict&& Value::Dict::Set(StringPiece key, List&& value) && {
597   return std::move(*this).Set(key, Value(std::move(value)));
598 }
599 
Remove(StringPiece key)600 bool Value::Dict::Remove(StringPiece key) {
601   DCHECK(IsStringUTF8AllowingNoncharacters(key));
602 
603   return storage_.erase(key) > 0;
604 }
605 
Extract(StringPiece key)606 std::optional<Value> Value::Dict::Extract(StringPiece key) {
607   DCHECK(IsStringUTF8AllowingNoncharacters(key));
608 
609   auto it = storage_.find(key);
610   if (it == storage_.end()) {
611     return std::nullopt;
612   }
613   Value v = std::move(*it->second);
614   storage_.erase(it);
615   return v;
616 }
617 
FindByDottedPath(StringPiece path) const618 const Value* Value::Dict::FindByDottedPath(StringPiece path) const {
619   DCHECK(!path.empty());
620   DCHECK(IsStringUTF8AllowingNoncharacters(path));
621 
622   const Dict* current_dict = this;
623   const Value* current_value = nullptr;
624   PathSplitter splitter(path);
625   while (true) {
626     current_value = current_dict->Find(splitter.Next());
627     if (!splitter.HasNext()) {
628       return current_value;
629     }
630     if (!current_value) {
631       return nullptr;
632     }
633     current_dict = current_value->GetIfDict();
634     if (!current_dict) {
635       return nullptr;
636     }
637   }
638 }
639 
FindByDottedPath(StringPiece path)640 Value* Value::Dict::FindByDottedPath(StringPiece path) {
641   return const_cast<Value*>(std::as_const(*this).FindByDottedPath(path));
642 }
643 
FindBoolByDottedPath(StringPiece path) const644 std::optional<bool> Value::Dict::FindBoolByDottedPath(StringPiece path) const {
645   const Value* v = FindByDottedPath(path);
646   return v ? v->GetIfBool() : std::nullopt;
647 }
648 
FindIntByDottedPath(StringPiece path) const649 std::optional<int> Value::Dict::FindIntByDottedPath(StringPiece path) const {
650   const Value* v = FindByDottedPath(path);
651   return v ? v->GetIfInt() : std::nullopt;
652 }
653 
FindDoubleByDottedPath(StringPiece path) const654 std::optional<double> Value::Dict::FindDoubleByDottedPath(
655     StringPiece path) const {
656   const Value* v = FindByDottedPath(path);
657   return v ? v->GetIfDouble() : std::nullopt;
658 }
659 
FindStringByDottedPath(StringPiece path) const660 const std::string* Value::Dict::FindStringByDottedPath(StringPiece path) const {
661   const Value* v = FindByDottedPath(path);
662   return v ? v->GetIfString() : nullptr;
663 }
664 
FindStringByDottedPath(StringPiece path)665 std::string* Value::Dict::FindStringByDottedPath(StringPiece path) {
666   Value* v = FindByDottedPath(path);
667   return v ? v->GetIfString() : nullptr;
668 }
669 
FindBlobByDottedPath(StringPiece path) const670 const Value::BlobStorage* Value::Dict::FindBlobByDottedPath(
671     StringPiece path) const {
672   const Value* v = FindByDottedPath(path);
673   return v ? v->GetIfBlob() : nullptr;
674 }
675 
FindDictByDottedPath(StringPiece path) const676 const Value::Dict* Value::Dict::FindDictByDottedPath(StringPiece path) const {
677   const Value* v = FindByDottedPath(path);
678   return v ? v->GetIfDict() : nullptr;
679 }
680 
FindDictByDottedPath(StringPiece path)681 Value::Dict* Value::Dict::FindDictByDottedPath(StringPiece path) {
682   Value* v = FindByDottedPath(path);
683   return v ? v->GetIfDict() : nullptr;
684 }
685 
FindListByDottedPath(StringPiece path) const686 const Value::List* Value::Dict::FindListByDottedPath(StringPiece path) const {
687   const Value* v = FindByDottedPath(path);
688   return v ? v->GetIfList() : nullptr;
689 }
690 
FindListByDottedPath(StringPiece path)691 Value::List* Value::Dict::FindListByDottedPath(StringPiece path) {
692   Value* v = FindByDottedPath(path);
693   return v ? v->GetIfList() : nullptr;
694 }
695 
SetByDottedPath(StringPiece path,Value && value)696 Value* Value::Dict::SetByDottedPath(StringPiece path, Value&& value) & {
697   DCHECK(!path.empty());
698   DCHECK(IsStringUTF8AllowingNoncharacters(path));
699 
700   Dict* current_dict = this;
701   Value* current_value = nullptr;
702   PathSplitter splitter(path);
703   while (true) {
704     StringPiece next_key = splitter.Next();
705     if (!splitter.HasNext()) {
706       return current_dict->Set(next_key, std::move(value));
707     }
708     // This could be clever to avoid a double-lookup via use of lower_bound(),
709     // but for now, just implement it the most straightforward way.
710     current_value = current_dict->Find(next_key);
711     if (current_value) {
712       // Unlike the legacy DictionaryValue API, encountering an intermediate
713       // node that is not a `Value::Type::DICT` is an error.
714       current_dict = current_value->GetIfDict();
715       if (!current_dict) {
716         return nullptr;
717       }
718     } else {
719       current_dict = &current_dict->Set(next_key, Dict())->GetDict();
720     }
721   }
722 }
723 
SetByDottedPath(StringPiece path,bool value)724 Value* Value::Dict::SetByDottedPath(StringPiece path, bool value) & {
725   return SetByDottedPath(path, Value(value));
726 }
727 
SetByDottedPath(StringPiece path,int value)728 Value* Value::Dict::SetByDottedPath(StringPiece path, int value) & {
729   return SetByDottedPath(path, Value(value));
730 }
731 
SetByDottedPath(StringPiece path,double value)732 Value* Value::Dict::SetByDottedPath(StringPiece path, double value) & {
733   return SetByDottedPath(path, Value(value));
734 }
735 
SetByDottedPath(StringPiece path,StringPiece value)736 Value* Value::Dict::SetByDottedPath(StringPiece path, StringPiece value) & {
737   return SetByDottedPath(path, Value(value));
738 }
739 
SetByDottedPath(StringPiece path,StringPiece16 value)740 Value* Value::Dict::SetByDottedPath(StringPiece path, StringPiece16 value) & {
741   return SetByDottedPath(path, Value(value));
742 }
743 
SetByDottedPath(StringPiece path,const char * value)744 Value* Value::Dict::SetByDottedPath(StringPiece path, const char* value) & {
745   return SetByDottedPath(path, Value(value));
746 }
747 
SetByDottedPath(StringPiece path,const char16_t * value)748 Value* Value::Dict::SetByDottedPath(StringPiece path, const char16_t* value) & {
749   return SetByDottedPath(path, Value(value));
750 }
751 
SetByDottedPath(StringPiece path,std::string && value)752 Value* Value::Dict::SetByDottedPath(StringPiece path, std::string&& value) & {
753   return SetByDottedPath(path, Value(std::move(value)));
754 }
755 
SetByDottedPath(StringPiece path,BlobStorage && value)756 Value* Value::Dict::SetByDottedPath(StringPiece path, BlobStorage&& value) & {
757   return SetByDottedPath(path, Value(std::move(value)));
758 }
759 
SetByDottedPath(StringPiece path,Dict && value)760 Value* Value::Dict::SetByDottedPath(StringPiece path, Dict&& value) & {
761   return SetByDottedPath(path, Value(std::move(value)));
762 }
763 
SetByDottedPath(StringPiece path,List && value)764 Value* Value::Dict::SetByDottedPath(StringPiece path, List&& value) & {
765   return SetByDottedPath(path, Value(std::move(value)));
766 }
767 
RemoveByDottedPath(StringPiece path)768 bool Value::Dict::RemoveByDottedPath(StringPiece path) {
769   return ExtractByDottedPath(path).has_value();
770 }
771 
SetByDottedPath(StringPiece path,Value && value)772 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, Value&& value) && {
773   SetByDottedPath(path, std::move(value));
774   return std::move(*this);
775 }
776 
SetByDottedPath(StringPiece path,bool value)777 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, bool value) && {
778   SetByDottedPath(path, Value(value));
779   return std::move(*this);
780 }
781 
SetByDottedPath(StringPiece path,int value)782 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, int value) && {
783   SetByDottedPath(path, Value(value));
784   return std::move(*this);
785 }
786 
SetByDottedPath(StringPiece path,double value)787 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, double value) && {
788   SetByDottedPath(path, Value(value));
789   return std::move(*this);
790 }
791 
SetByDottedPath(StringPiece path,StringPiece value)792 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
793                                            StringPiece value) && {
794   SetByDottedPath(path, Value(value));
795   return std::move(*this);
796 }
797 
SetByDottedPath(StringPiece path,StringPiece16 value)798 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
799                                            StringPiece16 value) && {
800   SetByDottedPath(path, Value(value));
801   return std::move(*this);
802 }
803 
SetByDottedPath(StringPiece path,const char * value)804 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
805                                            const char* value) && {
806   SetByDottedPath(path, Value(value));
807   return std::move(*this);
808 }
809 
SetByDottedPath(StringPiece path,const char16_t * value)810 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
811                                            const char16_t* value) && {
812   SetByDottedPath(path, Value(value));
813   return std::move(*this);
814 }
815 
SetByDottedPath(StringPiece path,std::string && value)816 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
817                                            std::string&& value) && {
818   SetByDottedPath(path, Value(std::move(value)));
819   return std::move(*this);
820 }
821 
SetByDottedPath(StringPiece path,BlobStorage && value)822 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
823                                            BlobStorage&& value) && {
824   SetByDottedPath(path, Value(std::move(value)));
825   return std::move(*this);
826 }
827 
SetByDottedPath(StringPiece path,Dict && value)828 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, Dict&& value) && {
829   SetByDottedPath(path, Value(std::move(value)));
830   return std::move(*this);
831 }
832 
SetByDottedPath(StringPiece path,List && value)833 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, List&& value) && {
834   SetByDottedPath(path, Value(std::move(value)));
835   return std::move(*this);
836 }
837 
ExtractByDottedPath(StringPiece path)838 std::optional<Value> Value::Dict::ExtractByDottedPath(StringPiece path) {
839   DCHECK(!path.empty());
840   DCHECK(IsStringUTF8AllowingNoncharacters(path));
841 
842   // Use recursion instead of PathSplitter here, as it simplifies code for
843   // removing dictionaries that become empty if a value matching `path` is
844   // extracted.
845   size_t dot_index = path.find('.');
846   if (dot_index == StringPiece::npos) {
847     return Extract(path);
848   }
849   // This could be clever to avoid a double-lookup by using storage_ directly,
850   // but for now, just implement it in the most straightforward way.
851   StringPiece next_key = path.substr(0, dot_index);
852   auto* next_dict = FindDict(next_key);
853   if (!next_dict) {
854     return std::nullopt;
855   }
856   std::optional<Value> extracted =
857       next_dict->ExtractByDottedPath(path.substr(dot_index + 1));
858   if (extracted && next_dict->empty()) {
859     Remove(next_key);
860   }
861   return extracted;
862 }
863 
EstimateMemoryUsage() const864 size_t Value::Dict::EstimateMemoryUsage() const {
865 #if BUILDFLAG(ENABLE_BASE_TRACING)
866   return base::trace_event::EstimateMemoryUsage(storage_);
867 #else   // BUILDFLAG(ENABLE_BASE_TRACING)
868   return 0;
869 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
870 }
871 
DebugString() const872 std::string Value::Dict::DebugString() const {
873   return DebugStringImpl(*this);
874 }
875 
876 #if BUILDFLAG(ENABLE_BASE_TRACING)
WriteIntoTrace(perfetto::TracedValue context) const877 void Value::Dict::WriteIntoTrace(perfetto::TracedValue context) const {
878   perfetto::TracedDictionary dict = std::move(context).WriteDictionary();
879   for (auto kv : *this) {
880     dict.Add(perfetto::DynamicString(kv.first), kv.second);
881   }
882 }
883 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
884 
Dict(const flat_map<std::string,std::unique_ptr<Value>> & storage)885 Value::Dict::Dict(
886     const flat_map<std::string, std::unique_ptr<Value>>& storage) {
887   storage_.reserve(storage.size());
888   for (const auto& [key, value] : storage) {
889     Set(key, value->Clone());
890   }
891 }
892 
operator ==(const Value::Dict & lhs,const Value::Dict & rhs)893 bool operator==(const Value::Dict& lhs, const Value::Dict& rhs) {
894   auto deref_2nd = [](const auto& p) { return std::tie(p.first, *p.second); };
895   return ranges::equal(lhs.storage_, rhs.storage_, {}, deref_2nd, deref_2nd);
896 }
897 
operator !=(const Value::Dict & lhs,const Value::Dict & rhs)898 bool operator!=(const Value::Dict& lhs, const Value::Dict& rhs) {
899   return !(lhs == rhs);
900 }
901 
operator <(const Value::Dict & lhs,const Value::Dict & rhs)902 bool operator<(const Value::Dict& lhs, const Value::Dict& rhs) {
903   auto deref_2nd = [](const auto& p) { return std::tie(p.first, *p.second); };
904   return ranges::lexicographical_compare(lhs.storage_, rhs.storage_, {},
905                                          deref_2nd, deref_2nd);
906 }
907 
operator >(const Value::Dict & lhs,const Value::Dict & rhs)908 bool operator>(const Value::Dict& lhs, const Value::Dict& rhs) {
909   return rhs < lhs;
910 }
911 
operator <=(const Value::Dict & lhs,const Value::Dict & rhs)912 bool operator<=(const Value::Dict& lhs, const Value::Dict& rhs) {
913   return !(rhs < lhs);
914 }
915 
operator >=(const Value::Dict & lhs,const Value::Dict & rhs)916 bool operator>=(const Value::Dict& lhs, const Value::Dict& rhs) {
917   return !(lhs < rhs);
918 }
919 
920 // static
with_capacity(size_t capacity)921 Value::List Value::List::with_capacity(size_t capacity) {
922   Value::List result;
923   result.reserve(capacity);
924   return result;
925 }
926 
927 Value::List::List() = default;
928 
929 Value::List::List(List&&) noexcept = default;
930 
931 Value::List& Value::List::operator=(List&&) noexcept = default;
932 
933 Value::List::~List() = default;
934 
empty() const935 bool Value::List::empty() const {
936   return storage_.empty();
937 }
938 
size() const939 size_t Value::List::size() const {
940   return storage_.size();
941 }
942 
begin()943 Value::List::iterator Value::List::begin() {
944   return iterator(base::to_address(storage_.begin()),
945                   base::to_address(storage_.end()));
946 }
947 
begin() const948 Value::List::const_iterator Value::List::begin() const {
949   return const_iterator(base::to_address(storage_.begin()),
950                         base::to_address(storage_.end()));
951 }
952 
cbegin() const953 Value::List::const_iterator Value::List::cbegin() const {
954   return const_iterator(base::to_address(storage_.cbegin()),
955                         base::to_address(storage_.cend()));
956 }
957 
end()958 Value::List::iterator Value::List::end() {
959   return iterator(base::to_address(storage_.begin()),
960                   base::to_address(storage_.end()),
961                   base::to_address(storage_.end()));
962 }
963 
end() const964 Value::List::const_iterator Value::List::end() const {
965   return const_iterator(base::to_address(storage_.begin()),
966                         base::to_address(storage_.end()),
967                         base::to_address(storage_.end()));
968 }
969 
cend() const970 Value::List::const_iterator Value::List::cend() const {
971   return const_iterator(base::to_address(storage_.cbegin()),
972                         base::to_address(storage_.cend()),
973                         base::to_address(storage_.cend()));
974 }
975 
rend()976 Value::List::reverse_iterator Value::List::rend() {
977   return reverse_iterator(begin());
978 }
979 
rend() const980 Value::List::const_reverse_iterator Value::List::rend() const {
981   return const_reverse_iterator(begin());
982 }
983 
rbegin()984 Value::List::reverse_iterator Value::List::rbegin() {
985   return reverse_iterator(end());
986 }
987 
rbegin() const988 Value::List::const_reverse_iterator Value::List::rbegin() const {
989   return const_reverse_iterator(end());
990 }
991 
front() const992 const Value& Value::List::front() const {
993   CHECK(!storage_.empty());
994   return storage_.front();
995 }
996 
front()997 Value& Value::List::front() {
998   CHECK(!storage_.empty());
999   return storage_.front();
1000 }
1001 
back() const1002 const Value& Value::List::back() const {
1003   CHECK(!storage_.empty());
1004   return storage_.back();
1005 }
1006 
back()1007 Value& Value::List::back() {
1008   CHECK(!storage_.empty());
1009   return storage_.back();
1010 }
1011 
reserve(size_t capacity)1012 void Value::List::reserve(size_t capacity) {
1013   storage_.reserve(capacity);
1014 }
1015 
resize(size_t new_size)1016 void Value::List::resize(size_t new_size) {
1017   storage_.resize(new_size);
1018 }
1019 
operator [](size_t index) const1020 const Value& Value::List::operator[](size_t index) const {
1021   CHECK_LT(index, storage_.size());
1022   return storage_[index];
1023 }
1024 
operator [](size_t index)1025 Value& Value::List::operator[](size_t index) {
1026   CHECK_LT(index, storage_.size());
1027   return storage_[index];
1028 }
1029 
clear()1030 void Value::List::clear() {
1031   storage_.clear();
1032 }
1033 
erase(iterator pos)1034 Value::List::iterator Value::List::erase(iterator pos) {
1035   auto next_it = storage_.erase(storage_.begin() + (pos - begin()));
1036   return iterator(base::to_address(storage_.begin()), base::to_address(next_it),
1037                   base::to_address(storage_.end()));
1038 }
1039 
erase(const_iterator pos)1040 Value::List::const_iterator Value::List::erase(const_iterator pos) {
1041   auto next_it = storage_.erase(storage_.begin() + (pos - begin()));
1042   return const_iterator(base::to_address(storage_.begin()),
1043                         base::to_address(next_it),
1044                         base::to_address(storage_.end()));
1045 }
1046 
erase(iterator first,iterator last)1047 Value::List::iterator Value::List::erase(iterator first, iterator last) {
1048   auto next_it = storage_.erase(storage_.begin() + (first - begin()),
1049                                 storage_.begin() + (last - begin()));
1050   return iterator(base::to_address(storage_.begin()), base::to_address(next_it),
1051                   base::to_address(storage_.end()));
1052 }
1053 
erase(const_iterator first,const_iterator last)1054 Value::List::const_iterator Value::List::erase(const_iterator first,
1055                                                const_iterator last) {
1056   auto next_it = storage_.erase(storage_.begin() + (first - begin()),
1057                                 storage_.begin() + (last - begin()));
1058   return const_iterator(base::to_address(storage_.begin()),
1059                         base::to_address(next_it),
1060                         base::to_address(storage_.end()));
1061 }
1062 
Clone() const1063 Value::List Value::List::Clone() const {
1064   return List(storage_);
1065 }
1066 
Append(Value && value)1067 void Value::List::Append(Value&& value) & {
1068   storage_.emplace_back(std::move(value));
1069 }
1070 
Append(bool value)1071 void Value::List::Append(bool value) & {
1072   storage_.emplace_back(value);
1073 }
1074 
Append(int value)1075 void Value::List::Append(int value) & {
1076   storage_.emplace_back(value);
1077 }
1078 
Append(double value)1079 void Value::List::Append(double value) & {
1080   storage_.emplace_back(value);
1081 }
1082 
Append(StringPiece value)1083 void Value::List::Append(StringPiece value) & {
1084   Append(Value(value));
1085 }
1086 
Append(StringPiece16 value)1087 void Value::List::Append(StringPiece16 value) & {
1088   storage_.emplace_back(value);
1089 }
1090 
Append(const char * value)1091 void Value::List::Append(const char* value) & {
1092   storage_.emplace_back(value);
1093 }
1094 
Append(const char16_t * value)1095 void Value::List::Append(const char16_t* value) & {
1096   storage_.emplace_back(value);
1097 }
1098 
Append(std::string && value)1099 void Value::List::Append(std::string&& value) & {
1100   storage_.emplace_back(std::move(value));
1101 }
1102 
Append(BlobStorage && value)1103 void Value::List::Append(BlobStorage&& value) & {
1104   storage_.emplace_back(std::move(value));
1105 }
1106 
Append(Dict && value)1107 void Value::List::Append(Dict&& value) & {
1108   storage_.emplace_back(std::move(value));
1109 }
1110 
Append(List && value)1111 void Value::List::Append(List&& value) & {
1112   storage_.emplace_back(std::move(value));
1113 }
1114 
Append(Value && value)1115 Value::List&& Value::List::Append(Value&& value) && {
1116   storage_.emplace_back(std::move(value));
1117   return std::move(*this);
1118 }
1119 
Append(bool value)1120 Value::List&& Value::List::Append(bool value) && {
1121   storage_.emplace_back(value);
1122   return std::move(*this);
1123 }
1124 
Append(int value)1125 Value::List&& Value::List::Append(int value) && {
1126   storage_.emplace_back(value);
1127   return std::move(*this);
1128 }
1129 
Append(double value)1130 Value::List&& Value::List::Append(double value) && {
1131   storage_.emplace_back(value);
1132   return std::move(*this);
1133 }
1134 
Append(StringPiece value)1135 Value::List&& Value::List::Append(StringPiece value) && {
1136   Append(Value(value));
1137   return std::move(*this);
1138 }
1139 
Append(StringPiece16 value)1140 Value::List&& Value::List::Append(StringPiece16 value) && {
1141   storage_.emplace_back(value);
1142   return std::move(*this);
1143 }
1144 
Append(const char * value)1145 Value::List&& Value::List::Append(const char* value) && {
1146   storage_.emplace_back(value);
1147   return std::move(*this);
1148 }
1149 
Append(const char16_t * value)1150 Value::List&& Value::List::Append(const char16_t* value) && {
1151   storage_.emplace_back(value);
1152   return std::move(*this);
1153 }
1154 
Append(std::string && value)1155 Value::List&& Value::List::Append(std::string&& value) && {
1156   storage_.emplace_back(std::move(value));
1157   return std::move(*this);
1158 }
1159 
Append(BlobStorage && value)1160 Value::List&& Value::List::Append(BlobStorage&& value) && {
1161   storage_.emplace_back(std::move(value));
1162   return std::move(*this);
1163 }
1164 
Append(Dict && value)1165 Value::List&& Value::List::Append(Dict&& value) && {
1166   storage_.emplace_back(std::move(value));
1167   return std::move(*this);
1168 }
1169 
Append(List && value)1170 Value::List&& Value::List::Append(List&& value) && {
1171   storage_.emplace_back(std::move(value));
1172   return std::move(*this);
1173 }
1174 
Insert(const_iterator pos,Value && value)1175 Value::List::iterator Value::List::Insert(const_iterator pos, Value&& value) {
1176   auto inserted_it =
1177       storage_.insert(storage_.begin() + (pos - begin()), std::move(value));
1178   return iterator(base::to_address(storage_.begin()),
1179                   base::to_address(inserted_it),
1180                   base::to_address(storage_.end()));
1181 }
1182 
EraseValue(const Value & value)1183 size_t Value::List::EraseValue(const Value& value) {
1184   return std::erase(storage_, value);
1185 }
1186 
EstimateMemoryUsage() const1187 size_t Value::List::EstimateMemoryUsage() const {
1188 #if BUILDFLAG(ENABLE_BASE_TRACING)
1189   return base::trace_event::EstimateMemoryUsage(storage_);
1190 #else   // BUILDFLAG(ENABLE_BASE_TRACING)
1191   return 0;
1192 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
1193 }
1194 
DebugString() const1195 std::string Value::List::DebugString() const {
1196   return DebugStringImpl(*this);
1197 }
1198 
1199 #if BUILDFLAG(ENABLE_BASE_TRACING)
WriteIntoTrace(perfetto::TracedValue context) const1200 void Value::List::WriteIntoTrace(perfetto::TracedValue context) const {
1201   perfetto::TracedArray array = std::move(context).WriteArray();
1202   for (const auto& item : *this) {
1203     array.Append(item);
1204   }
1205 }
1206 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
1207 
List(const std::vector<Value> & storage)1208 Value::List::List(const std::vector<Value>& storage) {
1209   storage_.reserve(storage.size());
1210   for (const auto& value : storage) {
1211     storage_.push_back(value.Clone());
1212   }
1213 }
1214 
operator ==(const Value::List & lhs,const Value::List & rhs)1215 bool operator==(const Value::List& lhs, const Value::List& rhs) {
1216   return lhs.storage_ == rhs.storage_;
1217 }
1218 
operator !=(const Value::List & lhs,const Value::List & rhs)1219 bool operator!=(const Value::List& lhs, const Value::List& rhs) {
1220   return !(lhs == rhs);
1221 }
1222 
operator <(const Value::List & lhs,const Value::List & rhs)1223 bool operator<(const Value::List& lhs, const Value::List& rhs) {
1224   return lhs.storage_ < rhs.storage_;
1225 }
1226 
operator >(const Value::List & lhs,const Value::List & rhs)1227 bool operator>(const Value::List& lhs, const Value::List& rhs) {
1228   return rhs < lhs;
1229 }
1230 
operator <=(const Value::List & lhs,const Value::List & rhs)1231 bool operator<=(const Value::List& lhs, const Value::List& rhs) {
1232   return !(rhs < lhs);
1233 }
1234 
operator >=(const Value::List & lhs,const Value::List & rhs)1235 bool operator>=(const Value::List& lhs, const Value::List& rhs) {
1236   return !(lhs < rhs);
1237 }
1238 
operator ==(const Value & lhs,const Value & rhs)1239 bool operator==(const Value& lhs, const Value& rhs) {
1240   return lhs.data_ == rhs.data_;
1241 }
1242 
operator !=(const Value & lhs,const Value & rhs)1243 bool operator!=(const Value& lhs, const Value& rhs) {
1244   return !(lhs == rhs);
1245 }
1246 
operator <(const Value & lhs,const Value & rhs)1247 bool operator<(const Value& lhs, const Value& rhs) {
1248   return lhs.data_ < rhs.data_;
1249 }
1250 
operator >(const Value & lhs,const Value & rhs)1251 bool operator>(const Value& lhs, const Value& rhs) {
1252   return rhs < lhs;
1253 }
1254 
operator <=(const Value & lhs,const Value & rhs)1255 bool operator<=(const Value& lhs, const Value& rhs) {
1256   return !(rhs < lhs);
1257 }
1258 
operator >=(const Value & lhs,const Value & rhs)1259 bool operator>=(const Value& lhs, const Value& rhs) {
1260   return !(lhs < rhs);
1261 }
1262 
operator ==(const Value & lhs,bool rhs)1263 bool operator==(const Value& lhs, bool rhs) {
1264   return lhs.is_bool() && lhs.GetBool() == rhs;
1265 }
1266 
operator ==(const Value & lhs,int rhs)1267 bool operator==(const Value& lhs, int rhs) {
1268   return lhs.is_int() && lhs.GetInt() == rhs;
1269 }
1270 
operator ==(const Value & lhs,double rhs)1271 bool operator==(const Value& lhs, double rhs) {
1272   return lhs.is_double() && lhs.GetDouble() == rhs;
1273 }
1274 
operator ==(const Value & lhs,StringPiece rhs)1275 bool operator==(const Value& lhs, StringPiece rhs) {
1276   return lhs.is_string() && lhs.GetString() == rhs;
1277 }
1278 
operator ==(const Value & lhs,const Value::Dict & rhs)1279 bool operator==(const Value& lhs, const Value::Dict& rhs) {
1280   return lhs.is_dict() && lhs.GetDict() == rhs;
1281 }
1282 
operator ==(const Value & lhs,const Value::List & rhs)1283 bool operator==(const Value& lhs, const Value::List& rhs) {
1284   return lhs.is_list() && lhs.GetList() == rhs;
1285 }
1286 
EstimateMemoryUsage() const1287 size_t Value::EstimateMemoryUsage() const {
1288   switch (type()) {
1289 #if BUILDFLAG(ENABLE_BASE_TRACING)
1290     case Type::STRING:
1291       return base::trace_event::EstimateMemoryUsage(GetString());
1292     case Type::BINARY:
1293       return base::trace_event::EstimateMemoryUsage(GetBlob());
1294     case Type::DICT:
1295       return GetDict().EstimateMemoryUsage();
1296     case Type::LIST:
1297       return GetList().EstimateMemoryUsage();
1298 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
1299     default:
1300       return 0;
1301   }
1302 }
1303 
DebugString() const1304 std::string Value::DebugString() const {
1305   return DebugStringImpl(*this);
1306 }
1307 
1308 #if BUILDFLAG(ENABLE_BASE_TRACING)
WriteIntoTrace(perfetto::TracedValue context) const1309 void Value::WriteIntoTrace(perfetto::TracedValue context) const {
1310   Visit([&](const auto& member) {
1311     using T = std::decay_t<decltype(member)>;
1312     if constexpr (std::is_same_v<T, absl::monostate>) {
1313       std::move(context).WriteString("<none>");
1314     } else if constexpr (std::is_same_v<T, bool>) {
1315       std::move(context).WriteBoolean(member);
1316     } else if constexpr (std::is_same_v<T, int>) {
1317       std::move(context).WriteInt64(member);
1318     } else if constexpr (std::is_same_v<T, DoubleStorage>) {
1319       std::move(context).WriteDouble(member);
1320     } else if constexpr (std::is_same_v<T, std::string>) {
1321       std::move(context).WriteString(member);
1322     } else if constexpr (std::is_same_v<T, BlobStorage>) {
1323       std::move(context).WriteString("<binary data not supported>");
1324     } else if constexpr (std::is_same_v<T, Dict>) {
1325       member.WriteIntoTrace(std::move(context));
1326     } else if constexpr (std::is_same_v<T, List>) {
1327       member.WriteIntoTrace(std::move(context));
1328     }
1329   });
1330 }
1331 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
1332 
ValueView(const Value & value)1333 ValueView::ValueView(const Value& value)
1334     : data_view_(
1335           value.Visit([](const auto& member) { return ViewType(member); })) {}
1336 
ToValue() const1337 Value ValueView::ToValue() const {
1338   return Value::CloningHelper::Clone(data_view_);
1339 }
1340 
1341 ValueSerializer::~ValueSerializer() = default;
1342 
1343 ValueDeserializer::~ValueDeserializer() = default;
1344 
operator <<(std::ostream & out,const Value & value)1345 std::ostream& operator<<(std::ostream& out, const Value& value) {
1346   return out << value.DebugString();
1347 }
1348 
operator <<(std::ostream & out,const Value::Dict & dict)1349 std::ostream& operator<<(std::ostream& out, const Value::Dict& dict) {
1350   return out << dict.DebugString();
1351 }
1352 
operator <<(std::ostream & out,const Value::List & list)1353 std::ostream& operator<<(std::ostream& out, const Value::List& list) {
1354   return out << list.DebugString();
1355 }
1356 
operator <<(std::ostream & out,const Value::Type & type)1357 std::ostream& operator<<(std::ostream& out, const Value::Type& type) {
1358   if (static_cast<int>(type) < 0 ||
1359       static_cast<size_t>(type) >= std::size(kTypeNames)) {
1360     return out << "Invalid Type (index = " << static_cast<int>(type) << ")";
1361   }
1362   return out << Value::GetTypeName(type);
1363 }
1364 
1365 }  // namespace base
1366