blob: 79ccb4fc26512bf7b96042518a84b18d6d05c266 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]101d5422008-09-26 20:22:425#ifndef BASE_VALUES_H_
6#define BASE_VALUES_H_
initial.commitd7cae122008-07-26 21:49:387
[email protected]c014f2b32013-09-03 23:29:128#include <stddef.h>
avi9b6f42932015-12-26 22:15:149#include <stdint.h>
[email protected]c014f2b32013-09-03 23:29:1210
Peter Kastingb2517a1d2025-01-19 22:45:4811#include <algorithm>
Daniel Cheng782d2ba32022-02-16 19:40:2912#include <array>
Joe Mason3ce6ff72025-03-18 21:29:1313#include <compare>
Peter Kastingb2517a1d2025-01-19 22:45:4814#include <concepts>
Lei Zhang935738a2021-05-17 21:35:5315#include <initializer_list>
[email protected]c014f2b32013-09-03 23:29:1216#include <iosfwd>
Matt Menkee311c6d2022-06-14 20:17:3917#include <iterator>
dcheng093de9b2016-04-04 21:25:5118#include <memory>
Arthur Sonzognie5fff99c2024-02-21 15:58:2419#include <optional>
[email protected]8e50b602009-03-03 22:59:4320#include <string>
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:2721#include <string_view>
[email protected]c014f2b32013-09-03 23:29:1222#include <utility>
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:3423#include <variant>
initial.commitd7cae122008-07-26 21:49:3824#include <vector>
25
[email protected]0bea7252011-08-05 15:34:0026#include "base/base_export.h"
Daniel Cheng782d2ba32022-02-16 19:40:2927#include "base/bit_cast.h"
Daniel Cheng8ac305b2022-02-17 00:05:1128#include "base/compiler_specific.h"
Jan Wilken Dörrie7e7a9792019-10-15 14:42:0529#include "base/containers/checked_iterators.h"
mkwstcd8067b2017-04-11 06:52:2130#include "base/containers/flat_map.h"
jdoerriecd022242017-08-23 08:38:2731#include "base/containers/span.h"
Alexander Timine68aeb32021-04-11 23:06:2132#include "base/trace_event/base_tracing_forward.h"
Andrew Paseltiner806b04bf2025-04-28 13:22:4833#include "base/types/pass_key.h"
jdoerrie44efa9d2017-07-14 14:47:2034#include "base/value_iterators.h"
initial.commitd7cae122008-07-26 21:49:3835
[email protected]f3a1c642011-07-12 19:15:0336namespace base {
37
Andrew Paseltinerc4c65fe2025-03-07 19:01:0138class DictValue;
39class Value;
40
Andrew Paseltiner806b04bf2025-04-28 13:22:4841namespace internal {
42class JSONParser;
43} // namespace internal
44
Andrew Paseltinerc4c65fe2025-03-07 19:01:0145using BlobStorage = std::vector<uint8_t>;
46
47// Represents a list of Values.
48class BASE_EXPORT GSL_OWNER ListValue {
49 public:
50 using iterator = CheckedContiguousIterator<Value>;
51 using const_iterator = CheckedContiguousConstIterator<Value>;
52 using reverse_iterator = std::reverse_iterator<iterator>;
53 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
54 using value_type = Value;
55
56 // Creates a list with the given capacity reserved.
57 // Correctly using this will greatly reduce the code size and improve
58 // performance when creating a list whose size is known up front.
59 static ListValue with_capacity(size_t capacity);
60
61 ListValue();
62
63 ListValue(ListValue&&) noexcept;
64 ListValue& operator=(ListValue&&) noexcept;
65
66 // Deleted to prevent accidental copying.
67 ListValue(const ListValue&) = delete;
68 ListValue& operator=(const ListValue&) = delete;
69
70 ~ListValue();
71
72 // Returns true if there are no values in this list and false otherwise.
73 bool empty() const;
74
75 // Returns the number of values in this list.
76 size_t size() const;
77
78 // Returns an iterator to the first value in this list.
79 iterator begin();
80 const_iterator begin() const;
81 const_iterator cbegin() const;
82
83 // Returns an iterator following the last value in this list. May not be
84 // dereferenced.
85 iterator end();
86 const_iterator end() const;
87 const_iterator cend() const;
88
89 // Returns a reverse iterator preceding the first value in this list. May
90 // not be dereferenced.
91 reverse_iterator rend();
92 const_reverse_iterator rend() const;
93
94 // Returns a reverse iterator to the last value in this list.
95 reverse_iterator rbegin();
96 const_reverse_iterator rbegin() const;
97
98 // Returns a reference to the first value in the container. Fails with
99 // `CHECK()` if the list is empty.
100 const Value& front() const LIFETIME_BOUND;
101 Value& front() LIFETIME_BOUND;
102
103 // Returns a reference to the last value in the container. Fails with
104 // `CHECK()` if the list is empty.
105 const Value& back() const LIFETIME_BOUND;
106 Value& back() LIFETIME_BOUND;
107
108 // Increase the capacity of the backing container, but does not change
109 // the size. Assume all existing iterators will be invalidated.
110 void reserve(size_t capacity);
111
112 // Resizes the list.
113 // If `new_size` is greater than current size, the extra elements in the
114 // back will be destroyed.
115 // If `new_size` is less than current size, new default-initialized elements
116 // will be added to the back.
117 // Assume all existing iterators will be invalidated.
118 void resize(size_t new_size);
119
120 // Returns a reference to the value at `index` in this list. Fails with a
121 // `CHECK()` if `index >= size()`.
122 const Value& operator[](size_t index) const;
123 Value& operator[](size_t index);
124
125 // Returns true if the specified `val` is present in the list.
126 bool contains(bool val) const;
127 bool contains(int val) const;
128 bool contains(double val) const;
129 // Note: std::u16string_view overload intentionally omitted: Value
130 // internally stores strings as UTF-8.
131 bool contains(std::string_view val) const;
132 bool contains(const char* val) const;
133 bool contains(const BlobStorage& val) const;
134 bool contains(const DictValue& val) const;
135 bool contains(const ListValue& val) const;
136
137 // Removes all value from this list.
138 REINITIALIZES_AFTER_MOVE void clear();
139
140 // Removes the value referenced by `pos` in this list and returns an
141 // iterator to the value following the removed value.
142 iterator erase(iterator pos);
143 const_iterator erase(const_iterator pos);
144
145 // Remove the values in the range [`first`, `last`). Returns iterator to the
146 // first value following the removed range, which is `last`. If `first` ==
147 // `last`, removes nothing and returns `last`.
148 iterator erase(iterator first, iterator last);
149 const_iterator erase(const_iterator first, const_iterator last);
150
151 // Creates a deep copy of this dictionary.
152 ListValue Clone() const;
153
154 // Appends `value` to the end of this list.
155 void Append(Value&& value) &;
156 void Append(bool value) &;
157 template <typename T>
158 void Append(const T*) & = delete;
159 void Append(int value) &;
160 void Append(double value) &;
161 void Append(std::string_view value) &;
162 void Append(std::u16string_view value) &;
163 void Append(const char* value) &;
164 void Append(const char16_t* value) &;
165 void Append(std::string&& value) &;
166 void Append(BlobStorage&& value) &;
167 void Append(DictValue&& value) &;
168 void Append(ListValue&& value) &;
169
170 // Rvalue overrides of the `Append` methods, which allow you to construct
171 // a `Value::List` builder-style:
172 //
173 // Value::List result =
174 // Value::List().Append("first value").Append(2).Append(true);
175 //
176 // Each method returns a rvalue reference to `this`, so this is as efficient
177 // as stand-alone calls to `Append`, while at the same time making it harder
178 // to accidentally append to the wrong list.
179 //
180 // The equivalent code without using these builder-style methods:
181 //
182 // Value::List no_builder_example;
183 // no_builder_example.Append("first value");
184 // no_builder_example.Append(2);
185 // no_builder_example.Append(true);
186 //
187 ListValue&& Append(Value&& value) &&;
188 ListValue&& Append(bool value) &&;
189 template <typename T>
190 ListValue&& Append(const T*) && = delete;
191 ListValue&& Append(int value) &&;
192 ListValue&& Append(double value) &&;
193 ListValue&& Append(std::string_view value) &&;
194 ListValue&& Append(std::u16string_view value) &&;
195 ListValue&& Append(const char* value) &&;
196 ListValue&& Append(const char16_t* value) &&;
197 ListValue&& Append(std::string&& value) &&;
198 ListValue&& Append(BlobStorage&& value) &&;
199 ListValue&& Append(DictValue&& value) &&;
200 ListValue&& Append(ListValue&& value) &&;
201
202 // Inserts `value` before `pos` in this list. Returns an iterator to the
203 // inserted value.
204 // TODO(dcheng): Should this provide the same set of overloads that Append()
205 // does?
206 iterator Insert(const_iterator pos, Value&& value);
207
208 // Erases all values equal to `value` from this list.
209 size_t EraseValue(const Value& value);
210
211 // Erases all values for which `predicate` evaluates to true from this list.
212 template <typename Predicate>
213 size_t EraseIf(Predicate predicate) {
214 return std::erase_if(storage_, predicate);
215 }
216
Etienne Pierre-doray4c826fa2025-06-04 19:10:58217 // Estimates dynamic memory usage. See
Andrew Paseltinerc4c65fe2025-03-07 19:01:01218 // base/trace_event/memory_usage_estimator.h for more info.
219 size_t EstimateMemoryUsage() const;
220
221 // Serializes to a string for logging and debug purposes.
222 std::string DebugString() const;
223
Andrew Paseltinerc4c65fe2025-03-07 19:01:01224 // Write this object into a trace.
225 void WriteIntoTrace(perfetto::TracedValue) const;
Andrew Paseltinerc4c65fe2025-03-07 19:01:01226
227 private:
228 using ListStorage = std::vector<Value>;
229
Joe Mason3ce6ff72025-03-18 21:29:13230 friend bool operator==(const ListValue& lhs, const ListValue& rhs) = default;
231 BASE_EXPORT friend std::partial_ordering operator<=>(const ListValue& lhs,
232 const ListValue& rhs);
Andrew Paseltinerc4c65fe2025-03-07 19:01:01233
234 explicit ListValue(const std::vector<Value>& storage);
235
236 // Shared implementation of public `contains()` methods.
237 template <typename T, typename R>
238 requires std::equality_comparable_with<T, R>
239 bool contains(const T& val,
240 bool (Value::*test)() const,
241 R (Value::*get)() const) const;
242
243 std::vector<Value> storage_;
244};
245
246// Represents a dictionary of string keys to Values.
247class BASE_EXPORT GSL_OWNER DictValue {
248 public:
249 using iterator = detail::dict_iterator;
250 using const_iterator = detail::const_dict_iterator;
Etienne Dechamps26e6c602025-04-14 16:43:53251 using value_type = detail::const_dict_iterator::value_type;
Andrew Paseltinerc4c65fe2025-03-07 19:01:01252
253 DictValue();
254
255 DictValue(DictValue&&) noexcept;
256 DictValue& operator=(DictValue&&) noexcept;
257
258 // Deleted to prevent accidental copying.
259 DictValue(const DictValue&) = delete;
260 DictValue& operator=(const DictValue&) = delete;
261
262 // Takes move_iterators iterators that return std::pair<std::string, Value>,
263 // and moves their values into a new Dict. Adding all entries at once
264 // results in a faster initial sort operation. Takes move iterators to avoid
265 // having to clone the input.
266 template <class IteratorType>
Lei Zhangb39481fd2025-06-26 01:03:40267 DictValue(std::move_iterator<IteratorType> first,
268 std::move_iterator<IteratorType> last);
Andrew Paseltinerc4c65fe2025-03-07 19:01:01269
Andrew Paseltiner806b04bf2025-04-28 13:22:48270 DictValue(PassKey<internal::JSONParser>,
271 flat_map<std::string, std::unique_ptr<Value>>);
272
Andrew Paseltinerc4c65fe2025-03-07 19:01:01273 ~DictValue();
274
275 // Returns true if there are no entries in this dictionary and false
276 // otherwise.
277 bool empty() const;
278
279 // Returns the number of entries in this dictionary.
280 size_t size() const;
281
282 // Returns an iterator to the first entry in this dictionary.
283 iterator begin();
284 const_iterator begin() const;
285 const_iterator cbegin() const;
286
287 // Returns an iterator following the last entry in this dictionary. May not
288 // be dereferenced.
289 iterator end();
290 const_iterator end() const;
291 const_iterator cend() const;
292
293 // Returns true if `key` is an entry in this dictionary.
294 bool contains(std::string_view key) const;
295
296 // Removes all entries from this dictionary.
297 REINITIALIZES_AFTER_MOVE void clear();
298
299 // Removes the entry referenced by `pos` in this dictionary and returns an
300 // iterator to the entry following the removed entry.
301 iterator erase(iterator pos);
302 iterator erase(const_iterator pos);
303
304 // Creates a deep copy of this dictionary.
305 DictValue Clone() const;
306
307 // Merges the entries from `dict` into this dictionary. If an entry with the
308 // same key exists in this dictionary and `dict`:
309 // - if both entries are dictionaries, they will be recursively merged
310 // - otherwise, the already-existing entry in this dictionary will be
311 // overwritten with the entry from `dict`.
312 void Merge(DictValue dict);
313
314 // Finds the entry corresponding to `key` in this dictionary. Returns
315 // nullptr if there is no such entry.
316 const Value* Find(std::string_view key) const;
317 Value* Find(std::string_view key);
318
319 // Similar to `Find()` above, but returns `std::nullopt`/`nullptr` if the
320 // type of the entry does not match. `bool`, `int`, and `double` are
321 // returned in a wrapped `std::optional`; blobs, `Value::Dict`, and
322 // `Value::List` are returned by pointer.
323 std::optional<bool> FindBool(std::string_view key) const;
324 std::optional<int> FindInt(std::string_view key) const;
325 // Returns a non-null value for both `Value::Type::DOUBLE` and
326 // `Value::Type::INT`, converting the latter to a double.
327 std::optional<double> FindDouble(std::string_view key) const;
328 const std::string* FindString(std::string_view key) const;
329 std::string* FindString(std::string_view key);
330 const BlobStorage* FindBlob(std::string_view key) const;
331 BlobStorage* FindBlob(std::string_view key);
332 const DictValue* FindDict(std::string_view key) const;
333 DictValue* FindDict(std::string_view key);
334 const ListValue* FindList(std::string_view key) const;
335 ListValue* FindList(std::string_view key);
336
337 // If there's a value of the specified type at `key` in this dictionary,
338 // returns it. Otherwise, creates an empty container of the specified type,
339 // inserts it at `key`, and returns it. If there's a value of some other
340 // type at `key`, will overwrite that entry.
341 DictValue* EnsureDict(std::string_view key);
342 ListValue* EnsureList(std::string_view key);
343
344 // Sets an entry with `key` and `value` in this dictionary, overwriting any
345 // existing entry with the same `key`. Returns a pointer to the set `value`.
346 Value* Set(std::string_view key, Value&& value) &;
347 Value* Set(std::string_view key, bool value) &;
348 template <typename T>
349 Value* Set(std::string_view, const T*) & = delete;
350 Value* Set(std::string_view key, int value) &;
351 Value* Set(std::string_view key, double value) &;
352 Value* Set(std::string_view key, std::string_view value) &;
353 Value* Set(std::string_view key, std::u16string_view value) &;
354 Value* Set(std::string_view key, const char* value) &;
355 Value* Set(std::string_view key, const char16_t* value) &;
356 Value* Set(std::string_view key, std::string&& value) &;
357 Value* Set(std::string_view key, BlobStorage&& value) &;
358 Value* Set(std::string_view key, DictValue&& value) &;
359 Value* Set(std::string_view key, ListValue&& value) &;
360
361 // Rvalue overrides of the `Set` methods, which allow you to construct
362 // a `Value::Dict` builder-style:
363 //
364 // Value::Dict result =
365 // Value::Dict()
366 // .Set("key-1", "first value")
367 // .Set("key-2", 2)
368 // .Set("key-3", true)
369 // .Set("nested-dictionary", Value::Dict()
370 // .Set("nested-key-1", "value")
371 // .Set("nested-key-2", true))
372 // .Set("nested-list", Value::List()
373 // .Append("nested-list-value")
374 // .Append(5)
375 // .Append(true));
376 //
377 // Each method returns a rvalue reference to `this`, so this is as efficient
378 // as stand-alone calls to `Set`, while also making it harder to
379 // accidentally insert items in the wrong dictionary.
380 //
381 // The equivalent code without using these builder-style methods:
382 //
383 // Value::Dict no_builder_example;
384 // no_builder_example.Set("key-1", "first value")
385 // no_builder_example.Set("key-2", 2)
386 // no_builder_example.Set("key-3", true)
387 // Value::Dict nested_dictionary;
388 // nested_dictionary.Set("nested-key-1", "value");
389 // nested_dictionary.Set("nested-key-2", true);
390 // no_builder_example.Set("nested_dictionary",
391 // std::move(nested_dictionary));
392 // Value::List nested_list;
393 // nested_list.Append("nested-list-value");
394 // nested_list.Append(5);
395 // nested_list.Append(true);
396 // no_builder_example.Set("nested-list", std::move(nested_list));
397 //
398 // Sometimes `git cl format` does a less than perfect job formatting these
399 // chained `Set` calls. In these cases you can use a trailing empty comment
400 // to influence the code formatting:
401 //
402 // Value::Dict result = Value::Dict().Set(
403 // "nested",
404 // base::Value::Dict().Set("key", "value").Set("other key", "other"));
405 //
406 // Value::Dict result = Value::Dict().Set("nested",
407 // base::Value::Dict() //
408 // .Set("key", "value")
409 // .Set("other key", "value"));
410 //
411 DictValue&& Set(std::string_view key, Value&& value) &&;
412 DictValue&& Set(std::string_view key, bool value) &&;
413 template <typename T>
414 DictValue&& Set(std::string_view, const T*) && = delete;
415 DictValue&& Set(std::string_view key, int value) &&;
416 DictValue&& Set(std::string_view key, double value) &&;
417 DictValue&& Set(std::string_view key, std::string_view value) &&;
418 DictValue&& Set(std::string_view key, std::u16string_view value) &&;
419 DictValue&& Set(std::string_view key, const char* value) &&;
420 DictValue&& Set(std::string_view key, const char16_t* value) &&;
421 DictValue&& Set(std::string_view key, std::string&& value) &&;
422 DictValue&& Set(std::string_view key, BlobStorage&& value) &&;
423 DictValue&& Set(std::string_view key, DictValue&& value) &&;
424 DictValue&& Set(std::string_view key, ListValue&& value) &&;
425
426 // Removes the entry corresponding to `key` from this dictionary. Returns
427 // true if an entry was removed or false otherwise.
428 bool Remove(std::string_view key);
429
430 // Similar to `Remove()`, but returns the value corresponding to the removed
431 // entry or `std::nullopt` otherwise.
432 std::optional<Value> Extract(std::string_view key);
433
434 // Equivalent to the above methods but operating on paths instead of keys.
435 // A path is shorthand syntax for referring to a key nested inside
436 // intermediate dictionaries, with components delimited by ".". Paths may
437 // not be empty.
438 //
439 // Prefer the non-path methods above when possible. Paths that have only one
440 // component (i.e. no dots in the path) should never use the path-based
441 // methods.
442 //
443 // Originally, the path-based APIs were the only way of specifying a key, so
444 // there are likely to be many legacy (and unnecessary) uses of the path
445 // APIs that do not actually require traversing nested dictionaries.
446 const Value* FindByDottedPath(std::string_view path) const;
447 Value* FindByDottedPath(std::string_view path);
448
449 std::optional<bool> FindBoolByDottedPath(std::string_view path) const;
450 std::optional<int> FindIntByDottedPath(std::string_view path) const;
451 // Returns a non-null value for both `Value::Type::DOUBLE` and
452 // `Value::Type::INT`, converting the latter to a double.
453 std::optional<double> FindDoubleByDottedPath(std::string_view path) const;
454 const std::string* FindStringByDottedPath(std::string_view path) const;
455 std::string* FindStringByDottedPath(std::string_view path);
456 const BlobStorage* FindBlobByDottedPath(std::string_view path) const;
457 BlobStorage* FindBlobByDottedPath(std::string_view path);
458 const DictValue* FindDictByDottedPath(std::string_view path) const;
459 DictValue* FindDictByDottedPath(std::string_view path);
460 const ListValue* FindListByDottedPath(std::string_view path) const;
461 ListValue* FindListByDottedPath(std::string_view path);
462
463 // Creates a new entry with a dictionary for any non-last component that is
464 // missing an entry while performing the path traversal. Will fail if any
465 // non-last component of the path refers to an already-existing entry that
466 // is not a dictionary. Returns `nullptr` on failure.
467 //
468 // Warning: repeatedly using this API to enter entries in the same nested
469 // dictionary is inefficient, so please do not write the following:
470 //
471 // bad_example.SetByDottedPath("a.nested.dictionary.field_1", 1);
472 // bad_example.SetByDottedPath("a.nested.dictionary.field_2", "value");
473 // bad_example.SetByDottedPath("a.nested.dictionary.field_3", 1);
474 //
475 Value* SetByDottedPath(std::string_view path, Value&& value) &;
476 Value* SetByDottedPath(std::string_view path, bool value) &;
477 template <typename T>
478 Value* SetByDottedPath(std::string_view, const T*) & = delete;
479 Value* SetByDottedPath(std::string_view path, int value) &;
480 Value* SetByDottedPath(std::string_view path, double value) &;
481 Value* SetByDottedPath(std::string_view path, std::string_view value) &;
482 Value* SetByDottedPath(std::string_view path, std::u16string_view value) &;
483 Value* SetByDottedPath(std::string_view path, const char* value) &;
484 Value* SetByDottedPath(std::string_view path, const char16_t* value) &;
485 Value* SetByDottedPath(std::string_view path, std::string&& value) &;
486 Value* SetByDottedPath(std::string_view path, BlobStorage&& value) &;
487 Value* SetByDottedPath(std::string_view path, DictValue&& value) &;
488 Value* SetByDottedPath(std::string_view path, ListValue&& value) &;
489
490 // Rvalue overrides of the `SetByDottedPath` methods, which allow you to
491 // construct a `Value::Dict` builder-style:
492 //
493 // Value::Dict result =
494 // Value::Dict()
495 // .SetByDottedPath("a.nested.dictionary.with.key-1", "first value")
496 // .Set("local-key-1", 2));
497 //
498 // Each method returns a rvalue reference to `this`, so this is as efficient
499 // as (and less mistake-prone than) stand-alone calls to `Set`.
500 //
501 // Warning: repeatedly using this API to enter entries in the same nested
502 // dictionary is inefficient, so do not write this:
503 //
504 // Value::Dict bad_example =
505 // Value::Dict()
506 // .SetByDottedPath("nested.dictionary.key-1", "first value")
507 // .SetByDottedPath("nested.dictionary.key-2", "second value")
508 // .SetByDottedPath("nested.dictionary.key-3", "third value");
509 //
510 // Instead, simply write this
511 //
512 // Value::Dict good_example =
513 // Value::Dict()
514 // .Set("nested",
515 // base::Value::Dict()
516 // .Set("dictionary",
517 // base::Value::Dict()
518 // .Set(key-1", "first value")
519 // .Set(key-2", "second value")
520 // .Set(key-3", "third value")));
521 //
522 //
523 DictValue&& SetByDottedPath(std::string_view path, Value&& value) &&;
524 DictValue&& SetByDottedPath(std::string_view path, bool value) &&;
525 template <typename T>
526 DictValue&& SetByDottedPath(std::string_view, const T*) && = delete;
527 DictValue&& SetByDottedPath(std::string_view path, int value) &&;
528 DictValue&& SetByDottedPath(std::string_view path, double value) &&;
529 DictValue&& SetByDottedPath(std::string_view path, std::string_view value) &&;
530 DictValue&& SetByDottedPath(std::string_view path,
531 std::u16string_view value) &&;
532 DictValue&& SetByDottedPath(std::string_view path, const char* value) &&;
533 DictValue&& SetByDottedPath(std::string_view path, const char16_t* value) &&;
534 DictValue&& SetByDottedPath(std::string_view path, std::string&& value) &&;
535 DictValue&& SetByDottedPath(std::string_view path, BlobStorage&& value) &&;
536 DictValue&& SetByDottedPath(std::string_view path, DictValue&& value) &&;
537 DictValue&& SetByDottedPath(std::string_view path, ListValue&& value) &&;
538
539 bool RemoveByDottedPath(std::string_view path);
540
541 std::optional<Value> ExtractByDottedPath(std::string_view path);
542
Etienne Pierre-doray4c826fa2025-06-04 19:10:58543 // Estimates dynamic memory usage. See
Andrew Paseltinerc4c65fe2025-03-07 19:01:01544 // base/trace_event/memory_usage_estimator.h for more info.
545 size_t EstimateMemoryUsage() const;
546
547 // Serializes to a string for logging and debug purposes.
548 std::string DebugString() const;
549
Andrew Paseltinerc4c65fe2025-03-07 19:01:01550 // Write this object into a trace.
551 void WriteIntoTrace(perfetto::TracedValue) const;
Andrew Paseltinerc4c65fe2025-03-07 19:01:01552
553 private:
554 BASE_EXPORT friend bool operator==(const DictValue& lhs,
555 const DictValue& rhs);
Joe Mason3ce6ff72025-03-18 21:29:13556 BASE_EXPORT friend std::partial_ordering operator<=>(const DictValue& lhs,
557 const DictValue& rhs);
Andrew Paseltinerc4c65fe2025-03-07 19:01:01558
Andrew Paseltiner806b04bf2025-04-28 13:22:48559 explicit DictValue(flat_map<std::string, std::unique_ptr<Value>>);
560
Andrew Paseltinerc4c65fe2025-03-07 19:01:01561 // TODO(dcheng): Replace with `flat_map<std::string, Value>` once no caller
562 // relies on stability of pointers anymore.
563 flat_map<std::string, std::unique_ptr<Value>> storage_;
564};
565
Daniel Chenga367fe52022-02-15 18:08:48566// The `Value` class is a variant type can hold one of the following types:
567// - null
568// - bool
569// - int
570// - double
571// - string (internally UTF8-encoded)
572// - binary data (i.e. a blob)
573// - dictionary of string keys to `Value`s
574// - list of `Value`s
[email protected]2f03f532013-07-17 08:43:33575//
Daniel Chenga367fe52022-02-15 18:08:48576// With the exception of binary blobs, `Value` is intended to be the C++ version
577// of data types that can be represented in JSON.
Brett Wilson4bef8ee2017-09-01 20:11:49578//
Daniel Chenga367fe52022-02-15 18:08:48579// Warning: blob support may be removed in the future.
580//
581// ## Usage
582//
583// Do not use `Value` if a more specific type would be more appropriate. For
584// example, a function that only accepts dictionary values should have a
585// `base::Value::Dict` parameter, not a `base::Value` parameter.
586//
587// Construction:
588//
589// `Value` is directly constructible from `bool`, `int`, `double`, binary blobs
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27590// (`std::vector<uint8_t>`), `std::string_view`, `std::u16string_view`,
Daniel Chenga367fe52022-02-15 18:08:48591// `Value::Dict`, and `Value::List`.
592//
593// Copying:
594//
595// `Value` does not support C++ copy semantics to make it harder to accidentally
596// copy large values. Instead, use `Clone()` to manually create a deep copy.
597//
598// Reading:
599//
600// `GetBool()`, GetInt()`, et cetera `CHECK()` that the `Value` has the correct
601// subtype before returning the contained value. `bool`, `int`, `double` are
602// returned by value. Binary blobs, `std::string`, `Value::Dict`, `Value::List`
603// are returned by reference.
604//
Arthur Sonzognie5fff99c2024-02-21 15:58:24605// `GetIfBool()`, `GetIfInt()`, et cetera return `std::nullopt`/`nullptr` if
Daniel Chenga367fe52022-02-15 18:08:48606// the `Value` does not have the correct subtype; otherwise, returns the value
Arthur Sonzognie5fff99c2024-02-21 15:58:24607// wrapped in an `std::optional` (for `bool`, `int`, `double`) or by pointer
Daniel Chenga367fe52022-02-15 18:08:48608// (for binary blobs, `std::string`, `Value::Dict`, `Value::List`).
609//
610// Note: both `GetDouble()` and `GetIfDouble()` still return a non-null result
611// when the subtype is `Value::Type::INT`. In that case, the stored value is
612// coerced to a double before being returned.
613//
614// Assignment:
615//
616// It is not possible to directly assign `bool`, `int`, et cetera to a `Value`.
617// Instead, wrap the underlying type in `Value` before assigning.
618//
619// ## Dictionaries and Lists
620//
621// `Value` provides the `Value::Dict` and `Value::List` container types for
622// working with dictionaries and lists of values respectively, rather than
623// exposing the underlying container types directly. This allows the types to
624// provide convenient helpers for dictionaries and lists, as well as giving
625// greater flexibility for changing implementation details in the future.
626//
627// Both container types support enough STL-isms to be usable in range-based for
628// loops and generic operations such as those from <algorithm>.
629//
630// Dictionaries support:
631// - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
632// `contains()`, `clear()`, `erase()`: Identical to the STL container
633// equivalents, with additional safety checks, e.g. iterators will
634// `CHECK()` if `end()` is dereferenced.
635//
636// - `Clone()`: Create a deep copy.
637// - `Merge()`: Merge another dictionary into this dictionary.
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27638// - `Find()`: Find a value by `std::string_view` key, returning nullptr if the
639// key is not present.
Daniel Chenga367fe52022-02-15 18:08:48640// - `FindBool()`, `FindInt()`, ...: Similar to `Find()`, but ensures that the
641// `Value` also has the correct subtype. Same return semantics as
Arthur Sonzognie5fff99c2024-02-21 15:58:24642// `GetIfBool()`, `GetIfInt()`, et cetera, returning `std::nullopt` or
Daniel Chenga367fe52022-02-15 18:08:48643// `nullptr` if the key is not present or the value has the wrong subtype.
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27644// - `Set()`: Associate a value with a `std::string_view` key. Accepts `Value`
645// or any of the subtypes that `Value` can hold.
Daniel Chenga367fe52022-02-15 18:08:48646// - `Remove()`: Remove the key from this dictionary, if present.
647// - `Extract()`: If the key is present in the dictionary, removes the key from
648// the dictionary and transfers ownership of `Value` to the caller.
Arthur Sonzognie5fff99c2024-02-21 15:58:24649// Otherwise, returns `std::nullopt`.
Daniel Chenga367fe52022-02-15 18:08:48650//
651// Dictionaries also support an additional set of helper methods that operate on
652// "paths": `FindByDottedPath()`, `SetByDottedPath()`, `RemoveByDottedPath()`,
653// and `ExtractByDottedPath()`. Dotted paths are a convenience method of naming
654// intermediate nested dictionaries, separating the components of the path using
655// '.' characters. For example, finding a string path on a `Value::Dict` using
656// the dotted path:
657//
658// "aaa.bbb.ccc"
659//
660// Will first look for a `Value::Type::DICT` associated with the key "aaa", then
661// another `Value::Type::DICT` under the "aaa" dict associated with the
662// key "bbb", and then a `Value::Type::STRING` under the "bbb" dict associated
663// with the key "ccc".
664//
Daniel Cheng619653b2022-02-17 18:33:12665// If a path only has one component (i.e. has no dots), please use the regular,
666// non-path APIs.
667//
Daniel Chenga367fe52022-02-15 18:08:48668// Lists support:
669// - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
Nan Lin0e8148a2023-06-27 11:44:34670// `rbegin()`, `rend()`, `front()`, `back()`, `reserve()`, `operator[]`,
Peter Kastingb2517a1d2025-01-19 22:45:48671// `contains()`, `clear()`, `erase()`: Identical to the STL container
672// equivalents, with additional safety checks, e.g. `operator[]` will
673// `CHECK()` if the index is out of range.
Daniel Chenga367fe52022-02-15 18:08:48674// - `Clone()`: Create a deep copy.
675// - `Append()`: Append a value to the end of the list. Accepts `Value` or any
676// of the subtypes that `Value` can hold.
677// - `Insert()`: Insert a `Value` at a specified point in the list.
678// - `EraseValue()`: Erases all matching `Value`s from the list.
679// - `EraseIf()`: Erase all `Value`s matching an arbitrary predicate from the
680// list.
Daniel Cheng8ac305b2022-02-17 00:05:11681class BASE_EXPORT GSL_OWNER Value {
initial.commitd7cae122008-07-26 21:49:38682 public:
Andrew Paseltinerc4c65fe2025-03-07 19:01:01683 using BlobStorage = BlobStorage;
Daniel Cheng773ce4502022-01-28 15:25:06684
Andrew Paseltinerc4c65fe2025-03-07 19:01:01685 using Dict = DictValue;
686 using List = ListValue;
Daniel Chenga367fe52022-02-15 18:08:48687
Jose Dapena Paz7685422a2019-04-03 18:35:04688 enum class Type : unsigned char {
jdoerriedc72ee942016-12-07 15:43:28689 NONE = 0,
690 BOOLEAN,
691 INTEGER,
692 DOUBLE,
693 STRING,
694 BINARY,
Daniel Chenga367fe52022-02-15 18:08:48695 DICT,
jdoerriee1b1f3a2019-03-16 04:08:01696 LIST,
[email protected]2f03f532013-07-17 08:43:33697 // Note: Do not add more types. See the file-level comment above for why.
[email protected]a502bbe72011-01-07 18:06:45698 };
699
Lei Zhang30895d52017-10-23 19:14:46700 // Adaptors for converting from the old way to the new way and vice versa.
701 static Value FromUniquePtrValue(std::unique_ptr<Value> val);
702 static std::unique_ptr<Value> ToUniquePtrValue(Value val);
703
Jan Wilken Dörrie79d022142020-08-19 18:18:32704 Value() noexcept;
jdoerriecc9f5732017-08-23 14:12:30705
Daniel Chenga367fe52022-02-15 18:08:48706 Value(Value&&) noexcept;
707 Value& operator=(Value&&) noexcept;
jdoerriecc9f5732017-08-23 14:12:30708
Daniel Chenga367fe52022-02-15 18:08:48709 // Deleted to prevent accidental copying.
David Bienvenu5f4d4f02020-09-27 16:55:03710 Value(const Value&) = delete;
711 Value& operator=(const Value&) = delete;
jdoerrie05eb3162017-02-01 10:36:56712
Daniel Chenga367fe52022-02-15 18:08:48713 // Creates a deep copy of this value.
714 Value Clone() const;
715
716 // Creates a `Value` of `type`. The data of the corresponding type will be
717 // default constructed.
718 explicit Value(Type type);
719
720 // Constructor for `Value::Type::BOOLEAN`.
721 explicit Value(bool value);
722
723 // Prevent pointers from implicitly converting to bool. Another way to write
724 // this would be to template the bool constructor and use SFINAE to only allow
725 // use if `std::is_same_v<T, bool>` is true, but this has surprising behavior
726 // with range-based for loops over a `std::vector<bool>` (which will
727 // unintuitively match the int overload instead).
728 //
729 // The `const` is load-bearing; otherwise, a `char*` argument would prefer the
730 // deleted overload due to requiring a qualification conversion.
731 template <typename T>
732 explicit Value(const T*) = delete;
733
734 // Constructor for `Value::Type::INT`.
735 explicit Value(int value);
736
737 // Constructor for `Value::Type::DOUBLE`.
738 explicit Value(double value);
739
740 // Constructors for `Value::Type::STRING`.
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27741 explicit Value(std::string_view value);
742 explicit Value(std::u16string_view value);
Daniel Chenga367fe52022-02-15 18:08:48743 // `char*` and `char16_t*` are needed to provide a more specific overload than
744 // the deleted `const T*` overload above.
745 explicit Value(const char* value);
746 explicit Value(const char16_t* value);
747 // `std::string&&` allows for efficient move construction.
748 explicit Value(std::string&& value) noexcept;
749
750 // Constructors for `Value::Type::BINARY`.
751 explicit Value(const std::vector<char>& value);
752 explicit Value(base::span<const uint8_t> value);
753 explicit Value(BlobStorage&& value) noexcept;
754
755 // Constructor for `Value::Type::DICT`.
756 explicit Value(Dict&& value) noexcept;
757
758 // Constructor for `Value::Type::LIST`.
759 explicit Value(List&& value) noexcept;
760
jdoerrie8e945542017-02-17 13:54:49761 ~Value();
jdoerrie05eb3162017-02-01 10:36:56762
Gabriel Charetteb49d73a2021-05-05 20:05:59763 // Returns the name for a given `type`.
thestig61709242016-07-19 00:39:30764 static const char* GetTypeName(Type type);
765
initial.commitd7cae122008-07-26 21:49:38766 // Returns the type of the value stored by the current Value object.
Jan Wilken Dörrie79d022142020-08-19 18:18:32767 Type type() const { return static_cast<Type>(data_.index()); }
initial.commitd7cae122008-07-26 21:49:38768
769 // Returns true if the current object represents a given type.
jdoerriecc9f5732017-08-23 14:12:30770 bool is_none() const { return type() == Type::NONE; }
jdoerrie05eb3162017-02-01 10:36:56771 bool is_bool() const { return type() == Type::BOOLEAN; }
772 bool is_int() const { return type() == Type::INTEGER; }
773 bool is_double() const { return type() == Type::DOUBLE; }
774 bool is_string() const { return type() == Type::STRING; }
775 bool is_blob() const { return type() == Type::BINARY; }
Daniel Chenga367fe52022-02-15 18:08:48776 bool is_dict() const { return type() == Type::DICT; }
jdoerrie05eb3162017-02-01 10:36:56777 bool is_list() const { return type() == Type::LIST; }
778
Arthur Sonzognie5fff99c2024-02-21 15:58:24779 // Returns the stored data if the type matches, or `std::nullopt`/`nullptr`
Daniel Chenga367fe52022-02-15 18:08:48780 // otherwise. `bool`, `int`, and `double` are returned in a wrapped
Arthur Sonzognie5fff99c2024-02-21 15:58:24781 // `std::optional`; blobs, `Value::Dict`, and `Value::List` are returned by
Daniel Chenga367fe52022-02-15 18:08:48782 // pointer.
Arthur Sonzognie5fff99c2024-02-21 15:58:24783 std::optional<bool> GetIfBool() const;
784 std::optional<int> GetIfInt() const;
Daniel Chenga367fe52022-02-15 18:08:48785 // Returns a non-null value for both `Value::Type::DOUBLE` and
786 // `Value::Type::INT`, converting the latter to a double.
Arthur Sonzognie5fff99c2024-02-21 15:58:24787 std::optional<double> GetIfDouble() const;
Jan Wilken Dörrie2e125622021-02-17 10:52:53788 const std::string* GetIfString() const;
Daniel Chenga367fe52022-02-15 18:08:48789 std::string* GetIfString();
Jan Wilken Dörrie2e125622021-02-17 10:52:53790 const BlobStorage* GetIfBlob() const;
Matt Menked3af52e2024-09-11 16:04:43791 BlobStorage* GetIfBlob();
Daniel Chenga367fe52022-02-15 18:08:48792 const Dict* GetIfDict() const;
793 Dict* GetIfDict();
794 const List* GetIfList() const;
795 List* GetIfList();
Jan Wilken Dörrie2e125622021-02-17 10:52:53796
Daniel Chenga367fe52022-02-15 18:08:48797 // Similar to the `GetIf...()` variants above, but fails with a `CHECK()` on a
798 // type mismatch. `bool`, `int`, and `double` are returned by value; blobs,
799 // `Value::Dict`, and `Value::List` are returned by reference.
jdoerrie05eb3162017-02-01 10:36:56800 bool GetBool() const;
801 int GetInt() const;
Daniel Chenga367fe52022-02-15 18:08:48802 // Returns a value for both `Value::Type::DOUBLE` and `Value::Type::INT`,
803 // converting the latter to a double.
804 double GetDouble() const;
Tom Sepez1705e3f02024-10-25 01:39:18805 const std::string& GetString() const LIFETIME_BOUND;
806 std::string& GetString() LIFETIME_BOUND;
807 const BlobStorage& GetBlob() const LIFETIME_BOUND;
808 BlobStorage& GetBlob() LIFETIME_BOUND;
809 const Dict& GetDict() const LIFETIME_BOUND;
810 Dict& GetDict() LIFETIME_BOUND;
811 const List& GetList() const LIFETIME_BOUND;
812 List& GetList() LIFETIME_BOUND;
Daniel Chenga367fe52022-02-15 18:08:48813
Maksim Ivanov66545a242022-09-07 16:30:45814 // Transfers ownership of the underlying value. Similarly to `Get...()`
815 // variants above, fails with a `CHECK()` on a type mismatch. After
816 // transferring the ownership `*this` is in a valid, but unspecified, state.
Maksim Ivanovc502885e2022-09-09 21:01:42817 // Prefer over `std::move(value.Get...())` so clang-tidy can warn about
Maksim Ivanov66545a242022-09-07 16:30:45818 // potential use-after-move mistakes.
Maksim Ivanov9c17ed542022-09-22 21:23:33819 std::string TakeString() &&;
Matt Menked3af52e2024-09-11 16:04:43820 BlobStorage TakeBlob() &&;
Maksim Ivanovc502885e2022-09-09 21:01:42821 Dict TakeDict() &&;
Maksim Ivanov66545a242022-09-07 16:30:45822 List TakeList() &&;
823
Peter Kastingb2517a1d2025-01-19 22:45:48824
jdoerriee03e80f2017-02-15 08:42:14825
[email protected]2f03f532013-07-17 08:43:33826 // Note: Do not add more types. See the file-level comment above for why.
initial.commitd7cae122008-07-26 21:49:38827
jdoerrie5c1cee112017-03-28 17:52:00828 // Comparison operators so that Values can easily be used with standard
829 // library algorithms and associative containers.
Joe Mason3ce6ff72025-03-18 21:29:13830 friend bool operator==(const Value& lhs, const Value& rhs) = default;
831 friend auto operator<=>(const Value& lhs, const Value& rhs) = default;
jdoerrie5c1cee112017-03-28 17:52:00832
Joe Mason3ce6ff72025-03-18 21:29:13833 bool operator==(bool rhs) const;
Daniel Cheng6b621cf2022-06-02 02:42:02834 template <typename T>
Joe Mason3ce6ff72025-03-18 21:29:13835 bool operator==(const T* rhs) const = delete;
836 bool operator==(int rhs) const;
837 bool operator==(double rhs) const;
Helmut Januschka1dce9dc2024-06-11 13:05:35838 // Note: std::u16string_view overload intentionally omitted: Value internally
839 // stores strings as UTF-8. While it is possible to implement a comparison
840 // operator that would not require first creating a new UTF-8 string from the
841 // UTF-16 string argument, it is simpler to just not implement it at all for a
842 // rare use case.
Joe Mason3ce6ff72025-03-18 21:29:13843 bool operator==(std::string_view rhs) const;
844 bool operator==(const char* rhs) const {
845 return *this == std::string_view(rhs);
Daniel Cheng0b0b6752022-05-25 02:59:48846 }
Joe Mason3ce6ff72025-03-18 21:29:13847 bool operator==(const std::string& rhs) const {
848 return *this == std::string_view(rhs);
Daniel Cheng6b621cf2022-06-02 02:42:02849 }
Daniel Cheng0b0b6752022-05-25 02:59:48850 // Note: Blob support intentionally omitted as an experiment for potentially
851 // wholly removing Blob support from Value itself in the future.
Joe Mason3ce6ff72025-03-18 21:29:13852 bool operator==(const DictValue& rhs) const;
853 bool operator==(const ListValue& rhs) const;
Daniel Cheng0b0b6752022-05-25 02:59:48854
Etienne Pierre-doray4c826fa2025-06-04 19:10:58855 // Estimates dynamic memory usage. See
Eric Secklerf6c544f2020-06-02 10:49:21856 // base/trace_event/memory_usage_estimator.h for more info.
Alexander Yashkinab504e72017-11-30 11:54:45857 size_t EstimateMemoryUsage() const;
858
Alan Cutter2dd83032020-12-08 21:55:00859 // Serializes to a string for logging and debug purposes.
860 std::string DebugString() const;
861
Alexander Timine68aeb32021-04-11 23:06:21862 // Write this object into a trace.
Alexander Timinbebb2002021-04-20 15:42:24863 void WriteIntoTrace(perfetto::TracedValue) const;
Alexander Timine68aeb32021-04-11 23:06:21864
Daniel Cheng8ac305b2022-02-17 00:05:11865 template <typename Visitor>
866 auto Visit(Visitor&& visitor) const {
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:34867 return std::visit(std::forward<Visitor>(visitor), data_);
Daniel Cheng8ac305b2022-02-17 00:05:11868 }
869
Jan Wilken Dörrie79d022142020-08-19 18:18:32870 private:
Daniel Cheng8ac305b2022-02-17 00:05:11871 // For access to DoubleStorage.
872 friend class ValueView;
873
David 'Digit' Turner2f287312019-04-03 14:32:09874 // Special case for doubles, which are aligned to 8 bytes on some
875 // 32-bit architectures. In this case, a simple declaration as a
876 // double member would make the whole union 8 byte-aligned, which
877 // would also force 4 bytes of wasted padding space before it in
878 // the Value layout.
David 'Digit' Turner806dedb82019-03-06 17:43:11879 //
David 'Digit' Turner2f287312019-04-03 14:32:09880 // To override this, store the value as an array of 32-bit integers, and
881 // perform the appropriate bit casts when reading / writing to it.
Daniel Cheng6b621cf2022-06-02 02:42:02882 class BASE_EXPORT DoubleStorage {
Daniel Cheng782d2ba32022-02-16 19:40:29883 public:
884 explicit DoubleStorage(double v);
885 DoubleStorage(const DoubleStorage&) = default;
886 DoubleStorage& operator=(const DoubleStorage&) = default;
887
Daniel Cheng8ac305b2022-02-17 00:05:11888 // Provide an implicit conversion to double to simplify the use of visitors
889 // with `Value::Visit()`. Otherwise, visitors would need a branch for
890 // handling `DoubleStorage` like:
891 //
892 // value.Visit([] (const auto& member) {
893 // using T = std::decay_t<decltype(member)>;
894 // if constexpr (std::is_same_v<T, Value::DoubleStorage>) {
895 // SomeFunction(double{member});
896 // } else {
897 // SomeFunction(member);
898 // }
899 // });
Peter Kastingcc88ac052022-05-03 09:58:01900 operator double() const { return base::bit_cast<double>(v_); }
Daniel Cheng782d2ba32022-02-16 19:40:29901
902 private:
903 friend bool operator==(const DoubleStorage& lhs, const DoubleStorage& rhs) {
Daniel Cheng8ac305b2022-02-17 00:05:11904 return double{lhs} == double{rhs};
Daniel Cheng782d2ba32022-02-16 19:40:29905 }
906
Joe Mason3ce6ff72025-03-18 21:29:13907 // doubles are partially ordered because NaN is unordered, so anything that
908 // can contain a DoubleStorage (ie. Value, List or Dict) must also use
909 // partial_ordering. `auto` will deduce this correctly but manually written
910 // operators will get cryptic compiler errors if the wrong ordering is
911 // chosen. The return type is specified explicitly here to document where
912 // the requirement comes from.
913 friend std::partial_ordering operator<=>(const DoubleStorage& lhs,
914 const DoubleStorage& rhs) {
915 return double{lhs} <=> double{rhs};
Daniel Cheng782d2ba32022-02-16 19:40:29916 }
917
918 alignas(4) std::array<char, sizeof(double)> v_;
919 };
David 'Digit' Turner2f287312019-04-03 14:32:09920
Jan Wilken Dörrie79d022142020-08-19 18:18:32921 // Internal constructors, allowing the simplify the implementation of Clone().
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:34922 explicit Value(std::monostate);
Jan Wilken Dörrie79d022142020-08-19 18:18:32923 explicit Value(DoubleStorage storage);
jdoerrie8e945542017-02-17 13:54:49924
Claudio DeSouzab8754a3e2022-07-25 18:08:45925 // A helper for static functions used for cloning a Value or a ValueView.
926 class CloningHelper;
927
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:34928 std::variant<std::monostate,
929 bool,
930 int,
931 DoubleStorage,
932 std::string,
933 BlobStorage,
934 Dict,
935 List>
Jan Wilken Dörrie79d022142020-08-19 18:18:32936 data_;
initial.commitd7cae122008-07-26 21:49:38937};
938
Daniel Cheng8ac305b2022-02-17 00:05:11939// Adapter so `Value::Dict` or `Value::List` can be directly passed to JSON
940// serialization methods without having to clone the contents and transfer
941// ownership of the clone to a `Value` wrapper object.
942//
Helmut Januschka1dce9dc2024-06-11 13:05:35943// Like `std::string_view` and `span<T>`, this adapter does NOT retain
944// ownership. Any underlying object that is passed by reference (i.e.
945// `std::string`, `Value::BlobStorage`, `Value::Dict`, `Value::List`, or
946// `Value`) MUST remain live as long as there is a `ValueView` referencing it.
Daniel Cheng8ac305b2022-02-17 00:05:11947//
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:34948// While it might be nice to just use the `std::variant` type directly, the
949// need to use `std::reference_wrapper` makes it clunky. `std::variant` and
Daniel Cheng8ac305b2022-02-17 00:05:11950// `std::reference_wrapper` both support implicit construction, but C++ only
951// allows at most one user-defined conversion in an implicit conversion
952// sequence. If this adapter and its implicit constructors did not exist,
953// callers would need to use `std::ref` or `std::cref` to pass `Value::Dict` or
954// `Value::List` to a function with a `ValueView` parameter.
955class BASE_EXPORT GSL_POINTER ValueView {
956 public:
Daniel Cheng6b621cf2022-06-02 02:42:02957 ValueView() = default;
Daniel Cheng8ac305b2022-02-17 00:05:11958 ValueView(bool value) : data_view_(value) {}
Daniel Cheng6b621cf2022-06-02 02:42:02959 template <typename T>
960 ValueView(const T*) = delete;
Daniel Cheng8ac305b2022-02-17 00:05:11961 ValueView(int value) : data_view_(value) {}
962 ValueView(double value)
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:34963 : data_view_(std::in_place_type_t<Value::DoubleStorage>(), value) {}
Aquibuzzaman Md. Sayem42abceb72024-05-08 18:48:27964 ValueView(std::string_view value) : data_view_(value) {}
965 ValueView(const char* value) : ValueView(std::string_view(value)) {}
966 ValueView(const std::string& value) : ValueView(std::string_view(value)) {}
Daniel Cheng6b621cf2022-06-02 02:42:02967 // Note: UTF-16 is intentionally not supported. ValueView is intended to be a
968 // low-cost view abstraction, but Value internally represents strings as
969 // UTF-8, so it would not be possible to implement this without allocating an
970 // entirely new UTF-8 string.
Daniel Cheng8ac305b2022-02-17 00:05:11971 ValueView(const Value::BlobStorage& value) : data_view_(value) {}
972 ValueView(const Value::Dict& value) : data_view_(value) {}
973 ValueView(const Value::List& value) : data_view_(value) {}
974 ValueView(const Value& value);
975
Daniel Cheng6b621cf2022-06-02 02:42:02976 // This is the only 'getter' method provided as `ValueView` is not intended
977 // to be a general replacement of `Value`.
Daniel Cheng8ac305b2022-02-17 00:05:11978 template <typename Visitor>
979 auto Visit(Visitor&& visitor) const {
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:34980 return std::visit(std::forward<Visitor>(visitor), data_view_);
Daniel Cheng8ac305b2022-02-17 00:05:11981 }
982
Claudio DeSouza75d1f3412022-07-22 21:06:42983 // Returns a clone of the underlying Value.
984 Value ToValue() const;
985
Daniel Cheng8ac305b2022-02-17 00:05:11986 private:
987 using ViewType =
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:34988 std::variant<std::monostate,
989 bool,
990 int,
991 Value::DoubleStorage,
992 std::string_view,
993 std::reference_wrapper<const Value::BlobStorage>,
994 std::reference_wrapper<const Value::Dict>,
995 std::reference_wrapper<const Value::List>>;
Daniel Cheng8ac305b2022-02-17 00:05:11996
Daniel Cheng6b621cf2022-06-02 02:42:02997 public:
998 using DoubleStorageForTest = Value::DoubleStorage;
999 const ViewType& data_view_for_test() const { return data_view_; }
1000
1001 private:
Daniel Cheng8ac305b2022-02-17 00:05:111002 ViewType data_view_;
1003};
1004
prashhir54a994502015-03-05 09:30:571005// This interface is implemented by classes that know how to serialize
1006// Value objects.
[email protected]0bea7252011-08-05 15:34:001007class BASE_EXPORT ValueSerializer {
initial.commitd7cae122008-07-26 21:49:381008 public:
[email protected]3a3d47472010-07-15 21:03:541009 virtual ~ValueSerializer();
[email protected]abb9d0c2008-08-06 15:46:591010
Daniel Cheng8ac305b2022-02-17 00:05:111011 virtual bool Serialize(ValueView root) = 0;
prashhir54a994502015-03-05 09:30:571012};
1013
1014// This interface is implemented by classes that know how to deserialize Value
1015// objects.
1016class BASE_EXPORT ValueDeserializer {
1017 public:
1018 virtual ~ValueDeserializer();
initial.commitd7cae122008-07-26 21:49:381019
1020 // This method deserializes the subclass-specific format into a Value object.
[email protected]b4cebf82008-12-29 19:59:081021 // If the return value is non-NULL, the caller takes ownership of returned
Nigel Tao410788e2020-06-24 07:12:271022 // Value.
1023 //
Gabriel Charetteb49d73a2021-05-05 20:05:591024 // If the return value is nullptr, and if `error_code` is non-nullptr,
1025 // `*error_code` will be set to an integer value representing the underlying
Nigel Tao410788e2020-06-24 07:12:271026 // error. See "enum ErrorCode" below for more detail about the integer value.
1027 //
Gabriel Charetteb49d73a2021-05-05 20:05:591028 // If `error_message` is non-nullptr, it will be filled in with a formatted
[email protected]ba399672010-04-06 15:42:391029 // error message including the location of the error if appropriate.
dcheng093de9b2016-04-04 21:25:511030 virtual std::unique_ptr<Value> Deserialize(int* error_code,
Nigel Tao410788e2020-06-24 07:12:271031 std::string* error_message) = 0;
1032
1033 // The integer-valued error codes form four groups:
1034 // - The value 0 means no error.
1035 // - Values between 1 and 999 inclusive mean an error in the data (i.e.
1036 // content). The bytes being deserialized are not in the right format.
1037 // - Values 1000 and above mean an error in the metadata (i.e. context). The
1038 // file could not be read, the network is down, etc.
1039 // - Negative values are reserved.
Caitlin Fischeraac06dc2021-12-17 00:21:321040 //
1041 // These values are persisted to logs. Entries should not be renumbered and
1042 // numeric values should never be reused.
Nigel Tao410788e2020-06-24 07:12:271043 enum ErrorCode {
1044 kErrorCodeNoError = 0,
1045 // kErrorCodeInvalidFormat is a generic error code for "the data is not in
1046 // the right format". Subclasses of ValueDeserializer may return other
1047 // values for more specific errors.
1048 kErrorCodeInvalidFormat = 1,
1049 // kErrorCodeFirstMetadataError is the minimum value (inclusive) of the
1050 // range of metadata errors.
1051 kErrorCodeFirstMetadataError = 1000,
1052 };
1053
Gabriel Charetteb49d73a2021-05-05 20:05:591054 // The `error_code` argument can be one of the ErrorCode values, but it is
Nigel Tao410788e2020-06-24 07:12:271055 // not restricted to only being 0, 1 or 1000. Subclasses of ValueDeserializer
1056 // can define their own error code values.
1057 static inline bool ErrorCodeIsDataError(int error_code) {
1058 return (kErrorCodeInvalidFormat <= error_code) &&
1059 (error_code < kErrorCodeFirstMetadataError);
1060 }
initial.commitd7cae122008-07-26 21:49:381061};
1062
Daniel Chenga367fe52022-02-15 18:08:481063// Stream operator so Values can be pretty printed by gtest.
[email protected]e4ef8312012-09-12 03:39:351064BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value);
Daniel Chenga367fe52022-02-15 18:08:481065BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1066 const Value::Dict& dict);
1067BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1068 const Value::List& list);
[email protected]e4ef8312012-09-12 03:39:351069
jdoerriedc72ee942016-12-07 15:43:281070// Stream operator so that enum class Types can be used in log statements.
1071BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1072 const Value::Type& type);
1073
Andrew Paseltinerc4c65fe2025-03-07 19:01:011074template <typename T, typename R>
1075 requires std::equality_comparable_with<T, R>
1076bool ListValue::contains(const T& val,
1077 bool (Value::*test)() const,
1078 R (Value::*get)() const) const {
1079 return std::ranges::any_of(storage_, [&](const Value& value) {
1080 return (value.*test)() && (value.*get)() == val;
1081 });
1082}
1083
Daniel Chengc46e4d02025-06-24 18:41:281084template <class IteratorType>
1085DictValue::DictValue(std::move_iterator<IteratorType> first,
1086 std::move_iterator<IteratorType> last) {
1087 // Need to move into a vector first, since `storage_` currently uses
1088 // unique_ptrs.
1089 std::vector<std::pair<std::string, std::unique_ptr<Value>>> values;
Alex Kalugind81a2eb02025-06-27 04:32:401090 values.reserve(static_cast<size_t>(std::distance(first, last)));
Daniel Chengc46e4d02025-06-24 18:41:281091 for (auto current = first; current != last; ++current) {
1092 // With move iterators, no need to call Clone(), but do need to move
1093 // to a temporary first, as accessing either field individually will
1094 // directly from the iterator will delete the other field.
1095 auto value = *current;
1096 values.emplace_back(std::move(value.first),
1097 std::make_unique<Value>(std::move(value.second)));
1098 }
1099 storage_ = flat_map<std::string, std::unique_ptr<Value>>(std::move(values));
1100}
1101
[email protected]f3a1c642011-07-12 19:15:031102} // namespace base
1103
[email protected]101d5422008-09-26 20:22:421104#endif // BASE_VALUES_H_