1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_VALUES_H_ 6 #define BASE_VALUES_H_ 7 8 #include <stddef.h> 9 #include <stdint.h> 10 11 #include <array> 12 #include <initializer_list> 13 #include <iosfwd> 14 #include <iterator> 15 #include <memory> 16 #include <string> 17 #include <utility> 18 #include <vector> 19 20 #include "base/base_export.h" 21 #include "base/bit_cast.h" 22 #include "base/compiler_specific.h" 23 #include "base/containers/checked_iterators.h" 24 #include "base/containers/cxx20_erase_vector.h" 25 #include "base/containers/flat_map.h" 26 #include "base/containers/span.h" 27 #include "base/memory/raw_ref.h" 28 #include "base/strings/string_piece.h" 29 #include "base/trace_event/base_tracing_forward.h" 30 #include "base/value_iterators.h" 31 #include "third_party/abseil-cpp/absl/types/optional.h" 32 #include "third_party/abseil-cpp/absl/types/variant.h" 33 34 namespace base { 35 36 // 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 45 // 46 // With the exception of binary blobs, `Value` is intended to be the C++ version 47 // of data types that can be represented in JSON. 48 // 49 // 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 // 135 // If a path only has one component (i.e. has no dots), please use the regular, 136 // non-path APIs. 137 // 138 // Lists support: 139 // - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`, 140 // `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. 144 // - `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. 151 class BASE_EXPORT GSL_OWNER Value { 152 public: 153 using BlobStorage = std::vector<uint8_t>; 154 155 class Dict; 156 class List; 157 158 enum class Type : unsigned char { 159 NONE = 0, 160 BOOLEAN, 161 INTEGER, 162 DOUBLE, 163 STRING, 164 BINARY, 165 DICT, 166 LIST, 167 // Note: Do not add more types. See the file-level comment above for why. 168 }; 169 170 // 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 174 Value() noexcept; 175 176 Value(Value&&) noexcept; 177 Value& operator=(Value&&) noexcept; 178 179 // Deleted to prevent accidental copying. 180 Value(const Value&) = delete; 181 Value& operator=(const Value&) = delete; 182 183 // 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 231 ~Value(); 232 233 // Returns the name for a given `type`. 234 static const char* GetTypeName(Type type); 235 236 // Returns the type of the value stored by the current Value object. type()237 Type type() const { return static_cast<Type>(data_.index()); } 238 239 // Returns true if the current object represents a given type. is_none()240 bool is_none() const { return type() == Type::NONE; } is_bool()241 bool is_bool() const { return type() == Type::BOOLEAN; } is_int()242 bool is_int() const { return type() == Type::INTEGER; } is_double()243 bool is_double() const { return type() == Type::DOUBLE; } is_string()244 bool is_string() const { return type() == Type::STRING; } is_blob()245 bool is_blob() const { return type() == Type::BINARY; } is_dict()246 bool is_dict() const { return type() == Type::DICT; } is_list()247 bool is_list() const { return type() == Type::LIST; } 248 249 // 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. 253 absl::optional<bool> GetIfBool() const; 254 absl::optional<int> GetIfInt() const; 255 // Returns a non-null value for both `Value::Type::DOUBLE` and 256 // `Value::Type::INT`, converting the latter to a double. 257 absl::optional<double> GetIfDouble() const; 258 const std::string* GetIfString() const; 259 std::string* GetIfString(); 260 const BlobStorage* GetIfBlob() const; 261 const Dict* GetIfDict() const; 262 Dict* GetIfDict(); 263 const List* GetIfList() const; 264 List* GetIfList(); 265 266 // 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. 269 bool GetBool() const; 270 int GetInt() const; 271 // Returns a value for both `Value::Type::DOUBLE` and `Value::Type::INT`, 272 // converting the latter to a double. 273 double GetDouble() const; 274 const std::string& GetString() const; 275 std::string& GetString(); 276 const BlobStorage& GetBlob() const; 277 const Dict& GetDict() const; 278 Dict& GetDict(); 279 const List& GetList() const; 280 List& GetList(); 281 282 // 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. 285 // Prefer over `std::move(value.Get...())` so clang-tidy can warn about 286 // potential use-after-move mistakes. 287 std::string TakeString() &&; 288 Dict TakeDict() &&; 289 List TakeList() &&; 290 291 // Represents a dictionary of string keys to Values. 292 class BASE_EXPORT GSL_OWNER Dict { 293 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 306 // 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> Dict(std::move_iterator<IteratorType> first,std::move_iterator<IteratorType> last)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 328 ~Dict(); 329 330 // 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. 352 REINITIALIZES_AFTER_MOVE void clear(); 353 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`. 367 void Merge(Dict dict); 368 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 391 // 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 398 // 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`. 400 Value* Set(StringPiece key, Value&& value) &; 401 Value* Set(StringPiece key, bool value) &; 402 template <typename T> 403 Value* Set(StringPiece, const T*) & = delete; 404 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 stand-alone calls to `Set`, while also making it harder to 433 // accidentally insert items in the wrong dictionary. 434 // 435 // The equivalent code without using these builder-style methods: 436 // 437 // 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) 441 // Value::Dict nested_dictionary; 442 // nested_dictionary.Set("nested-key-1", "value"); 443 // nested_dictionary.Set("nested-key-2", true); 444 // no_builder_example.Set("nested_dictionary", 445 // std::move(nested_dictionary)); 446 // Value::List nested_list; 447 // nested_list.Append("nested-list-value"); 448 // nested_list.Append(5); 449 // nested_list.Append(true); 450 // 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")); 464 // 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) &&; 479 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 // 493 // 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. 500 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 516 // 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. 520 // 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) &; 530 template <typename T> 531 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) &&; 590 591 bool RemoveByDottedPath(StringPiece path); 592 593 absl::optional<Value> ExtractByDottedPath(StringPiece path); 594 595 // 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 600 // Serializes to a string for logging and debug purposes. 601 std::string DebugString() const; 602 603 #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 608 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 616 explicit Dict(const flat_map<std::string, std::unique_ptr<Value>>& storage); 617 618 // TODO(dcheng): Replace with `flat_map<std::string, Value>` once no caller 619 // relies on stability of pointers anymore. 620 flat_map<std::string, std::unique_ptr<Value>> storage_; 621 }; 622 623 // Represents a list of Values. 624 class BASE_EXPORT GSL_OWNER List { 625 public: 626 using iterator = CheckedContiguousIterator<Value>; 627 using const_iterator = CheckedContiguousConstIterator<Value>; 628 using reverse_iterator = std::reverse_iterator<iterator>; 629 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 630 using value_type = Value; 631 632 // 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 637 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 648 // 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 665 // Returns a reverse iterator preceding the first value in this list. May 666 // not be dereferenced. 667 reverse_iterator rend(); 668 const_reverse_iterator rend() const; 669 670 // Returns a reverse iterator to the last value in this list. 671 reverse_iterator rbegin(); 672 const_reverse_iterator rbegin() const; 673 674 // 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 688 // 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 696 // 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. 702 REINITIALIZES_AFTER_MOVE void clear(); 703 704 // Removes the value referenced by `pos` in this list and returns an 705 // iterator to the value following the removed value. 706 iterator erase(iterator pos); 707 const_iterator erase(const_iterator pos); 708 709 // 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 715 // Creates a deep copy of this dictionary. 716 List Clone() const; 717 718 // Appends `value` to the end of this list. 719 void Append(Value&& value) &; 720 void Append(bool value) &; 721 template <typename T> 722 void Append(const T*) & = delete; 723 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 // 737 // Value::List result = 738 // Value::List().Append("first value").Append(2).Append(true); 739 // 740 // Each method returns a rvalue reference to `this`, so this is as efficient 741 // as stand-alone calls to `Append`, while at the same time making it harder 742 // to accidentally append to the wrong list. 743 // 744 // The equivalent code without using these builder-style methods: 745 // 746 // Value::List no_builder_example; 747 // no_builder_example.Append("first value"); 748 // no_builder_example.Append(2); 749 // no_builder_example.Append(true); 750 // 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) &&; 765 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> EraseIf(Predicate predicate)777 size_t EraseIf(Predicate predicate) { 778 return base::EraseIf(storage_, predicate); 779 } 780 781 // 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 786 // Serializes to a string for logging and debug purposes. 787 std::string DebugString() const; 788 789 #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 794 private: 795 using ListStorage = std::vector<Value>; 796 797 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 804 explicit List(const std::vector<Value>& storage); 805 806 std::vector<Value> storage_; 807 }; 808 809 // Note: Do not add more types. See the file-level comment above for why. 810 811 // 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 820 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); } 824 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; 832 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); } 840 // 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. 845 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 } 855 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 } 879 // 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 902 // 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. 905 size_t EstimateMemoryUsage() const; 906 907 // Serializes to a string for logging and debug purposes. 908 std::string DebugString() const; 909 910 #if BUILDFLAG(ENABLE_BASE_TRACING) 911 // Write this object into a trace. 912 void WriteIntoTrace(perfetto::TracedValue) const; 913 #endif // BUILDFLAG(ENABLE_BASE_TRACING) 914 915 template <typename Visitor> Visit(Visitor && visitor)916 auto Visit(Visitor&& visitor) const { 917 return absl::visit(std::forward<Visitor>(visitor), data_); 918 } 919 920 private: 921 // For access to DoubleStorage. 922 friend class ValueView; 923 924 // 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. 929 // 930 // 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. 932 class BASE_EXPORT DoubleStorage { 933 public: 934 explicit DoubleStorage(double v); 935 DoubleStorage(const DoubleStorage&) = default; 936 DoubleStorage& operator=(const DoubleStorage&) = default; 937 938 // 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 // }); 950 operator double() const { return base::bit_cast<double>(v_); } 951 952 private: 953 friend bool operator==(const DoubleStorage& lhs, const DoubleStorage& rhs) { 954 return double{lhs} == double{rhs}; 955 } 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) { 962 return double{lhs} < double{rhs}; 963 } 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 }; 979 980 // Internal constructors, allowing the simplify the implementation of Clone(). 981 explicit Value(absl::monostate); 982 explicit Value(DoubleStorage storage); 983 984 // A helper for static functions used for cloning a Value or a ValueView. 985 class CloningHelper; 986 987 absl::variant<absl::monostate, 988 bool, 989 int, 990 DoubleStorage, 991 std::string, 992 BlobStorage, 993 Dict, 994 List> 995 data_; 996 }; 997 998 // 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. 1014 class BASE_EXPORT GSL_POINTER ValueView { 1015 public: 1016 ValueView() = default; ValueView(bool value)1017 ValueView(bool value) : data_view_(value) {} 1018 template <typename T> 1019 ValueView(const T*) = delete; ValueView(int value)1020 ValueView(int value) : data_view_(value) {} ValueView(double value)1021 ValueView(double value) 1022 : data_view_(absl::in_place_type_t<Value::DoubleStorage>(), value) {} ValueView(StringPiece value)1023 ValueView(StringPiece value) : data_view_(value) {} ValueView(const char * value)1024 ValueView(const char* value) : ValueView(StringPiece(value)) {} ValueView(const std::string & 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. ValueView(const Value::BlobStorage & value)1030 ValueView(const Value::BlobStorage& value) : data_view_(value) {} ValueView(const Value::Dict & value)1031 ValueView(const Value::Dict& value) : data_view_(value) {} ValueView(const Value::List & value)1032 ValueView(const Value::List& value) : data_view_(value) {} 1033 ValueView(const Value& value); 1034 1035 // This is the only 'getter' method provided as `ValueView` is not intended 1036 // to be a general replacement of `Value`. 1037 template <typename Visitor> Visit(Visitor && visitor)1038 auto Visit(Visitor&& visitor) const { 1039 return absl::visit(std::forward<Visitor>(visitor), data_view_); 1040 } 1041 1042 // Returns a clone of the underlying Value. 1043 Value ToValue() const; 1044 1045 private: 1046 using ViewType = 1047 absl::variant<absl::monostate, 1048 bool, 1049 int, 1050 Value::DoubleStorage, 1051 StringPiece, 1052 std::reference_wrapper<const Value::BlobStorage>, 1053 std::reference_wrapper<const Value::Dict>, 1054 std::reference_wrapper<const Value::List>>; 1055 1056 public: 1057 using DoubleStorageForTest = Value::DoubleStorage; data_view_for_test()1058 const ViewType& data_view_for_test() const { return data_view_; } 1059 1060 private: 1061 ViewType data_view_; 1062 }; 1063 1064 // This interface is implemented by classes that know how to serialize 1065 // Value objects. 1066 class BASE_EXPORT ValueSerializer { 1067 public: 1068 virtual ~ValueSerializer(); 1069 1070 virtual bool Serialize(ValueView root) = 0; 1071 }; 1072 1073 // This interface is implemented by classes that know how to deserialize Value 1074 // objects. 1075 class BASE_EXPORT ValueDeserializer { 1076 public: 1077 virtual ~ValueDeserializer(); 1078 1079 // This method deserializes the subclass-specific format into a Value object. 1080 // If the return value is non-NULL, the caller takes ownership of returned 1081 // Value. 1082 // 1083 // 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 1085 // error. See "enum ErrorCode" below for more detail about the integer value. 1086 // 1087 // If `error_message` is non-nullptr, it will be filled in with a formatted 1088 // error message including the location of the error if appropriate. 1089 virtual std::unique_ptr<Value> Deserialize(int* error_code, 1090 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. 1099 // 1100 // These values are persisted to logs. Entries should not be renumbered and 1101 // numeric values should never be reused. 1102 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 1113 // The `error_code` argument can be one of the ErrorCode values, but it is 1114 // not restricted to only being 0, 1 or 1000. Subclasses of ValueDeserializer 1115 // can define their own error code values. ErrorCodeIsDataError(int error_code)1116 static inline bool ErrorCodeIsDataError(int error_code) { 1117 return (kErrorCodeInvalidFormat <= error_code) && 1118 (error_code < kErrorCodeFirstMetadataError); 1119 } 1120 }; 1121 1122 // Stream operator so Values can be pretty printed by gtest. 1123 BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value); 1124 BASE_EXPORT std::ostream& operator<<(std::ostream& out, 1125 const Value::Dict& dict); 1126 BASE_EXPORT std::ostream& operator<<(std::ostream& out, 1127 const Value::List& list); 1128 1129 // Stream operator so that enum class Types can be used in log statements. 1130 BASE_EXPORT std::ostream& operator<<(std::ostream& out, 1131 const Value::Type& type); 1132 1133 } // namespace base 1134 1135 #endif // BASE_VALUES_H_ 1136