[go: nahoru, domu]

blob: a6c27642a6b8eef9cdfc8c1ce70a091fe826f3d2 [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
darin@chromium.org101d5422008-09-26 20:22:425#ifndef BASE_VALUES_H_
6#define BASE_VALUES_H_
initial.commitd7cae122008-07-26 21:49:387
mostynb@opera.comc014f2b32013-09-03 23:29:128#include <stddef.h>
avi9b6f42932015-12-26 22:15:149#include <stdint.h>
mostynb@opera.comc014f2b32013-09-03 23:29:1210
Daniel Cheng782d2ba32022-02-16 19:40:2911#include <array>
Lei Zhang935738a2021-05-17 21:35:5312#include <initializer_list>
mostynb@opera.comc014f2b32013-09-03 23:29:1213#include <iosfwd>
Matt Menkee311c6d2022-06-14 20:17:3914#include <iterator>
dcheng093de9b2016-04-04 21:25:5115#include <memory>
nsylvain@chromium.org8e50b602009-03-03 22:59:4316#include <string>
mostynb@opera.comc014f2b32013-09-03 23:29:1217#include <utility>
initial.commitd7cae122008-07-26 21:49:3818#include <vector>
19
darin@chromium.org0bea7252011-08-05 15:34:0020#include "base/base_export.h"
Daniel Cheng782d2ba32022-02-16 19:40:2921#include "base/bit_cast.h"
Daniel Cheng8ac305b2022-02-17 00:05:1122#include "base/compiler_specific.h"
Jan Wilken Dörrie7e7a9792019-10-15 14:42:0523#include "base/containers/checked_iterators.h"
Lei Zhanga1209af2021-06-26 03:26:2424#include "base/containers/cxx20_erase_vector.h"
mkwstcd8067b2017-04-11 06:52:2125#include "base/containers/flat_map.h"
jdoerriecd022242017-08-23 08:38:2726#include "base/containers/span.h"
Ali Hijazia8877892022-11-10 20:51:0327#include "base/memory/raw_ref.h"
asvitkinedbd26533e2015-06-23 18:22:5228#include "base/strings/string_piece.h"
Alexander Timine68aeb32021-04-11 23:06:2129#include "base/trace_event/base_tracing_forward.h"
jdoerrie44efa9d2017-07-14 14:47:2030#include "base/value_iterators.h"
Anton Bikineev7dd58ad2021-05-18 01:01:3931#include "third_party/abseil-cpp/absl/types/optional.h"
Jan Wilken Dörrie79d022142020-08-19 18:18:3232#include "third_party/abseil-cpp/absl/types/variant.h"
initial.commitd7cae122008-07-26 21:49:3833
dmazzoni@chromium.orgf3a1c642011-07-12 19:15:0334namespace base {
35
Daniel Chenga367fe52022-02-15 18:08:4836// The `Value` class is a variant type can hold one of the following types:
37// - null
38// - bool
39// - int
40// - double
41// - string (internally UTF8-encoded)
42// - binary data (i.e. a blob)
43// - dictionary of string keys to `Value`s
44// - list of `Value`s
brettw@chromium.org2f03f532013-07-17 08:43:3345//
Daniel Chenga367fe52022-02-15 18:08:4846// With the exception of binary blobs, `Value` is intended to be the C++ version
47// of data types that can be represented in JSON.
Brett Wilson4bef8ee2017-09-01 20:11:4948//
Daniel Chenga367fe52022-02-15 18:08:4849// Warning: blob support may be removed in the future.
50//
51// ## Usage
52//
53// Do not use `Value` if a more specific type would be more appropriate. For
54// example, a function that only accepts dictionary values should have a
55// `base::Value::Dict` parameter, not a `base::Value` parameter.
56//
57// Construction:
58//
59// `Value` is directly constructible from `bool`, `int`, `double`, binary blobs
60// (`std::vector<uint8_t>`), `base::StringPiece`, `base::StringPiece16`,
61// `Value::Dict`, and `Value::List`.
62//
63// Copying:
64//
65// `Value` does not support C++ copy semantics to make it harder to accidentally
66// copy large values. Instead, use `Clone()` to manually create a deep copy.
67//
68// Reading:
69//
70// `GetBool()`, GetInt()`, et cetera `CHECK()` that the `Value` has the correct
71// subtype before returning the contained value. `bool`, `int`, `double` are
72// returned by value. Binary blobs, `std::string`, `Value::Dict`, `Value::List`
73// are returned by reference.
74//
75// `GetIfBool()`, `GetIfInt()`, et cetera return `absl::nullopt`/`nullptr` if
76// the `Value` does not have the correct subtype; otherwise, returns the value
77// wrapped in an `absl::optional` (for `bool`, `int`, `double`) or by pointer
78// (for binary blobs, `std::string`, `Value::Dict`, `Value::List`).
79//
80// Note: both `GetDouble()` and `GetIfDouble()` still return a non-null result
81// when the subtype is `Value::Type::INT`. In that case, the stored value is
82// coerced to a double before being returned.
83//
84// Assignment:
85//
86// It is not possible to directly assign `bool`, `int`, et cetera to a `Value`.
87// Instead, wrap the underlying type in `Value` before assigning.
88//
89// ## Dictionaries and Lists
90//
91// `Value` provides the `Value::Dict` and `Value::List` container types for
92// working with dictionaries and lists of values respectively, rather than
93// exposing the underlying container types directly. This allows the types to
94// provide convenient helpers for dictionaries and lists, as well as giving
95// greater flexibility for changing implementation details in the future.
96//
97// Both container types support enough STL-isms to be usable in range-based for
98// loops and generic operations such as those from <algorithm>.
99//
100// Dictionaries support:
101// - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
102// `contains()`, `clear()`, `erase()`: Identical to the STL container
103// equivalents, with additional safety checks, e.g. iterators will
104// `CHECK()` if `end()` is dereferenced.
105//
106// - `Clone()`: Create a deep copy.
107// - `Merge()`: Merge another dictionary into this dictionary.
108// - `Find()`: Find a value by `StringPiece` key, returning nullptr if the key
109// is not present.
110// - `FindBool()`, `FindInt()`, ...: Similar to `Find()`, but ensures that the
111// `Value` also has the correct subtype. Same return semantics as
112// `GetIfBool()`, `GetIfInt()`, et cetera, returning `absl::nullopt` or
113// `nullptr` if the key is not present or the value has the wrong subtype.
114// - `Set()`: Associate a value with a `StringPiece` key. Accepts `Value` or any
115// of the subtypes that `Value` can hold.
116// - `Remove()`: Remove the key from this dictionary, if present.
117// - `Extract()`: If the key is present in the dictionary, removes the key from
118// the dictionary and transfers ownership of `Value` to the caller.
119// Otherwise, returns `absl::nullopt`.
120//
121// Dictionaries also support an additional set of helper methods that operate on
122// "paths": `FindByDottedPath()`, `SetByDottedPath()`, `RemoveByDottedPath()`,
123// and `ExtractByDottedPath()`. Dotted paths are a convenience method of naming
124// intermediate nested dictionaries, separating the components of the path using
125// '.' characters. For example, finding a string path on a `Value::Dict` using
126// the dotted path:
127//
128// "aaa.bbb.ccc"
129//
130// Will first look for a `Value::Type::DICT` associated with the key "aaa", then
131// another `Value::Type::DICT` under the "aaa" dict associated with the
132// key "bbb", and then a `Value::Type::STRING` under the "bbb" dict associated
133// with the key "ccc".
134//
Daniel Cheng619653b2022-02-17 18:33:12135// If a path only has one component (i.e. has no dots), please use the regular,
136// non-path APIs.
137//
Daniel Chenga367fe52022-02-15 18:08:48138// Lists support:
139// - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`,
Nan Lin0e8148a2023-06-27 11:44:34140// `rbegin()`, `rend()`, `front()`, `back()`, `reserve()`, `operator[]`,
141// `clear()`, `erase()`: Identical to the STL container equivalents, with
142// additional safety checks, e.g. `operator[]` will `CHECK()` if the index
143// is out of range.
Daniel Chenga367fe52022-02-15 18:08:48144// - `Clone()`: Create a deep copy.
145// - `Append()`: Append a value to the end of the list. Accepts `Value` or any
146// of the subtypes that `Value` can hold.
147// - `Insert()`: Insert a `Value` at a specified point in the list.
148// - `EraseValue()`: Erases all matching `Value`s from the list.
149// - `EraseIf()`: Erase all `Value`s matching an arbitrary predicate from the
150// list.
Daniel Cheng8ac305b2022-02-17 00:05:11151class BASE_EXPORT GSL_OWNER Value {
initial.commitd7cae122008-07-26 21:49:38152 public:
jdoerrie9970f20e2018-07-20 21:41:18153 using BlobStorage = std::vector<uint8_t>;
Daniel Cheng773ce452022-01-28 15:25:06154
Daniel Chenga367fe52022-02-15 18:08:48155 class Dict;
156 class List;
157
Jose Dapena Paz7685422a2019-04-03 18:35:04158 enum class Type : unsigned char {
jdoerriedc72ee942016-12-07 15:43:28159 NONE = 0,
160 BOOLEAN,
161 INTEGER,
162 DOUBLE,
163 STRING,
164 BINARY,
Daniel Chenga367fe52022-02-15 18:08:48165 DICT,
jdoerriee1b1f3a2019-03-16 04:08:01166 LIST,
brettw@chromium.org2f03f532013-07-17 08:43:33167 // Note: Do not add more types. See the file-level comment above for why.
erg@google.coma502bbe72011-01-07 18:06:45168 };
169
Lei Zhang30895d52017-10-23 19:14:46170 // Adaptors for converting from the old way to the new way and vice versa.
171 static Value FromUniquePtrValue(std::unique_ptr<Value> val);
172 static std::unique_ptr<Value> ToUniquePtrValue(Value val);
173
Jan Wilken Dörrie79d022142020-08-19 18:18:32174 Value() noexcept;
jdoerriecc9f5732017-08-23 14:12:30175
Daniel Chenga367fe52022-02-15 18:08:48176 Value(Value&&) noexcept;
177 Value& operator=(Value&&) noexcept;
jdoerriecc9f5732017-08-23 14:12:30178
Daniel Chenga367fe52022-02-15 18:08:48179 // Deleted to prevent accidental copying.
David Bienvenu5f4d4f02020-09-27 16:55:03180 Value(const Value&) = delete;
181 Value& operator=(const Value&) = delete;
jdoerrie05eb3162017-02-01 10:36:56182
Daniel Chenga367fe52022-02-15 18:08:48183 // Creates a deep copy of this value.
184 Value Clone() const;
185
186 // Creates a `Value` of `type`. The data of the corresponding type will be
187 // default constructed.
188 explicit Value(Type type);
189
190 // Constructor for `Value::Type::BOOLEAN`.
191 explicit Value(bool value);
192
193 // Prevent pointers from implicitly converting to bool. Another way to write
194 // this would be to template the bool constructor and use SFINAE to only allow
195 // use if `std::is_same_v<T, bool>` is true, but this has surprising behavior
196 // with range-based for loops over a `std::vector<bool>` (which will
197 // unintuitively match the int overload instead).
198 //
199 // The `const` is load-bearing; otherwise, a `char*` argument would prefer the
200 // deleted overload due to requiring a qualification conversion.
201 template <typename T>
202 explicit Value(const T*) = delete;
203
204 // Constructor for `Value::Type::INT`.
205 explicit Value(int value);
206
207 // Constructor for `Value::Type::DOUBLE`.
208 explicit Value(double value);
209
210 // Constructors for `Value::Type::STRING`.
211 explicit Value(StringPiece value);
212 explicit Value(StringPiece16 value);
213 // `char*` and `char16_t*` are needed to provide a more specific overload than
214 // the deleted `const T*` overload above.
215 explicit Value(const char* value);
216 explicit Value(const char16_t* value);
217 // `std::string&&` allows for efficient move construction.
218 explicit Value(std::string&& value) noexcept;
219
220 // Constructors for `Value::Type::BINARY`.
221 explicit Value(const std::vector<char>& value);
222 explicit Value(base::span<const uint8_t> value);
223 explicit Value(BlobStorage&& value) noexcept;
224
225 // Constructor for `Value::Type::DICT`.
226 explicit Value(Dict&& value) noexcept;
227
228 // Constructor for `Value::Type::LIST`.
229 explicit Value(List&& value) noexcept;
230
jdoerrie8e945542017-02-17 13:54:49231 ~Value();
jdoerrie05eb3162017-02-01 10:36:56232
Gabriel Charetteb49d73a2021-05-05 20:05:59233 // Returns the name for a given `type`.
thestig61709242016-07-19 00:39:30234 static const char* GetTypeName(Type type);
235
initial.commitd7cae122008-07-26 21:49:38236 // Returns the type of the value stored by the current Value object.
Jan Wilken Dörrie79d022142020-08-19 18:18:32237 Type type() const { return static_cast<Type>(data_.index()); }
initial.commitd7cae122008-07-26 21:49:38238
239 // Returns true if the current object represents a given type.
jdoerriecc9f5732017-08-23 14:12:30240 bool is_none() const { return type() == Type::NONE; }
jdoerrie05eb3162017-02-01 10:36:56241 bool is_bool() const { return type() == Type::BOOLEAN; }
242 bool is_int() const { return type() == Type::INTEGER; }
243 bool is_double() const { return type() == Type::DOUBLE; }
244 bool is_string() const { return type() == Type::STRING; }
245 bool is_blob() const { return type() == Type::BINARY; }
Daniel Chenga367fe52022-02-15 18:08:48246 bool is_dict() const { return type() == Type::DICT; }
jdoerrie05eb3162017-02-01 10:36:56247 bool is_list() const { return type() == Type::LIST; }
248
Daniel Chenga367fe52022-02-15 18:08:48249 // Returns the stored data if the type matches, or `absl::nullopt`/`nullptr`
250 // otherwise. `bool`, `int`, and `double` are returned in a wrapped
251 // `absl::optional`; blobs, `Value::Dict`, and `Value::List` are returned by
252 // pointer.
Anton Bikineev7dd58ad2021-05-18 01:01:39253 absl::optional<bool> GetIfBool() const;
254 absl::optional<int> GetIfInt() const;
Daniel Chenga367fe52022-02-15 18:08:48255 // Returns a non-null value for both `Value::Type::DOUBLE` and
256 // `Value::Type::INT`, converting the latter to a double.
Anton Bikineev7dd58ad2021-05-18 01:01:39257 absl::optional<double> GetIfDouble() const;
Jan Wilken Dörrie2e125622021-02-17 10:52:53258 const std::string* GetIfString() const;
Daniel Chenga367fe52022-02-15 18:08:48259 std::string* GetIfString();
Jan Wilken Dörrie2e125622021-02-17 10:52:53260 const BlobStorage* GetIfBlob() const;
Daniel Chenga367fe52022-02-15 18:08:48261 const Dict* GetIfDict() const;
262 Dict* GetIfDict();
263 const List* GetIfList() const;
264 List* GetIfList();
Jan Wilken Dörrie2e125622021-02-17 10:52:53265
Daniel Chenga367fe52022-02-15 18:08:48266 // Similar to the `GetIf...()` variants above, but fails with a `CHECK()` on a
267 // type mismatch. `bool`, `int`, and `double` are returned by value; blobs,
268 // `Value::Dict`, and `Value::List` are returned by reference.
jdoerrie05eb3162017-02-01 10:36:56269 bool GetBool() const;
270 int GetInt() const;
Daniel Chenga367fe52022-02-15 18:08:48271 // Returns a value for both `Value::Type::DOUBLE` and `Value::Type::INT`,
272 // converting the latter to a double.
273 double GetDouble() const;
jdoerrief38f37b2017-02-01 14:38:32274 const std::string& GetString() const;
Dominic Battre08cbe972019-07-31 03:57:19275 std::string& GetString();
jdoerrie5f12b6272017-04-18 10:22:41276 const BlobStorage& GetBlob() const;
Daniel Chenga367fe52022-02-15 18:08:48277 const Dict& GetDict() const;
278 Dict& GetDict();
279 const List& GetList() const;
280 List& GetList();
281
Maksim Ivanov66545a242022-09-07 16:30:45282 // Transfers ownership of the underlying value. Similarly to `Get...()`
283 // variants above, fails with a `CHECK()` on a type mismatch. After
284 // transferring the ownership `*this` is in a valid, but unspecified, state.
Maksim Ivanovc502885e2022-09-09 21:01:42285 // Prefer over `std::move(value.Get...())` so clang-tidy can warn about
Maksim Ivanov66545a242022-09-07 16:30:45286 // potential use-after-move mistakes.
Maksim Ivanov9c17ed542022-09-22 21:23:33287 std::string TakeString() &&;
Maksim Ivanovc502885e2022-09-09 21:01:42288 Dict TakeDict() &&;
Maksim Ivanov66545a242022-09-07 16:30:45289 List TakeList() &&;
290
Daniel Chenga367fe52022-02-15 18:08:48291 // Represents a dictionary of string keys to Values.
Daniel Cheng8ac305b2022-02-17 00:05:11292 class BASE_EXPORT GSL_OWNER Dict {
Daniel Chenga367fe52022-02-15 18:08:48293 public:
294 using iterator = detail::dict_iterator;
295 using const_iterator = detail::const_dict_iterator;
296
297 Dict();
298
299 Dict(Dict&&) noexcept;
300 Dict& operator=(Dict&&) noexcept;
301
302 // Deleted to prevent accidental copying.
303 Dict(const Dict&) = delete;
304 Dict& operator=(const Dict&) = delete;
305
Matt Menkee311c6d2022-06-14 20:17:39306 // Takes move_iterators iterators that return std::pair<std::string, Value>,
307 // and moves their values into a new Dict. Adding all entries at once
308 // results in a faster initial sort operation. Takes move iterators to avoid
309 // having to clone the input.
310 template <class IteratorType>
311 explicit Dict(std::move_iterator<IteratorType> first,
312 std::move_iterator<IteratorType> last) {
313 // Need to move into a vector first, since `storage_` currently uses
314 // unique_ptrs.
315 std::vector<std::pair<std::string, std::unique_ptr<Value>>> values;
316 for (auto current = first; current != last; ++current) {
317 // With move iterators, no need to call Clone(), but do need to move
318 // to a temporary first, as accessing either field individually will
319 // directly from the iterator will delete the other field.
320 auto value = *current;
321 values.emplace_back(std::move(value.first),
322 std::make_unique<Value>(std::move(value.second)));
323 }
324 storage_ =
325 flat_map<std::string, std::unique_ptr<Value>>(std::move(values));
326 }
327
Daniel Chenga367fe52022-02-15 18:08:48328 ~Dict();
329
Daniel Chenga367fe52022-02-15 18:08:48330 // Returns true if there are no entries in this dictionary and false
331 // otherwise.
332 bool empty() const;
333
334 // Returns the number of entries in this dictionary.
335 size_t size() const;
336
337 // Returns an iterator to the first entry in this dictionary.
338 iterator begin();
339 const_iterator begin() const;
340 const_iterator cbegin() const;
341
342 // Returns an iterator following the last entry in this dictionary. May not
343 // be dereferenced.
344 iterator end();
345 const_iterator end() const;
346 const_iterator cend() const;
347
348 // Returns true if `key` is an entry in this dictionary.
349 bool contains(base::StringPiece key) const;
350
351 // Removes all entries from this dictionary.
Marijn Kruisselbrink8af7d722022-12-13 19:03:42352 REINITIALIZES_AFTER_MOVE void clear();
Daniel Chenga367fe52022-02-15 18:08:48353
354 // Removes the entry referenced by `pos` in this dictionary and returns an
355 // iterator to the entry following the removed entry.
356 iterator erase(iterator pos);
357 iterator erase(const_iterator pos);
358
359 // Creates a deep copy of this dictionary.
360 Dict Clone() const;
361
362 // Merges the entries from `dict` into this dictionary. If an entry with the
363 // same key exists in this dictionary and `dict`:
364 // - if both entries are dictionaries, they will be recursively merged
365 // - otherwise, the already-existing entry in this dictionary will be
366 // overwritten with the entry from `dict`.
Daniel Cheng1cdf99782022-06-29 19:25:58367 void Merge(Dict dict);
Daniel Chenga367fe52022-02-15 18:08:48368
369 // Finds the entry corresponding to `key` in this dictionary. Returns
370 // nullptr if there is no such entry.
371 const Value* Find(StringPiece key) const;
372 Value* Find(StringPiece key);
373
374 // Similar to `Find()` above, but returns `absl::nullopt`/`nullptr` if the
375 // type of the entry does not match. `bool`, `int`, and `double` are
376 // returned in a wrapped `absl::optional`; blobs, `Value::Dict`, and
377 // `Value::List` are returned by pointer.
378 absl::optional<bool> FindBool(StringPiece key) const;
379 absl::optional<int> FindInt(StringPiece key) const;
380 // Returns a non-null value for both `Value::Type::DOUBLE` and
381 // `Value::Type::INT`, converting the latter to a double.
382 absl::optional<double> FindDouble(StringPiece key) const;
383 const std::string* FindString(StringPiece key) const;
384 std::string* FindString(StringPiece key);
385 const BlobStorage* FindBlob(StringPiece key) const;
386 const Dict* FindDict(StringPiece key) const;
387 Dict* FindDict(StringPiece key);
388 const List* FindList(StringPiece key) const;
389 List* FindList(StringPiece key);
390
Matt Menkef8f453e2022-08-09 17:52:02391 // If there's a value of the specified type at `key` in this dictionary,
392 // returns it. Otherwise, creates an empty container of the specified type,
393 // inserts it at `key`, and returns it. If there's a value of some other
394 // type at `key`, will overwrite that entry.
395 Dict* EnsureDict(StringPiece key);
396 List* EnsureList(StringPiece key);
397
Daniel Chenga367fe52022-02-15 18:08:48398 // Sets an entry with `key` and `value` in this dictionary, overwriting any
399 // existing entry with the same `key`. Returns a pointer to the set `value`.
Jeroen Dhollander45a243342023-03-15 14:37:29400 Value* Set(StringPiece key, Value&& value) &;
401 Value* Set(StringPiece key, bool value) &;
Daniel Chenga367fe52022-02-15 18:08:48402 template <typename T>
Daniel Chengb3b759c12023-09-14 20:32:26403 Value* Set(StringPiece, const T*) & = delete;
Jeroen Dhollander45a243342023-03-15 14:37:29404 Value* Set(StringPiece key, int value) &;
405 Value* Set(StringPiece key, double value) &;
406 Value* Set(StringPiece key, StringPiece value) &;
407 Value* Set(StringPiece key, StringPiece16 value) &;
408 Value* Set(StringPiece key, const char* value) &;
409 Value* Set(StringPiece key, const char16_t* value) &;
410 Value* Set(StringPiece key, std::string&& value) &;
411 Value* Set(StringPiece key, BlobStorage&& value) &;
412 Value* Set(StringPiece key, Dict&& value) &;
413 Value* Set(StringPiece key, List&& value) &;
414
415 // Rvalue overrides of the `Set` methods, which allow you to construct
416 // a `Value::Dict` builder-style:
417 //
418 // Value::Dict result =
419 // Value::Dict()
420 // .Set("key-1", "first value")
421 // .Set("key-2", 2)
422 // .Set("key-3", true)
423 // .Set("nested-dictionary", Value::Dict()
424 // .Set("nested-key-1", "value")
425 // .Set("nested-key-2", true))
426 // .Set("nested-list", Value::List()
427 // .Append("nested-list-value")
428 // .Append(5)
429 // .Append(true));
430 //
431 // Each method returns a rvalue reference to `this`, so this is as efficient
Jeroen Dhollanderec527a702023-11-02 18:31:24432 // as stand-alone calls to `Set`, while also making it harder to
433 // accidentally insert items in the wrong dictionary.
Jeroen Dhollander45a243342023-03-15 14:37:29434 //
435 // The equivalent code without using these builder-style methods:
436 //
Jeroen Dhollanderec527a702023-11-02 18:31:24437 // Value::Dict no_builder_example;
438 // no_builder_example.Set("key-1", "first value")
439 // no_builder_example.Set("key-2", 2)
440 // no_builder_example.Set("key-3", true)
Jeroen Dhollander45a243342023-03-15 14:37:29441 // Value::Dict nested_dictionary;
442 // nested_dictionary.Set("nested-key-1", "value");
443 // nested_dictionary.Set("nested-key-2", true);
Jeroen Dhollanderec527a702023-11-02 18:31:24444 // no_builder_example.Set("nested_dictionary",
445 // std::move(nested_dictionary));
Jeroen Dhollander45a243342023-03-15 14:37:29446 // Value::List nested_list;
447 // nested_list.Append("nested-list-value");
448 // nested_list.Append(5);
449 // nested_list.Append(true);
Jeroen Dhollanderec527a702023-11-02 18:31:24450 // no_builder_example.Set("nested-list", std::move(nested_list));
451 //
452 // Sometimes `git cl format` does a less than perfect job formatting these
453 // chained `Set` calls. In these cases you can use a trailing empty comment
454 // to influence the code formatting:
455 //
456 // Value::Dict result = Value::Dict().Set(
457 // "nested",
458 // base::Value::Dict().Set("key", "value").Set("other key", "other"));
459 //
460 // Value::Dict result = Value::Dict().Set("nested",
461 // base::Value::Dict() //
462 // .Set("key", "value")
463 // .Set("other key", "value"));
Jeroen Dhollander45a243342023-03-15 14:37:29464 //
465 Dict&& Set(StringPiece key, Value&& value) &&;
466 Dict&& Set(StringPiece key, bool value) &&;
467 template <typename T>
468 Dict&& Set(StringPiece, const T*) && = delete;
469 Dict&& Set(StringPiece key, int value) &&;
470 Dict&& Set(StringPiece key, double value) &&;
471 Dict&& Set(StringPiece key, StringPiece value) &&;
472 Dict&& Set(StringPiece key, StringPiece16 value) &&;
473 Dict&& Set(StringPiece key, const char* value) &&;
474 Dict&& Set(StringPiece key, const char16_t* value) &&;
475 Dict&& Set(StringPiece key, std::string&& value) &&;
476 Dict&& Set(StringPiece key, BlobStorage&& value) &&;
477 Dict&& Set(StringPiece key, Dict&& value) &&;
478 Dict&& Set(StringPiece key, List&& value) &&;
Daniel Chenga367fe52022-02-15 18:08:48479
480 // Removes the entry corresponding to `key` from this dictionary. Returns
481 // true if an entry was removed or false otherwise.
482 bool Remove(StringPiece key);
483
484 // Similar to `Remove()`, but returns the value corresponding to the removed
485 // entry or `absl::nullopt` otherwise.
486 absl::optional<Value> Extract(StringPiece key);
487
488 // Equivalent to the above methods but operating on paths instead of keys.
489 // A path is shorthand syntax for referring to a key nested inside
490 // intermediate dictionaries, with components delimited by ".". Paths may
491 // not be empty.
492 //
Daniel Cheng619653b2022-02-17 18:33:12493 // Prefer the non-path methods above when possible. Paths that have only one
494 // component (i.e. no dots in the path) should never use the path-based
495 // methods.
496 //
497 // Originally, the path-based APIs were the only way of specifying a key, so
498 // there are likely to be many legacy (and unnecessary) uses of the path
499 // APIs that do not actually require traversing nested dictionaries.
Daniel Chenga367fe52022-02-15 18:08:48500 const Value* FindByDottedPath(StringPiece path) const;
501 Value* FindByDottedPath(StringPiece path);
502
503 absl::optional<bool> FindBoolByDottedPath(StringPiece path) const;
504 absl::optional<int> FindIntByDottedPath(StringPiece path) const;
505 // Returns a non-null value for both `Value::Type::DOUBLE` and
506 // `Value::Type::INT`, converting the latter to a double.
507 absl::optional<double> FindDoubleByDottedPath(StringPiece path) const;
508 const std::string* FindStringByDottedPath(StringPiece path) const;
509 std::string* FindStringByDottedPath(StringPiece path);
510 const BlobStorage* FindBlobByDottedPath(StringPiece path) const;
511 const Dict* FindDictByDottedPath(StringPiece path) const;
512 Dict* FindDictByDottedPath(StringPiece path);
513 const List* FindListByDottedPath(StringPiece path) const;
514 List* FindListByDottedPath(StringPiece path);
515
Daniel Cheng619653b2022-02-17 18:33:12516 // Creates a new entry with a dictionary for any non-last component that is
517 // missing an entry while performing the path traversal. Will fail if any
518 // non-last component of the path refers to an already-existing entry that
519 // is not a dictionary. Returns `nullptr` on failure.
Jeroen Dhollander864a0e92023-08-01 16:10:51520 //
521 // Warning: repeatedly using this API to enter entries in the same nested
522 // dictionary is inefficient, so please do not write the following:
523 //
524 // bad_example.SetByDottedPath("a.nested.dictionary.field_1", 1);
525 // bad_example.SetByDottedPath("a.nested.dictionary.field_2", "value");
526 // bad_example.SetByDottedPath("a.nested.dictionary.field_3", 1);
527 //
528 Value* SetByDottedPath(StringPiece path, Value&& value) &;
529 Value* SetByDottedPath(StringPiece path, bool value) &;
Daniel Chenga367fe52022-02-15 18:08:48530 template <typename T>
Jeroen Dhollander864a0e92023-08-01 16:10:51531 Value* SetByDottedPath(StringPiece, const T*) & = delete;
532 Value* SetByDottedPath(StringPiece path, int value) &;
533 Value* SetByDottedPath(StringPiece path, double value) &;
534 Value* SetByDottedPath(StringPiece path, StringPiece value) &;
535 Value* SetByDottedPath(StringPiece path, StringPiece16 value) &;
536 Value* SetByDottedPath(StringPiece path, const char* value) &;
537 Value* SetByDottedPath(StringPiece path, const char16_t* value) &;
538 Value* SetByDottedPath(StringPiece path, std::string&& value) &;
539 Value* SetByDottedPath(StringPiece path, BlobStorage&& value) &;
540 Value* SetByDottedPath(StringPiece path, Dict&& value) &;
541 Value* SetByDottedPath(StringPiece path, List&& value) &;
542
543 // Rvalue overrides of the `SetByDottedPath` methods, which allow you to
544 // construct a `Value::Dict` builder-style:
545 //
546 // Value::Dict result =
547 // Value::Dict()
548 // .SetByDottedPath("a.nested.dictionary.with.key-1", "first value")
549 // .Set("local-key-1", 2));
550 //
551 // Each method returns a rvalue reference to `this`, so this is as efficient
552 // as (and less mistake-prone than) stand-alone calls to `Set`.
553 //
554 // Warning: repeatedly using this API to enter entries in the same nested
555 // dictionary is inefficient, so do not write this:
556 //
557 // Value::Dict bad_example =
558 // Value::Dict()
559 // .SetByDottedPath("nested.dictionary.key-1", "first value")
560 // .SetByDottedPath("nested.dictionary.key-2", "second value")
561 // .SetByDottedPath("nested.dictionary.key-3", "third value");
562 //
563 // Instead, simply write this
564 //
565 // Value::Dict good_example =
566 // Value::Dict()
567 // .Set("nested",
568 // base::Value::Dict()
569 // .Set("dictionary",
570 // base::Value::Dict()
571 // .Set(key-1", "first value")
572 // .Set(key-2", "second value")
573 // .Set(key-3", "third value")));
574 //
575 //
576 Dict&& SetByDottedPath(StringPiece path, Value&& value) &&;
577 Dict&& SetByDottedPath(StringPiece path, bool value) &&;
578 template <typename T>
579 Dict&& SetByDottedPath(StringPiece, const T*) && = delete;
580 Dict&& SetByDottedPath(StringPiece path, int value) &&;
581 Dict&& SetByDottedPath(StringPiece path, double value) &&;
582 Dict&& SetByDottedPath(StringPiece path, StringPiece value) &&;
583 Dict&& SetByDottedPath(StringPiece path, StringPiece16 value) &&;
584 Dict&& SetByDottedPath(StringPiece path, const char* value) &&;
585 Dict&& SetByDottedPath(StringPiece path, const char16_t* value) &&;
586 Dict&& SetByDottedPath(StringPiece path, std::string&& value) &&;
587 Dict&& SetByDottedPath(StringPiece path, BlobStorage&& value) &&;
588 Dict&& SetByDottedPath(StringPiece path, Dict&& value) &&;
589 Dict&& SetByDottedPath(StringPiece path, List&& value) &&;
Daniel Chenga367fe52022-02-15 18:08:48590
591 bool RemoveByDottedPath(StringPiece path);
592
593 absl::optional<Value> ExtractByDottedPath(StringPiece path);
594
Avi Drissman4dbbee22023-01-31 22:02:35595 // Estimates dynamic memory usage. Requires tracing support
596 // (enable_base_tracing gn flag), otherwise always returns 0. See
597 // base/trace_event/memory_usage_estimator.h for more info.
598 size_t EstimateMemoryUsage() const;
599
Scott Haseleye51040782022-03-09 17:32:37600 // Serializes to a string for logging and debug purposes.
601 std::string DebugString() const;
602
Daniel Chengb5862bc2022-06-09 17:04:06603#if BUILDFLAG(ENABLE_BASE_TRACING)
604 // Write this object into a trace.
605 void WriteIntoTrace(perfetto::TracedValue) const;
606#endif // BUILDFLAG(ENABLE_BASE_TRACING)
607
Daniel Chenga367fe52022-02-15 18:08:48608 private:
609 BASE_EXPORT friend bool operator==(const Dict& lhs, const Dict& rhs);
610 BASE_EXPORT friend bool operator!=(const Dict& lhs, const Dict& rhs);
611 BASE_EXPORT friend bool operator<(const Dict& lhs, const Dict& rhs);
612 BASE_EXPORT friend bool operator>(const Dict& lhs, const Dict& rhs);
613 BASE_EXPORT friend bool operator<=(const Dict& lhs, const Dict& rhs);
614 BASE_EXPORT friend bool operator>=(const Dict& lhs, const Dict& rhs);
615
Daniel Chenga367fe52022-02-15 18:08:48616 explicit Dict(const flat_map<std::string, std::unique_ptr<Value>>& storage);
617
Avi Drissman4dbbee22023-01-31 22:02:35618 // TODO(dcheng): Replace with `flat_map<std::string, Value>` once no caller
619 // relies on stability of pointers anymore.
Daniel Chenga367fe52022-02-15 18:08:48620 flat_map<std::string, std::unique_ptr<Value>> storage_;
621 };
622
623 // Represents a list of Values.
Daniel Cheng8ac305b2022-02-17 00:05:11624 class BASE_EXPORT GSL_OWNER List {
Daniel Chenga367fe52022-02-15 18:08:48625 public:
626 using iterator = CheckedContiguousIterator<Value>;
627 using const_iterator = CheckedContiguousConstIterator<Value>;
Nan Lin0e8148a2023-06-27 11:44:34628 using reverse_iterator = std::reverse_iterator<iterator>;
629 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
Jan Keitel56a92682022-07-11 11:19:21630 using value_type = Value;
Daniel Chenga367fe52022-02-15 18:08:48631
Jeroen Dhollander45a243342023-03-15 14:37:29632 // Creates a list with the given capacity reserved.
633 // Correctly using this will greatly reduce the code size and improve
634 // performance when creating a list whose size is known up front.
635 static List with_capacity(size_t capacity);
636
Daniel Chenga367fe52022-02-15 18:08:48637 List();
638
639 List(List&&) noexcept;
640 List& operator=(List&&) noexcept;
641
642 // Deleted to prevent accidental copying.
643 List(const List&) = delete;
644 List& operator=(const List&) = delete;
645
646 ~List();
647
Daniel Chenga367fe52022-02-15 18:08:48648 // Returns true if there are no values in this list and false otherwise.
649 bool empty() const;
650
651 // Returns the number of values in this list.
652 size_t size() const;
653
654 // Returns an iterator to the first value in this list.
655 iterator begin();
656 const_iterator begin() const;
657 const_iterator cbegin() const;
658
659 // Returns an iterator following the last value in this list. May not be
660 // dereferenced.
661 iterator end();
662 const_iterator end() const;
663 const_iterator cend() const;
664
Oksana Zhuravlovae48b9962023-05-23 14:36:24665 // Returns a reverse iterator preceding the first value in this list. May
666 // not be dereferenced.
Nan Lin0e8148a2023-06-27 11:44:34667 reverse_iterator rend();
668 const_reverse_iterator rend() const;
Oksana Zhuravlovae48b9962023-05-23 14:36:24669
670 // Returns a reverse iterator to the last value in this list.
Nan Lin0e8148a2023-06-27 11:44:34671 reverse_iterator rbegin();
672 const_reverse_iterator rbegin() const;
Oksana Zhuravlovae48b9962023-05-23 14:36:24673
Daniel Chengc9ab0ef2022-02-18 02:34:07674 // Returns a reference to the first value in the container. Fails with
675 // `CHECK()` if the list is empty.
676 const Value& front() const;
677 Value& front();
678
679 // Returns a reference to the last value in the container. Fails with
680 // `CHECK()` if the list is empty.
681 const Value& back() const;
682 Value& back();
683
684 // Increase the capacity of the backing container, but does not change
685 // the size. Assume all existing iterators will be invalidated.
686 void reserve(size_t capacity);
687
Andrew Rayskiy972ed6362023-05-25 14:32:36688 // Resizes the list.
689 // If `new_size` is greater than current size, the extra elements in the
690 // back will be destroyed.
691 // If `new_size` is less than current size, new default-initialized elements
692 // will be added to the back.
693 // Assume all existing iterators will be invalidated.
694 void resize(size_t new_size);
695
Daniel Chenga367fe52022-02-15 18:08:48696 // Returns a reference to the value at `index` in this list. Fails with a
697 // `CHECK()` if `index >= size()`.
698 const Value& operator[](size_t index) const;
699 Value& operator[](size_t index);
700
701 // Removes all value from this list.
Marijn Kruisselbrink8af7d722022-12-13 19:03:42702 REINITIALIZES_AFTER_MOVE void clear();
Daniel Chenga367fe52022-02-15 18:08:48703
Daniel Chengc9ab0ef2022-02-18 02:34:07704 // Removes the value referenced by `pos` in this list and returns an
705 // iterator to the value following the removed value.
Daniel Chenga367fe52022-02-15 18:08:48706 iterator erase(iterator pos);
707 const_iterator erase(const_iterator pos);
708
Matt Menke3a0de712022-07-14 23:45:08709 // Remove the values in the range [`first`, `last`). Returns iterator to the
710 // first value following the removed range, which is `last`. If `first` ==
711 // `last`, removes nothing and returns `last`.
712 iterator erase(iterator first, iterator last);
713 const_iterator erase(const_iterator first, const_iterator last);
714
Daniel Chenga367fe52022-02-15 18:08:48715 // Creates a deep copy of this dictionary.
716 List Clone() const;
717
718 // Appends `value` to the end of this list.
Jeroen Dhollander45a243342023-03-15 14:37:29719 void Append(Value&& value) &;
720 void Append(bool value) &;
Daniel Chenga367fe52022-02-15 18:08:48721 template <typename T>
Daniel Chengb3b759c12023-09-14 20:32:26722 void Append(const T*) & = delete;
Jeroen Dhollander45a243342023-03-15 14:37:29723 void Append(int value) &;
724 void Append(double value) &;
725 void Append(StringPiece value) &;
726 void Append(StringPiece16 value) &;
727 void Append(const char* value) &;
728 void Append(const char16_t* value) &;
729 void Append(std::string&& value) &;
730 void Append(BlobStorage&& value) &;
731 void Append(Dict&& value) &;
732 void Append(List&& value) &;
733
734 // Rvalue overrides of the `Append` methods, which allow you to construct
735 // a `Value::List` builder-style:
736 //
Jeroen Dhollanderec527a702023-11-02 18:31:24737 // Value::List result =
738 // Value::List().Append("first value").Append(2).Append(true);
Jeroen Dhollander45a243342023-03-15 14:37:29739 //
740 // Each method returns a rvalue reference to `this`, so this is as efficient
Jeroen Dhollanderec527a702023-11-02 18:31:24741 // as stand-alone calls to `Append`, while at the same time making it harder
742 // to accidentally append to the wrong list.
Jeroen Dhollander45a243342023-03-15 14:37:29743 //
744 // The equivalent code without using these builder-style methods:
745 //
Jeroen Dhollanderec527a702023-11-02 18:31:24746 // Value::List no_builder_example;
747 // no_builder_example.Append("first value");
748 // no_builder_example.Append(2);
749 // no_builder_example.Append(true);
Jeroen Dhollander45a243342023-03-15 14:37:29750 //
751 List&& Append(Value&& value) &&;
752 List&& Append(bool value) &&;
753 template <typename T>
754 List&& Append(const T*) && = delete;
755 List&& Append(int value) &&;
756 List&& Append(double value) &&;
757 List&& Append(StringPiece value) &&;
758 List&& Append(StringPiece16 value) &&;
759 List&& Append(const char* value) &&;
760 List&& Append(const char16_t* value) &&;
761 List&& Append(std::string&& value) &&;
762 List&& Append(BlobStorage&& value) &&;
763 List&& Append(Dict&& value) &&;
764 List&& Append(List&& value) &&;
Daniel Chenga367fe52022-02-15 18:08:48765
766 // Inserts `value` before `pos` in this list. Returns an iterator to the
767 // inserted value.
768 // TODO(dcheng): Should this provide the same set of overloads that Append()
769 // does?
770 iterator Insert(const_iterator pos, Value&& value);
771
772 // Erases all values equal to `value` from this list.
773 size_t EraseValue(const Value& value);
774
775 // Erases all values for which `predicate` evaluates to true from this list.
776 template <typename Predicate>
777 size_t EraseIf(Predicate predicate) {
778 return base::EraseIf(storage_, predicate);
779 }
780
Matt Menkee5772892023-01-10 03:10:31781 // Estimates dynamic memory usage. Requires tracing support
782 // (enable_base_tracing gn flag), otherwise always returns 0. See
783 // base/trace_event/memory_usage_estimator.h for more info.
784 size_t EstimateMemoryUsage() const;
785
Scott Haseleye51040782022-03-09 17:32:37786 // Serializes to a string for logging and debug purposes.
787 std::string DebugString() const;
788
Daniel Chengb5862bc2022-06-09 17:04:06789#if BUILDFLAG(ENABLE_BASE_TRACING)
790 // Write this object into a trace.
791 void WriteIntoTrace(perfetto::TracedValue) const;
792#endif // BUILDFLAG(ENABLE_BASE_TRACING)
793
Daniel Chenga367fe52022-02-15 18:08:48794 private:
Matt Menkee5772892023-01-10 03:10:31795 using ListStorage = std::vector<Value>;
796
Daniel Chenga367fe52022-02-15 18:08:48797 BASE_EXPORT friend bool operator==(const List& lhs, const List& rhs);
798 BASE_EXPORT friend bool operator!=(const List& lhs, const List& rhs);
799 BASE_EXPORT friend bool operator<(const List& lhs, const List& rhs);
800 BASE_EXPORT friend bool operator>(const List& lhs, const List& rhs);
801 BASE_EXPORT friend bool operator<=(const List& lhs, const List& rhs);
802 BASE_EXPORT friend bool operator>=(const List& lhs, const List& rhs);
803
Daniel Chenga367fe52022-02-15 18:08:48804 explicit List(const std::vector<Value>& storage);
805
806 std::vector<Value> storage_;
807 };
jdoerriee03e80f2017-02-15 08:42:14808
brettw@chromium.org2f03f532013-07-17 08:43:33809 // Note: Do not add more types. See the file-level comment above for why.
initial.commitd7cae122008-07-26 21:49:38810
jdoerrie5c1cee112017-03-28 17:52:00811 // Comparison operators so that Values can easily be used with standard
812 // library algorithms and associative containers.
813 BASE_EXPORT friend bool operator==(const Value& lhs, const Value& rhs);
814 BASE_EXPORT friend bool operator!=(const Value& lhs, const Value& rhs);
815 BASE_EXPORT friend bool operator<(const Value& lhs, const Value& rhs);
816 BASE_EXPORT friend bool operator>(const Value& lhs, const Value& rhs);
817 BASE_EXPORT friend bool operator<=(const Value& lhs, const Value& rhs);
818 BASE_EXPORT friend bool operator>=(const Value& lhs, const Value& rhs);
819
Daniel Cheng0b0b6752022-05-25 02:59:48820 BASE_EXPORT friend bool operator==(const Value& lhs, bool rhs);
821 friend bool operator==(bool lhs, const Value& rhs) { return rhs == lhs; }
822 friend bool operator!=(const Value& lhs, bool rhs) { return !(lhs == rhs); }
823 friend bool operator!=(bool lhs, const Value& rhs) { return !(lhs == rhs); }
Daniel Cheng6b621cf2022-06-02 02:42:02824 template <typename T>
825 friend bool operator==(const Value& lhs, const T* rhs) = delete;
826 template <typename T>
827 friend bool operator==(const T* lhs, const Value& rhs) = delete;
828 template <typename T>
829 friend bool operator!=(const Value& lhs, const T* rhs) = delete;
830 template <typename T>
831 friend bool operator!=(const T* lhs, const Value& rhs) = delete;
Daniel Cheng0b0b6752022-05-25 02:59:48832 BASE_EXPORT friend bool operator==(const Value& lhs, int rhs);
833 friend bool operator==(int lhs, const Value& rhs) { return rhs == lhs; }
834 friend bool operator!=(const Value& lhs, int rhs) { return !(lhs == rhs); }
835 friend bool operator!=(int lhs, const Value& rhs) { return !(lhs == rhs); }
836 BASE_EXPORT friend bool operator==(const Value& lhs, double rhs);
837 friend bool operator==(double lhs, const Value& rhs) { return rhs == lhs; }
838 friend bool operator!=(const Value& lhs, double rhs) { return !(lhs == rhs); }
839 friend bool operator!=(double lhs, const Value& rhs) { return !(lhs == rhs); }
Daniel Cheng6b621cf2022-06-02 02:42:02840 // Note: StringPiece16 overload intentionally omitted: Value internally stores
841 // strings as UTF-8. While it is possible to implement a comparison operator
842 // that would not require first creating a new UTF-8 string from the UTF-16
843 // string argument, it is simpler to just not implement it at all for a rare
844 // use case.
Daniel Cheng0b0b6752022-05-25 02:59:48845 BASE_EXPORT friend bool operator==(const Value& lhs, StringPiece rhs);
846 friend bool operator==(StringPiece lhs, const Value& rhs) {
847 return rhs == lhs;
848 }
849 friend bool operator!=(const Value& lhs, StringPiece rhs) {
850 return !(lhs == rhs);
851 }
852 friend bool operator!=(StringPiece lhs, const Value& rhs) {
853 return !(lhs == rhs);
854 }
Daniel Cheng6b621cf2022-06-02 02:42:02855 friend bool operator==(const Value& lhs, const char* rhs) {
856 return lhs == StringPiece(rhs);
857 }
858 friend bool operator==(const char* lhs, const Value& rhs) {
859 return rhs == lhs;
860 }
861 friend bool operator!=(const Value& lhs, const char* rhs) {
862 return !(lhs == rhs);
863 }
864 friend bool operator!=(const char* lhs, const Value& rhs) {
865 return !(lhs == rhs);
866 }
867 friend bool operator==(const Value& lhs, const std::string& rhs) {
868 return lhs == StringPiece(rhs);
869 }
870 friend bool operator==(const std::string& lhs, const Value& rhs) {
871 return rhs == lhs;
872 }
873 friend bool operator!=(const Value& lhs, const std::string& rhs) {
874 return !(lhs == rhs);
875 }
876 friend bool operator!=(const std::string& lhs, const Value& rhs) {
877 return !(lhs == rhs);
878 }
Daniel Cheng0b0b6752022-05-25 02:59:48879 // Note: Blob support intentionally omitted as an experiment for potentially
880 // wholly removing Blob support from Value itself in the future.
881 BASE_EXPORT friend bool operator==(const Value& lhs, const Value::Dict& rhs);
882 friend bool operator==(const Value::Dict& lhs, const Value& rhs) {
883 return rhs == lhs;
884 }
885 friend bool operator!=(const Value& lhs, const Value::Dict& rhs) {
886 return !(lhs == rhs);
887 }
888 friend bool operator!=(const Value::Dict& lhs, const Value& rhs) {
889 return !(lhs == rhs);
890 }
891 BASE_EXPORT friend bool operator==(const Value& lhs, const Value::List& rhs);
892 friend bool operator==(const Value::List& lhs, const Value& rhs) {
893 return rhs == lhs;
894 }
895 friend bool operator!=(const Value& lhs, const Value::List& rhs) {
896 return !(lhs == rhs);
897 }
898 friend bool operator!=(const Value::List& lhs, const Value& rhs) {
899 return !(lhs == rhs);
900 }
901
Eric Secklerf6c544f2020-06-02 10:49:21902 // Estimates dynamic memory usage. Requires tracing support
903 // (enable_base_tracing gn flag), otherwise always returns 0. See
904 // base/trace_event/memory_usage_estimator.h for more info.
Alexander Yashkinab504e72017-11-30 11:54:45905 size_t EstimateMemoryUsage() const;
906
Alan Cutter2dd83032020-12-08 21:55:00907 // Serializes to a string for logging and debug purposes.
908 std::string DebugString() const;
909
Peter Kotwicz83a231372021-04-13 17:42:12910#if BUILDFLAG(ENABLE_BASE_TRACING)
Alexander Timine68aeb32021-04-11 23:06:21911 // Write this object into a trace.
Alexander Timinbebb2002021-04-20 15:42:24912 void WriteIntoTrace(perfetto::TracedValue) const;
Peter Kotwicz83a231372021-04-13 17:42:12913#endif // BUILDFLAG(ENABLE_BASE_TRACING)
Alexander Timine68aeb32021-04-11 23:06:21914
Daniel Cheng8ac305b2022-02-17 00:05:11915 template <typename Visitor>
916 auto Visit(Visitor&& visitor) const {
917 return absl::visit(std::forward<Visitor>(visitor), data_);
918 }
919
Jan Wilken Dörrie79d022142020-08-19 18:18:32920 private:
Daniel Cheng8ac305b2022-02-17 00:05:11921 // For access to DoubleStorage.
922 friend class ValueView;
923
David 'Digit' Turner2f287312019-04-03 14:32:09924 // Special case for doubles, which are aligned to 8 bytes on some
925 // 32-bit architectures. In this case, a simple declaration as a
926 // double member would make the whole union 8 byte-aligned, which
927 // would also force 4 bytes of wasted padding space before it in
928 // the Value layout.
David 'Digit' Turner806dedb2019-03-06 17:43:11929 //
David 'Digit' Turner2f287312019-04-03 14:32:09930 // To override this, store the value as an array of 32-bit integers, and
931 // perform the appropriate bit casts when reading / writing to it.
Daniel Cheng6b621cf2022-06-02 02:42:02932 class BASE_EXPORT DoubleStorage {
Daniel Cheng782d2ba32022-02-16 19:40:29933 public:
934 explicit DoubleStorage(double v);
935 DoubleStorage(const DoubleStorage&) = default;
936 DoubleStorage& operator=(const DoubleStorage&) = default;
937
Daniel Cheng8ac305b2022-02-17 00:05:11938 // Provide an implicit conversion to double to simplify the use of visitors
939 // with `Value::Visit()`. Otherwise, visitors would need a branch for
940 // handling `DoubleStorage` like:
941 //
942 // value.Visit([] (const auto& member) {
943 // using T = std::decay_t<decltype(member)>;
944 // if constexpr (std::is_same_v<T, Value::DoubleStorage>) {
945 // SomeFunction(double{member});
946 // } else {
947 // SomeFunction(member);
948 // }
949 // });
Peter Kastingcc88ac052022-05-03 09:58:01950 operator double() const { return base::bit_cast<double>(v_); }
Daniel Cheng782d2ba32022-02-16 19:40:29951
952 private:
953 friend bool operator==(const DoubleStorage& lhs, const DoubleStorage& rhs) {
Daniel Cheng8ac305b2022-02-17 00:05:11954 return double{lhs} == double{rhs};
Daniel Cheng782d2ba32022-02-16 19:40:29955 }
956
957 friend bool operator!=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
958 return !(lhs == rhs);
959 }
960
961 friend bool operator<(const DoubleStorage& lhs, const DoubleStorage& rhs) {
Daniel Cheng8ac305b2022-02-17 00:05:11962 return double{lhs} < double{rhs};
Daniel Cheng782d2ba32022-02-16 19:40:29963 }
964
965 friend bool operator>(const DoubleStorage& lhs, const DoubleStorage& rhs) {
966 return rhs < lhs;
967 }
968
969 friend bool operator<=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
970 return !(rhs < lhs);
971 }
972
973 friend bool operator>=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
974 return !(lhs < rhs);
975 }
976
977 alignas(4) std::array<char, sizeof(double)> v_;
978 };
David 'Digit' Turner2f287312019-04-03 14:32:09979
Jan Wilken Dörrie79d022142020-08-19 18:18:32980 // Internal constructors, allowing the simplify the implementation of Clone().
981 explicit Value(absl::monostate);
982 explicit Value(DoubleStorage storage);
jdoerrie8e945542017-02-17 13:54:49983
Claudio DeSouzab8754a3e2022-07-25 18:08:45984 // A helper for static functions used for cloning a Value or a ValueView.
985 class CloningHelper;
986
Jan Wilken Dörrie79d022142020-08-19 18:18:32987 absl::variant<absl::monostate,
988 bool,
989 int,
990 DoubleStorage,
991 std::string,
992 BlobStorage,
Daniel Chenga367fe52022-02-15 18:08:48993 Dict,
994 List>
Jan Wilken Dörrie79d022142020-08-19 18:18:32995 data_;
initial.commitd7cae122008-07-26 21:49:38996};
997
Daniel Cheng8ac305b2022-02-17 00:05:11998// Adapter so `Value::Dict` or `Value::List` can be directly passed to JSON
999// serialization methods without having to clone the contents and transfer
1000// ownership of the clone to a `Value` wrapper object.
1001//
1002// Like `StringPiece` and `span<T>`, this adapter does NOT retain ownership. Any
1003// underlying object that is passed by reference (i.e. `std::string`,
1004// `Value::BlobStorage`, `Value::Dict`, `Value::List`, or `Value`) MUST remain
1005// live as long as there is a `ValueView` referencing it.
1006//
1007// While it might be nice to just use the `absl::variant` type directly, the
1008// need to use `std::reference_wrapper` makes it clunky. `absl::variant` and
1009// `std::reference_wrapper` both support implicit construction, but C++ only
1010// allows at most one user-defined conversion in an implicit conversion
1011// sequence. If this adapter and its implicit constructors did not exist,
1012// callers would need to use `std::ref` or `std::cref` to pass `Value::Dict` or
1013// `Value::List` to a function with a `ValueView` parameter.
1014class BASE_EXPORT GSL_POINTER ValueView {
1015 public:
Daniel Cheng6b621cf2022-06-02 02:42:021016 ValueView() = default;
Daniel Cheng8ac305b2022-02-17 00:05:111017 ValueView(bool value) : data_view_(value) {}
Daniel Cheng6b621cf2022-06-02 02:42:021018 template <typename T>
1019 ValueView(const T*) = delete;
Daniel Cheng8ac305b2022-02-17 00:05:111020 ValueView(int value) : data_view_(value) {}
1021 ValueView(double value)
1022 : data_view_(absl::in_place_type_t<Value::DoubleStorage>(), value) {}
Daniel Cheng6b621cf2022-06-02 02:42:021023 ValueView(StringPiece value) : data_view_(value) {}
1024 ValueView(const char* value) : ValueView(StringPiece(value)) {}
1025 ValueView(const std::string& value) : ValueView(StringPiece(value)) {}
1026 // Note: UTF-16 is intentionally not supported. ValueView is intended to be a
1027 // low-cost view abstraction, but Value internally represents strings as
1028 // UTF-8, so it would not be possible to implement this without allocating an
1029 // entirely new UTF-8 string.
Daniel Cheng8ac305b2022-02-17 00:05:111030 ValueView(const Value::BlobStorage& value) : data_view_(value) {}
1031 ValueView(const Value::Dict& value) : data_view_(value) {}
1032 ValueView(const Value::List& value) : data_view_(value) {}
1033 ValueView(const Value& value);
1034
Daniel Cheng6b621cf2022-06-02 02:42:021035 // This is the only 'getter' method provided as `ValueView` is not intended
1036 // to be a general replacement of `Value`.
Daniel Cheng8ac305b2022-02-17 00:05:111037 template <typename Visitor>
1038 auto Visit(Visitor&& visitor) const {
1039 return absl::visit(std::forward<Visitor>(visitor), data_view_);
1040 }
1041
Claudio DeSouza75d1f3412022-07-22 21:06:421042 // Returns a clone of the underlying Value.
1043 Value ToValue() const;
1044
Daniel Cheng8ac305b2022-02-17 00:05:111045 private:
1046 using ViewType =
1047 absl::variant<absl::monostate,
1048 bool,
1049 int,
1050 Value::DoubleStorage,
Daniel Cheng6b621cf2022-06-02 02:42:021051 StringPiece,
Daniel Cheng8ac305b2022-02-17 00:05:111052 std::reference_wrapper<const Value::BlobStorage>,
1053 std::reference_wrapper<const Value::Dict>,
1054 std::reference_wrapper<const Value::List>>;
1055
Daniel Cheng6b621cf2022-06-02 02:42:021056 public:
1057 using DoubleStorageForTest = Value::DoubleStorage;
1058 const ViewType& data_view_for_test() const { return data_view_; }
1059
1060 private:
Daniel Cheng8ac305b2022-02-17 00:05:111061 ViewType data_view_;
1062};
1063
prashhir54a994502015-03-05 09:30:571064// This interface is implemented by classes that know how to serialize
1065// Value objects.
darin@chromium.org0bea7252011-08-05 15:34:001066class BASE_EXPORT ValueSerializer {
initial.commitd7cae122008-07-26 21:49:381067 public:
erg@chromium.org3a3d47472010-07-15 21:03:541068 virtual ~ValueSerializer();
mmentovai@google.comabb9d0c2008-08-06 15:46:591069
Daniel Cheng8ac305b2022-02-17 00:05:111070 virtual bool Serialize(ValueView root) = 0;
prashhir54a994502015-03-05 09:30:571071};
1072
1073// This interface is implemented by classes that know how to deserialize Value
1074// objects.
1075class BASE_EXPORT ValueDeserializer {
1076 public:
1077 virtual ~ValueDeserializer();
initial.commitd7cae122008-07-26 21:49:381078
1079 // This method deserializes the subclass-specific format into a Value object.
aa@chromium.orgb4cebf82008-12-29 19:59:081080 // If the return value is non-NULL, the caller takes ownership of returned
Nigel Tao410788e2020-06-24 07:12:271081 // Value.
1082 //
Gabriel Charetteb49d73a2021-05-05 20:05:591083 // If the return value is nullptr, and if `error_code` is non-nullptr,
1084 // `*error_code` will be set to an integer value representing the underlying
Nigel Tao410788e2020-06-24 07:12:271085 // error. See "enum ErrorCode" below for more detail about the integer value.
1086 //
Gabriel Charetteb49d73a2021-05-05 20:05:591087 // If `error_message` is non-nullptr, it will be filled in with a formatted
erikkay@chromium.orgba399672010-04-06 15:42:391088 // error message including the location of the error if appropriate.
dcheng093de9b2016-04-04 21:25:511089 virtual std::unique_ptr<Value> Deserialize(int* error_code,
Nigel Tao410788e2020-06-24 07:12:271090 std::string* error_message) = 0;
1091
1092 // The integer-valued error codes form four groups:
1093 // - The value 0 means no error.
1094 // - Values between 1 and 999 inclusive mean an error in the data (i.e.
1095 // content). The bytes being deserialized are not in the right format.
1096 // - Values 1000 and above mean an error in the metadata (i.e. context). The
1097 // file could not be read, the network is down, etc.
1098 // - Negative values are reserved.
Caitlin Fischeraac06dc2021-12-17 00:21:321099 //
1100 // These values are persisted to logs. Entries should not be renumbered and
1101 // numeric values should never be reused.
Nigel Tao410788e2020-06-24 07:12:271102 enum ErrorCode {
1103 kErrorCodeNoError = 0,
1104 // kErrorCodeInvalidFormat is a generic error code for "the data is not in
1105 // the right format". Subclasses of ValueDeserializer may return other
1106 // values for more specific errors.
1107 kErrorCodeInvalidFormat = 1,
1108 // kErrorCodeFirstMetadataError is the minimum value (inclusive) of the
1109 // range of metadata errors.
1110 kErrorCodeFirstMetadataError = 1000,
1111 };
1112
Gabriel Charetteb49d73a2021-05-05 20:05:591113 // The `error_code` argument can be one of the ErrorCode values, but it is
Nigel Tao410788e2020-06-24 07:12:271114 // not restricted to only being 0, 1 or 1000. Subclasses of ValueDeserializer
1115 // can define their own error code values.
1116 static inline bool ErrorCodeIsDataError(int error_code) {
1117 return (kErrorCodeInvalidFormat <= error_code) &&
1118 (error_code < kErrorCodeFirstMetadataError);
1119 }
initial.commitd7cae122008-07-26 21:49:381120};
1121
Daniel Chenga367fe52022-02-15 18:08:481122// Stream operator so Values can be pretty printed by gtest.
kalman@chromium.orge4ef8312012-09-12 03:39:351123BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value);
Daniel Chenga367fe52022-02-15 18:08:481124BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1125 const Value::Dict& dict);
1126BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1127 const Value::List& list);
kalman@chromium.orge4ef8312012-09-12 03:39:351128
jdoerriedc72ee942016-12-07 15:43:281129// Stream operator so that enum class Types can be used in log statements.
1130BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1131 const Value::Type& type);
1132
dmazzoni@chromium.orgf3a1c642011-07-12 19:15:031133} // namespace base
1134
darin@chromium.org101d5422008-09-26 20:22:421135#endif // BASE_VALUES_H_