Fix emulator build error
[platform/framework/web/chromium-efl.git] / base / values.cc
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 <ostream>
9 #include <tuple>
10 #include <utility>
11
12 #include "base/bit_cast.h"
13 #include "base/check.h"
14 #include "base/check_op.h"
15 #include "base/containers/checked_iterators.h"
16 #include "base/containers/cxx20_erase_vector.h"
17 #include "base/containers/map_util.h"
18 #include "base/cxx20_to_address.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 "third_party/abseil-cpp/absl/types/optional.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:
58   explicit PathSplitter(StringPiece path) : path_(path) {}
59
60   bool HasNext() const { return pos_ < path_.size(); }
61
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
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>
99   static const T& UnwrapReference(std::reference_wrapper<const T> value) {
100     return value.get();
101   }
102
103   template <typename T>
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>
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
127 Value Value::FromUniquePtrValue(std::unique_ptr<Value> val) {
128   return std::move(*val);
129 }
130
131 // static
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
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
174 Value::Value(bool value) : data_(value) {}
175
176 Value::Value(int value) : data_(value) {}
177
178 Value::Value(double value)
179     : data_(absl::in_place_type_t<DoubleStorage>(), value) {}
180
181 Value::Value(StringPiece value) : Value(std::string(value)) {}
182
183 Value::Value(StringPiece16 value) : Value(UTF16ToUTF8(value)) {}
184
185 Value::Value(const char* value) : Value(std::string(value)) {}
186
187 Value::Value(const char16_t* value) : Value(UTF16ToUTF8(value)) {}
188
189 Value::Value(std::string&& value) noexcept : data_(std::move(value)) {
190   DCHECK(IsStringUTF8AllowingNoncharacters(GetString()));
191 }
192
193 Value::Value(const std::vector<char>& value)
194     : data_(absl::in_place_type_t<BlobStorage>(), value.begin(), value.end()) {}
195
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
203 Value::Value(BlobStorage&& value) noexcept : data_(std::move(value)) {}
204
205 Value::Value(Dict&& value) noexcept : data_(std::move(value)) {}
206
207 Value::Value(List&& value) noexcept : data_(std::move(value)) {}
208
209 Value::Value(absl::monostate) {}
210
211 Value::Value(DoubleStorage storage) : data_(std::move(storage)) {}
212
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
221 Value Value::Clone() const {
222   return CloningHelper::Clone(data_);
223 }
224
225 Value::~Value() = default;
226
227 // static
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
234 absl::optional<bool> Value::GetIfBool() const {
235   return is_bool() ? absl::make_optional(GetBool()) : absl::nullopt;
236 }
237
238 absl::optional<int> Value::GetIfInt() const {
239   return is_int() ? absl::make_optional(GetInt()) : absl::nullopt;
240 }
241
242 absl::optional<double> Value::GetIfDouble() const {
243   return (is_int() || is_double()) ? absl::make_optional(GetDouble())
244                                    : absl::nullopt;
245 }
246
247 const std::string* Value::GetIfString() const {
248   return absl::get_if<std::string>(&data_);
249 }
250
251 std::string* Value::GetIfString() {
252   return absl::get_if<std::string>(&data_);
253 }
254
255 const Value::BlobStorage* Value::GetIfBlob() const {
256   return absl::get_if<BlobStorage>(&data_);
257 }
258
259 const Value::Dict* Value::GetIfDict() const {
260   return absl::get_if<Dict>(&data_);
261 }
262
263 Value::Dict* Value::GetIfDict() {
264   return absl::get_if<Dict>(&data_);
265 }
266
267 const Value::List* Value::GetIfList() const {
268   return absl::get_if<List>(&data_);
269 }
270
271 Value::List* Value::GetIfList() {
272   return absl::get_if<List>(&data_);
273 }
274
275 bool Value::GetBool() const {
276   DCHECK(is_bool());
277   return absl::get<bool>(data_);
278 }
279
280 int Value::GetInt() const {
281   DCHECK(is_int());
282   return absl::get<int>(data_);
283 }
284
285 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
296 const std::string& Value::GetString() const {
297   DCHECK(is_string());
298   return absl::get<std::string>(data_);
299 }
300
301 std::string& Value::GetString() {
302   DCHECK(is_string());
303   return absl::get<std::string>(data_);
304 }
305
306 const Value::BlobStorage& Value::GetBlob() const {
307   DCHECK(is_blob());
308   return absl::get<BlobStorage>(data_);
309 }
310
311 const Value::Dict& Value::GetDict() const {
312   DCHECK(is_dict());
313   return absl::get<Dict>(data_);
314 }
315
316 Value::Dict& Value::GetDict() {
317   DCHECK(is_dict());
318   return absl::get<Dict>(data_);
319 }
320
321 const Value::List& Value::GetList() const {
322   DCHECK(is_list());
323   return absl::get<List>(data_);
324 }
325
326 Value::List& Value::GetList() {
327   DCHECK(is_list());
328   return absl::get<List>(data_);
329 }
330
331 std::string Value::TakeString() && {
332   return std::move(GetString());
333 }
334
335 Value::Dict Value::TakeDict() && {
336   return std::move(GetDict());
337 }
338
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
351 bool Value::Dict::empty() const {
352   return storage_.empty();
353 }
354
355 size_t Value::Dict::size() const {
356   return storage_.size();
357 }
358
359 Value::Dict::iterator Value::Dict::begin() {
360   return iterator(storage_.begin());
361 }
362
363 Value::Dict::const_iterator Value::Dict::begin() const {
364   return const_iterator(storage_.begin());
365 }
366
367 Value::Dict::const_iterator Value::Dict::cbegin() const {
368   return const_iterator(storage_.cbegin());
369 }
370
371 Value::Dict::iterator Value::Dict::end() {
372   return iterator(storage_.end());
373 }
374
375 Value::Dict::const_iterator Value::Dict::end() const {
376   return const_iterator(storage_.end());
377 }
378
379 Value::Dict::const_iterator Value::Dict::cend() const {
380   return const_iterator(storage_.cend());
381 }
382
383 bool Value::Dict::contains(base::StringPiece key) const {
384   DCHECK(IsStringUTF8AllowingNoncharacters(key));
385
386   return storage_.contains(key);
387 }
388
389 void Value::Dict::clear() {
390   return storage_.clear();
391 }
392
393 Value::Dict::iterator Value::Dict::erase(iterator pos) {
394   return iterator(storage_.erase(pos.GetUnderlyingIteratorDoNotUse()));
395 }
396
397 Value::Dict::iterator Value::Dict::erase(const_iterator pos) {
398   return iterator(storage_.erase(pos.GetUnderlyingIteratorDoNotUse()));
399 }
400
401 Value::Dict Value::Dict::Clone() const {
402   return Dict(storage_);
403 }
404
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
422 const Value* Value::Dict::Find(StringPiece key) const {
423   DCHECK(IsStringUTF8AllowingNoncharacters(key));
424   return FindPtrOrNull(storage_, key);
425 }
426
427 Value* Value::Dict::Find(StringPiece key) {
428   return FindPtrOrNull(storage_, key);
429 }
430
431 absl::optional<bool> Value::Dict::FindBool(StringPiece key) const {
432   const Value* v = Find(key);
433   return v ? v->GetIfBool() : absl::nullopt;
434 }
435
436 absl::optional<int> Value::Dict::FindInt(StringPiece key) const {
437   const Value* v = Find(key);
438   return v ? v->GetIfInt() : absl::nullopt;
439 }
440
441 absl::optional<double> Value::Dict::FindDouble(StringPiece key) const {
442   const Value* v = Find(key);
443   return v ? v->GetIfDouble() : absl::nullopt;
444 }
445
446 const std::string* Value::Dict::FindString(StringPiece key) const {
447   const Value* v = Find(key);
448   return v ? v->GetIfString() : nullptr;
449 }
450
451 std::string* Value::Dict::FindString(StringPiece key) {
452   Value* v = Find(key);
453   return v ? v->GetIfString() : nullptr;
454 }
455
456 const Value::BlobStorage* Value::Dict::FindBlob(StringPiece key) const {
457   const Value* v = Find(key);
458   return v ? v->GetIfBlob() : nullptr;
459 }
460
461 const Value::Dict* Value::Dict::FindDict(StringPiece key) const {
462   const Value* v = Find(key);
463   return v ? v->GetIfDict() : nullptr;
464 }
465
466 Value::Dict* Value::Dict::FindDict(StringPiece key) {
467   Value* v = Find(key);
468   return v ? v->GetIfDict() : nullptr;
469 }
470
471 const Value::List* Value::Dict::FindList(StringPiece key) const {
472   const Value* v = Find(key);
473   return v ? v->GetIfList() : nullptr;
474 }
475
476 Value::List* Value::Dict::FindList(StringPiece key) {
477   Value* v = Find(key);
478   return v ? v->GetIfList() : nullptr;
479 }
480
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
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
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
506 Value* Value::Dict::Set(StringPiece key, bool value) & {
507   return Set(key, Value(value));
508 }
509
510 Value* Value::Dict::Set(StringPiece key, int value) & {
511   return Set(key, Value(value));
512 }
513
514 Value* Value::Dict::Set(StringPiece key, double value) & {
515   return Set(key, Value(value));
516 }
517
518 Value* Value::Dict::Set(StringPiece key, StringPiece value) & {
519   return Set(key, Value(value));
520 }
521
522 Value* Value::Dict::Set(StringPiece key, StringPiece16 value) & {
523   return Set(key, Value(value));
524 }
525
526 Value* Value::Dict::Set(StringPiece key, const char* value) & {
527   return Set(key, Value(value));
528 }
529
530 Value* Value::Dict::Set(StringPiece key, const char16_t* value) & {
531   return Set(key, Value(value));
532 }
533
534 Value* Value::Dict::Set(StringPiece key, std::string&& value) & {
535   return Set(key, Value(std::move(value)));
536 }
537
538 Value* Value::Dict::Set(StringPiece key, BlobStorage&& value) & {
539   return Set(key, Value(std::move(value)));
540 }
541
542 Value* Value::Dict::Set(StringPiece key, Dict&& value) & {
543   return Set(key, Value(std::move(value)));
544 }
545
546 Value* Value::Dict::Set(StringPiece key, List&& value) & {
547   return Set(key, Value(std::move(value)));
548 }
549
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
556 Value::Dict&& Value::Dict::Set(StringPiece key, bool value) && {
557   return std::move(*this).Set(key, Value(value));
558 }
559
560 Value::Dict&& Value::Dict::Set(StringPiece key, int value) && {
561   return std::move(*this).Set(key, Value(value));
562 }
563
564 Value::Dict&& Value::Dict::Set(StringPiece key, double value) && {
565   return std::move(*this).Set(key, Value(value));
566 }
567
568 Value::Dict&& Value::Dict::Set(StringPiece key, StringPiece value) && {
569   return std::move(*this).Set(key, Value(value));
570 }
571
572 Value::Dict&& Value::Dict::Set(StringPiece key, StringPiece16 value) && {
573   return std::move(*this).Set(key, Value(value));
574 }
575
576 Value::Dict&& Value::Dict::Set(StringPiece key, const char* value) && {
577   return std::move(*this).Set(key, Value(value));
578 }
579
580 Value::Dict&& Value::Dict::Set(StringPiece key, const char16_t* value) && {
581   return std::move(*this).Set(key, Value(value));
582 }
583
584 Value::Dict&& Value::Dict::Set(StringPiece key, std::string&& value) && {
585   return std::move(*this).Set(key, Value(std::move(value)));
586 }
587
588 Value::Dict&& Value::Dict::Set(StringPiece key, BlobStorage&& value) && {
589   return std::move(*this).Set(key, Value(std::move(value)));
590 }
591
592 Value::Dict&& Value::Dict::Set(StringPiece key, Dict&& value) && {
593   return std::move(*this).Set(key, Value(std::move(value)));
594 }
595
596 Value::Dict&& Value::Dict::Set(StringPiece key, List&& value) && {
597   return std::move(*this).Set(key, Value(std::move(value)));
598 }
599
600 bool Value::Dict::Remove(StringPiece key) {
601   DCHECK(IsStringUTF8AllowingNoncharacters(key));
602
603   return storage_.erase(key) > 0;
604 }
605
606 absl::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 absl::nullopt;
612   }
613   Value v = std::move(*it->second);
614   storage_.erase(it);
615   return v;
616 }
617
618 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
640 Value* Value::Dict::FindByDottedPath(StringPiece path) {
641   return const_cast<Value*>(std::as_const(*this).FindByDottedPath(path));
642 }
643
644 absl::optional<bool> Value::Dict::FindBoolByDottedPath(StringPiece path) const {
645   const Value* v = FindByDottedPath(path);
646   return v ? v->GetIfBool() : absl::nullopt;
647 }
648
649 absl::optional<int> Value::Dict::FindIntByDottedPath(StringPiece path) const {
650   const Value* v = FindByDottedPath(path);
651   return v ? v->GetIfInt() : absl::nullopt;
652 }
653
654 absl::optional<double> Value::Dict::FindDoubleByDottedPath(
655     StringPiece path) const {
656   const Value* v = FindByDottedPath(path);
657   return v ? v->GetIfDouble() : absl::nullopt;
658 }
659
660 const std::string* Value::Dict::FindStringByDottedPath(StringPiece path) const {
661   const Value* v = FindByDottedPath(path);
662   return v ? v->GetIfString() : nullptr;
663 }
664
665 std::string* Value::Dict::FindStringByDottedPath(StringPiece path) {
666   Value* v = FindByDottedPath(path);
667   return v ? v->GetIfString() : nullptr;
668 }
669
670 const Value::BlobStorage* Value::Dict::FindBlobByDottedPath(
671     StringPiece path) const {
672   const Value* v = FindByDottedPath(path);
673   return v ? v->GetIfBlob() : nullptr;
674 }
675
676 const Value::Dict* Value::Dict::FindDictByDottedPath(StringPiece path) const {
677   const Value* v = FindByDottedPath(path);
678   return v ? v->GetIfDict() : nullptr;
679 }
680
681 Value::Dict* Value::Dict::FindDictByDottedPath(StringPiece path) {
682   Value* v = FindByDottedPath(path);
683   return v ? v->GetIfDict() : nullptr;
684 }
685
686 const Value::List* Value::Dict::FindListByDottedPath(StringPiece path) const {
687   const Value* v = FindByDottedPath(path);
688   return v ? v->GetIfList() : nullptr;
689 }
690
691 Value::List* Value::Dict::FindListByDottedPath(StringPiece path) {
692   Value* v = FindByDottedPath(path);
693   return v ? v->GetIfList() : nullptr;
694 }
695
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
724 Value* Value::Dict::SetByDottedPath(StringPiece path, bool value) & {
725   return SetByDottedPath(path, Value(value));
726 }
727
728 Value* Value::Dict::SetByDottedPath(StringPiece path, int value) & {
729   return SetByDottedPath(path, Value(value));
730 }
731
732 Value* Value::Dict::SetByDottedPath(StringPiece path, double value) & {
733   return SetByDottedPath(path, Value(value));
734 }
735
736 Value* Value::Dict::SetByDottedPath(StringPiece path, StringPiece value) & {
737   return SetByDottedPath(path, Value(value));
738 }
739
740 Value* Value::Dict::SetByDottedPath(StringPiece path, StringPiece16 value) & {
741   return SetByDottedPath(path, Value(value));
742 }
743
744 Value* Value::Dict::SetByDottedPath(StringPiece path, const char* value) & {
745   return SetByDottedPath(path, Value(value));
746 }
747
748 Value* Value::Dict::SetByDottedPath(StringPiece path, const char16_t* value) & {
749   return SetByDottedPath(path, Value(value));
750 }
751
752 Value* Value::Dict::SetByDottedPath(StringPiece path, std::string&& value) & {
753   return SetByDottedPath(path, Value(std::move(value)));
754 }
755
756 Value* Value::Dict::SetByDottedPath(StringPiece path, BlobStorage&& value) & {
757   return SetByDottedPath(path, Value(std::move(value)));
758 }
759
760 Value* Value::Dict::SetByDottedPath(StringPiece path, Dict&& value) & {
761   return SetByDottedPath(path, Value(std::move(value)));
762 }
763
764 Value* Value::Dict::SetByDottedPath(StringPiece path, List&& value) & {
765   return SetByDottedPath(path, Value(std::move(value)));
766 }
767
768 bool Value::Dict::RemoveByDottedPath(StringPiece path) {
769   return ExtractByDottedPath(path).has_value();
770 }
771
772 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, Value&& value) && {
773   SetByDottedPath(path, std::move(value));
774   return std::move(*this);
775 }
776
777 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, bool value) && {
778   SetByDottedPath(path, Value(value));
779   return std::move(*this);
780 }
781
782 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, int value) && {
783   SetByDottedPath(path, Value(value));
784   return std::move(*this);
785 }
786
787 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, double value) && {
788   SetByDottedPath(path, Value(value));
789   return std::move(*this);
790 }
791
792 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
793                                            StringPiece value) && {
794   SetByDottedPath(path, Value(value));
795   return std::move(*this);
796 }
797
798 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
799                                            StringPiece16 value) && {
800   SetByDottedPath(path, Value(value));
801   return std::move(*this);
802 }
803
804 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path,
805                                            const char* value) && {
806   SetByDottedPath(path, Value(value));
807   return std::move(*this);
808 }
809
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
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
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
828 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, Dict&& value) && {
829   SetByDottedPath(path, Value(std::move(value)));
830   return std::move(*this);
831 }
832
833 Value::Dict&& Value::Dict::SetByDottedPath(StringPiece path, List&& value) && {
834   SetByDottedPath(path, Value(std::move(value)));
835   return std::move(*this);
836 }
837
838 absl::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 absl::nullopt;
855   }
856   absl::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
864 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
872 std::string Value::Dict::DebugString() const {
873   return DebugStringImpl(*this);
874 }
875
876 #if BUILDFLAG(ENABLE_BASE_TRACING)
877 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
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
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
898 bool operator!=(const Value::Dict& lhs, const Value::Dict& rhs) {
899   return !(lhs == rhs);
900 }
901
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
908 bool operator>(const Value::Dict& lhs, const Value::Dict& rhs) {
909   return rhs < lhs;
910 }
911
912 bool operator<=(const Value::Dict& lhs, const Value::Dict& rhs) {
913   return !(rhs < lhs);
914 }
915
916 bool operator>=(const Value::Dict& lhs, const Value::Dict& rhs) {
917   return !(lhs < rhs);
918 }
919
920 // static
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
935 bool Value::List::empty() const {
936   return storage_.empty();
937 }
938
939 size_t Value::List::size() const {
940   return storage_.size();
941 }
942
943 Value::List::iterator Value::List::begin() {
944   return iterator(base::to_address(storage_.begin()),
945                   base::to_address(storage_.end()));
946 }
947
948 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
953 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
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
964 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
970 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
976 Value::List::reverse_iterator Value::List::rend() {
977   return reverse_iterator(begin());
978 }
979
980 Value::List::const_reverse_iterator Value::List::rend() const {
981   return const_reverse_iterator(begin());
982 }
983
984 Value::List::reverse_iterator Value::List::rbegin() {
985   return reverse_iterator(end());
986 }
987
988 Value::List::const_reverse_iterator Value::List::rbegin() const {
989   return const_reverse_iterator(end());
990 }
991
992 const Value& Value::List::front() const {
993   CHECK(!storage_.empty());
994   return storage_.front();
995 }
996
997 Value& Value::List::front() {
998   CHECK(!storage_.empty());
999   return storage_.front();
1000 }
1001
1002 const Value& Value::List::back() const {
1003   CHECK(!storage_.empty());
1004   return storage_.back();
1005 }
1006
1007 Value& Value::List::back() {
1008   CHECK(!storage_.empty());
1009   return storage_.back();
1010 }
1011
1012 void Value::List::reserve(size_t capacity) {
1013   storage_.reserve(capacity);
1014 }
1015
1016 void Value::List::resize(size_t new_size) {
1017   storage_.resize(new_size);
1018 }
1019
1020 const Value& Value::List::operator[](size_t index) const {
1021   CHECK_LT(index, storage_.size());
1022   return storage_[index];
1023 }
1024
1025 Value& Value::List::operator[](size_t index) {
1026   CHECK_LT(index, storage_.size());
1027   return storage_[index];
1028 }
1029
1030 void Value::List::clear() {
1031   storage_.clear();
1032 }
1033
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
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
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
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
1063 Value::List Value::List::Clone() const {
1064   return List(storage_);
1065 }
1066
1067 void Value::List::Append(Value&& value) & {
1068   storage_.emplace_back(std::move(value));
1069 }
1070
1071 void Value::List::Append(bool value) & {
1072   storage_.emplace_back(value);
1073 }
1074
1075 void Value::List::Append(int value) & {
1076   storage_.emplace_back(value);
1077 }
1078
1079 void Value::List::Append(double value) & {
1080   storage_.emplace_back(value);
1081 }
1082
1083 void Value::List::Append(StringPiece value) & {
1084   Append(Value(value));
1085 }
1086
1087 void Value::List::Append(StringPiece16 value) & {
1088   storage_.emplace_back(value);
1089 }
1090
1091 void Value::List::Append(const char* value) & {
1092   storage_.emplace_back(value);
1093 }
1094
1095 void Value::List::Append(const char16_t* value) & {
1096   storage_.emplace_back(value);
1097 }
1098
1099 void Value::List::Append(std::string&& value) & {
1100   storage_.emplace_back(std::move(value));
1101 }
1102
1103 void Value::List::Append(BlobStorage&& value) & {
1104   storage_.emplace_back(std::move(value));
1105 }
1106
1107 void Value::List::Append(Dict&& value) & {
1108   storage_.emplace_back(std::move(value));
1109 }
1110
1111 void Value::List::Append(List&& value) & {
1112   storage_.emplace_back(std::move(value));
1113 }
1114
1115 Value::List&& Value::List::Append(Value&& value) && {
1116   storage_.emplace_back(std::move(value));
1117   return std::move(*this);
1118 }
1119
1120 Value::List&& Value::List::Append(bool value) && {
1121   storage_.emplace_back(value);
1122   return std::move(*this);
1123 }
1124
1125 Value::List&& Value::List::Append(int value) && {
1126   storage_.emplace_back(value);
1127   return std::move(*this);
1128 }
1129
1130 Value::List&& Value::List::Append(double value) && {
1131   storage_.emplace_back(value);
1132   return std::move(*this);
1133 }
1134
1135 Value::List&& Value::List::Append(StringPiece value) && {
1136   Append(Value(value));
1137   return std::move(*this);
1138 }
1139
1140 Value::List&& Value::List::Append(StringPiece16 value) && {
1141   storage_.emplace_back(value);
1142   return std::move(*this);
1143 }
1144
1145 Value::List&& Value::List::Append(const char* value) && {
1146   storage_.emplace_back(value);
1147   return std::move(*this);
1148 }
1149
1150 Value::List&& Value::List::Append(const char16_t* value) && {
1151   storage_.emplace_back(value);
1152   return std::move(*this);
1153 }
1154
1155 Value::List&& Value::List::Append(std::string&& value) && {
1156   storage_.emplace_back(std::move(value));
1157   return std::move(*this);
1158 }
1159
1160 Value::List&& Value::List::Append(BlobStorage&& value) && {
1161   storage_.emplace_back(std::move(value));
1162   return std::move(*this);
1163 }
1164
1165 Value::List&& Value::List::Append(Dict&& value) && {
1166   storage_.emplace_back(std::move(value));
1167   return std::move(*this);
1168 }
1169
1170 Value::List&& Value::List::Append(List&& value) && {
1171   storage_.emplace_back(std::move(value));
1172   return std::move(*this);
1173 }
1174
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
1183 size_t Value::List::EraseValue(const Value& value) {
1184   return Erase(storage_, value);
1185 }
1186
1187 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
1195 std::string Value::List::DebugString() const {
1196   return DebugStringImpl(*this);
1197 }
1198
1199 #if BUILDFLAG(ENABLE_BASE_TRACING)
1200 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
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
1215 bool operator==(const Value::List& lhs, const Value::List& rhs) {
1216   return lhs.storage_ == rhs.storage_;
1217 }
1218
1219 bool operator!=(const Value::List& lhs, const Value::List& rhs) {
1220   return !(lhs == rhs);
1221 }
1222
1223 bool operator<(const Value::List& lhs, const Value::List& rhs) {
1224   return lhs.storage_ < rhs.storage_;
1225 }
1226
1227 bool operator>(const Value::List& lhs, const Value::List& rhs) {
1228   return rhs < lhs;
1229 }
1230
1231 bool operator<=(const Value::List& lhs, const Value::List& rhs) {
1232   return !(rhs < lhs);
1233 }
1234
1235 bool operator>=(const Value::List& lhs, const Value::List& rhs) {
1236   return !(lhs < rhs);
1237 }
1238
1239 bool operator==(const Value& lhs, const Value& rhs) {
1240   return lhs.data_ == rhs.data_;
1241 }
1242
1243 bool operator!=(const Value& lhs, const Value& rhs) {
1244   return !(lhs == rhs);
1245 }
1246
1247 bool operator<(const Value& lhs, const Value& rhs) {
1248   return lhs.data_ < rhs.data_;
1249 }
1250
1251 bool operator>(const Value& lhs, const Value& rhs) {
1252   return rhs < lhs;
1253 }
1254
1255 bool operator<=(const Value& lhs, const Value& rhs) {
1256   return !(rhs < lhs);
1257 }
1258
1259 bool operator>=(const Value& lhs, const Value& rhs) {
1260   return !(lhs < rhs);
1261 }
1262
1263 bool operator==(const Value& lhs, bool rhs) {
1264   return lhs.is_bool() && lhs.GetBool() == rhs;
1265 }
1266
1267 bool operator==(const Value& lhs, int rhs) {
1268   return lhs.is_int() && lhs.GetInt() == rhs;
1269 }
1270
1271 bool operator==(const Value& lhs, double rhs) {
1272   return lhs.is_double() && lhs.GetDouble() == rhs;
1273 }
1274
1275 bool operator==(const Value& lhs, StringPiece rhs) {
1276   return lhs.is_string() && lhs.GetString() == rhs;
1277 }
1278
1279 bool operator==(const Value& lhs, const Value::Dict& rhs) {
1280   return lhs.is_dict() && lhs.GetDict() == rhs;
1281 }
1282
1283 bool operator==(const Value& lhs, const Value::List& rhs) {
1284   return lhs.is_list() && lhs.GetList() == rhs;
1285 }
1286
1287 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
1304 std::string Value::DebugString() const {
1305   return DebugStringImpl(*this);
1306 }
1307
1308 #if BUILDFLAG(ENABLE_BASE_TRACING)
1309 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
1333 ValueView::ValueView(const Value& value)
1334     : data_view_(
1335           value.Visit([](const auto& member) { return ViewType(member); })) {}
1336
1337 Value ValueView::ToValue() const {
1338   return Value::CloningHelper::Clone(data_view_);
1339 }
1340
1341 ValueSerializer::~ValueSerializer() = default;
1342
1343 ValueDeserializer::~ValueDeserializer() = default;
1344
1345 std::ostream& operator<<(std::ostream& out, const Value& value) {
1346   return out << value.DebugString();
1347 }
1348
1349 std::ostream& operator<<(std::ostream& out, const Value::Dict& dict) {
1350   return out << dict.DebugString();
1351 }
1352
1353 std::ostream& operator<<(std::ostream& out, const Value::List& list) {
1354   return out << list.DebugString();
1355 }
1356
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