// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_VALUES_H_ #define BASE_VALUES_H_ #include <stddef.h> #include <stdint.h> #include <array> #include <initializer_list> #include <iosfwd> #include <iterator> #include <memory> #include <optional> #include <string> #include <string_view> #include <utility> #include <vector> #include "base/base_export.h" #include "base/bit_cast.h" #include "base/compiler_specific.h" #include "base/containers/checked_iterators.h" #include "base/containers/flat_map.h" #include "base/containers/span.h" #include "base/memory/raw_ref.h" #include "base/trace_event/base_tracing_forward.h" #include "base/value_iterators.h" #include "third_party/abseil-cpp/absl/types/variant.h" namespace base { // The `Value` class is a variant type can hold one of the following types: // - null // - bool // - int // - double // - string (internally UTF8-encoded) // - binary data (i.e. a blob) // - dictionary of string keys to `Value`s // - list of `Value`s // // With the exception of binary blobs, `Value` is intended to be the C++ version // of data types that can be represented in JSON. // // Warning: blob support may be removed in the future. // // ## Usage // // Do not use `Value` if a more specific type would be more appropriate. For // example, a function that only accepts dictionary values should have a // `base::Value::Dict` parameter, not a `base::Value` parameter. // // Construction: // // `Value` is directly constructible from `bool`, `int`, `double`, binary blobs // (`std::vector<uint8_t>`), `std::string_view`, `std::u16string_view`, // `Value::Dict`, and `Value::List`. // // Copying: // // `Value` does not support C++ copy semantics to make it harder to accidentally // copy large values. Instead, use `Clone()` to manually create a deep copy. // // Reading: // // `GetBool()`, GetInt()`, et cetera `CHECK()` that the `Value` has the correct // subtype before returning the contained value. `bool`, `int`, `double` are // returned by value. Binary blobs, `std::string`, `Value::Dict`, `Value::List` // are returned by reference. // // `GetIfBool()`, `GetIfInt()`, et cetera return `std::nullopt`/`nullptr` if // the `Value` does not have the correct subtype; otherwise, returns the value // wrapped in an `std::optional` (for `bool`, `int`, `double`) or by pointer // (for binary blobs, `std::string`, `Value::Dict`, `Value::List`). // // Note: both `GetDouble()` and `GetIfDouble()` still return a non-null result // when the subtype is `Value::Type::INT`. In that case, the stored value is // coerced to a double before being returned. // // Assignment: // // It is not possible to directly assign `bool`, `int`, et cetera to a `Value`. // Instead, wrap the underlying type in `Value` before assigning. // // ## Dictionaries and Lists // // `Value` provides the `Value::Dict` and `Value::List` container types for // working with dictionaries and lists of values respectively, rather than // exposing the underlying container types directly. This allows the types to // provide convenient helpers for dictionaries and lists, as well as giving // greater flexibility for changing implementation details in the future. // // Both container types support enough STL-isms to be usable in range-based for // loops and generic operations such as those from <algorithm>. // // Dictionaries support: // - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`, // `contains()`, `clear()`, `erase()`: Identical to the STL container // equivalents, with additional safety checks, e.g. iterators will // `CHECK()` if `end()` is dereferenced. // // - `Clone()`: Create a deep copy. // - `Merge()`: Merge another dictionary into this dictionary. // - `Find()`: Find a value by `std::string_view` key, returning nullptr if the // key is not present. // - `FindBool()`, `FindInt()`, ...: Similar to `Find()`, but ensures that the // `Value` also has the correct subtype. Same return semantics as // `GetIfBool()`, `GetIfInt()`, et cetera, returning `std::nullopt` or // `nullptr` if the key is not present or the value has the wrong subtype. // - `Set()`: Associate a value with a `std::string_view` key. Accepts `Value` // or any of the subtypes that `Value` can hold. // - `Remove()`: Remove the key from this dictionary, if present. // - `Extract()`: If the key is present in the dictionary, removes the key from // the dictionary and transfers ownership of `Value` to the caller. // Otherwise, returns `std::nullopt`. // // Dictionaries also support an additional set of helper methods that operate on // "paths": `FindByDottedPath()`, `SetByDottedPath()`, `RemoveByDottedPath()`, // and `ExtractByDottedPath()`. Dotted paths are a convenience method of naming // intermediate nested dictionaries, separating the components of the path using // '.' characters. For example, finding a string path on a `Value::Dict` using // the dotted path: // // "aaa.bbb.ccc" // // Will first look for a `Value::Type::DICT` associated with the key "aaa", then // another `Value::Type::DICT` under the "aaa" dict associated with the // key "bbb", and then a `Value::Type::STRING` under the "bbb" dict associated // with the key "ccc". // // If a path only has one component (i.e. has no dots), please use the regular, // non-path APIs. // // Lists support: // - `empty()`, `size()`, `begin()`, `end()`, `cbegin()`, `cend()`, // `rbegin()`, `rend()`, `front()`, `back()`, `reserve()`, `operator[]`, // `clear()`, `erase()`: Identical to the STL container equivalents, with // additional safety checks, e.g. `operator[]` will `CHECK()` if the index // is out of range. // - `Clone()`: Create a deep copy. // - `Append()`: Append a value to the end of the list. Accepts `Value` or any // of the subtypes that `Value` can hold. // - `Insert()`: Insert a `Value` at a specified point in the list. // - `EraseValue()`: Erases all matching `Value`s from the list. // - `EraseIf()`: Erase all `Value`s matching an arbitrary predicate from the // list. class BASE_EXPORT GSL_OWNER Value { … }; // Adapter so `Value::Dict` or `Value::List` can be directly passed to JSON // serialization methods without having to clone the contents and transfer // ownership of the clone to a `Value` wrapper object. // // Like `std::string_view` and `span<T>`, this adapter does NOT retain // ownership. Any underlying object that is passed by reference (i.e. // `std::string`, `Value::BlobStorage`, `Value::Dict`, `Value::List`, or // `Value`) MUST remain live as long as there is a `ValueView` referencing it. // // While it might be nice to just use the `absl::variant` type directly, the // need to use `std::reference_wrapper` makes it clunky. `absl::variant` and // `std::reference_wrapper` both support implicit construction, but C++ only // allows at most one user-defined conversion in an implicit conversion // sequence. If this adapter and its implicit constructors did not exist, // callers would need to use `std::ref` or `std::cref` to pass `Value::Dict` or // `Value::List` to a function with a `ValueView` parameter. class BASE_EXPORT GSL_POINTER ValueView { … }; // This interface is implemented by classes that know how to serialize // Value objects. class BASE_EXPORT ValueSerializer { … }; // This interface is implemented by classes that know how to deserialize Value // objects. class BASE_EXPORT ValueDeserializer { … }; // Stream operator so Values can be pretty printed by gtest. BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value& value); BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value::Dict& dict); BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value::List& list); // Stream operator so that enum class Types can be used in log statements. BASE_EXPORT std::ostream& operator<<(std::ostream& out, const Value::Type& type); } // namespace base #endif // BASE_VALUES_H_