blob: 465a7f401ac4811a85a0cb35d82f9ba52c5361d1 [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
Daniel Cheng782d2ba32022-02-16 19:40:2911#include <array>
Lei Zhang935738a2021-05-17 21:35:5312#include <initializer_list>
[email protected]c014f2b32013-09-03 23:29:1213#include <iosfwd>
Matt Menkee311c6d2022-06-14 20:17:3914#include <iterator>
dcheng093de9b2016-04-04 21:25:5115#include <memory>
[email protected]8e50b602009-03-03 22:59:4316#include <string>
[email protected]c014f2b32013-09-03 23:29:1217#include <utility>
initial.commitd7cae122008-07-26 21:49:3818#include <vector>
19
[email protected]0bea7252011-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
[email protected]f3a1c642011-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
[email protected]2f03f532013-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 Cheng773ce4502022-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,
[email protected]2f03f532013-07-17 08:43:33167 // Note: Do not add more types. See the file-level comment above for why.
[email protected]a502bbe72011-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>
403 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
432 // as (and less mistake-prone than) stand-alone calls to `Set`.
433 //
434 // The equivalent code without using these builder-style methods:
435 //
436 // Value::Dict bad_example;
437 // bad_example.Set("key-1", "first value")
438 // bad_example.Set("key-2", 2)
439 // bad_example.Set("key-3", true)
440 // Value::Dict nested_dictionary;
441 // nested_dictionary.Set("nested-key-1", "value");
442 // nested_dictionary.Set("nested-key-2", true);
443 // bad_example.Set("nested_dictionary", std::move(nested_dictionary));
444 // Value::List nested_list;
445 // nested_list.Append("nested-list-value");
446 // nested_list.Append(5);
447 // nested_list.Append(true);
448 // bad_example.Set("nested-list", std::move(nested_list));
449 //
450 Dict&& Set(StringPiece key, Value&& value) &&;
451 Dict&& Set(StringPiece key, bool value) &&;
452 template <typename T>
453 Dict&& Set(StringPiece, const T*) && = delete;
454 Dict&& Set(StringPiece key, int value) &&;
455 Dict&& Set(StringPiece key, double value) &&;
456 Dict&& Set(StringPiece key, StringPiece value) &&;
457 Dict&& Set(StringPiece key, StringPiece16 value) &&;
458 Dict&& Set(StringPiece key, const char* value) &&;
459 Dict&& Set(StringPiece key, const char16_t* value) &&;
460 Dict&& Set(StringPiece key, std::string&& value) &&;
461 Dict&& Set(StringPiece key, BlobStorage&& value) &&;
462 Dict&& Set(StringPiece key, Dict&& value) &&;
463 Dict&& Set(StringPiece key, List&& value) &&;
Daniel Chenga367fe52022-02-15 18:08:48464
465 // Removes the entry corresponding to `key` from this dictionary. Returns
466 // true if an entry was removed or false otherwise.
467 bool Remove(StringPiece key);
468
469 // Similar to `Remove()`, but returns the value corresponding to the removed
470 // entry or `absl::nullopt` otherwise.
471 absl::optional<Value> Extract(StringPiece key);
472
473 // Equivalent to the above methods but operating on paths instead of keys.
474 // A path is shorthand syntax for referring to a key nested inside
475 // intermediate dictionaries, with components delimited by ".". Paths may
476 // not be empty.
477 //
Daniel Cheng619653b2022-02-17 18:33:12478 // Prefer the non-path methods above when possible. Paths that have only one
479 // component (i.e. no dots in the path) should never use the path-based
480 // methods.
481 //
482 // Originally, the path-based APIs were the only way of specifying a key, so
483 // there are likely to be many legacy (and unnecessary) uses of the path
484 // APIs that do not actually require traversing nested dictionaries.
Daniel Chenga367fe52022-02-15 18:08:48485 const Value* FindByDottedPath(StringPiece path) const;
486 Value* FindByDottedPath(StringPiece path);
487
488 absl::optional<bool> FindBoolByDottedPath(StringPiece path) const;
489 absl::optional<int> FindIntByDottedPath(StringPiece path) const;
490 // Returns a non-null value for both `Value::Type::DOUBLE` and
491 // `Value::Type::INT`, converting the latter to a double.
492 absl::optional<double> FindDoubleByDottedPath(StringPiece path) const;
493 const std::string* FindStringByDottedPath(StringPiece path) const;
494 std::string* FindStringByDottedPath(StringPiece path);
495 const BlobStorage* FindBlobByDottedPath(StringPiece path) const;
496 const Dict* FindDictByDottedPath(StringPiece path) const;
497 Dict* FindDictByDottedPath(StringPiece path);
498 const List* FindListByDottedPath(StringPiece path) const;
499 List* FindListByDottedPath(StringPiece path);
500
Daniel Cheng619653b2022-02-17 18:33:12501 // Creates a new entry with a dictionary for any non-last component that is
502 // missing an entry while performing the path traversal. Will fail if any
503 // non-last component of the path refers to an already-existing entry that
504 // is not a dictionary. Returns `nullptr` on failure.
Jeroen Dhollander864a0e92023-08-01 16:10:51505 //
506 // Warning: repeatedly using this API to enter entries in the same nested
507 // dictionary is inefficient, so please do not write the following:
508 //
509 // bad_example.SetByDottedPath("a.nested.dictionary.field_1", 1);
510 // bad_example.SetByDottedPath("a.nested.dictionary.field_2", "value");
511 // bad_example.SetByDottedPath("a.nested.dictionary.field_3", 1);
512 //
513 Value* SetByDottedPath(StringPiece path, Value&& value) &;
514 Value* SetByDottedPath(StringPiece path, bool value) &;
Daniel Chenga367fe52022-02-15 18:08:48515 template <typename T>
Jeroen Dhollander864a0e92023-08-01 16:10:51516 Value* SetByDottedPath(StringPiece, const T*) & = delete;
517 Value* SetByDottedPath(StringPiece path, int value) &;
518 Value* SetByDottedPath(StringPiece path, double value) &;
519 Value* SetByDottedPath(StringPiece path, StringPiece value) &;
520 Value* SetByDottedPath(StringPiece path, StringPiece16 value) &;
521 Value* SetByDottedPath(StringPiece path, const char* value) &;
522 Value* SetByDottedPath(StringPiece path, const char16_t* value) &;
523 Value* SetByDottedPath(StringPiece path, std::string&& value) &;
524 Value* SetByDottedPath(StringPiece path, BlobStorage&& value) &;
525 Value* SetByDottedPath(StringPiece path, Dict&& value) &;
526 Value* SetByDottedPath(StringPiece path, List&& value) &;
527
528 // Rvalue overrides of the `SetByDottedPath` methods, which allow you to
529 // construct a `Value::Dict` builder-style:
530 //
531 // Value::Dict result =
532 // Value::Dict()
533 // .SetByDottedPath("a.nested.dictionary.with.key-1", "first value")
534 // .Set("local-key-1", 2));
535 //
536 // Each method returns a rvalue reference to `this`, so this is as efficient
537 // as (and less mistake-prone than) stand-alone calls to `Set`.
538 //
539 // Warning: repeatedly using this API to enter entries in the same nested
540 // dictionary is inefficient, so do not write this:
541 //
542 // Value::Dict bad_example =
543 // Value::Dict()
544 // .SetByDottedPath("nested.dictionary.key-1", "first value")
545 // .SetByDottedPath("nested.dictionary.key-2", "second value")
546 // .SetByDottedPath("nested.dictionary.key-3", "third value");
547 //
548 // Instead, simply write this
549 //
550 // Value::Dict good_example =
551 // Value::Dict()
552 // .Set("nested",
553 // base::Value::Dict()
554 // .Set("dictionary",
555 // base::Value::Dict()
556 // .Set(key-1", "first value")
557 // .Set(key-2", "second value")
558 // .Set(key-3", "third value")));
559 //
560 //
561 Dict&& SetByDottedPath(StringPiece path, Value&& value) &&;
562 Dict&& SetByDottedPath(StringPiece path, bool value) &&;
563 template <typename T>
564 Dict&& SetByDottedPath(StringPiece, const T*) && = delete;
565 Dict&& SetByDottedPath(StringPiece path, int value) &&;
566 Dict&& SetByDottedPath(StringPiece path, double value) &&;
567 Dict&& SetByDottedPath(StringPiece path, StringPiece value) &&;
568 Dict&& SetByDottedPath(StringPiece path, StringPiece16 value) &&;
569 Dict&& SetByDottedPath(StringPiece path, const char* value) &&;
570 Dict&& SetByDottedPath(StringPiece path, const char16_t* value) &&;
571 Dict&& SetByDottedPath(StringPiece path, std::string&& value) &&;
572 Dict&& SetByDottedPath(StringPiece path, BlobStorage&& value) &&;
573 Dict&& SetByDottedPath(StringPiece path, Dict&& value) &&;
574 Dict&& SetByDottedPath(StringPiece path, List&& value) &&;
Daniel Chenga367fe52022-02-15 18:08:48575
576 bool RemoveByDottedPath(StringPiece path);
577
578 absl::optional<Value> ExtractByDottedPath(StringPiece path);
579
Avi Drissman4dbbee22023-01-31 22:02:35580 // Estimates dynamic memory usage. Requires tracing support
581 // (enable_base_tracing gn flag), otherwise always returns 0. See
582 // base/trace_event/memory_usage_estimator.h for more info.
583 size_t EstimateMemoryUsage() const;
584
Scott Haseleye51040782022-03-09 17:32:37585 // Serializes to a string for logging and debug purposes.
586 std::string DebugString() const;
587
Daniel Chengb5862bc2022-06-09 17:04:06588#if BUILDFLAG(ENABLE_BASE_TRACING)
589 // Write this object into a trace.
590 void WriteIntoTrace(perfetto::TracedValue) const;
591#endif // BUILDFLAG(ENABLE_BASE_TRACING)
592
Daniel Chenga367fe52022-02-15 18:08:48593 private:
594 BASE_EXPORT friend bool operator==(const Dict& lhs, const Dict& rhs);
595 BASE_EXPORT friend bool operator!=(const Dict& lhs, const Dict& rhs);
596 BASE_EXPORT friend bool operator<(const Dict& lhs, const Dict& rhs);
597 BASE_EXPORT friend bool operator>(const Dict& lhs, const Dict& rhs);
598 BASE_EXPORT friend bool operator<=(const Dict& lhs, const Dict& rhs);
599 BASE_EXPORT friend bool operator>=(const Dict& lhs, const Dict& rhs);
600
Daniel Chenga367fe52022-02-15 18:08:48601 explicit Dict(const flat_map<std::string, std::unique_ptr<Value>>& storage);
602
Avi Drissman4dbbee22023-01-31 22:02:35603 // TODO(dcheng): Replace with `flat_map<std::string, Value>` once no caller
604 // relies on stability of pointers anymore.
Daniel Chenga367fe52022-02-15 18:08:48605 flat_map<std::string, std::unique_ptr<Value>> storage_;
606 };
607
608 // Represents a list of Values.
Daniel Cheng8ac305b2022-02-17 00:05:11609 class BASE_EXPORT GSL_OWNER List {
Daniel Chenga367fe52022-02-15 18:08:48610 public:
611 using iterator = CheckedContiguousIterator<Value>;
612 using const_iterator = CheckedContiguousConstIterator<Value>;
Nan Lin0e8148a2023-06-27 11:44:34613 using reverse_iterator = std::reverse_iterator<iterator>;
614 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
Jan Keitel56a92682022-07-11 11:19:21615 using value_type = Value;
Daniel Chenga367fe52022-02-15 18:08:48616
Jeroen Dhollander45a243342023-03-15 14:37:29617 // Creates a list with the given capacity reserved.
618 // Correctly using this will greatly reduce the code size and improve
619 // performance when creating a list whose size is known up front.
620 static List with_capacity(size_t capacity);
621
Daniel Chenga367fe52022-02-15 18:08:48622 List();
623
624 List(List&&) noexcept;
625 List& operator=(List&&) noexcept;
626
627 // Deleted to prevent accidental copying.
628 List(const List&) = delete;
629 List& operator=(const List&) = delete;
630
631 ~List();
632
Daniel Chenga367fe52022-02-15 18:08:48633 // Returns true if there are no values in this list and false otherwise.
634 bool empty() const;
635
636 // Returns the number of values in this list.
637 size_t size() const;
638
639 // Returns an iterator to the first value in this list.
640 iterator begin();
641 const_iterator begin() const;
642 const_iterator cbegin() const;
643
644 // Returns an iterator following the last value in this list. May not be
645 // dereferenced.
646 iterator end();
647 const_iterator end() const;
648 const_iterator cend() const;
649
Oksana Zhuravlovae48b9962023-05-23 14:36:24650 // Returns a reverse iterator preceding the first value in this list. May
651 // not be dereferenced.
Nan Lin0e8148a2023-06-27 11:44:34652 reverse_iterator rend();
653 const_reverse_iterator rend() const;
Oksana Zhuravlovae48b9962023-05-23 14:36:24654
655 // Returns a reverse iterator to the last value in this list.
Nan Lin0e8148a2023-06-27 11:44:34656 reverse_iterator rbegin();
657 const_reverse_iterator rbegin() const;
Oksana Zhuravlovae48b9962023-05-23 14:36:24658
Daniel Chengc9ab0ef2022-02-18 02:34:07659 // Returns a reference to the first value in the container. Fails with
660 // `CHECK()` if the list is empty.
661 const Value& front() const;
662 Value& front();
663
664 // Returns a reference to the last value in the container. Fails with
665 // `CHECK()` if the list is empty.
666 const Value& back() const;
667 Value& back();
668
669 // Increase the capacity of the backing container, but does not change
670 // the size. Assume all existing iterators will be invalidated.
671 void reserve(size_t capacity);
672
Andrew Rayskiy972ed6362023-05-25 14:32:36673 // Resizes the list.
674 // If `new_size` is greater than current size, the extra elements in the
675 // back will be destroyed.
676 // If `new_size` is less than current size, new default-initialized elements
677 // will be added to the back.
678 // Assume all existing iterators will be invalidated.
679 void resize(size_t new_size);
680
Daniel Chenga367fe52022-02-15 18:08:48681 // Returns a reference to the value at `index` in this list. Fails with a
682 // `CHECK()` if `index >= size()`.
683 const Value& operator[](size_t index) const;
684 Value& operator[](size_t index);
685
686 // Removes all value from this list.
Marijn Kruisselbrink8af7d722022-12-13 19:03:42687 REINITIALIZES_AFTER_MOVE void clear();
Daniel Chenga367fe52022-02-15 18:08:48688
Daniel Chengc9ab0ef2022-02-18 02:34:07689 // Removes the value referenced by `pos` in this list and returns an
690 // iterator to the value following the removed value.
Daniel Chenga367fe52022-02-15 18:08:48691 iterator erase(iterator pos);
692 const_iterator erase(const_iterator pos);
693
Matt Menke3a0de712022-07-14 23:45:08694 // Remove the values in the range [`first`, `last`). Returns iterator to the
695 // first value following the removed range, which is `last`. If `first` ==
696 // `last`, removes nothing and returns `last`.
697 iterator erase(iterator first, iterator last);
698 const_iterator erase(const_iterator first, const_iterator last);
699
Daniel Chenga367fe52022-02-15 18:08:48700 // Creates a deep copy of this dictionary.
701 List Clone() const;
702
703 // Appends `value` to the end of this list.
Jeroen Dhollander45a243342023-03-15 14:37:29704 void Append(Value&& value) &;
705 void Append(bool value) &;
Daniel Chenga367fe52022-02-15 18:08:48706 template <typename T>
707 void Append(const T*) = delete;
Jeroen Dhollander45a243342023-03-15 14:37:29708 void Append(int value) &;
709 void Append(double value) &;
710 void Append(StringPiece value) &;
711 void Append(StringPiece16 value) &;
712 void Append(const char* value) &;
713 void Append(const char16_t* value) &;
714 void Append(std::string&& value) &;
715 void Append(BlobStorage&& value) &;
716 void Append(Dict&& value) &;
717 void Append(List&& value) &;
718
719 // Rvalue overrides of the `Append` methods, which allow you to construct
720 // a `Value::List` builder-style:
721 //
722 // Value::List result = Value::List()
723 // .Append("first value")
724 // .Append(2)
725 // .Append(true);
726 //
727 // Each method returns a rvalue reference to `this`, so this is as efficient
728 // as (and less mistake-prone than) stand-alone calls to `Append`.
729 //
730 // The equivalent code without using these builder-style methods:
731 //
732 // Value::List bad_example;
733 // bad_example.Append("first value");
734 // bad_example.Append(2);
735 // bad_example.Append(true);
736 //
737 List&& Append(Value&& value) &&;
738 List&& Append(bool value) &&;
739 template <typename T>
740 List&& Append(const T*) && = delete;
741 List&& Append(int value) &&;
742 List&& Append(double value) &&;
743 List&& Append(StringPiece value) &&;
744 List&& Append(StringPiece16 value) &&;
745 List&& Append(const char* value) &&;
746 List&& Append(const char16_t* value) &&;
747 List&& Append(std::string&& value) &&;
748 List&& Append(BlobStorage&& value) &&;
749 List&& Append(Dict&& value) &&;
750 List&& Append(List&& value) &&;
Daniel Chenga367fe52022-02-15 18:08:48751
752 // Inserts `value` before `pos` in this list. Returns an iterator to the
753 // inserted value.
754 // TODO(dcheng): Should this provide the same set of overloads that Append()
755 // does?
756 iterator Insert(const_iterator pos, Value&& value);
757
758 // Erases all values equal to `value` from this list.
759 size_t EraseValue(const Value& value);
760
761 // Erases all values for which `predicate` evaluates to true from this list.
762 template <typename Predicate>
763 size_t EraseIf(Predicate predicate) {
764 return base::EraseIf(storage_, predicate);
765 }
766
Matt Menkee5772892023-01-10 03:10:31767 // Estimates dynamic memory usage. Requires tracing support
768 // (enable_base_tracing gn flag), otherwise always returns 0. See
769 // base/trace_event/memory_usage_estimator.h for more info.
770 size_t EstimateMemoryUsage() const;
771
Scott Haseleye51040782022-03-09 17:32:37772 // Serializes to a string for logging and debug purposes.
773 std::string DebugString() const;
774
Daniel Chengb5862bc2022-06-09 17:04:06775#if BUILDFLAG(ENABLE_BASE_TRACING)
776 // Write this object into a trace.
777 void WriteIntoTrace(perfetto::TracedValue) const;
778#endif // BUILDFLAG(ENABLE_BASE_TRACING)
779
Daniel Chenga367fe52022-02-15 18:08:48780 private:
Matt Menkee5772892023-01-10 03:10:31781 using ListStorage = std::vector<Value>;
782
Daniel Chenga367fe52022-02-15 18:08:48783 BASE_EXPORT friend bool operator==(const List& lhs, const List& rhs);
784 BASE_EXPORT friend bool operator!=(const List& lhs, const List& rhs);
785 BASE_EXPORT friend bool operator<(const List& lhs, const List& rhs);
786 BASE_EXPORT friend bool operator>(const List& lhs, const List& rhs);
787 BASE_EXPORT friend bool operator<=(const List& lhs, const List& rhs);
788 BASE_EXPORT friend bool operator>=(const List& lhs, const List& rhs);
789
Daniel Chenga367fe52022-02-15 18:08:48790 explicit List(const std::vector<Value>& storage);
791
792 std::vector<Value> storage_;
793 };
jdoerriee03e80f2017-02-15 08:42:14794
[email protected]2f03f532013-07-17 08:43:33795 // Note: Do not add more types. See the file-level comment above for why.
initial.commitd7cae122008-07-26 21:49:38796
jdoerrie5c1cee112017-03-28 17:52:00797 // Comparison operators so that Values can easily be used with standard
798 // library algorithms and associative containers.
799 BASE_EXPORT friend bool operator==(const Value& lhs, const Value& rhs);
800 BASE_EXPORT friend bool operator!=(const Value& lhs, const Value& rhs);
801 BASE_EXPORT friend bool operator<(const Value& lhs, const Value& rhs);
802 BASE_EXPORT friend bool operator>(const Value& lhs, const Value& rhs);
803 BASE_EXPORT friend bool operator<=(const Value& lhs, const Value& rhs);
804 BASE_EXPORT friend bool operator>=(const Value& lhs, const Value& rhs);
805
Daniel Cheng0b0b6752022-05-25 02:59:48806 BASE_EXPORT friend bool operator==(const Value& lhs, bool rhs);
807 friend bool operator==(bool lhs, const Value& rhs) { return rhs == lhs; }
808 friend bool operator!=(const Value& lhs, bool rhs) { return !(lhs == rhs); }
809 friend bool operator!=(bool lhs, const Value& rhs) { return !(lhs == rhs); }
Daniel Cheng6b621cf2022-06-02 02:42:02810 template <typename T>
811 friend bool operator==(const Value& lhs, const T* rhs) = delete;
812 template <typename T>
813 friend bool operator==(const T* lhs, const Value& rhs) = delete;
814 template <typename T>
815 friend bool operator!=(const Value& lhs, const T* rhs) = delete;
816 template <typename T>
817 friend bool operator!=(const T* lhs, const Value& rhs) = delete;
Daniel Cheng0b0b6752022-05-25 02:59:48818 BASE_EXPORT friend bool operator==(const Value& lhs, int rhs);
819 friend bool operator==(int lhs, const Value& rhs) { return rhs == lhs; }
820 friend bool operator!=(const Value& lhs, int rhs) { return !(lhs == rhs); }
821 friend bool operator!=(int lhs, const Value& rhs) { return !(lhs == rhs); }
822 BASE_EXPORT friend bool operator==(const Value& lhs, double rhs);
823 friend bool operator==(double lhs, const Value& rhs) { return rhs == lhs; }
824 friend bool operator!=(const Value& lhs, double rhs) { return !(lhs == rhs); }
825 friend bool operator!=(double lhs, const Value& rhs) { return !(lhs == rhs); }
Daniel Cheng6b621cf2022-06-02 02:42:02826 // Note: StringPiece16 overload intentionally omitted: Value internally stores
827 // strings as UTF-8. While it is possible to implement a comparison operator
828 // that would not require first creating a new UTF-8 string from the UTF-16
829 // string argument, it is simpler to just not implement it at all for a rare
830 // use case.
Daniel Cheng0b0b6752022-05-25 02:59:48831 BASE_EXPORT friend bool operator==(const Value& lhs, StringPiece rhs);
832 friend bool operator==(StringPiece lhs, const Value& rhs) {
833 return rhs == lhs;
834 }
835 friend bool operator!=(const Value& lhs, StringPiece rhs) {
836 return !(lhs == rhs);
837 }
838 friend bool operator!=(StringPiece lhs, const Value& rhs) {
839 return !(lhs == rhs);
840 }
Daniel Cheng6b621cf2022-06-02 02:42:02841 friend bool operator==(const Value& lhs, const char* rhs) {
842 return lhs == StringPiece(rhs);
843 }
844 friend bool operator==(const char* lhs, const Value& rhs) {
845 return rhs == lhs;
846 }
847 friend bool operator!=(const Value& lhs, const char* rhs) {
848 return !(lhs == rhs);
849 }
850 friend bool operator!=(const char* lhs, const Value& rhs) {
851 return !(lhs == rhs);
852 }
853 friend bool operator==(const Value& lhs, const std::string& rhs) {
854 return lhs == StringPiece(rhs);
855 }
856 friend bool operator==(const std::string& lhs, const Value& rhs) {
857 return rhs == lhs;
858 }
859 friend bool operator!=(const Value& lhs, const std::string& rhs) {
860 return !(lhs == rhs);
861 }
862 friend bool operator!=(const std::string& lhs, const Value& rhs) {
863 return !(lhs == rhs);
864 }
Daniel Cheng0b0b6752022-05-25 02:59:48865 // Note: Blob support intentionally omitted as an experiment for potentially
866 // wholly removing Blob support from Value itself in the future.
867 BASE_EXPORT friend bool operator==(const Value& lhs, const Value::Dict& rhs);
868 friend bool operator==(const Value::Dict& lhs, const Value& rhs) {
869 return rhs == lhs;
870 }
871 friend bool operator!=(const Value& lhs, const Value::Dict& rhs) {
872 return !(lhs == rhs);
873 }
874 friend bool operator!=(const Value::Dict& lhs, const Value& rhs) {
875 return !(lhs == rhs);
876 }
877 BASE_EXPORT friend bool operator==(const Value& lhs, const Value::List& rhs);
878 friend bool operator==(const Value::List& lhs, const Value& rhs) {
879 return rhs == lhs;
880 }
881 friend bool operator!=(const Value& lhs, const Value::List& rhs) {
882 return !(lhs == rhs);
883 }
884 friend bool operator!=(const Value::List& lhs, const Value& rhs) {
885 return !(lhs == rhs);
886 }
887
Eric Secklerf6c544f2020-06-02 10:49:21888 // Estimates dynamic memory usage. Requires tracing support
889 // (enable_base_tracing gn flag), otherwise always returns 0. See
890 // base/trace_event/memory_usage_estimator.h for more info.
Alexander Yashkinab504e72017-11-30 11:54:45891 size_t EstimateMemoryUsage() const;
892
Alan Cutter2dd83032020-12-08 21:55:00893 // Serializes to a string for logging and debug purposes.
894 std::string DebugString() const;
895
Peter Kotwicz83a231372021-04-13 17:42:12896#if BUILDFLAG(ENABLE_BASE_TRACING)
Alexander Timine68aeb32021-04-11 23:06:21897 // Write this object into a trace.
Alexander Timinbebb2002021-04-20 15:42:24898 void WriteIntoTrace(perfetto::TracedValue) const;
Peter Kotwicz83a231372021-04-13 17:42:12899#endif // BUILDFLAG(ENABLE_BASE_TRACING)
Alexander Timine68aeb32021-04-11 23:06:21900
Daniel Cheng8ac305b2022-02-17 00:05:11901 template <typename Visitor>
902 auto Visit(Visitor&& visitor) const {
903 return absl::visit(std::forward<Visitor>(visitor), data_);
904 }
905
Jan Wilken Dörrie79d022142020-08-19 18:18:32906 private:
Daniel Cheng8ac305b2022-02-17 00:05:11907 // For access to DoubleStorage.
908 friend class ValueView;
909
David 'Digit' Turner2f287312019-04-03 14:32:09910 // Special case for doubles, which are aligned to 8 bytes on some
911 // 32-bit architectures. In this case, a simple declaration as a
912 // double member would make the whole union 8 byte-aligned, which
913 // would also force 4 bytes of wasted padding space before it in
914 // the Value layout.
David 'Digit' Turner806dedb82019-03-06 17:43:11915 //
David 'Digit' Turner2f287312019-04-03 14:32:09916 // To override this, store the value as an array of 32-bit integers, and
917 // perform the appropriate bit casts when reading / writing to it.
Daniel Cheng6b621cf2022-06-02 02:42:02918 class BASE_EXPORT DoubleStorage {
Daniel Cheng782d2ba32022-02-16 19:40:29919 public:
920 explicit DoubleStorage(double v);
921 DoubleStorage(const DoubleStorage&) = default;
922 DoubleStorage& operator=(const DoubleStorage&) = default;
923
Daniel Cheng8ac305b2022-02-17 00:05:11924 // Provide an implicit conversion to double to simplify the use of visitors
925 // with `Value::Visit()`. Otherwise, visitors would need a branch for
926 // handling `DoubleStorage` like:
927 //
928 // value.Visit([] (const auto& member) {
929 // using T = std::decay_t<decltype(member)>;
930 // if constexpr (std::is_same_v<T, Value::DoubleStorage>) {
931 // SomeFunction(double{member});
932 // } else {
933 // SomeFunction(member);
934 // }
935 // });
Peter Kastingcc88ac052022-05-03 09:58:01936 operator double() const { return base::bit_cast<double>(v_); }
Daniel Cheng782d2ba32022-02-16 19:40:29937
938 private:
939 friend bool operator==(const DoubleStorage& lhs, const DoubleStorage& rhs) {
Daniel Cheng8ac305b2022-02-17 00:05:11940 return double{lhs} == double{rhs};
Daniel Cheng782d2ba32022-02-16 19:40:29941 }
942
943 friend bool operator!=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
944 return !(lhs == rhs);
945 }
946
947 friend bool operator<(const DoubleStorage& lhs, const DoubleStorage& rhs) {
Daniel Cheng8ac305b2022-02-17 00:05:11948 return double{lhs} < double{rhs};
Daniel Cheng782d2ba32022-02-16 19:40:29949 }
950
951 friend bool operator>(const DoubleStorage& lhs, const DoubleStorage& rhs) {
952 return rhs < lhs;
953 }
954
955 friend bool operator<=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
956 return !(rhs < lhs);
957 }
958
959 friend bool operator>=(const DoubleStorage& lhs, const DoubleStorage& rhs) {
960 return !(lhs < rhs);
961 }
962
963 alignas(4) std::array<char, sizeof(double)> v_;
964 };
David 'Digit' Turner2f287312019-04-03 14:32:09965
Jan Wilken Dörrie79d022142020-08-19 18:18:32966 // Internal constructors, allowing the simplify the implementation of Clone().
967 explicit Value(absl::monostate);
968 explicit Value(DoubleStorage storage);
jdoerrie8e945542017-02-17 13:54:49969
Claudio DeSouzab8754a3e2022-07-25 18:08:45970 // A helper for static functions used for cloning a Value or a ValueView.
971 class CloningHelper;
972
Jan Wilken Dörrie79d022142020-08-19 18:18:32973 absl::variant<absl::monostate,
974 bool,
975 int,
976 DoubleStorage,
977 std::string,
978 BlobStorage,
Daniel Chenga367fe52022-02-15 18:08:48979 Dict,
980 List>
Jan Wilken Dörrie79d022142020-08-19 18:18:32981 data_;
initial.commitd7cae122008-07-26 21:49:38982};
983
Daniel Cheng8ac305b2022-02-17 00:05:11984// Adapter so `Value::Dict` or `Value::List` can be directly passed to JSON
985// serialization methods without having to clone the contents and transfer
986// ownership of the clone to a `Value` wrapper object.
987//
988// Like `StringPiece` and `span<T>`, this adapter does NOT retain ownership. Any
989// underlying object that is passed by reference (i.e. `std::string`,
990// `Value::BlobStorage`, `Value::Dict`, `Value::List`, or `Value`) MUST remain
991// live as long as there is a `ValueView` referencing it.
992//
993// While it might be nice to just use the `absl::variant` type directly, the
994// need to use `std::reference_wrapper` makes it clunky. `absl::variant` and
995// `std::reference_wrapper` both support implicit construction, but C++ only
996// allows at most one user-defined conversion in an implicit conversion
997// sequence. If this adapter and its implicit constructors did not exist,
998// callers would need to use `std::ref` or `std::cref` to pass `Value::Dict` or
999// `Value::List` to a function with a `ValueView` parameter.
1000class BASE_EXPORT GSL_POINTER ValueView {
1001 public:
Daniel Cheng6b621cf2022-06-02 02:42:021002 ValueView() = default;
Daniel Cheng8ac305b2022-02-17 00:05:111003 ValueView(bool value) : data_view_(value) {}
Daniel Cheng6b621cf2022-06-02 02:42:021004 template <typename T>
1005 ValueView(const T*) = delete;
Daniel Cheng8ac305b2022-02-17 00:05:111006 ValueView(int value) : data_view_(value) {}
1007 ValueView(double value)
1008 : data_view_(absl::in_place_type_t<Value::DoubleStorage>(), value) {}
Daniel Cheng6b621cf2022-06-02 02:42:021009 ValueView(StringPiece value) : data_view_(value) {}
1010 ValueView(const char* value) : ValueView(StringPiece(value)) {}
1011 ValueView(const std::string& value) : ValueView(StringPiece(value)) {}
1012 // Note: UTF-16 is intentionally not supported. ValueView is intended to be a
1013 // low-cost view abstraction, but Value internally represents strings as
1014 // UTF-8, so it would not be possible to implement this without allocating an
1015 // entirely new UTF-8 string.
Daniel Cheng8ac305b2022-02-17 00:05:111016 ValueView(const Value::BlobStorage& value) : data_view_(value) {}
1017 ValueView(const Value::Dict& value) : data_view_(value) {}
1018 ValueView(const Value::List& value) : data_view_(value) {}
1019 ValueView(const Value& value);
1020
Daniel Cheng6b621cf2022-06-02 02:42:021021 // This is the only 'getter' method provided as `ValueView` is not intended
1022 // to be a general replacement of `Value`.
Daniel Cheng8ac305b2022-02-17 00:05:111023 template <typename Visitor>
1024 auto Visit(Visitor&& visitor) const {
1025 return absl::visit(std::forward<Visitor>(visitor), data_view_);
1026 }
1027
Claudio DeSouza75d1f3412022-07-22 21:06:421028 // Returns a clone of the underlying Value.
1029 Value ToValue() const;
1030
Daniel Cheng8ac305b2022-02-17 00:05:111031 private:
1032 using ViewType =
1033 absl::variant<absl::monostate,
1034 bool,
1035 int,
1036 Value::DoubleStorage,
Daniel Cheng6b621cf2022-06-02 02:42:021037 StringPiece,
Daniel Cheng8ac305b2022-02-17 00:05:111038 std::reference_wrapper<const Value::BlobStorage>,
1039 std::reference_wrapper<const Value::Dict>,
1040 std::reference_wrapper<const Value::List>>;
1041
Daniel Cheng6b621cf2022-06-02 02:42:021042 public:
1043 using DoubleStorageForTest = Value::DoubleStorage;
1044 const ViewType& data_view_for_test() const { return data_view_; }
1045
1046 private:
Daniel Cheng8ac305b2022-02-17 00:05:111047 ViewType data_view_;
1048};
1049
prashhir54a994502015-03-05 09:30:571050// This interface is implemented by classes that know how to serialize
1051// Value objects.
[email protected]0bea7252011-08-05 15:34:001052class BASE_EXPORT ValueSerializer {
initial.commitd7cae122008-07-26 21:49:381053 public:
[email protected]3a3d47472010-07-15 21:03:541054 virtual ~ValueSerializer();
[email protected]abb9d0c2008-08-06 15:46:591055
Daniel Cheng8ac305b2022-02-17 00:05:111056 virtual bool Serialize(ValueView root) = 0;
prashhir54a994502015-03-05 09:30:571057};
1058
1059// This interface is implemented by classes that know how to deserialize Value
1060// objects.
1061class BASE_EXPORT ValueDeserializer {
1062 public:
1063 virtual ~ValueDeserializer();
initial.commitd7cae122008-07-26 21:49:381064
1065 // This method deserializes the subclass-specific format into a Value object.
[email protected]b4cebf82008-12-29 19:59:081066 // If the return value is non-NULL, the caller takes ownership of returned
Nigel Tao410788e2020-06-24 07:12:271067 // Value.
1068 //
Gabriel Charetteb49d73a2021-05-05 20:05:591069 // If the return value is nullptr, and if `error_code` is non-nullptr,
1070 // `*error_code` will be set to an integer value representing the underlying
Nigel Tao410788e2020-06-24 07:12:271071 // error. See "enum ErrorCode" below for more detail about the integer value.
1072 //
Gabriel Charetteb49d73a2021-05-05 20:05:591073 // If `error_message` is non-nullptr, it will be filled in with a formatted
[email protected]ba399672010-04-06 15:42:391074 // error message including the location of the error if appropriate.
dcheng093de9b2016-04-04 21:25:511075 virtual std::unique_ptr<Value> Deserialize(int* error_code,
Nigel Tao410788e2020-06-24 07:12:271076 std::string* error_message) = 0;
1077
1078 // The integer-valued error codes form four groups:
1079 // - The value 0 means no error.
1080 // - Values between 1 and 999 inclusive mean an error in the data (i.e.
1081 // content). The bytes being deserialized are not in the right format.
1082 // - Values 1000 and above mean an error in the metadata (i.e. context). The
1083 // file could not be read, the network is down, etc.
1084 // - Negative values are reserved.
Caitlin Fischeraac06dc2021-12-17 00:21:321085 //
1086 // These values are persisted to logs. Entries should not be renumbered and
1087 // numeric values should never be reused.
Nigel Tao410788e2020-06-24 07:12:271088 enum ErrorCode {
1089 kErrorCodeNoError = 0,
1090 // kErrorCodeInvalidFormat is a generic error code for "the data is not in
1091 // the right format". Subclasses of ValueDeserializer may return other
1092 // values for more specific errors.
1093 kErrorCodeInvalidFormat = 1,
1094 // kErrorCodeFirstMetadataError is the minimum value (inclusive) of the
1095 // range of metadata errors.
1096 kErrorCodeFirstMetadataError = 1000,
1097 };
1098
Gabriel Charetteb49d73a2021-05-05 20:05:591099 // The `error_code` argument can be one of the ErrorCode values, but it is
Nigel Tao410788e2020-06-24 07:12:271100 // not restricted to only being 0, 1 or 1000. Subclasses of ValueDeserializer
1101 // can define their own error code values.
1102 static inline bool ErrorCodeIsDataError(int error_code) {
1103 return (kErrorCodeInvalidFormat <= error_code) &&
1104 (error_code < kErrorCodeFirstMetadataError);
1105 }
initial.commitd7cae122008-07-26 21:49:381106};
1107
Daniel Chenga367fe52022-02-15 18:08:481108// Stream operator so Values can be pretty printed by gtest.
[email protected]e4ef8312012-09-12 03:39:351109BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value);
Daniel Chenga367fe52022-02-15 18:08:481110BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1111 const Value::Dict& dict);
1112BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1113 const Value::List& list);
[email protected]e4ef8312012-09-12 03:39:351114
jdoerriedc72ee942016-12-07 15:43:281115// Stream operator so that enum class Types can be used in log statements.
1116BASE_EXPORT std::ostream& operator<<(std::ostream& out,
1117 const Value::Type& type);
1118
[email protected]f3a1c642011-07-12 19:15:031119} // namespace base
1120
[email protected]101d5422008-09-26 20:22:421121#endif // BASE_VALUES_H_